Skip to content

Commit 984193b

Browse files
committed
Wrap FieldMask via shared message-to-struct hook on the base converter
Move the FieldMask case into BaseProtoCelValueConverter, delegating to a new fromProtoMessageToStructValue hook that both the full and lite converters implement. This reuses the existing non-well-known message wrapping path (removing the duplicated ProtoMessageValue.create call) and extends the fix to the lite runtime. Adds a lite-converter test.
1 parent 95faaa8 commit 984193b

4 files changed

Lines changed: 38 additions & 18 deletions

File tree

common/src/main/java/dev/cel/common/values/BaseProtoCelValueConverter.java

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,6 @@
1717
import static com.google.common.collect.ImmutableList.toImmutableList;
1818
import static com.google.common.collect.ImmutableMap.toImmutableMap;
1919

20-
import com.google.common.base.CaseFormat;
21-
import com.google.common.base.Joiner;
2220
import com.google.common.base.Preconditions;
2321
import com.google.common.collect.ImmutableList;
2422
import com.google.common.collect.ImmutableMap;
@@ -29,7 +27,6 @@
2927
import com.google.protobuf.BytesValue;
3028
import com.google.protobuf.DoubleValue;
3129
import com.google.protobuf.Duration;
32-
import com.google.protobuf.FieldMask;
3330
import com.google.protobuf.FloatValue;
3431
import com.google.protobuf.Int32Value;
3532
import com.google.protobuf.Int64Value;
@@ -44,8 +41,6 @@
4441
import dev.cel.common.annotations.Internal;
4542
import dev.cel.common.internal.ProtoTimeUtils;
4643
import dev.cel.common.internal.WellKnownProto;
47-
import java.util.ArrayList;
48-
import java.util.List;
4944

5045
/**
5146
* {@code BaseProtoCelValueConverter} contains the common logic for converting between native Java
@@ -73,6 +68,12 @@ public Object toRuntimeValue(Object value) {
7368
return super.toRuntimeValue(value);
7469
}
7570

71+
/** Wraps a protobuf message as a navigable struct value. */
72+
protected StructValue<String, ?> fromProtoMessageToStructValue(MessageLiteOrBuilder message) {
73+
throw new UnsupportedOperationException(
74+
"This converter does not support wrapping protobuf messages as struct values.");
75+
}
76+
7677
protected Object fromWellKnownProto(MessageLiteOrBuilder message, WellKnownProto wellKnownProto) {
7778
switch (wellKnownProto) {
7879
case JSON_VALUE:
@@ -104,14 +105,7 @@ protected Object fromWellKnownProto(MessageLiteOrBuilder message, WellKnownProto
104105
case UINT64_VALUE:
105106
return UnsignedLong.fromLongBits(((UInt64Value) message).getValue());
106107
case FIELD_MASK:
107-
FieldMask fieldMask = (FieldMask) message;
108-
List<String> paths = new ArrayList<>(fieldMask.getPathsCount());
109-
for (String path : fieldMask.getPathsList()) {
110-
if (!path.isEmpty()) {
111-
paths.add(CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, path));
112-
}
113-
}
114-
return normalizePrimitive(Joiner.on(",").join(paths));
108+
return fromProtoMessageToStructValue(message);
115109
case EMPTY:
116110
return ImmutableMap.of();
117111
default:

common/src/main/java/dev/cel/common/values/ProtoCelValueConverter.java

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -71,14 +71,17 @@ protected Object fromWellKnownProto(MessageLiteOrBuilder msg, WellKnownProto wel
7171
"Unpacking failed for message: " + message.getDescriptorForType().getFullName(), e);
7272
}
7373
return toRuntimeValue(unpackedMessage);
74-
case FIELD_MASK:
75-
return ProtoMessageValue.create(
76-
(Message) message, celDescriptorPool, this, celOptions.enableJsonFieldNames());
7774
default:
7875
return super.fromWellKnownProto(message, wellKnownProto);
7976
}
8077
}
8178

