Skip to content

Commit 69efe77

Browse files
l46kokcopybara-github
authored andcommitted
No public description
PiperOrigin-RevId: 997600155
1 parent 32ba216 commit 69efe77

18 files changed

Lines changed: 1010 additions & 151 deletions

File tree

‎common/src/main/java/dev/cel/common/values/BUILD.bazel‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,7 @@ java_library(
329329
deps = [
330330
":base_proto_cel_value_converter",
331331
":optimized_selectable",
332+
":preadapted_list",
332333
":select_field",
333334
":values",
334335
"//:auto_value",
@@ -360,6 +361,7 @@ cel_android_library(
360361
deps = [
361362
":base_proto_cel_value_converter_android",
362363
":optimized_selectable_android",
364+
":preadapted_list_android",
363365
":select_field_android",
364366
":values_android",
365367
"//:auto_value",

‎common/src/main/java/dev/cel/common/values/ProtoLiteCelValueConverter.java‎

Lines changed: 164 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,14 @@
2525
import com.google.protobuf.ByteString;
2626
import com.google.protobuf.CodedInputStream;
2727
import com.google.protobuf.ExtensionRegistryLite;
28+
import com.google.protobuf.Internal.EnumLite;
2829
import com.google.protobuf.InvalidProtocolBufferException;
2930
import com.google.protobuf.MessageLite;
3031
import com.google.protobuf.WireFormat;
3132
import dev.cel.common.annotations.Internal;
3233
import dev.cel.common.internal.CelLiteDescriptorPool;
3334
import dev.cel.common.internal.WellKnownProto;
35+
import dev.cel.protobuf.CelLiteDescriptor;
3436
import dev.cel.protobuf.CelLiteDescriptor.FieldLiteDescriptor;
3537
import dev.cel.protobuf.CelLiteDescriptor.FieldLiteDescriptor.EncodingType;
3638
import dev.cel.protobuf.CelLiteDescriptor.FieldLiteDescriptor.JavaType;
@@ -118,34 +120,39 @@ private Object readLengthDelimitedField(
118120
return CelByteString.of(inputStream.readByteArray());
119121
case MESSAGE:
120122
return mergeOrReadMessageField(
121-
inputStream.readBytes(), fieldDescriptor.getFieldProtoTypeName(), existingValue);
123+
inputStream.readBytes(),
124+
fieldDescriptor.getFieldProtoTypeName(),
125+
existingValue,
126+
/* isView= */ true);
122127
case STRING:
123128
return inputStream.readStringRequireUtf8();
124129
default:
125130
throw new IllegalStateException("Unexpected field type: " + fieldType);
126131
}
127132
}
128133

134+
// Reads bytes of their own, not a view of another message's.
129135
private Object readMessageField(ByteString bytes, String fieldProtoTypeName) {
130-
return mergeOrReadMessageField(bytes, fieldProtoTypeName, /* existingValue= */ null);
136+
return mergeOrReadMessageField(
137+
bytes, fieldProtoTypeName, /* existingValue= */ null, /* isView= */ false);
131138
}
132139

133140
private Object mergeOrReadMessageField(
134-
ByteString bytes, String fieldProtoTypeName, @Nullable Object existingValue) {
141+
ByteString bytes, String fieldProtoTypeName, @Nullable Object existingValue, boolean isView) {
135142
MessageLiteDescriptor descriptor =
136143
descriptorPool.findDescriptor(fieldProtoTypeName).orElse(null);
137144
if (descriptor == null) {
138145
if (existingValue instanceof RawProtoMessageLiteValue) {
139146
bytes = ((RawProtoMessageLiteValue) existingValue).toByteString().concat(bytes);
140147
}
141-
return RawProtoMessageLiteValue.create(bytes, fieldProtoTypeName, this, /* isView= */ true);
148+
return RawProtoMessageLiteValue.create(bytes, fieldProtoTypeName, this, isView);
142149
}
143150
WellKnownProto wellKnownProto = WellKnownProto.getByTypeName(fieldProtoTypeName).orElse(null);
144151
if (isStructLike(wellKnownProto)) {
145152
if (existingValue instanceof ProtoMessageLiteValue) {
146153
bytes = ((ProtoMessageLiteValue) existingValue).toByteString().concat(bytes);
147154
}
148-
return ProtoMessageLiteValue.create(bytes, fieldProtoTypeName, this);
155+
return ProtoMessageLiteValue.create(bytes, descriptor, this);
149156
}
150157
if (existingValue instanceof MessageLite) {
151158
return mergeMessageLite(((MessageLite) existingValue).toBuilder(), bytes, fieldProtoTypeName);
@@ -169,18 +176,7 @@ private Optional<FieldLiteDescriptor> findFieldDescriptor(String protoTypeName,
169176
.flatMap(desc -> desc.findByFieldNumber(fieldNumber));
170177
}
171178

172-
Optional<FieldLiteDescriptor> findFieldDescriptor(String protoTypeName, String fieldName) {
173-
return descriptorPool
174-
.findDescriptor(protoTypeName)
175-
.flatMap(desc -> desc.findByFieldName(fieldName));
176-
}
177-
178-
MessageLite parseMessageLite(ByteString bytes, String protoTypeName) {
179-
MessageLiteDescriptor descriptor = descriptorPool.getDescriptorOrThrow(protoTypeName);
180-
return parseMessageLite(bytes, descriptor);
181-
}
182-
183-
private static MessageLite parseMessageLite(ByteString bytes, MessageLiteDescriptor descriptor) {
179+
static MessageLite parseMessageLite(ByteString bytes, MessageLiteDescriptor descriptor) {
184180
if (bytes.isEmpty()) {
185181
return descriptor.newMessageBuilder().getDefaultInstanceForType();
186182
}
@@ -216,7 +212,7 @@ private Object toRuntimeValue(MessageLite msg, MessageLiteDescriptor descriptor)
216212
WellKnownProto wellKnownProto =
217213
WellKnownProto.getByTypeName(descriptor.getProtoTypeName()).orElse(null);
218214
if (isStructLike(wellKnownProto)) {
219-
return ProtoMessageLiteValue.create(msg, descriptor.getProtoTypeName(), this);
215+
return ProtoMessageLiteValue.create(msg, descriptor, this);
220216
}
221217

222218
return fromWellKnownProto(msg, checkNotNull(wellKnownProto));
@@ -464,6 +460,145 @@ boolean hasFieldByNumber(ByteString bytes, String protoTypeName, SelectField fie
464460
return false;
465461
}
466462

463+
/**
464+
* Reads {@code fieldDescriptor} of {@code message} with its generated getter rather than from
465+
* wire bytes: its CEL value, null if it's absent, or {@link CelLiteDescriptor#NO_GETTER} if it
466+
* can't be read that way.
467+
*/
468+
@SuppressWarnings("ReferenceEquality") // NO_GETTER is a sentinel instance.
469+
@Nullable Object readFieldByGetter(
470+
ProtoMessageLiteValue message, FieldLiteDescriptor fieldDescriptor) {
471+
MessageLite msg = message.rawValue();
472+
if (msg == null) {
473+
return CelLiteDescriptor.NO_GETTER;
474+
}
475+
Object value = message.descriptor().getFieldValue(msg, fieldDescriptor.getFieldNumber());
476+
if (value == null || value == CelLiteDescriptor.NO_GETTER) {
477+
return value;
478+
}
479+
switch (fieldDescriptor.getEncodingType()) {
480+
case LIST:
481+
List<?> list = (List<?>) value;
482+
if (list.isEmpty()) {
483+
return null;
484+
}
485+
switch (fieldDescriptor.getProtoFieldType()) {
486+
case INT64:
487+
case SINT64:
488+
case SFIXED64:
489+
case DOUBLE:
490+
case BOOL:
491+
case STRING:
492+
// These elements are their own CEL values, so the immutable list needn't be copied.
493+
return CelPreAdaptedList.wrap(list);
494+
default:
495+
break;
496+
}
497+
ImmutableList.Builder<Object> listBuilder =
498+
ImmutableList.builderWithExpectedSize(list.size());
499+
for (int i = 0; i < list.size(); i++) {
500+
listBuilder.add(fromGetterValue(list.get(i), fieldDescriptor));
501+
}
502+
return listBuilder.build();
503+
case MAP:
504+
Map<?, ?> map = (Map<?, ?>) value;
505+
if (map.isEmpty()) {
506+
return null;
507+
}
508+
MessageLiteDescriptor entryDescriptor =
509+
descriptorPool.getDescriptorOrThrow(fieldDescriptor.getFieldProtoTypeName());
510+
FieldLiteDescriptor keyDescriptor =
511+
entryDescriptor.getByFieldNumberOrThrow(MAP_KEY_FIELD_NUMBER);
512+
FieldLiteDescriptor valueDescriptor =
513+
entryDescriptor.getByFieldNumberOrThrow(MAP_VALUE_FIELD_NUMBER);
514+
ImmutableMap.Builder<Object, Object> mapBuilder =
515+
ImmutableMap.builderWithExpectedSize(map.size());
516+
for (Map.Entry<?, ?> entry : map.entrySet()) {
517+
mapBuilder.put(
518+
fromGetterValue(entry.getKey(), keyDescriptor),
519+
fromGetterValue(entry.getValue(), valueDescriptor));
520+
}
521+
return mapBuilder.buildOrThrow();
522+
case SINGULAR:
523+
return fieldDescriptor.getJavaType() == JavaType.MESSAGE
524+
? readSubmessage(message, (MessageLite) value, fieldDescriptor)
525+
: fromGetterValue(value, fieldDescriptor);
526+
}
527+
throw new IllegalStateException(
528+
"Unexpected encoding type: " + fieldDescriptor.getEncodingType());
529+
}
530+
531+
/** Like {@link #fromGetterValue}, reusing {@code parent}'s last submessage value. */
532+
@SuppressWarnings("ReferenceEquality") // Checks whether the getter returned the same instance.
533+
private Object readSubmessage(
534+
ProtoMessageLiteValue parent, MessageLite submessage, FieldLiteDescriptor fieldDescriptor) {
535+
Object last = parent.lastSubmessage();
536+
if (last instanceof ProtoMessageLiteValue
537+
&& ((ProtoMessageLiteValue) last).rawValue() == submessage) {
538+
return last;
539+
}
540+
if (last instanceof SerializedSubmessage
541+
&& ((SerializedSubmessage) last).submessage == submessage) {
542+
return ((SerializedSubmessage) last).value;
543+
}
544+
Object value = fromGetterValue(submessage, fieldDescriptor);
545+
if (value instanceof ProtoMessageLiteValue) {
546+
parent.setLastSubmessage(value);
547+
} else if (value instanceof RawProtoMessageLiteValue) {
548+
// Serialized, for lack of a descriptor for its class.
549+
parent.setLastSubmessage(new SerializedSubmessage(submessage, value));
550+
}
551+
return value;
552+
}
553+
554+
/** Like {@link #hasFieldByNumber}, through the field's generated getter if it has one. */
555+
@SuppressWarnings("ReferenceEquality") // NO_GETTER is a sentinel instance.
556+
Object hasByGetter(ProtoMessageLiteValue message, SelectField field) {
557+
MessageLite msg = message.rawValue();
558+
if (msg == null) {
559+
return CelLiteDescriptor.NO_GETTER;
560+
}
561+
Object value = message.descriptor().getFieldValue(msg, field.fieldNumber());
562+
if (value == CelLiteDescriptor.NO_GETTER) {
563+
return value;
564+
}
565+
if (value instanceof List) {
566+
return !((List<?>) value).isEmpty();
567+
}
568+
if (value instanceof Map) {
569+
return !((Map<?, ?>) value).isEmpty();
570+
}
571+
return value != null;
572+
}
573+
574+
/** Converts a field's (or element's) Java value as returned by its getter to its CEL value. */
575+
private Object fromGetterValue(Object value, FieldLiteDescriptor fieldDescriptor) {
576+
switch (fieldDescriptor.getProtoFieldType()) {
577+
case UINT32:
578+
case FIXED32:
579+
return UnsignedLong.fromLongBits(Integer.toUnsignedLong((Integer) value));
580+
case UINT64:
581+
case FIXED64:
582+
return UnsignedLong.fromLongBits((Long) value);
583+
case ENUM:
584+
// Open enums are read as their numbers; closed ones as enum constants.
585+
return value instanceof Integer
586+
? ((Integer) value).longValue()
587+
: (long) ((EnumLite) value).getNumber();
588+
case MESSAGE:
589+
MessageLite message = (MessageLite) value;
590+
MessageLiteDescriptor descriptor = descriptorPool.findDescriptor(message).orElse(null);
591+
// A submessage whose class has no descriptor is read from its own bytes, not its root's:
592+
// by its type's descriptor if the pool has one for another class (such as an older
593+
// version of it), or else descriptorless.
594+
return descriptor != null
595+
? toRuntimeValue(message, descriptor)
596+
: readMessageField(message.toByteString(), fieldDescriptor.getFieldProtoTypeName());
597+
default:
598+
return super.toRuntimeValue(value);
599+
}
600+
}
601+
467602
/** Describes {@code field} by the type information it carries, built once and kept on it. */
468603
private static FieldLiteDescriptor newFieldDescriptor(SelectField field) {
469604
Object cached = field.liteFieldDescriptor();
@@ -648,6 +783,17 @@ private static IllegalArgumentException newDecodeException(String protoTypeName,
648783
"Failed to decode proto message of type: " + protoTypeName, e);
649784
}
650785

786+
/** A submessage serialized for lack of a descriptor for its class, and its value. */
787+
private static final class SerializedSubmessage {
788+
private final MessageLite submessage;
789+
private final Object value;
790+
791+
private SerializedSubmessage(MessageLite submessage, Object value) {
792+
this.submessage = submessage;
793+
this.value = value;
794+
}
795+
}
796+
651797
private ProtoLiteCelValueConverter(CelLiteDescriptorPool celLiteDescriptorPool) {
652798
this.descriptorPool = checkNotNull(celLiteDescriptorPool);
653799
}

0 commit comments

Comments
 (0)