2525import com .google .protobuf .ByteString ;
2626import com .google .protobuf .CodedInputStream ;
2727import com .google .protobuf .ExtensionRegistryLite ;
28+ import com .google .protobuf .Internal .EnumLite ;
2829import com .google .protobuf .InvalidProtocolBufferException ;
2930import com .google .protobuf .MessageLite ;
3031import com .google .protobuf .WireFormat ;
@@ -118,34 +119,39 @@ private Object readLengthDelimitedField(
118119 return CelByteString .of (inputStream .readByteArray ());
119120 case MESSAGE :
120121 return mergeOrReadMessageField (
121- inputStream .readBytes (), fieldDescriptor .getFieldProtoTypeName (), existingValue );
122+ inputStream .readBytes (),
123+ fieldDescriptor .getFieldProtoTypeName (),
124+ existingValue ,
125+ /* isView= */ true );
122126 case STRING :
123127 return inputStream .readStringRequireUtf8 ();
124128 default :
125129 throw new IllegalStateException ("Unexpected field type: " + fieldType );
126130 }
127131 }
128132
133+ // Reads bytes of their own, not a view of another message's.
129134 private Object readMessageField (ByteString bytes , String fieldProtoTypeName ) {
130- return mergeOrReadMessageField (bytes , fieldProtoTypeName , /* existingValue= */ null );
135+ return mergeOrReadMessageField (
136+ bytes , fieldProtoTypeName , /* existingValue= */ null , /* isView= */ false );
131137 }
132138
133139 private Object mergeOrReadMessageField (
134- ByteString bytes , String fieldProtoTypeName , @ Nullable Object existingValue ) {
140+ ByteString bytes , String fieldProtoTypeName , @ Nullable Object existingValue , boolean isView ) {
135141 MessageLiteDescriptor descriptor =
136142 descriptorPool .findDescriptor (fieldProtoTypeName ).orElse (null );
137143 if (descriptor == null ) {
138144 if (existingValue instanceof RawProtoMessageLiteValue ) {
139145 bytes = ((RawProtoMessageLiteValue ) existingValue ).toByteString ().concat (bytes );
140146 }
141- return RawProtoMessageLiteValue .create (bytes , fieldProtoTypeName , this , /* isView= */ true );
147+ return RawProtoMessageLiteValue .create (bytes , fieldProtoTypeName , this , isView );
142148 }
143149 WellKnownProto wellKnownProto = WellKnownProto .getByTypeName (fieldProtoTypeName ).orElse (null );
144150 if (isStructLike (wellKnownProto )) {
145151 if (existingValue instanceof ProtoMessageLiteValue ) {
146152 bytes = ((ProtoMessageLiteValue ) existingValue ).toByteString ().concat (bytes );
147153 }
148- return ProtoMessageLiteValue .create (bytes , fieldProtoTypeName , this );
154+ return ProtoMessageLiteValue .create (bytes , descriptor , this );
149155 }
150156 if (existingValue instanceof MessageLite ) {
151157 return mergeMessageLite (((MessageLite ) existingValue ).toBuilder (), bytes , fieldProtoTypeName );
@@ -163,24 +169,19 @@ Object getDefaultCelValue(FieldLiteDescriptor fieldDescriptor) {
163169 return toRuntimeValue (getDefaultValue (fieldDescriptor ));
164170 }
165171
166- private Optional <FieldLiteDescriptor > findFieldDescriptor (String protoTypeName , int fieldNumber ) {
167- return descriptorPool
168- .findDescriptor (protoTypeName )
169- .flatMap (desc -> desc .findByFieldNumber (fieldNumber ));
172+ // A selected field's default value: the one in the SelectField, else its type's.
173+ Object getDefaultCelValue (SelectField field , FieldLiteDescriptor fieldDescriptor ) {
174+ return field .defaultValue () != null
175+ ? field .defaultValue ()
176+ : getDefaultCelValue (fieldDescriptor );
170177 }
171178
172- Optional <FieldLiteDescriptor > findFieldDescriptor (String protoTypeName , String fieldName ) {
173- return descriptorPool
174- .findDescriptor (protoTypeName )
175- .flatMap (desc -> desc .findByFieldName (fieldName ));
179+ private @ Nullable FieldLiteDescriptor findFieldDescriptor (String protoTypeName , int fieldNumber ) {
180+ MessageLiteDescriptor descriptor = descriptorPool .findDescriptor (protoTypeName ).orElse (null );
181+ return descriptor == null ? null : descriptor .findByFieldNumber (fieldNumber );
176182 }
177183
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 ) {
184+ static MessageLite parseMessageLite (ByteString bytes , MessageLiteDescriptor descriptor ) {
184185 if (bytes .isEmpty ()) {
185186 return descriptor .newMessageBuilder ().getDefaultInstanceForType ();
186187 }
@@ -216,7 +217,7 @@ private Object toRuntimeValue(MessageLite msg, MessageLiteDescriptor descriptor)
216217 WellKnownProto wellKnownProto =
217218 WellKnownProto .getByTypeName (descriptor .getProtoTypeName ()).orElse (null );
218219 if (isStructLike (wellKnownProto )) {
219- return ProtoMessageLiteValue .create (msg , descriptor . getProtoTypeName () , this );
220+ return ProtoMessageLiteValue .create (msg , descriptor , this );
220221 }
221222
222223 return fromWellKnownProto (msg , checkNotNull (wellKnownProto ));
@@ -316,15 +317,8 @@ private Map.Entry<Object, Object> readSingleMapEntry(
316317 return scanField (bytes , protoTypeName , fieldDescriptor , null , null );
317318 }
318319
319- /** Reads {@code field}, by its own type information if {@code fieldDescriptor} is null. */
320- private @ Nullable Object readField (
321- ByteString bytes ,
322- String protoTypeName ,
323- @ Nullable FieldLiteDescriptor fieldDescriptor ,
324- SelectField field ) {
325- if (fieldDescriptor != null ) {
326- return readField (bytes , protoTypeName , fieldDescriptor );
327- }
320+ /** Reads {@code field} using the type information it carries. */
321+ private @ Nullable Object readField (ByteString bytes , String protoTypeName , SelectField field ) {
328322 SelectField .MapEntrySpec mapEntrySpec = field .mapEntrySpec ();
329323 if (mapEntrySpec == null ) {
330324 return readField (bytes , protoTypeName , newFieldDescriptor (field ));
@@ -355,6 +349,9 @@ private Map.Entry<Object, Object> readSingleMapEntry(
355349 FieldLiteDescriptor fieldDescriptor ,
356350 @ Nullable FieldLiteDescriptor keyDescriptor ,
357351 @ Nullable FieldLiteDescriptor valueDescriptor ) {
352+ if (fieldDescriptor .getProtoFieldType ().equals (FieldLiteDescriptor .Type .GROUP )) {
353+ throw new UnsupportedOperationException ("Groups are not supported" );
354+ }
358355 CodedInputStream inputStream = bytes .newCodedInput ();
359356 // Submessages alias bytes; unwrapping parses or copies them, so no view outlives evaluation.
360357 inputStream .enableAliasing (true );
@@ -400,40 +397,31 @@ private Map.Entry<Object, Object> readSingleMapEntry(
400397 }
401398
402399 /**
403- * Selects {@code field} from {@code bytes}, decoding it by the type information in {@code field}
404- * for fields missing from the descriptor pool . Returns the field's default value if it's absent.
400+ * Selects {@code field}, which its message's descriptor doesn't have, from {@code bytes} by the
401+ * type information it carries . Returns the field's default value if it's absent.
405402 */
406403 Object selectByFieldNumber (ByteString bytes , String protoTypeName , SelectField field ) {
407- FieldLiteDescriptor fieldDescriptor =
408- findFieldDescriptor (protoTypeName , field .fieldNumber ()).orElse (null );
409- Object fieldValue = readField (bytes , protoTypeName , fieldDescriptor , field );
410- if (fieldValue != null ) {
411- return fieldValue ;
412- }
413- if (field .defaultValue () != null ) {
414- return field .defaultValue ();
415- }
416- return getDefaultCelValue (
417- fieldDescriptor != null ? fieldDescriptor : newFieldDescriptor (field ));
404+ Object fieldValue = readField (bytes , protoTypeName , field );
405+ return fieldValue != null ? fieldValue : getDefaultCelValue (field , newFieldDescriptor (field ));
418406 }
419407
420408 /**
421- * Finds {@code field} in {@code bytes}, decoding it by the type information in {@code field} for
422- * fields missing from the descriptor pool . A field without a type code is decoded as a message.
409+ * Finds {@code field}, which its message's descriptor doesn't have, in {@code bytes} by the type
410+ * information it carries . A field without a type code is decoded as a message.
423411 */
424412 Optional <Object > findByFieldNumber (ByteString bytes , String protoTypeName , SelectField field ) {
425- FieldLiteDescriptor fieldDescriptor =
426- findFieldDescriptor (protoTypeName , field .fieldNumber ()).orElse (null );
427- return Optional .ofNullable (readField (bytes , protoTypeName , fieldDescriptor , field ));
413+ return Optional .ofNullable (readField (bytes , protoTypeName , field ));
428414 }
429415
430416 /** Returns whether {@code field} is present in {@code bytes}. */
431417 boolean hasFieldByNumber (ByteString bytes , String protoTypeName , SelectField field ) {
432- FieldLiteDescriptor fieldDescriptor =
433- findFieldDescriptor (protoTypeName , field .fieldNumber ()).orElse (null );
418+ FieldLiteDescriptor fieldDescriptor = findFieldDescriptor (protoTypeName , field .fieldNumber ());
434419 if (fieldDescriptor == null ) {
435420 fieldDescriptor = newFieldDescriptor (field );
436421 }
422+ if (fieldDescriptor .getProtoFieldType ().equals (FieldLiteDescriptor .Type .GROUP )) {
423+ throw new UnsupportedOperationException ("Groups are not supported" );
424+ }
437425 boolean isPackableList =
438426 fieldDescriptor .getEncodingType ().equals (EncodingType .LIST ) && isPackable (fieldDescriptor );
439427 CodedInputStream inputStream = bytes .newCodedInput ();
@@ -464,6 +452,103 @@ boolean hasFieldByNumber(ByteString bytes, String protoTypeName, SelectField fie
464452 return false ;
465453 }
466454
455+ /**
456+ * Reads {@code fieldDescriptor} of {@code message} with its generated getter rather than from
457+ * wire bytes: its CEL value, or null if it's absent.
458+ */
459+ @ Nullable Object readFieldByGetter (
460+ ProtoMessageLiteValue message , FieldLiteDescriptor fieldDescriptor ) {
461+ Object value = readGetter (message , fieldDescriptor .getFieldNumber ());
462+ if (value == null ) {
463+ return null ;
464+ }
465+ switch (fieldDescriptor .getEncodingType ()) {
466+ case LIST :
467+ List <?> list = (List <?>) value ;
468+ switch (fieldDescriptor .getProtoFieldType ()) {
469+ case INT64 :
470+ case SINT64 :
471+ case SFIXED64 :
472+ case DOUBLE :
473+ case BOOL :
474+ case STRING :
475+ // These elements are their own CEL values, so the immutable list needn't be copied.
476+ return CelPreAdaptedList .wrap (list );
477+ default :
478+ break ;
479+ }
480+ ImmutableList .Builder <Object > listBuilder =
481+ ImmutableList .builderWithExpectedSize (list .size ());
482+ for (int i = 0 ; i < list .size (); i ++) {
483+ listBuilder .add (fromGetterValue (list .get (i ), fieldDescriptor ));
484+ }
485+ return listBuilder .build ();
486+ case MAP :
487+ Map <?, ?> map = (Map <?, ?>) value ;
488+ MessageLiteDescriptor entryDescriptor =
489+ descriptorPool .getDescriptorOrThrow (fieldDescriptor .getFieldProtoTypeName ());
490+ FieldLiteDescriptor keyDescriptor =
491+ entryDescriptor .getByFieldNumberOrThrow (MAP_KEY_FIELD_NUMBER );
492+ FieldLiteDescriptor valueDescriptor =
493+ entryDescriptor .getByFieldNumberOrThrow (MAP_VALUE_FIELD_NUMBER );
494+ ImmutableMap .Builder <Object , Object > mapBuilder =
495+ ImmutableMap .builderWithExpectedSize (map .size ());
496+ for (Map .Entry <?, ?> entry : map .entrySet ()) {
497+ mapBuilder .put (
498+ fromGetterValue (entry .getKey (), keyDescriptor ),
499+ fromGetterValue (entry .getValue (), valueDescriptor ));
500+ }
501+ return mapBuilder .buildOrThrow ();
502+ case SINGULAR :
503+ return fromGetterValue (value , fieldDescriptor );
504+ }
505+ throw new IllegalStateException (
506+ "Unexpected encoding type: " + fieldDescriptor .getEncodingType ());
507+ }
508+
509+ /** Like {@link #hasFieldByNumber}, through the field's generated getter. */
510+ boolean hasByGetter (ProtoMessageLiteValue message , SelectField field ) {
511+ return readGetter (message , field .fieldNumber ()) != null ;
512+ }
513+
514+ // A field's value as its getter returns it, or null if it's unset or an empty repeated or map.
515+ private static @ Nullable Object readGetter (ProtoMessageLiteValue message , int fieldNumber ) {
516+ Object value =
517+ message .descriptor ().getFieldValue (checkNotNull (message .rawValue ()), fieldNumber );
518+ boolean isEmpty =
519+ (value instanceof List && ((List <?>) value ).isEmpty ())
520+ || (value instanceof Map && ((Map <?, ?>) value ).isEmpty ());
521+ return isEmpty ? null : value ;
522+ }
523+
524+ // Converts a field's (or element's) Java value as returned by its getter to its CEL value.
525+ private Object fromGetterValue (Object value , FieldLiteDescriptor fieldDescriptor ) {
526+ switch (fieldDescriptor .getProtoFieldType ()) {
527+ case UINT32 :
528+ case FIXED32 :
529+ return UnsignedLong .fromLongBits (Integer .toUnsignedLong ((Integer ) value ));
530+ case UINT64 :
531+ case FIXED64 :
532+ return UnsignedLong .fromLongBits ((Long ) value );
533+ case ENUM :
534+ // Open enums are read as their numbers; closed ones as enum constants.
535+ return value instanceof Integer
536+ ? ((Integer ) value ).longValue ()
537+ : (long ) ((EnumLite ) value ).getNumber ();
538+ case MESSAGE :
539+ MessageLite message = (MessageLite ) value ;
540+ MessageLiteDescriptor descriptor = descriptorPool .findDescriptor (message ).orElse (null );
541+ // A submessage whose class has no descriptor is read from its own bytes, not its root's:
542+ // by its type's descriptor if the pool has one for another class (such as an older
543+ // version of it), or else descriptorless.
544+ return descriptor != null
545+ ? toRuntimeValue (message , descriptor )
546+ : readMessageField (message .toByteString (), fieldDescriptor .getFieldProtoTypeName ());
547+ default :
548+ return super .toRuntimeValue (value );
549+ }
550+ }
551+
467552 /** Describes {@code field} by the type information it carries, built once and kept on it. */
468553 private static FieldLiteDescriptor newFieldDescriptor (SelectField field ) {
469554 Object cached = field .liteFieldDescriptor ();
0 commit comments