79+
@Override
80+
protected ProtoMessageValue fromProtoMessageToStructValue(MessageLiteOrBuilder message) {
81+
return ProtoMessageValue.create(
82+
(Message) message, celDescriptorPool, this, celOptions.enableJsonFieldNames());
83+
}
84+
8285
@Override
8386
public Object toRuntimeValue(Object value) {
8487
if (value instanceof EnumValueDescriptor) {
@@ -102,8 +105,7 @@ public Object toRuntimeValue(Object value) {
102105
WellKnownProto wellKnownProto =
103106
WellKnownProto.getByTypeName(message.getDescriptorForType().getFullName()).orElse(null);
104107
if (wellKnownProto == null) {
105-
return ProtoMessageValue.create(
106-
message, celDescriptorPool, this, celOptions.enableJsonFieldNames());
108+
return fromProtoMessageToStructValue(message);
107109
}
108110

109111
return fromWellKnownProto(message, wellKnownProto);

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import com.google.protobuf.CodedInputStream;
2929
import com.google.protobuf.ExtensionRegistryLite;
3030
import com.google.protobuf.MessageLite;
31+
import com.google.protobuf.MessageLiteOrBuilder;
3132
import com.google.protobuf.WireFormat;
3233
import dev.cel.common.annotations.Internal;
3334
import dev.cel.common.internal.CelLiteDescriptorPool;
@@ -184,6 +185,17 @@ public Object toRuntimeValue(Object value) {
184185
return super.toRuntimeValue(value);
185186
}
186187

188+
@Override
189+
protected ProtoMessageLiteValue fromProtoMessageToStructValue(MessageLiteOrBuilder message) {
190+
MessageLite msg = (MessageLite) message;
191+
MessageLiteDescriptor descriptor =
192+
descriptorPool
193+
.findDescriptor(msg)
194+
.orElseThrow(
195+
() -> new NoSuchElementException("Could not find a descriptor for: " + msg));
196+
return ProtoMessageLiteValue.create(msg, descriptor.getProtoTypeName(), this);
197+
}
198+
187199
private Object getDefaultValue(FieldLiteDescriptor fieldDescriptor) {
188200
EncodingType encodingType = fieldDescriptor.getEncodingType();
189201
switch (encodingType) {

common/src/test/java/dev/cel/common/values/ProtoLiteCelValueConverterTest.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import com.google.protobuf.DoubleValue;
2828
import com.google.protobuf.Duration;
2929
import com.google.protobuf.ExtensionRegistryLite;
30+
import com.google.protobuf.FieldMask;
3031
import com.google.protobuf.FloatValue;
3132
import com.google.protobuf.Int32Value;
3233
import com.google.protobuf.Int64Value;
@@ -104,6 +105,17 @@ public void fromProtoMessageToCelValue_withWellKnownProto_convertsToPrimitivesFr
104105
assertThat(adaptedValue).isEqualTo(testCase.value);
105106
}
106107

108+
@Test
109+
public void fromProtoMessageToCelValue_fieldMask_returnsProtoMessageLiteValue() {
110+
FieldMask fieldMask = FieldMask.newBuilder().addPaths("foo").addPaths("bar").build();
111+
112+
Object adaptedValue = PROTO_LITE_CEL_VALUE_CONVERTER.toRuntimeValue(fieldMask);
113+
114+
assertThat(adaptedValue).isInstanceOf(ProtoMessageLiteValue.class);
115+
assertThat(((ProtoMessageLiteValue) adaptedValue).select("paths"))
116+
.isEqualTo(ImmutableList.of("foo", "bar"));
117+
}
118+
107119
/** Test cases for repeated_int64: 1L,2L,3L */
108120
@SuppressWarnings("ImmutableEnumChecker") // Test only
109121
private enum RepeatedFieldBytesTestCase {

0 commit comments

Comments
 (0)