diff --git a/common/src/main/java/dev/cel/common/internal/BUILD.bazel b/common/src/main/java/dev/cel/common/internal/BUILD.bazel index be5fc29a5..52e399609 100644 --- a/common/src/main/java/dev/cel/common/internal/BUILD.bazel +++ b/common/src/main/java/dev/cel/common/internal/BUILD.bazel @@ -217,7 +217,6 @@ java_library( "//common/annotations", "@maven//:com_google_guava_guava", "@maven//:com_google_protobuf_protobuf_java", - "@maven//:org_jspecify_jspecify", ], ) diff --git a/common/src/main/java/dev/cel/common/internal/DefaultDescriptorPool.java b/common/src/main/java/dev/cel/common/internal/DefaultDescriptorPool.java index df1907e42..fc703c905 100644 --- a/common/src/main/java/dev/cel/common/internal/DefaultDescriptorPool.java +++ b/common/src/main/java/dev/cel/common/internal/DefaultDescriptorPool.java @@ -22,26 +22,9 @@ import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMultimap; import com.google.errorprone.annotations.Immutable; -import com.google.protobuf.Any; -import com.google.protobuf.BoolValue; -import com.google.protobuf.BytesValue; import com.google.protobuf.Descriptors.Descriptor; import com.google.protobuf.Descriptors.FieldDescriptor; -import com.google.protobuf.DoubleValue; -import com.google.protobuf.Duration; -import com.google.protobuf.Empty; import com.google.protobuf.ExtensionRegistry; -import com.google.protobuf.FieldMask; -import com.google.protobuf.FloatValue; -import com.google.protobuf.Int32Value; -import com.google.protobuf.Int64Value; -import com.google.protobuf.ListValue; -import com.google.protobuf.StringValue; -import com.google.protobuf.Struct; -import com.google.protobuf.Timestamp; -import com.google.protobuf.UInt32Value; -import com.google.protobuf.UInt64Value; -import com.google.protobuf.Value; import dev.cel.common.CelDescriptors; import dev.cel.common.annotations.Internal; import java.util.HashMap; @@ -57,36 +40,14 @@ @Immutable @Internal public final class DefaultDescriptorPool implements CelDescriptorPool { - - private static final ImmutableMap WELL_KNOWN_PROTO_TO_DESCRIPTORS = - ImmutableMap.builder() - .put(WellKnownProto.ANY_VALUE, Any.getDescriptor()) - .put(WellKnownProto.BOOL_VALUE, BoolValue.getDescriptor()) - .put(WellKnownProto.BYTES_VALUE, BytesValue.getDescriptor()) - .put(WellKnownProto.DOUBLE_VALUE, DoubleValue.getDescriptor()) - .put(WellKnownProto.DURATION, Duration.getDescriptor()) - .put(WellKnownProto.FLOAT_VALUE, FloatValue.getDescriptor()) - .put(WellKnownProto.INT32_VALUE, Int32Value.getDescriptor()) - .put(WellKnownProto.INT64_VALUE, Int64Value.getDescriptor()) - .put(WellKnownProto.STRING_VALUE, StringValue.getDescriptor()) - .put(WellKnownProto.TIMESTAMP, Timestamp.getDescriptor()) - .put(WellKnownProto.UINT32_VALUE, UInt32Value.getDescriptor()) - .put(WellKnownProto.UINT64_VALUE, UInt64Value.getDescriptor()) - .put(WellKnownProto.JSON_LIST_VALUE, ListValue.getDescriptor()) - .put(WellKnownProto.JSON_STRUCT_VALUE, Struct.getDescriptor()) - .put(WellKnownProto.JSON_VALUE, Value.getDescriptor()) - .put(WellKnownProto.EMPTY, Empty.getDescriptor()) - .put(WellKnownProto.FIELD_MASK, FieldMask.getDescriptor()) - .buildOrThrow(); - - private static final ImmutableMap WELL_KNOWN_TYPE_NAME_TO_DESCRIPTORS = + private static final ImmutableMap WELL_KNOWN_TYPE_DESCRIPTORS = stream(WellKnownProto.values()) - .collect(toImmutableMap(WellKnownProto::typeName, WELL_KNOWN_PROTO_TO_DESCRIPTORS::get)); + .collect(toImmutableMap(WellKnownProto::typeName, WellKnownProto::descriptor)); /** A DefaultDescriptorPool instance with just well known types loaded. */ public static final DefaultDescriptorPool INSTANCE = new DefaultDescriptorPool( - WELL_KNOWN_TYPE_NAME_TO_DESCRIPTORS, + WELL_KNOWN_TYPE_DESCRIPTORS, ImmutableMultimap.of(), ExtensionRegistry.getEmptyRegistry()); @@ -106,8 +67,8 @@ public static DefaultDescriptorPool create(CelDescriptors celDescriptors) { public static DefaultDescriptorPool create( CelDescriptors celDescriptors, ExtensionRegistry extensionRegistry) { - Map descriptorMap = - new HashMap<>(WELL_KNOWN_TYPE_NAME_TO_DESCRIPTORS); // Using a hashmap to allow deduping + Map descriptorMap = new HashMap<>(); // Using a hashmap to allow deduping + stream(WellKnownProto.values()).forEach(d -> descriptorMap.put(d.typeName(), d.descriptor())); for (Descriptor descriptor : celDescriptors.messageTypeDescriptors()) { descriptorMap.putIfAbsent(descriptor.getFullName(), descriptor); diff --git a/common/src/main/java/dev/cel/common/internal/ProtoAdapter.java b/common/src/main/java/dev/cel/common/internal/ProtoAdapter.java index 35d277210..28da7e5d0 100644 --- a/common/src/main/java/dev/cel/common/internal/ProtoAdapter.java +++ b/common/src/main/java/dev/cel/common/internal/ProtoAdapter.java @@ -157,7 +157,7 @@ public Object adaptProtoToValue(MessageOrBuilder proto) { // If the proto is not a well-known type, then the input Message is what's expected as the // output return value. WellKnownProto wellKnownProto = - WellKnownProto.getByTypeName(typeName(proto.getDescriptorForType())); + WellKnownProto.getByDescriptorName(typeName(proto.getDescriptorForType())); if (wellKnownProto == null) { return proto; } @@ -335,7 +335,7 @@ private BidiConverter fieldToValueConverter(FieldDescriptor fieldDescriptor) { */ @SuppressWarnings("unchecked") public Optional adaptValueToProto(Object value, String protoTypeName) { - WellKnownProto wellKnownProto = WellKnownProto.getByTypeName(protoTypeName); + WellKnownProto wellKnownProto = WellKnownProto.getByDescriptorName(protoTypeName); if (wellKnownProto == null) { if (value instanceof Message) { return Optional.of((Message) value); @@ -376,7 +376,7 @@ public Optional adaptValueToProto(Object value, String protoTypeName) { break; case DOUBLE_VALUE: return Optional.ofNullable(adaptValueToDouble(value)); - case DURATION: + case DURATION_VALUE: return Optional.of((Duration) value); case FLOAT_VALUE: return Optional.ofNullable(adaptValueToFloat(value)); @@ -389,14 +389,12 @@ public Optional adaptValueToProto(Object value, String protoTypeName) { return Optional.of(StringValue.of((String) value)); } break; - case TIMESTAMP: + case TIMESTAMP_VALUE: return Optional.of((Timestamp) value); case UINT32_VALUE: return Optional.ofNullable(adaptValueToUint32(value)); case UINT64_VALUE: return Optional.ofNullable(adaptValueToUint64(value)); - default: - throw new IllegalArgumentException("Unsupported conversion: " + wellKnownProto); } return Optional.empty(); } @@ -581,7 +579,7 @@ private static boolean isWrapperType(FieldDescriptor fieldDescriptor) { return false; } String fieldTypeName = fieldDescriptor.getMessageType().getFullName(); - WellKnownProto wellKnownProto = WellKnownProto.getByTypeName(fieldTypeName); + WellKnownProto wellKnownProto = WellKnownProto.getByDescriptorName(fieldTypeName); return wellKnownProto != null && wellKnownProto.isWrapperType(); } diff --git a/common/src/main/java/dev/cel/common/internal/WellKnownProto.java b/common/src/main/java/dev/cel/common/internal/WellKnownProto.java index 476891181..14da4396d 100644 --- a/common/src/main/java/dev/cel/common/internal/WellKnownProto.java +++ b/common/src/main/java/dev/cel/common/internal/WellKnownProto.java @@ -21,10 +21,9 @@ import com.google.protobuf.Any; import com.google.protobuf.BoolValue; import com.google.protobuf.BytesValue; +import com.google.protobuf.Descriptors.Descriptor; import com.google.protobuf.DoubleValue; import com.google.protobuf.Duration; -import com.google.protobuf.Empty; -import com.google.protobuf.FieldMask; import com.google.protobuf.FloatValue; import com.google.protobuf.Int32Value; import com.google.protobuf.Int64Value; @@ -37,7 +36,6 @@ import com.google.protobuf.Value; import dev.cel.common.annotations.Internal; import java.util.function.Function; -import org.jspecify.annotations.Nullable; /** * WellKnownProto types used throughout CEL. These types are specially handled to ensure that @@ -46,32 +44,24 @@ */ @Internal public enum WellKnownProto { - ANY_VALUE("google.protobuf.Any", Any.class.getName()), - DURATION("google.protobuf.Duration", Duration.class.getName()), - JSON_LIST_VALUE("google.protobuf.ListValue", ListValue.class.getName()), - JSON_STRUCT_VALUE("google.protobuf.Struct", Struct.class.getName()), - JSON_VALUE("google.protobuf.Value", Value.class.getName()), - TIMESTAMP("google.protobuf.Timestamp", Timestamp.class.getName()), - // Wrapper types - FLOAT_VALUE("google.protobuf.FloatValue", FloatValue.class.getName(), /* isWrapperType= */ true), - INT32_VALUE("google.protobuf.Int32Value", Int32Value.class.getName(), /* isWrapperType= */ true), - INT64_VALUE("google.protobuf.Int64Value", Int64Value.class.getName(), /* isWrapperType= */ true), - STRING_VALUE( - "google.protobuf.StringValue", StringValue.class.getName(), /* isWrapperType= */ true), - BOOL_VALUE("google.protobuf.BoolValue", BoolValue.class.getName(), /* isWrapperType= */ true), - BYTES_VALUE("google.protobuf.BytesValue", BytesValue.class.getName(), /* isWrapperType= */ true), - DOUBLE_VALUE( - "google.protobuf.DoubleValue", DoubleValue.class.getName(), /* isWrapperType= */ true), - UINT32_VALUE( - "google.protobuf.UInt32Value", UInt32Value.class.getName(), /* isWrapperType= */ true), - UINT64_VALUE( - "google.protobuf.UInt64Value", UInt64Value.class.getName(), /* isWrapperType= */ true), - // These aren't explicitly called out as wrapper types in the spec, but behave like one, because - // they are still converted into an equivalent primitive type. - - EMPTY("google.protobuf.Empty", Empty.class.getName(), /* isWrapperType= */ true), - FIELD_MASK("google.protobuf.FieldMask", FieldMask.class.getName(), /* isWrapperType= */ true), - ; + JSON_VALUE(Value.getDescriptor()), + JSON_STRUCT_VALUE(Struct.getDescriptor()), + JSON_LIST_VALUE(ListValue.getDescriptor()), + ANY_VALUE(Any.getDescriptor()), + BOOL_VALUE(BoolValue.getDescriptor(), true), + BYTES_VALUE(BytesValue.getDescriptor(), true), + DOUBLE_VALUE(DoubleValue.getDescriptor(), true), + FLOAT_VALUE(FloatValue.getDescriptor(), true), + INT32_VALUE(Int32Value.getDescriptor(), true), + INT64_VALUE(Int64Value.getDescriptor(), true), + STRING_VALUE(StringValue.getDescriptor(), true), + UINT32_VALUE(UInt32Value.getDescriptor(), true), + UINT64_VALUE(UInt64Value.getDescriptor(), true), + DURATION_VALUE(Duration.getDescriptor()), + TIMESTAMP_VALUE(Timestamp.getDescriptor()); + + private final Descriptor descriptor; + private final boolean isWrapperType; private static final ImmutableMap WELL_KNOWN_PROTO_MAP; @@ -81,42 +71,28 @@ public enum WellKnownProto { .collect(toImmutableMap(WellKnownProto::typeName, Function.identity())); } - private final String wellKnownProtoFullName; - private final String javaClassName; - private final boolean isWrapperType; - - public String typeName() { - return wellKnownProtoFullName; + WellKnownProto(Descriptor descriptor) { + this(descriptor, /* isWrapperType= */ false); } - public String javaClassName() { - return this.javaClassName; + WellKnownProto(Descriptor descriptor, boolean isWrapperType) { + this.descriptor = descriptor; + this.isWrapperType = isWrapperType; } - public static @Nullable WellKnownProto getByTypeName(String typeName) { - return WELL_KNOWN_PROTO_MAP.get(typeName); + public Descriptor descriptor() { + return descriptor; } - public static boolean isWrapperType(String typeName) { - WellKnownProto wellKnownProto = getByTypeName(typeName); - if (wellKnownProto == null) { - return false; - } - - return wellKnownProto.isWrapperType(); + public String typeName() { + return descriptor.getFullName(); } public boolean isWrapperType() { return isWrapperType; } - WellKnownProto(String wellKnownProtoFullName, String javaClassName) { - this(wellKnownProtoFullName, javaClassName, /* isWrapperType= */ false); - } - - WellKnownProto(String wellKnownProtoFullName, String javaClassName, boolean isWrapperType) { - this.wellKnownProtoFullName = wellKnownProtoFullName; - this.javaClassName = javaClassName; - this.isWrapperType = isWrapperType; + public static WellKnownProto getByDescriptorName(String name) { + return WELL_KNOWN_PROTO_MAP.get(name); } } diff --git a/common/src/main/java/dev/cel/common/values/ProtoCelValueConverter.java b/common/src/main/java/dev/cel/common/values/ProtoCelValueConverter.java index 16d1a8956..152adbffb 100644 --- a/common/src/main/java/dev/cel/common/values/ProtoCelValueConverter.java +++ b/common/src/main/java/dev/cel/common/values/ProtoCelValueConverter.java @@ -107,7 +107,7 @@ public CelValue fromProtoMessageToCelValue(MessageOrBuilder message) { } WellKnownProto wellKnownProto = - WellKnownProto.getByTypeName(message.getDescriptorForType().getFullName()); + WellKnownProto.getByDescriptorName(message.getDescriptorForType().getFullName()); if (wellKnownProto == null) { return ProtoMessageValue.create((Message) message, celDescriptorPool, this); } @@ -128,10 +128,10 @@ public CelValue fromProtoMessageToCelValue(MessageOrBuilder message) { return adaptJsonStructToCelValue((Struct) message); case JSON_LIST_VALUE: return adaptJsonListToCelValue((com.google.protobuf.ListValue) message); - case DURATION: + case DURATION_VALUE: return DurationValue.create( TimeUtils.toJavaDuration((com.google.protobuf.Duration) message)); - case TIMESTAMP: + case TIMESTAMP_VALUE: return TimestampValue.create(TimeUtils.toJavaInstant((Timestamp) message)); case BOOL_VALUE: return fromJavaPrimitiveToCelValue(((BoolValue) message).getValue()); @@ -154,10 +154,10 @@ public CelValue fromProtoMessageToCelValue(MessageOrBuilder message) { case UINT64_VALUE: return UintValue.create( ((UInt64Value) message).getValue(), celOptions.enableUnsignedLongs()); - default: - throw new UnsupportedOperationException( - "Unsupported message to CelValue conversion - " + message); } + + throw new UnsupportedOperationException( + "Unsupported message to CelValue conversion - " + message); } /** diff --git a/common/src/test/java/dev/cel/common/internal/BUILD.bazel b/common/src/test/java/dev/cel/common/internal/BUILD.bazel index d1fb8b8e2..f394508d2 100644 --- a/common/src/test/java/dev/cel/common/internal/BUILD.bazel +++ b/common/src/test/java/dev/cel/common/internal/BUILD.bazel @@ -26,7 +26,6 @@ java_library( "//common/internal:errors", "//common/internal:proto_equality", "//common/internal:proto_message_factory", - "//common/internal:well_known_proto", "//common/src/test/resources:default_instance_message_test_protos_java_proto", "//common/src/test/resources:multi_file_java_proto", "//common/src/test/resources:service_conflicting_name_java_proto", diff --git a/common/src/test/java/dev/cel/common/internal/WellKnownProtoTest.java b/common/src/test/java/dev/cel/common/internal/WellKnownProtoTest.java deleted file mode 100644 index 7fc6eabfd..000000000 --- a/common/src/test/java/dev/cel/common/internal/WellKnownProtoTest.java +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package dev.cel.common.internal; - -import static com.google.common.truth.Truth.assertThat; - -import com.google.testing.junit.testparameterinjector.TestParameterInjector; -import com.google.testing.junit.testparameterinjector.TestParameters; -import org.junit.Test; -import org.junit.runner.RunWith; - -@RunWith(TestParameterInjector.class) -public class WellKnownProtoTest { - - @Test - @TestParameters("{typeName: 'google.protobuf.FloatValue'}") - @TestParameters("{typeName: 'google.protobuf.Int32Value'}") - @TestParameters("{typeName: 'google.protobuf.Int64Value'}") - @TestParameters("{typeName: 'google.protobuf.StringValue'}") - @TestParameters("{typeName: 'google.protobuf.BoolValue'}") - @TestParameters("{typeName: 'google.protobuf.BytesValue'}") - @TestParameters("{typeName: 'google.protobuf.DoubleValue'}") - @TestParameters("{typeName: 'google.protobuf.UInt32Value'}") - @TestParameters("{typeName: 'google.protobuf.UInt64Value'}") - @TestParameters("{typeName: 'google.protobuf.Empty'}") - @TestParameters("{typeName: 'google.protobuf.FieldMask'}") - public void isWrapperType_withTypeName_true(String typeName) { - assertThat(WellKnownProto.isWrapperType(typeName)).isTrue(); - } - - @Test - @TestParameters("{typeName: 'not.wellknown.type'}") - @TestParameters("{typeName: 'google.protobuf.Any'}") - @TestParameters("{typeName: 'google.protobuf.Duration'}") - @TestParameters("{typeName: 'google.protobuf.ListValue'}") - @TestParameters("{typeName: 'google.protobuf.Struct'}") - @TestParameters("{typeName: 'google.protobuf.Value'}") - @TestParameters("{typeName: 'google.protobuf.Timestamp'}") - public void isWrapperType_withTypeName_false(String typeName) { - assertThat(WellKnownProto.isWrapperType(typeName)).isFalse(); - } - - @Test - public void getJavaClassName() { - assertThat(WellKnownProto.ANY_VALUE.javaClassName()).isEqualTo("com.google.protobuf.Any"); - } -} diff --git a/runtime/src/test/java/dev/cel/runtime/DescriptorMessageProviderTest.java b/runtime/src/test/java/dev/cel/runtime/DescriptorMessageProviderTest.java index 5dcab8c10..b9092dd9e 100644 --- a/runtime/src/test/java/dev/cel/runtime/DescriptorMessageProviderTest.java +++ b/runtime/src/test/java/dev/cel/runtime/DescriptorMessageProviderTest.java @@ -207,8 +207,7 @@ public void createMessage_wellKnownType_withCustomMessageProvider( return; } - Descriptor wellKnownDescriptor = - DefaultDescriptorPool.INSTANCE.findDescriptor(wellKnownProto.typeName()).get(); + Descriptor wellKnownDescriptor = wellKnownProto.descriptor(); DescriptorMessageProvider messageProvider = new DescriptorMessageProvider( msgName ->