diff --git a/common/internal/BUILD.bazel b/common/internal/BUILD.bazel
index f52cfc36c..95b367684 100644
--- a/common/internal/BUILD.bazel
+++ b/common/internal/BUILD.bazel
@@ -35,7 +35,6 @@ java_library(
java_library(
name = "errors",
- visibility = ["//visibility:public"],
exports = ["//common/src/main/java/dev/cel/common/internal:errors"],
)
@@ -43,3 +42,28 @@ java_library(
name = "env_visitor",
exports = ["//common/src/main/java/dev/cel/common/internal:env_visitor"],
)
+
+java_library(
+ name = "default_instance_message_factory",
+ exports = ["//common/src/main/java/dev/cel/common/internal:default_instance_message_factory"],
+)
+
+java_library(
+ name = "well_known_proto",
+ exports = ["//common/src/main/java/dev/cel/common/internal:well_known_proto"],
+)
+
+java_library(
+ name = "proto_message_factory",
+ exports = ["//common/src/main/java/dev/cel/common/internal:proto_message_factory"],
+)
+
+java_library(
+ name = "default_message_factory",
+ exports = ["//common/src/main/java/dev/cel/common/internal:default_message_factory"],
+)
+
+java_library(
+ name = "cel_descriptor_pools",
+ exports = ["//common/src/main/java/dev/cel/common/internal:cel_descriptor_pools"],
+)
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 e345633a2..715185e3a 100644
--- a/common/src/main/java/dev/cel/common/internal/BUILD.bazel
+++ b/common/src/main/java/dev/cel/common/internal/BUILD.bazel
@@ -24,6 +24,13 @@ ENV_VISITOR_SOURCES = [
"EnvVisitor.java",
]
+# keep sorted
+CEL_DESCRIPTOR_POOL_SOURCES = [
+ "CelDescriptorPool.java",
+ "CombinedDescriptorPool.java",
+ "DefaultDescriptorPool.java",
+]
+
java_library(
name = "internal",
srcs = INTERNAL_SOURCES,
@@ -84,14 +91,26 @@ java_library(
],
)
-# keep sorted
DYNAMIC_PROTO_SOURCES = [
- "DefaultInstanceMessageFactory.java",
"DynamicProto.java",
"ProtoAdapter.java",
"ProtoRegistryProvider.java",
]
+java_library(
+ name = "default_instance_message_factory",
+ srcs = ["DefaultInstanceMessageFactory.java"],
+ tags = [
+ ],
+ deps = [
+ "//common/annotations",
+ "@maven//:com_google_guava_guava",
+ "@maven//:com_google_protobuf_protobuf_java",
+ ],
+)
+
+# keep sorted
+
java_library(
name = "dynamic_proto",
srcs = DYNAMIC_PROTO_SOURCES,
@@ -99,12 +118,12 @@ java_library(
],
deps = [
":converter",
+ ":proto_message_factory",
+ ":well_known_proto",
"//:auto_value",
- "//common",
"//common:error_codes",
"//common:runtime_exception",
"//common/annotations",
- "//common/types:cel_types",
"@cel_spec//proto/cel/expr:expr_java_proto",
"@maven//:com_google_code_findbugs_annotations",
"@maven//:com_google_errorprone_error_prone_annotations",
@@ -155,3 +174,56 @@ java_library(
"@cel_spec//proto/cel/expr:expr_java_proto",
],
)
+
+java_library(
+ name = "well_known_proto",
+ srcs = ["WellKnownProto.java"],
+ tags = [
+ ],
+ deps = [
+ "//common/annotations",
+ "@maven//:com_google_protobuf_protobuf_java",
+ ],
+)
+
+java_library(
+ name = "default_message_factory",
+ srcs = ["DefaultMessageFactory.java"],
+ tags = [
+ ],
+ deps = [
+ ":cel_descriptor_pools",
+ ":default_instance_message_factory",
+ ":proto_message_factory",
+ "//common/annotations",
+ "@maven//:com_google_protobuf_protobuf_java",
+ ],
+)
+
+java_library(
+ name = "proto_message_factory",
+ srcs = ["ProtoMessageFactory.java"],
+ tags = [
+ ],
+ deps = [
+ ":cel_descriptor_pools",
+ "@maven//:com_google_errorprone_error_prone_annotations",
+ "@maven//:com_google_guava_guava",
+ "@maven//:com_google_protobuf_protobuf_java",
+ ],
+)
+
+java_library(
+ name = "cel_descriptor_pools",
+ srcs = CEL_DESCRIPTOR_POOL_SOURCES,
+ tags = [
+ ],
+ deps = [
+ ":well_known_proto",
+ "//common",
+ "//common/annotations",
+ "@maven//:com_google_errorprone_error_prone_annotations",
+ "@maven//:com_google_guava_guava",
+ "@maven//:com_google_protobuf_protobuf_java",
+ ],
+)
diff --git a/common/src/main/java/dev/cel/common/internal/CelDescriptorPool.java b/common/src/main/java/dev/cel/common/internal/CelDescriptorPool.java
new file mode 100644
index 000000000..b2c0533b1
--- /dev/null
+++ b/common/src/main/java/dev/cel/common/internal/CelDescriptorPool.java
@@ -0,0 +1,46 @@
+// Copyright 2023 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 com.google.errorprone.annotations.Immutable;
+import com.google.protobuf.Descriptors.Descriptor;
+import com.google.protobuf.Descriptors.FieldDescriptor;
+import com.google.protobuf.ExtensionRegistry;
+import dev.cel.common.annotations.Internal;
+import java.util.Optional;
+
+/**
+ * {@link CelDescriptorPool} allows lookup of descriptors for message types and field descriptors
+ * for Proto2 extension messages.
+ *
+ *
CEL Library Internals. Do Not Use.
+ */
+@Immutable
+@Internal
+public interface CelDescriptorPool {
+
+ /** Finds the descriptor by fully qualified message type. */
+ Optional findDescriptor(String name);
+
+ /** Finds the corresponding field descriptor for an extension field on a message. */
+ Optional findExtensionDescriptor(
+ Descriptor containingDescriptor, String fieldName);
+
+ /**
+ * Retrieves the registered extension registry. This is specifically needed to handle unpacking
+ * Any messages containing Proto2 extension messages.
+ */
+ ExtensionRegistry getExtensionRegistry();
+}
diff --git a/common/src/main/java/dev/cel/common/internal/CombinedDescriptorPool.java b/common/src/main/java/dev/cel/common/internal/CombinedDescriptorPool.java
new file mode 100644
index 000000000..ee2108f91
--- /dev/null
+++ b/common/src/main/java/dev/cel/common/internal/CombinedDescriptorPool.java
@@ -0,0 +1,85 @@
+// Copyright 2023 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 com.google.common.collect.ImmutableList;
+import com.google.errorprone.annotations.Immutable;
+import com.google.protobuf.Descriptors.Descriptor;
+import com.google.protobuf.Descriptors.FieldDescriptor;
+import com.google.protobuf.ExtensionRegistry;
+import dev.cel.common.annotations.Internal;
+import java.util.Optional;
+
+/**
+ * The {@link CombinedDescriptorPool} takes one or more {@link CelDescriptorPool} instances and
+ * supports descriptor lookups in the order the descriptor pools are added to the constructor.
+ *
+ *
CEL Library Internals. Do Not Use.
+ */
+@Immutable
+@Internal
+public final class CombinedDescriptorPool implements CelDescriptorPool {
+ private final ImmutableList descriptorPools;
+
+ @SuppressWarnings("Immutable") // ExtensionRegistry is immutable, just not marked as such.
+ private final ExtensionRegistry extensionRegistry;
+
+ public static CombinedDescriptorPool create(ImmutableList descriptorPools) {
+ return new CombinedDescriptorPool(descriptorPools);
+ }
+
+ @Override
+ public Optional findDescriptor(String name) {
+ for (CelDescriptorPool descriptorPool : descriptorPools) {
+ Optional maybeDescriptor = descriptorPool.findDescriptor(name);
+ if (maybeDescriptor.isPresent()) {
+ return maybeDescriptor;
+ }
+ }
+
+ return Optional.empty();
+ }
+
+ @Override
+ public Optional findExtensionDescriptor(
+ Descriptor containingDescriptor, String fieldName) {
+ for (CelDescriptorPool descriptorPool : descriptorPools) {
+ Optional maybeExtensionDescriptor =
+ descriptorPool.findExtensionDescriptor(containingDescriptor, fieldName);
+ if (maybeExtensionDescriptor.isPresent()) {
+ return maybeExtensionDescriptor;
+ }
+ }
+
+ return Optional.empty();
+ }
+
+ @Override
+ public ExtensionRegistry getExtensionRegistry() {
+ return extensionRegistry;
+ }
+
+ private CombinedDescriptorPool(ImmutableList descriptorPools) {
+ this.descriptorPools = descriptorPools;
+ // Grab the populated extension registry.
+ // TODO: Combine the extension registry.
+ this.extensionRegistry =
+ descriptorPools.stream()
+ .map(CelDescriptorPool::getExtensionRegistry)
+ .filter(e -> !e.equals(ExtensionRegistry.getEmptyRegistry()))
+ .findFirst()
+ .orElse(ExtensionRegistry.getEmptyRegistry());
+ }
+}
diff --git a/common/src/main/java/dev/cel/common/internal/DefaultDescriptorPool.java b/common/src/main/java/dev/cel/common/internal/DefaultDescriptorPool.java
new file mode 100644
index 000000000..d18b95801
--- /dev/null
+++ b/common/src/main/java/dev/cel/common/internal/DefaultDescriptorPool.java
@@ -0,0 +1,98 @@
+// Copyright 2023 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.base.Preconditions.checkNotNull;
+import static com.google.common.collect.ImmutableMap.toImmutableMap;
+import static java.util.Arrays.stream;
+
+import com.google.common.collect.ImmutableCollection;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableMultimap;
+import com.google.errorprone.annotations.Immutable;
+import com.google.protobuf.Descriptors.Descriptor;
+import com.google.protobuf.Descriptors.FieldDescriptor;
+import com.google.protobuf.ExtensionRegistry;
+import dev.cel.common.CelDescriptors;
+import dev.cel.common.annotations.Internal;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+
+/**
+ * A descriptor pool that has descriptors pre-loaded for well-known types defined by {@link
+ * WellKnownProto}.
+ *
+ *
CEL Library Internals. Do Not Use.
+ */
+@Immutable
+@Internal
+public final class DefaultDescriptorPool implements CelDescriptorPool {
+ private static final ImmutableMap WELL_KNOWN_TYPE_DESCRIPTORS =
+ stream(WellKnownProto.values())
+ .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_DESCRIPTORS, ImmutableMultimap.of());
+
+ // K: Fully qualified message type name, V: Message descriptor
+ private final ImmutableMap descriptorMap;
+
+ // K: Fully qualified message type name (of containing descriptor)
+ // V: Field descriptor for the extension message
+ private final ImmutableMultimap extensionDescriptorMap;
+
+ public static DefaultDescriptorPool create(CelDescriptors celDescriptors) {
+ 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);
+ }
+
+ return new DefaultDescriptorPool(
+ ImmutableMap.copyOf(descriptorMap), celDescriptors.extensionDescriptors());
+ }
+
+ @Override
+ public Optional findDescriptor(String name) {
+ return Optional.ofNullable(descriptorMap.get(name));
+ }
+
+ @Override
+ public Optional findExtensionDescriptor(
+ Descriptor containingDescriptor, String fieldName) {
+ String typeName = containingDescriptor.getFullName();
+ ImmutableCollection fieldDescriptors = extensionDescriptorMap.get(typeName);
+ if (fieldDescriptors.isEmpty()) {
+ return Optional.empty();
+ }
+
+ return fieldDescriptors.stream().filter(d -> d.getFullName().equals(fieldName)).findFirst();
+ }
+
+ @Override
+ public ExtensionRegistry getExtensionRegistry() {
+ return ExtensionRegistry.getEmptyRegistry();
+ }
+
+ private DefaultDescriptorPool(
+ ImmutableMap descriptorMap,
+ ImmutableMultimap extensionDescriptorMap) {
+ this.descriptorMap = checkNotNull(descriptorMap);
+ this.extensionDescriptorMap = checkNotNull(extensionDescriptorMap);
+ }
+}
diff --git a/common/src/main/java/dev/cel/common/internal/DefaultInstanceMessageFactory.java b/common/src/main/java/dev/cel/common/internal/DefaultInstanceMessageFactory.java
index 6466ee9c9..35dd8244c 100644
--- a/common/src/main/java/dev/cel/common/internal/DefaultInstanceMessageFactory.java
+++ b/common/src/main/java/dev/cel/common/internal/DefaultInstanceMessageFactory.java
@@ -38,7 +38,7 @@
*
CEL Library Internals. Do Not Use.
*/
@Internal
-final class DefaultInstanceMessageFactory {
+public final class DefaultInstanceMessageFactory {
// Controls how many times we should recursively inspect a nested message for building fully
// qualified java class name before aborting.
diff --git a/common/src/main/java/dev/cel/common/internal/DefaultMessageFactory.java b/common/src/main/java/dev/cel/common/internal/DefaultMessageFactory.java
new file mode 100644
index 000000000..381a5de9e
--- /dev/null
+++ b/common/src/main/java/dev/cel/common/internal/DefaultMessageFactory.java
@@ -0,0 +1,60 @@
+// Copyright 2023 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 com.google.protobuf.Descriptors.Descriptor;
+import com.google.protobuf.DynamicMessage;
+import com.google.protobuf.Message;
+import dev.cel.common.annotations.Internal;
+import java.util.Optional;
+
+/** DefaultMessageFactory produces {@link Message.Builder} instances by protobuf name. */
+@Internal
+public final class DefaultMessageFactory implements ProtoMessageFactory {
+ private final CelDescriptorPool celDescriptorPool;
+
+ public static DefaultMessageFactory create(CelDescriptorPool celDescriptorPool) {
+ return new DefaultMessageFactory(celDescriptorPool);
+ }
+
+ @Override
+ public CelDescriptorPool getDescriptorPool() {
+ return celDescriptorPool;
+ }
+
+ @Override
+ public Optional newBuilder(String messageName) {
+ Optional descriptor = celDescriptorPool.findDescriptor(messageName);
+ if (!descriptor.isPresent()) {
+ return Optional.empty();
+ }
+
+ // If the descriptor that's resolved does not match the descriptor instance in the message
+ // factory, the call to fetch the prototype will return null, and a dynamic proto message
+ // should be used as a fallback.
+ Optional message =
+ DefaultInstanceMessageFactory.getInstance().getPrototype(descriptor.get());
+
+ if (message.isPresent()) {
+ return message.map(Message::toBuilder);
+ }
+
+ return Optional.of(DynamicMessage.newBuilder(descriptor.get()));
+ }
+
+ private DefaultMessageFactory(CelDescriptorPool celDescriptorPool) {
+ this.celDescriptorPool = celDescriptorPool;
+ }
+}
diff --git a/common/src/main/java/dev/cel/common/internal/DynamicProto.java b/common/src/main/java/dev/cel/common/internal/DynamicProto.java
index 755a990e6..98e7081c8 100644
--- a/common/src/main/java/dev/cel/common/internal/DynamicProto.java
+++ b/common/src/main/java/dev/cel/common/internal/DynamicProto.java
@@ -15,29 +15,16 @@
package dev.cel.common.internal;
import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.collect.ImmutableMap.toImmutableMap;
-import static java.util.Arrays.stream;
-import com.google.auto.value.AutoBuilder;
-import com.google.common.collect.ImmutableCollection;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableMultimap;
import com.google.errorprone.annotations.CheckReturnValue;
import com.google.errorprone.annotations.Immutable;
import com.google.protobuf.Any;
import com.google.protobuf.ByteString;
-import com.google.protobuf.Descriptors.Descriptor;
-import com.google.protobuf.Descriptors.FieldDescriptor;
import com.google.protobuf.DynamicMessage;
import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.Message;
-import dev.cel.common.CelDescriptorUtil;
-import dev.cel.common.CelDescriptors;
import dev.cel.common.annotations.Internal;
-import dev.cel.common.types.CelTypes;
-import java.util.Map.Entry;
import java.util.Optional;
-import org.jspecify.nullness.Nullable;
/**
* The {@code DynamicProto} class supports the conversion of {@link Any} values to concrete {@code
@@ -49,58 +36,13 @@
@CheckReturnValue
@Internal
public final class DynamicProto {
-
- private static final ImmutableMap WELL_KNOWN_DESCRIPTORS =
- stream(ProtoAdapter.WellKnownProto.values())
- .collect(toImmutableMap(d -> d.typeName(), d -> d.descriptor()));
-
- private final ImmutableMap dynamicDescriptors;
- private final ImmutableMultimap dynamicExtensionDescriptors;
private final ProtoMessageFactory protoMessageFactory;
- /** {@code ProtoMessageFactory} provides a method to create a protobuf builder objects by name. */
- @Immutable
- @FunctionalInterface
- public interface ProtoMessageFactory {
- Message.@Nullable Builder newBuilder(String messageName);
- }
-
- /** Builder for configuring the {@link DynamicProto}. */
- @AutoBuilder(ofClass = DynamicProto.class)
- public abstract static class Builder {
-
- /** Sets {@link CelDescriptors} to unpack any message types. */
- public abstract Builder setDynamicDescriptors(CelDescriptors celDescriptors);
-
- /** Sets a custom type factory to unpack any message types. */
- public abstract Builder setProtoMessageFactory(ProtoMessageFactory factory);
-
- /** Builds a new instance of {@link DynamicProto} */
- @CheckReturnValue
- public abstract DynamicProto build();
+ public static DynamicProto create(ProtoMessageFactory protoMessageFactory) {
+ return new DynamicProto(protoMessageFactory);
}
- public static Builder newBuilder() {
- return new AutoBuilder_DynamicProto_Builder()
- .setDynamicDescriptors(CelDescriptors.builder().build())
- .setProtoMessageFactory((typeName) -> null);
- }
-
- DynamicProto(
- CelDescriptors dynamicDescriptors,
- ProtoMessageFactory protoMessageFactory) {
- ImmutableMap messageTypeDescriptorMap =
- CelDescriptorUtil.descriptorCollectionToMap(dynamicDescriptors.messageTypeDescriptors());
- ImmutableMap filteredDescriptors =
- messageTypeDescriptorMap.entrySet().stream()
- .filter(e -> !WELL_KNOWN_DESCRIPTORS.containsKey(e.getKey()))
- .collect(toImmutableMap(Entry::getKey, Entry::getValue));
- this.dynamicDescriptors =
- ImmutableMap.builder()
- .putAll(WELL_KNOWN_DESCRIPTORS)
- .putAll(filteredDescriptors)
- .buildOrThrow();
- this.dynamicExtensionDescriptors = checkNotNull(dynamicDescriptors.extensionDescriptors());
+ DynamicProto(ProtoMessageFactory protoMessageFactory) {
this.protoMessageFactory = checkNotNull(protoMessageFactory);
}
@@ -120,7 +62,8 @@ public Message unpack(Any any) throws InvalidProtocolBufferException {
String.format("malformed type URL: %s", any.getTypeUrl())));
Message.Builder builder =
- newMessageBuilder(messageTypeName)
+ protoMessageFactory
+ .newBuilder(messageTypeName)
.orElseThrow(
() ->
new InvalidProtocolBufferException(
@@ -136,7 +79,7 @@ public Message unpack(Any any) throws InvalidProtocolBufferException {
*/
public Message maybeAdaptDynamicMessage(DynamicMessage input) {
Optional maybeBuilder =
- newMessageBuilder(input.getDescriptorForType().getFullName());
+ protoMessageFactory.newBuilder(input.getDescriptorForType().getFullName());
if (!maybeBuilder.isPresent() || maybeBuilder.get() instanceof DynamicMessage.Builder) {
// Just return the same input if:
// 1. We didn't get a builder back because there's no descriptor (nothing we can do)
@@ -148,61 +91,6 @@ public Message maybeAdaptDynamicMessage(DynamicMessage input) {
return merge(maybeBuilder.get(), input.toByteString());
}
- /**
- * This method instantiates a builder for the given {@code typeName} assuming one is configured
- * within the descriptor set provided to the {@code DynamicProto} constructor.
- *
- *
When the {@code useLinkedTypes} flag is set, the {@code Message.Builder} returned will be
- * the concrete builder instance linked into the binary if it is present; otherwise, the result
- * will be a {@code DynamicMessageBuilder}.
- */
- public Optional newMessageBuilder(String typeName) {
- if (!CelTypes.isWellKnownType(typeName)) {
- // Check if the message factory can produce a concrete message via custom type factory
- // first.
- Message.Builder builder = protoMessageFactory.newBuilder(typeName);
- if (builder != null) {
- return Optional.of(builder);
- }
- }
-
- Optional descriptor = maybeGetDescriptor(typeName);
- if (!descriptor.isPresent()) {
- return Optional.empty();
- }
- // If the descriptor that's resolved does not match the descriptor instance in the message
- // factory, the call to fetch the prototype will return null, and a dynamic proto message
- // should be used as a fallback.
- Optional message =
- DefaultInstanceMessageFactory.getInstance().getPrototype(descriptor.get());
- if (message.isPresent()) {
- return Optional.of(message.get().toBuilder());
- }
-
- // Fallback to a dynamic proto instance.
- return Optional.of(DynamicMessage.newBuilder(descriptor.get()));
- }
-
- private Optional maybeGetDescriptor(String typeName) {
-
- Descriptor descriptor = ProtoRegistryProvider.getTypeRegistry().find(typeName);
- return Optional.ofNullable(descriptor != null ? descriptor : dynamicDescriptors.get(typeName));
- }
-
- /** Gets the corresponding field descriptor for an extension field on a message. */
- public Optional maybeGetExtensionDescriptor(
- Descriptor containingDescriptor, String fieldName) {
-
- String typeName = containingDescriptor.getFullName();
- ImmutableCollection fieldDescriptors =
- dynamicExtensionDescriptors.get(typeName);
- if (fieldDescriptors.isEmpty()) {
- return Optional.empty();
- }
-
- return fieldDescriptors.stream().filter(d -> d.getFullName().equals(fieldName)).findFirst();
- }
-
/**
* Merge takes in a Message builder and merges another message bytes into the builder. Some
* example usages are:
@@ -214,7 +102,9 @@ public Optional maybeGetExtensionDescriptor(
*/
private Message merge(Message.Builder builder, ByteString inputBytes) {
try {
- return builder.mergeFrom(inputBytes, ProtoRegistryProvider.getExtensionRegistry()).build();
+ return builder
+ .mergeFrom(inputBytes, protoMessageFactory.getDescriptorPool().getExtensionRegistry())
+ .build();
} catch (InvalidProtocolBufferException e) {
throw new AssertionError("Failed to merge input message into the message builder", e);
}
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 822bce2b7..f66fe26a7 100644
--- a/common/src/main/java/dev/cel/common/internal/ProtoAdapter.java
+++ b/common/src/main/java/dev/cel/common/internal/ProtoAdapter.java
@@ -143,53 +143,6 @@ public final class ProtoAdapter {
stream(WellKnownProto.values())
.collect(toImmutableMap(WellKnownProto::typeName, Function.identity()));
- /**
- * WellKnownProto types used throughout CEL. These types are specially handled to ensure that
- * bidirectional conversion between CEL native values and these well-known types is performed
- * consistently across runtimes.
- */
- enum WellKnownProto {
- 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;
-
- WellKnownProto(Descriptor descriptor) {
- this(descriptor, /* isWrapperType= */ false);
- }
-
- WellKnownProto(Descriptor descriptor, boolean isWrapperType) {
- this.descriptor = descriptor;
- this.isWrapperType = isWrapperType;
- }
-
- Descriptor descriptor() {
- return descriptor;
- }
-
- String typeName() {
- return descriptor.getFullName();
- }
-
- boolean isWrapperType() {
- return isWrapperType;
- }
- }
-
private final DynamicProto dynamicProto;
private final boolean enableUnsignedLongs;
diff --git a/common/src/main/java/dev/cel/common/internal/ProtoMessageFactory.java b/common/src/main/java/dev/cel/common/internal/ProtoMessageFactory.java
new file mode 100644
index 000000000..28b5313e1
--- /dev/null
+++ b/common/src/main/java/dev/cel/common/internal/ProtoMessageFactory.java
@@ -0,0 +1,57 @@
+// Copyright 2023 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 com.google.common.collect.ImmutableList;
+import com.google.errorprone.annotations.Immutable;
+import com.google.protobuf.Message;
+import java.util.Optional;
+
+/** {@code ProtoMessageFactory} provides a method to create a protobuf builder objects by name. */
+@Immutable
+@FunctionalInterface
+public interface ProtoMessageFactory {
+ Optional newBuilder(String messageName);
+
+ default CelDescriptorPool getDescriptorPool() {
+ return DefaultDescriptorPool.INSTANCE;
+ }
+
+ /**
+ * The {@link CombinedMessageFactory} takes one or more {@link ProtoMessageFactory} instances and
+ * attempts to create a {@code Message.Builder} instance for a given message name by calling each
+ * message factory in the order that they are provided to the constructor.
+ */
+ @Immutable
+ final class CombinedMessageFactory implements ProtoMessageFactory {
+
+ private final ImmutableList messageFactories;
+
+ public CombinedMessageFactory(Iterable messageFactories) {
+ this.messageFactories = ImmutableList.copyOf(messageFactories);
+ }
+
+ @Override
+ public Optional newBuilder(String messageName) {
+ for (ProtoMessageFactory messageFactory : messageFactories) {
+ Optional builder = messageFactory.newBuilder(messageName);
+ if (builder.isPresent()) {
+ return builder;
+ }
+ }
+ return Optional.empty();
+ }
+ }
+}
diff --git a/common/src/main/java/dev/cel/common/internal/WellKnownProto.java b/common/src/main/java/dev/cel/common/internal/WellKnownProto.java
new file mode 100644
index 000000000..f3520f447
--- /dev/null
+++ b/common/src/main/java/dev/cel/common/internal/WellKnownProto.java
@@ -0,0 +1,81 @@
+// Copyright 2023 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 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.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.annotations.Internal;
+
+/**
+ * WellKnownProto types used throughout CEL. These types are specially handled to ensure that
+ * bidirectional conversion between CEL native values and these well-known types is performed
+ * consistently across runtimes.
+ */
+@Internal
+public enum WellKnownProto {
+ 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;
+
+ WellKnownProto(Descriptor descriptor) {
+ this(descriptor, /* isWrapperType= */ false);
+ }
+
+ WellKnownProto(Descriptor descriptor, boolean isWrapperType) {
+ this.descriptor = descriptor;
+ this.isWrapperType = isWrapperType;
+ }
+
+ public Descriptor descriptor() {
+ return descriptor;
+ }
+
+ public String typeName() {
+ return descriptor.getFullName();
+ }
+
+ boolean isWrapperType() {
+ return isWrapperType;
+ }
+}
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 846219e42..c8771bec9 100644
--- a/common/src/test/java/dev/cel/common/internal/BUILD.bazel
+++ b/common/src/test/java/dev/cel/common/internal/BUILD.bazel
@@ -15,11 +15,15 @@ java_library(
"//common:options",
"//common/ast",
"//common/internal",
+ "//common/internal:cel_descriptor_pools",
"//common/internal:comparison_functions",
"//common/internal:converter",
+ "//common/internal:default_instance_message_factory",
+ "//common/internal:default_message_factory",
"//common/internal:dynamic_proto",
"//common/internal:errors",
"//common/internal:proto_equality",
+ "//common/resources/testdata/proto2:test_all_types_java_proto",
"//common/resources/testdata/proto3:test_all_types_java_proto",
"//common/src/test/resources:default_instance_message_test_protos_java_proto",
"//common/src/test/resources:multi_file_java_proto",
diff --git a/common/src/test/java/dev/cel/common/internal/DefaultMessageFactoryTest.java b/common/src/test/java/dev/cel/common/internal/DefaultMessageFactoryTest.java
new file mode 100644
index 000000000..3b4f82269
--- /dev/null
+++ b/common/src/test/java/dev/cel/common/internal/DefaultMessageFactoryTest.java
@@ -0,0 +1,102 @@
+// Copyright 2023 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 static com.google.common.truth.Truth8.assertThat;
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+import com.google.common.base.Ascii;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.io.Resources;
+import com.google.protobuf.DescriptorProtos.FileDescriptorSet;
+import com.google.protobuf.Descriptors.FileDescriptor;
+import com.google.protobuf.DynamicMessage;
+import com.google.protobuf.TextFormat;
+import com.google.protobuf.Value;
+import dev.cel.common.CelDescriptorUtil;
+import dev.cel.common.CelDescriptors;
+import dev.cel.testing.testdata.proto2.TestAllTypesProto.TestAllTypes;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public final class DefaultMessageFactoryTest {
+
+ @Test
+ public void newBuilder_wellKnownType_producesNewMessage() {
+ DefaultMessageFactory messageFactory =
+ DefaultMessageFactory.create(DefaultDescriptorPool.INSTANCE);
+
+ Value.Builder valueBuilder =
+ (Value.Builder) messageFactory.newBuilder("google.protobuf.Value").get();
+
+ assertThat(valueBuilder.setStringValue("hello").build())
+ .isEqualTo(Value.newBuilder().setStringValue("hello").build());
+ }
+
+ @Test
+ public void newBuilder_withDescriptor_producesNewMessageBuilder() {
+ CelDescriptorPool celDescriptorPool =
+ DefaultDescriptorPool.create(
+ CelDescriptorUtil.getAllDescriptorsFromFileDescriptor(
+ TestAllTypes.getDescriptor().getFile()));
+ DefaultMessageFactory messageFactory = DefaultMessageFactory.create(celDescriptorPool);
+
+ TestAllTypes.Builder builder =
+ (TestAllTypes.Builder)
+ messageFactory.newBuilder("dev.cel.testing.testdata.proto2.TestAllTypes").get();
+
+ assertThat(builder.setSingleInt64(5L).build())
+ .isEqualTo(TestAllTypes.newBuilder().setSingleInt64(5L).build());
+ }
+
+ @Test
+ public void newBuilder_unknownMessage_returnsEmpty() {
+ DefaultMessageFactory messageFactory =
+ DefaultMessageFactory.create(DefaultDescriptorPool.INSTANCE);
+
+ assertThat(messageFactory.newBuilder("unknown_message")).isEmpty();
+ }
+
+ @Test
+ public void newBuilder_unequalDescriptorForSameMessage_returnsDynamicMessage() throws Exception {
+ String fdsContent =
+ Resources.toString(Resources.getResource(Ascii.toLowerCase("value.fds")), UTF_8);
+ FileDescriptorSet fds = TextFormat.parse(fdsContent, FileDescriptorSet.class);
+ ImmutableSet files =
+ CelDescriptorUtil.getFileDescriptorsFromFileDescriptorSet(fds);
+ CelDescriptors celDescriptors = CelDescriptorUtil.getAllDescriptorsFromFileDescriptor(files);
+
+ DefaultMessageFactory messageFactory =
+ DefaultMessageFactory.create(DefaultDescriptorPool.create(celDescriptors));
+
+ assertThat(messageFactory.newBuilder("google.api.expr.Value")).isPresent();
+ assertThat(messageFactory.newBuilder("google.api.expr.Value").get())
+ .isInstanceOf(DynamicMessage.Builder.class);
+ }
+
+ @Test
+ public void getDescriptorPoolTest() {
+ CelDescriptorPool celDescriptorPool =
+ DefaultDescriptorPool.create(
+ CelDescriptorUtil.getAllDescriptorsFromFileDescriptor(
+ TestAllTypes.getDescriptor().getFile()));
+ DefaultMessageFactory messageFactory = DefaultMessageFactory.create(celDescriptorPool);
+
+ assertThat(messageFactory.getDescriptorPool()).isEqualTo(celDescriptorPool);
+ }
+}
diff --git a/common/src/test/java/dev/cel/common/internal/DynamicProtoTest.java b/common/src/test/java/dev/cel/common/internal/DynamicProtoTest.java
index d563d01a3..39afd25a1 100644
--- a/common/src/test/java/dev/cel/common/internal/DynamicProtoTest.java
+++ b/common/src/test/java/dev/cel/common/internal/DynamicProtoTest.java
@@ -15,7 +15,6 @@
package dev.cel.common.internal;
import static com.google.common.truth.Truth.assertThat;
-import static com.google.common.truth.Truth8.assertThat;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.junit.Assert.assertThrows;
@@ -55,7 +54,8 @@ public void unpackLinkedMessageType_withTypeRegistry() throws Exception {
CelDescriptors celDescriptors =
CelDescriptorUtil.getAllDescriptorsFromFileDescriptor(Expr.getDescriptor().getFile());
DynamicProto dynamicProto =
- DynamicProto.newBuilder().setDynamicDescriptors(celDescriptors).build();
+ DynamicProto.create(
+ DefaultMessageFactory.create(DefaultDescriptorPool.create(celDescriptors)));
Message unpacked = dynamicProto.unpack(packedExpr);
@@ -74,7 +74,8 @@ public void unpackLinkedMessageType_withTypeRegistry_multiFileNested() throws Ex
CelDescriptors celDescriptors =
CelDescriptorUtil.getAllDescriptorsFromFileDescriptor(MultiFile.getDescriptor().getFile());
DynamicProto dynamicProto =
- DynamicProto.newBuilder().setDynamicDescriptors(celDescriptors).build();
+ DynamicProto.create(
+ DefaultMessageFactory.create(DefaultDescriptorPool.create(celDescriptors)));
Message unpacked = dynamicProto.unpack(packed);
@@ -89,7 +90,8 @@ public void unpackLinkedMessageType_withTypeRegistry_singleFileNested() throws E
CelDescriptors celDescriptors =
CelDescriptorUtil.getAllDescriptorsFromFileDescriptor(SingleFile.getDescriptor().getFile());
DynamicProto dynamicProto =
- DynamicProto.newBuilder().setDynamicDescriptors(celDescriptors).build();
+ DynamicProto.create(
+ DefaultMessageFactory.create(DefaultDescriptorPool.create(celDescriptors)));
Message unpacked = dynamicProto.unpack(packed);
@@ -105,7 +107,8 @@ public void unpackLinkedMessageType_withTypeRegistryCached() throws Exception {
CelDescriptors celDescriptors =
CelDescriptorUtil.getAllDescriptorsFromFileDescriptor(Expr.getDescriptor().getFile());
DynamicProto dynamicProto =
- DynamicProto.newBuilder().setDynamicDescriptors(celDescriptors).build();
+ DynamicProto.create(
+ DefaultMessageFactory.create(DefaultDescriptorPool.create(celDescriptors)));
// Order is important here.
Message unpacked = dynamicProto.unpack(packedExpr);
@@ -131,7 +134,8 @@ public void unpackLinkedMessageType_removeDescriptorLocalLinkedType() throws Exc
CelDescriptors celDescriptors =
CelDescriptorUtil.getAllDescriptorsFromFileDescriptor(fileDescriptorBuilder.build());
DynamicProto dynamicProto =
- DynamicProto.newBuilder().setDynamicDescriptors(celDescriptors).build();
+ DynamicProto.create(
+ DefaultMessageFactory.create(DefaultDescriptorPool.create(celDescriptors)));
Message unpacked = dynamicProto.unpack(packedStruct);
@@ -142,8 +146,7 @@ public void unpackLinkedMessageType_removeDescriptorLocalLinkedType() throws Exc
@Test
public void unpackDynamicMessageType_noDescriptor() throws Exception {
DynamicProto dynamicProto =
- DynamicProto.newBuilder()
- .build();
+ DynamicProto.create(DefaultMessageFactory.create(DefaultDescriptorPool.INSTANCE));
Any.Builder anyValue = Any.newBuilder();
TextFormat.merge(readFile("value.textproto"), anyValue);
assertThat(anyValue.getTypeUrl()).isEqualTo("type.googleapis.com/google.api.expr.Value");
@@ -152,7 +155,8 @@ public void unpackDynamicMessageType_noDescriptor() throws Exception {
@Test
public void unpackDynamicMessageType_badDescriptor() throws Exception {
- DynamicProto dynamicProto = DynamicProto.newBuilder().build();
+ DynamicProto dynamicProto =
+ DynamicProto.create(DefaultMessageFactory.create(DefaultDescriptorPool.INSTANCE));
Any.Builder anyValue = Any.newBuilder();
TextFormat.merge(readFile("value.textproto"), anyValue);
anyValue.setTypeUrl("google.api.expr.Value");
@@ -166,7 +170,8 @@ public void unpackDynamicMessageType() throws Exception {
CelDescriptorUtil.getFileDescriptorsFromFileDescriptorSet(fds);
CelDescriptors celDescriptors = CelDescriptorUtil.getAllDescriptorsFromFileDescriptor(files);
DynamicProto dynamicProto =
- DynamicProto.newBuilder().setDynamicDescriptors(celDescriptors).build();
+ DynamicProto.create(
+ DefaultMessageFactory.create(DefaultDescriptorPool.create(celDescriptors)));
Any.Builder anyValue = Any.newBuilder();
TextFormat.merge(readFile("value.textproto"), anyValue);
assertThat(anyValue.getTypeUrl()).isEqualTo("type.googleapis.com/google.api.expr.Value");
@@ -201,7 +206,8 @@ public void unpackDynamicMessageType_cached() throws Exception {
CelDescriptorUtil.getFileDescriptorsFromFileDescriptorSet(fds);
CelDescriptors celDescriptors = CelDescriptorUtil.getAllDescriptorsFromFileDescriptor(files);
DynamicProto dynamicProto =
- DynamicProto.newBuilder().setDynamicDescriptors(celDescriptors).build();
+ DynamicProto.create(
+ DefaultMessageFactory.create(DefaultDescriptorPool.create(celDescriptors)));
Any.Builder anyValue = Any.newBuilder();
TextFormat.merge(readFile("value.textproto"), anyValue);
assertThat(anyValue.getTypeUrl()).isEqualTo("type.googleapis.com/google.api.expr.Value");
@@ -212,7 +218,8 @@ public void unpackDynamicMessageType_cached() throws Exception {
@Test
public void maybeAdaptDynamicMessage() throws Exception {
- DynamicProto dynamicProto = DynamicProto.newBuilder().build();
+ DynamicProto dynamicProto =
+ DynamicProto.create(DefaultMessageFactory.create(DefaultDescriptorPool.INSTANCE));
Struct struct =
Struct.newBuilder()
.putFields("hello", Value.newBuilder().setStringValue("world").build())
@@ -228,7 +235,8 @@ public void maybeAdaptDynamicMessage() throws Exception {
@Test
public void maybeAdaptDynamicMessage_cached() throws Exception {
- DynamicProto dynamicProto = DynamicProto.newBuilder().build();
+ DynamicProto dynamicProto =
+ DynamicProto.create(DefaultMessageFactory.create(DefaultDescriptorPool.INSTANCE));
Struct struct =
Struct.newBuilder()
.putFields("hello", Value.newBuilder().setStringValue("world").build())
@@ -251,9 +259,8 @@ public void maybeAdaptDynamicMessage_notLinked() throws Exception {
CelDescriptorUtil.getFileDescriptorsFromFileDescriptorSet(fds);
CelDescriptors celDescriptors = CelDescriptorUtil.getAllDescriptorsFromFileDescriptor(files);
DynamicProto dynamicProto =
- DynamicProto.newBuilder()
- .setDynamicDescriptors(celDescriptors)
- .build();
+ DynamicProto.create(
+ DefaultMessageFactory.create(DefaultDescriptorPool.create(celDescriptors)));
Any any = TextFormat.parse(readFile("value.textproto"), Any.class);
Message unpacked = dynamicProto.unpack(any);
assertThat(unpacked).isInstanceOf(DynamicMessage.class);
@@ -261,49 +268,6 @@ public void maybeAdaptDynamicMessage_notLinked() throws Exception {
.isSameInstanceAs(unpacked);
}
- @Test
- public void newBuilder() throws Exception {
- DynamicProto dynamicProto =
- DynamicProto.newBuilder()
- .setDynamicDescriptors(
- CelDescriptorUtil.getAllDescriptorsFromFileDescriptor(
- Value.getDescriptor().getFile()))
- .build();
- Value.Builder valueBuilder =
- (Value.Builder) dynamicProto.newMessageBuilder("google.protobuf.Value").get();
- assertThat(valueBuilder.setStringValue("hello").build())
- .isEqualTo(Value.newBuilder().setStringValue("hello").build());
- }
-
- @Test
- public void newBuilder_notLinked() throws Exception {
- DynamicProto dynamicProto =
- DynamicProto.newBuilder()
- .setDynamicDescriptors(
- CelDescriptorUtil.getAllDescriptorsFromFileDescriptor(
- Value.getDescriptor().getFile()))
- .build();
- FieldDescriptor stringValueField = Value.getDescriptor().findFieldByName("string_value");
- Message.Builder valueBuilder = dynamicProto.newMessageBuilder("google.protobuf.Value").get();
- assertThat(valueBuilder.setField(stringValueField, "hello").build())
- .isEqualTo(Value.newBuilder().setStringValue("hello").build());
- }
-
- @Test
- public void newBuilder_dynamic() throws Exception {
- FileDescriptorSet fds = TextFormat.parse(readFile("value.fds"), FileDescriptorSet.class);
- ImmutableSet files =
- CelDescriptorUtil.getFileDescriptorsFromFileDescriptorSet(fds);
- CelDescriptors celDescriptors = CelDescriptorUtil.getAllDescriptorsFromFileDescriptor(files);
- DynamicProto dynamicProto =
- DynamicProto.newBuilder()
- .setDynamicDescriptors(celDescriptors)
- .build();
- assertThat(dynamicProto.newMessageBuilder("google.api.expr.Value")).isPresent();
- assertThat(dynamicProto.newMessageBuilder("google.api.expr.Value").get())
- .isInstanceOf(DynamicMessage.Builder.class);
- }
-
private static String readFile(String path) throws IOException {
return Resources.toString(Resources.getResource(Ascii.toLowerCase(path)), UTF_8);
}
diff --git a/common/src/test/java/dev/cel/common/internal/ProtoAdapterTest.java b/common/src/test/java/dev/cel/common/internal/ProtoAdapterTest.java
index 65d114c97..7268d75cc 100644
--- a/common/src/test/java/dev/cel/common/internal/ProtoAdapterTest.java
+++ b/common/src/test/java/dev/cel/common/internal/ProtoAdapterTest.java
@@ -40,6 +40,7 @@
import dev.cel.common.CelOptions;
import java.util.Arrays;
import java.util.List;
+import java.util.Optional;
import org.junit.Test;
import org.junit.experimental.runners.Enclosed;
import org.junit.runner.RunWith;
@@ -55,6 +56,9 @@ public final class ProtoAdapterTest {
private static final CelOptions CURRENT =
CelOptions.newBuilder().enableUnsignedLongs(true).build();
+ private static final DynamicProto DYNAMIC_PROTO =
+ DynamicProto.create(DefaultMessageFactory.create(DefaultDescriptorPool.INSTANCE));
+
@RunWith(Parameterized.class)
public static class BidirectionalConversionTest {
@Parameter(0)
@@ -156,8 +160,9 @@ public static List