diff --git a/common/src/main/java/dev/cel/common/values/BUILD.bazel b/common/src/main/java/dev/cel/common/values/BUILD.bazel
index c39eaaa73..7073686b0 100644
--- a/common/src/main/java/dev/cel/common/values/BUILD.bazel
+++ b/common/src/main/java/dev/cel/common/values/BUILD.bazel
@@ -434,3 +434,85 @@ cel_android_library(
"@maven//:com_google_errorprone_error_prone_annotations",
],
)
+
+java_library(
+ name = "select_field",
+ srcs = ["SelectField.java"],
+ tags = [
+ ],
+ deps = [
+ "//:auto_value",
+ "//common/annotations",
+ "@maven//:com_google_errorprone_error_prone_annotations",
+ "@maven//:com_google_guava_guava",
+ "@maven//:org_jspecify_jspecify",
+ ],
+)
+
+cel_android_library(
+ name = "select_field_android",
+ srcs = ["SelectField.java"],
+ tags = [
+ ],
+ deps = [
+ "//:auto_value",
+ "//common/annotations",
+ "@maven//:com_google_errorprone_error_prone_annotations",
+ "@maven//:org_jspecify_jspecify",
+ "@maven_android//:com_google_guava_guava",
+ ],
+)
+
+java_library(
+ name = "optimized_selectable",
+ srcs = ["OptimizedSelectable.java"],
+ tags = [
+ ],
+ deps = [
+ ":select_field",
+ "//common/annotations",
+ "@maven//:com_google_errorprone_error_prone_annotations",
+ ],
+)
+
+cel_android_library(
+ name = "optimized_selectable_android",
+ srcs = ["OptimizedSelectable.java"],
+ tags = [
+ ],
+ deps = [
+ ":select_field_android",
+ "//common/annotations",
+ "@maven//:com_google_errorprone_error_prone_annotations",
+ ],
+)
+
+java_library(
+ name = "optimized_select_traversal",
+ srcs = ["OptimizedSelectTraversal.java"],
+ tags = [
+ ],
+ deps = [
+ ":optimized_selectable",
+ ":select_field",
+ ":values",
+ "//common/annotations",
+ "//common/exceptions:attribute_not_found",
+ "@maven//:com_google_guava_guava",
+ ],
+)
+
+cel_android_library(
+ name = "optimized_select_traversal_android",
+ srcs = ["OptimizedSelectTraversal.java"],
+ tags = [
+ ],
+ deps = [
+ ":optimized_selectable_android",
+ ":select_field_android",
+ ":values_android",
+ "//common/annotations",
+ "//common/exceptions:attribute_not_found",
+ "@maven_android//:com_google_guava_guava",
+ ],
+)
diff --git a/common/src/main/java/dev/cel/common/values/OptimizedSelectTraversal.java b/common/src/main/java/dev/cel/common/values/OptimizedSelectTraversal.java
new file mode 100644
index 000000000..9fb08a0a2
--- /dev/null
+++ b/common/src/main/java/dev/cel/common/values/OptimizedSelectTraversal.java
@@ -0,0 +1,120 @@
+// Copyright 2026 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.values;
+
+import com.google.common.collect.ImmutableList;
+import dev.cel.common.annotations.Internal;
+import dev.cel.common.exceptions.CelAttributeNotFoundException;
+import java.util.Optional;
+
+/**
+ * Walks a sequence of {@link SelectField} selections, dispatching each field over {@link
+ * OptimizedSelectable} or {@link SelectableValue}.
+ *
+ *
CEL Library Internals. Do Not Use.
+ */
+@Internal
+public final class OptimizedSelectTraversal {
+
+ /**
+ * Qualifies {@code target} through every field in {@code fields} and returns the terminal value.
+ */
+ public static Object qualify(Object target, ImmutableList fields) {
+ Object current = target;
+ for (int i = 0; i < fields.size(); i++) {
+ current = qualifyField(current, fields.get(i));
+ }
+ return current;
+ }
+
+ /**
+ * Presence tests the terminal field of {@code fields}, navigating through all preceding fields.
+ *
+ * Absence of any intermediate field short-circuits to {@code false}.
+ */
+ public static boolean hasField(Object target, ImmutableList fields) {
+ if (fields.isEmpty()) {
+ return false;
+ }
+ Object current = target;
+ int terminalIndex = fields.size() - 1;
+ for (int i = 0; i < terminalIndex; i++) {
+ // Invariant: Select optimization is only applied to structs (proto messages). Maps and
+ // repeated fields are excluded from optimized field selection, so an absent intermediate
+ // field is guaranteed to be an unset message field rather than a missing map key or
+ // invalid field access, safely short-circuiting to false.
+ Optional next = navigateField(current, fields.get(i));
+ if (!next.isPresent()) {
+ return false;
+ }
+ current = next.get();
+ }
+ return hasTerminalField(current, fields.get(terminalIndex));
+ }
+
+ // SelectableValue is only ever instantiated with String keys in the select path.
+ @SuppressWarnings("unchecked")
+ private static Object qualifyField(Object target, SelectField field) {
+ if (target instanceof ErrorValue) {
+ return target;
+ }
+ if (target instanceof OptimizedSelectable) {
+ return ((OptimizedSelectable) target).selectByFieldNumber(field);
+ }
+ if (target instanceof SelectableValue) {
+ SelectableValue selectable = (SelectableValue) target;
+ if (field.defaultValue() != null) {
+ return selectable
+ .find(field.fieldName())
+ .map(Object.class::cast)
+ .orElse(field.defaultValue());
+ }
+ return selectable.select(field.fieldName());
+ }
+ throw CelAttributeNotFoundException.forFieldResolution(field.fieldName());
+ }
+
+ // SelectableValue is only ever instantiated with String keys in the select path.
+ @SuppressWarnings("unchecked")
+ private static Optional navigateField(Object target, SelectField field) {
+ if (target instanceof ErrorValue) {
+ return Optional.of(target);
+ }
+ if (target instanceof OptimizedSelectable) {
+ return ((OptimizedSelectable) target).findByFieldNumber(field);
+ }
+ if (target instanceof SelectableValue) {
+ return ((SelectableValue) target).find(field.fieldName()).map(Object.class::cast);
+ }
+ throw CelAttributeNotFoundException.forFieldResolution(field.fieldName());
+ }
+
+ // SelectableValue is only ever instantiated with String keys in the select path.
+ @SuppressWarnings("unchecked")
+ private static boolean hasTerminalField(Object target, SelectField field) {
+ if (target instanceof ErrorValue) {
+ return false;
+ }
+ if (target instanceof OptimizedSelectable) {
+ return ((OptimizedSelectable) target).hasFieldByNumber(field);
+ }
+ if (target instanceof SelectableValue) {
+ return ((SelectableValue) target).find(field.fieldName()).isPresent();
+ }
+ throw CelAttributeNotFoundException.forFieldResolution(field.fieldName());
+ }
+
+ private OptimizedSelectTraversal() {}
+}
diff --git a/common/src/main/java/dev/cel/common/values/OptimizedSelectable.java b/common/src/main/java/dev/cel/common/values/OptimizedSelectable.java
new file mode 100644
index 000000000..828d15227
--- /dev/null
+++ b/common/src/main/java/dev/cel/common/values/OptimizedSelectable.java
@@ -0,0 +1,45 @@
+// Copyright 2026 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.values;
+
+import com.google.errorprone.annotations.Immutable;
+import dev.cel.common.annotations.Internal;
+import java.util.Optional;
+
+/**
+ * Resolves an optimized field selection within a selection chain rewritten by the select optimizer.
+ *
+ * Implementations resolve individual field selections against themselves by protobuf field
+ * number. Walking the chain across multiple fields and heterogeneous values belongs to {@link
+ * OptimizedSelectTraversal}.
+ *
+ *
CEL Library Internals. Do Not Use.
+ */
+@Internal
+@Immutable
+public interface OptimizedSelectable {
+
+ /** Selects {@code field}, falling back to its default value or an empty submessage if absent. */
+ Object selectByFieldNumber(SelectField field);
+
+ /** Returns whether {@code field} is present. */
+ boolean hasFieldByNumber(SelectField field);
+
+ /**
+ * Returns the value of the field at {@code field} (a scalar or submessage) for an intermediate
+ * step of a presence test, or empty if absent.
+ */
+ Optional findByFieldNumber(SelectField field);
+}
diff --git a/common/src/main/java/dev/cel/common/values/SelectField.java b/common/src/main/java/dev/cel/common/values/SelectField.java
new file mode 100644
index 000000000..8bee5a0d7
--- /dev/null
+++ b/common/src/main/java/dev/cel/common/values/SelectField.java
@@ -0,0 +1,124 @@
+// Copyright 2026 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.values;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.auto.value.AutoValue;
+import com.google.errorprone.annotations.Immutable;
+import dev.cel.common.annotations.Internal;
+import org.jspecify.annotations.Nullable;
+
+/**
+ * Represents a single field selection in an optimized selection chain.
+ *
+ * CEL Library Internals. Do Not Use.
+ */
+@Internal
+@AutoValue
+@AutoValue.CopyAnnotations
+@Immutable
+@SuppressWarnings("Immutable") // Default value is an immutable CEL literal or null
+public abstract class SelectField {
+
+ private static final int MAX_FIELD_NUMBER = 536870911;
+
+ /** CEL-specific type code used to encode CEL maps on the wire. */
+ public static final int CEL_MAP_TYPE_CODE = -1;
+
+ /** Sentinel for a presence-test qualifier, whose 2-tuple carries no type code. */
+ public static final int NO_TYPE_CODE = 0;
+
+ /** Protobuf field type code for {@code TYPE_MESSAGE} ({@code FieldDescriptorProto.Type}). */
+ public static final int MESSAGE_TYPE_CODE = 11;
+
+ // Mirrors FieldDescriptorProto.Type. Not validated against a protobuf enum because the :values
+ // target is deliberately protobuf-free; keep in sync with CelLiteDescriptor.FieldLiteDescriptor.
+ private static final int MIN_PROTO_TYPE_CODE = 1; // TYPE_DOUBLE
+ private static final int MAX_PROTO_TYPE_CODE = 18; // TYPE_SINT64
+ private static final int GROUP_PROTO_TYPE_CODE = 10; // Unsupported by CEL.
+
+ /** Protobuf field number of this hop. */
+ public abstract int fieldNumber();
+
+ /** Protobuf field name or map key of this hop. */
+ public abstract String fieldName();
+
+ /**
+ * Protobuf wire type code (1..18, except 10), {@link #CEL_MAP_TYPE_CODE}, or {@link
+ * #NO_TYPE_CODE}.
+ */
+ public abstract int typeCode();
+
+ /**
+ * Default value for this hop, or null if unspecified. When non-null, this must be an immutable
+ * CEL literal value.
+ */
+ public abstract @Nullable Object defaultValue();
+
+ /**
+ * Creates a presence-test qualifier hop.
+ *
+ * @param fieldNumber Protobuf field number. Takes {@code long} for compatibility with CEL's int64
+ * constant representations.
+ * @param fieldName Protobuf field name.
+ */
+ public static SelectField create(long fieldNumber, String fieldName) {
+ checkArgument(
+ fieldNumber >= 1 && fieldNumber <= MAX_FIELD_NUMBER,
+ "Field number out of protobuf range: %s",
+ fieldNumber);
+ checkNotNull(fieldName);
+ return new AutoValue_SelectField(
+ (int) fieldNumber, fieldName, NO_TYPE_CODE, /* defaultValue= */ null);
+ }
+
+ /**
+ * Creates a fully-specified field selection hop with type code and optional default value.
+ *
+ * @param fieldNumber Protobuf field number. Takes {@code long} for compatibility with CEL's int64
+ * constant representations.
+ * @param fieldName Protobuf field name.
+ * @param typeCode Protobuf wire type code or {@link #CEL_MAP_TYPE_CODE}. Takes {@code long} for
+ * compatibility with CEL's int64 constant representations.
+ * @param defaultValue Default value for the field, or null if unspecified.
+ */
+ public static SelectField create(
+ long fieldNumber, String fieldName, long typeCode, @Nullable Object defaultValue) {
+ checkArgument(
+ fieldNumber >= 1 && fieldNumber <= MAX_FIELD_NUMBER,
+ "Field number out of protobuf range: %s",
+ fieldNumber);
+ checkNotNull(fieldName);
+ checkArgument(isSupportedTypeCode(typeCode), "Invalid protobuf type code: %s", typeCode);
+ return new AutoValue_SelectField((int) fieldNumber, fieldName, (int) typeCode, defaultValue);
+ }
+
+ /**
+ * Returns whether {@code typeCode} is a protobuf field type code CEL supports, or the {@link
+ * #CEL_MAP_TYPE_CODE} sentinel.
+ */
+ public static boolean isSupportedTypeCode(long typeCode) {
+ if (typeCode == CEL_MAP_TYPE_CODE) {
+ return true;
+ }
+ return typeCode >= MIN_PROTO_TYPE_CODE
+ && typeCode <= MAX_PROTO_TYPE_CODE
+ && typeCode != GROUP_PROTO_TYPE_CODE;
+ }
+
+ SelectField() {}
+}
diff --git a/common/src/test/java/dev/cel/common/values/BUILD.bazel b/common/src/test/java/dev/cel/common/values/BUILD.bazel
index baa33ebc3..6b83f0a60 100644
--- a/common/src/test/java/dev/cel/common/values/BUILD.bazel
+++ b/common/src/test/java/dev/cel/common/values/BUILD.bazel
@@ -29,10 +29,13 @@ java_library(
"//common/values:cel_value_provider",
"//common/values:combined_cel_value_converter",
"//common/values:combined_cel_value_provider",
+ "//common/values:optimized_select_traversal",
+ "//common/values:optimized_selectable",
"//common/values:proto_message_lite_value",
"//common/values:proto_message_lite_value_provider",
"//common/values:proto_message_value",
"//common/values:proto_message_value_provider",
+ "//common/values:select_field",
"//protobuf:cel_lite_descriptor",
"//testing/protos:test_all_types_cel_java_proto3",
"@cel_spec//proto/cel/expr/conformance/proto2:test_all_types_java_proto",
diff --git a/common/src/test/java/dev/cel/common/values/OptimizedSelectTraversalTest.java b/common/src/test/java/dev/cel/common/values/OptimizedSelectTraversalTest.java
new file mode 100644
index 000000000..0fd1295c5
--- /dev/null
+++ b/common/src/test/java/dev/cel/common/values/OptimizedSelectTraversalTest.java
@@ -0,0 +1,328 @@
+// Copyright 2026 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.values;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.junit.Assert.assertThrows;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.testing.junit.testparameterinjector.TestParameter;
+import com.google.testing.junit.testparameterinjector.TestParameterInjector;
+import dev.cel.common.exceptions.CelAttributeNotFoundException;
+import java.util.Map;
+import java.util.Optional;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(TestParameterInjector.class)
+public final class OptimizedSelectTraversalTest {
+
+ private enum TargetType {
+ OPTIMIZED_SELECTABLE {
+ @Override
+ Object createTarget(Map data) {
+ return new FakeOptimizedSelectable(data);
+ }
+
+ @Override
+ Object createNestedTarget(Map innerData) {
+ return new FakeOptimizedSelectable(
+ ImmutableMap.of("outer_key", new FakeOptimizedSelectable(innerData)));
+ }
+ },
+ SELECTABLE_VALUE {
+ @Override
+ Object createTarget(Map data) {
+ return new FakeSelectableValue(data);
+ }
+
+ @Override
+ Object createNestedTarget(Map innerData) {
+ return new FakeSelectableValue(
+ ImmutableMap.of("outer_key", new FakeSelectableValue(innerData)));
+ }
+ };
+
+ abstract Object createTarget(Map data);
+
+ abstract Object createNestedTarget(Map innerData);
+ }
+
+ @SuppressWarnings("Immutable")
+ private enum NestedPresenceTestCase {
+ ALL_PRESENT(
+ ImmutableMap.of("inner_key", "nested_val"), "outer_key", "inner_key", /* expected= */ true),
+ INTERMEDIATE_MISSING(
+ ImmutableMap.of("inner_key", "nested_val"),
+ "missing_outer",
+ "inner_key",
+ /* expected= */ false),
+ TERMINAL_MISSING(
+ ImmutableMap.of("other_key", "nested_val"),
+ "outer_key",
+ "missing_terminal",
+ /* expected= */ false);
+
+ final ImmutableMap innerData;
+ final String outerField;
+ final String innerField;
+ final boolean expected;
+
+ NestedPresenceTestCase(
+ ImmutableMap innerData,
+ String outerField,
+ String innerField,
+ boolean expected) {
+ this.innerData = innerData;
+ this.outerField = outerField;
+ this.innerField = innerField;
+ this.expected = expected;
+ }
+ }
+
+ @Test
+ public void qualify_emptyFields_returnsTargetInstance() {
+ Object target = new Object();
+
+ Object result = OptimizedSelectTraversal.qualify(target, ImmutableList.of());
+
+ assertThat(result).isSameInstanceAs(target);
+ }
+
+ @Test
+ public void qualify_singleField_success(@TestParameter TargetType targetType) {
+ Object target = targetType.createTarget(ImmutableMap.of("key", "value"));
+ ImmutableList fields = ImmutableList.of(SelectField.create(1L, "key", 9, ""));
+
+ Object result = OptimizedSelectTraversal.qualify(target, fields);
+
+ assertThat(result).isEqualTo("value");
+ }
+
+ @Test
+ public void qualify_nested_success(@TestParameter TargetType targetType) {
+ Object target = targetType.createNestedTarget(ImmutableMap.of("inner_key", "nested_value"));
+ ImmutableList fields =
+ ImmutableList.of(
+ SelectField.create(1L, "outer_key", 11, null),
+ SelectField.create(2L, "inner_key", 9, ""));
+
+ Object result = OptimizedSelectTraversal.qualify(target, fields);
+
+ assertThat(result).isEqualTo("nested_value");
+ }
+
+ @Test
+ public void qualify_singleField_missingThrowsException(@TestParameter TargetType targetType) {
+ Object target = targetType.createTarget(ImmutableMap.of("present", "value"));
+ ImmutableList fields =
+ ImmutableList.of(SelectField.create(1L, "missing", 9, null));
+
+ CelAttributeNotFoundException thrown =
+ assertThrows(
+ CelAttributeNotFoundException.class,
+ () -> OptimizedSelectTraversal.qualify(target, fields));
+
+ assertThat(thrown).hasMessageThat().contains("missing");
+ }
+
+ @Test
+ public void qualify_optimizedSelectable_absentWithDefaultValue_returnsDefault() {
+ FakeOptimizedSelectable selectable = new FakeOptimizedSelectable(ImmutableMap.of());
+ ImmutableList fields =
+ ImmutableList.of(SelectField.create(1L, "absent", 9, "default_fallback"));
+
+ Object result = OptimizedSelectTraversal.qualify(selectable, fields);
+
+ assertThat(result).isEqualTo("default_fallback");
+ }
+
+ @Test
+ public void qualify_selectableValue_absentWithDefaultValue_returnsDefault() {
+ FakeSelectableValue selectable = new FakeSelectableValue(ImmutableMap.of());
+ ImmutableList fields =
+ ImmutableList.of(SelectField.create(1L, "absent", 9, "default_fallback"));
+
+ Object result = OptimizedSelectTraversal.qualify(selectable, fields);
+
+ assertThat(result).isEqualTo("default_fallback");
+ }
+
+ @Test
+ public void qualify_unsupportedTarget_throwsException() {
+ ImmutableList fields = ImmutableList.of(SelectField.create(1L, "invalid_field"));
+
+ CelAttributeNotFoundException thrown =
+ assertThrows(
+ CelAttributeNotFoundException.class,
+ () -> OptimizedSelectTraversal.qualify(12345L, fields));
+
+ assertThat(thrown).hasMessageThat().contains("invalid_field");
+ }
+
+ @Test
+ public void qualify_intermediateUnsupportedTarget_throwsException() {
+ FakeOptimizedSelectable target = new FakeOptimizedSelectable(ImmutableMap.of("scalar", 999L));
+ ImmutableList fields =
+ ImmutableList.of(
+ SelectField.create(1L, "scalar", 3, 0L), SelectField.create(2L, "unreachable", 9, ""));
+
+ CelAttributeNotFoundException thrown =
+ assertThrows(
+ CelAttributeNotFoundException.class,
+ () -> OptimizedSelectTraversal.qualify(target, fields));
+
+ assertThat(thrown).hasMessageThat().contains("unreachable");
+ }
+
+ @Test
+ public void hasField_emptyFields_returnsFalse() {
+ Object target = new Object();
+
+ boolean hasField = OptimizedSelectTraversal.hasField(target, ImmutableList.of());
+
+ assertThat(hasField).isFalse();
+ }
+
+ @Test
+ public void hasField_singleField(
+ @TestParameter TargetType targetType,
+ @TestParameter({"present_key", "missing_key"}) String queryKey) {
+ Object target = targetType.createTarget(ImmutableMap.of("present_key", "val"));
+ ImmutableList fields = ImmutableList.of(SelectField.create(1L, queryKey));
+
+ boolean hasField = OptimizedSelectTraversal.hasField(target, fields);
+
+ assertThat(hasField).isEqualTo(queryKey.equals("present_key"));
+ }
+
+ @Test
+ public void hasField_nestedFields(
+ @TestParameter TargetType targetType, @TestParameter NestedPresenceTestCase testCase) {
+ Object target = targetType.createNestedTarget(testCase.innerData);
+ ImmutableList fields =
+ ImmutableList.of(
+ SelectField.create(1L, testCase.outerField),
+ SelectField.create(2L, testCase.innerField));
+
+ boolean hasField = OptimizedSelectTraversal.hasField(target, fields);
+
+ assertThat(hasField).isEqualTo(testCase.expected);
+ }
+
+ @Test
+ public void hasField_intermediateUnsupportedTarget_throwsException() {
+ FakeOptimizedSelectable target =
+ new FakeOptimizedSelectable(ImmutableMap.of("scalar_key", 100L));
+ ImmutableList fields =
+ ImmutableList.of(SelectField.create(1L, "scalar_key"), SelectField.create(2L, "child_key"));
+
+ CelAttributeNotFoundException thrown =
+ assertThrows(
+ CelAttributeNotFoundException.class,
+ () -> OptimizedSelectTraversal.hasField(target, fields));
+
+ assertThat(thrown).hasMessageThat().contains("child_key");
+ }
+
+ @Test
+ public void hasField_unsupportedTarget_throwsException() {
+ ImmutableList fields = ImmutableList.of(SelectField.create(1L, "invalid_field"));
+
+ CelAttributeNotFoundException thrown =
+ assertThrows(
+ CelAttributeNotFoundException.class,
+ () -> OptimizedSelectTraversal.hasField(12345L, fields));
+
+ assertThat(thrown).hasMessageThat().contains("invalid_field");
+ }
+
+ @Test
+ public void qualify_errorValue_propagatesError() {
+ ErrorValue error = ErrorValue.create(1L, new RuntimeException("test error"));
+ ImmutableList fields =
+ ImmutableList.of(SelectField.create(1L, "field1"), SelectField.create(2L, "field2"));
+
+ Object result = OptimizedSelectTraversal.qualify(error, fields);
+
+ assertThat(result).isSameInstanceAs(error);
+ }
+
+ @Test
+ public void hasField_errorValue_returnsFalse() {
+ ErrorValue error = ErrorValue.create(1L, new RuntimeException("test error"));
+ ImmutableList fields =
+ ImmutableList.of(SelectField.create(1L, "field1"), SelectField.create(2L, "field2"));
+
+ boolean result = OptimizedSelectTraversal.hasField(error, fields);
+
+ assertThat(result).isFalse();
+ }
+
+ @SuppressWarnings("Immutable")
+ private static final class FakeOptimizedSelectable implements OptimizedSelectable {
+ private final ImmutableMap values;
+
+ @Override
+ public Object selectByFieldNumber(SelectField field) {
+ Object value = values.get(field.fieldName());
+ if (value != null) {
+ return value;
+ }
+ if (field.defaultValue() != null) {
+ return field.defaultValue();
+ }
+ throw CelAttributeNotFoundException.forFieldResolution(field.fieldName());
+ }
+
+ @Override
+ public boolean hasFieldByNumber(SelectField field) {
+ return values.containsKey(field.fieldName());
+ }
+
+ @Override
+ public Optional findByFieldNumber(SelectField field) {
+ return Optional.ofNullable(values.get(field.fieldName()));
+ }
+
+ FakeOptimizedSelectable(Map values) {
+ this.values = ImmutableMap.copyOf(values);
+ }
+ }
+
+ @SuppressWarnings("Immutable")
+ private static final class FakeSelectableValue implements SelectableValue {
+ private final ImmutableMap values;
+
+ @Override
+ public Object select(String field) {
+ Object value = values.get(field);
+ if (value != null) {
+ return value;
+ }
+ throw CelAttributeNotFoundException.forFieldResolution(field);
+ }
+
+ @Override
+ public Optional find(String field) {
+ return Optional.ofNullable(values.get(field));
+ }
+
+ FakeSelectableValue(Map values) {
+ this.values = ImmutableMap.copyOf(values);
+ }
+ }
+}
diff --git a/common/src/test/java/dev/cel/common/values/SelectFieldTest.java b/common/src/test/java/dev/cel/common/values/SelectFieldTest.java
new file mode 100644
index 000000000..ba9dc7008
--- /dev/null
+++ b/common/src/test/java/dev/cel/common/values/SelectFieldTest.java
@@ -0,0 +1,133 @@
+// Copyright 2026 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.values;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.junit.Assert.assertThrows;
+
+import com.google.common.testing.EqualsTester;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public final class SelectFieldTest {
+
+ @Test
+ public void create_twoArguments_success() {
+ SelectField field = SelectField.create(1L, "foo");
+
+ assertThat(field.fieldNumber()).isEqualTo(1);
+ assertThat(field.fieldName()).isEqualTo("foo");
+ assertThat(field.typeCode()).isEqualTo(SelectField.NO_TYPE_CODE);
+ assertThat(field.defaultValue()).isNull();
+ }
+
+ @Test
+ public void create_fourArguments_success() {
+ SelectField field = SelectField.create(2L, "bar", 9, "default_str");
+
+ assertThat(field.fieldNumber()).isEqualTo(2);
+ assertThat(field.fieldName()).isEqualTo("bar");
+ assertThat(field.typeCode()).isEqualTo(9);
+ assertThat(field.defaultValue()).isEqualTo("default_str");
+ }
+
+ @Test
+ public void create_mapTypeCode_success() {
+ SelectField field = SelectField.create(3L, "map_field", -1, null);
+
+ assertThat(field.typeCode()).isEqualTo(-1);
+ }
+
+ @Test
+ public void create_twoArgNullFieldName_throwsNullPointerException() {
+ assertThrows(NullPointerException.class, () -> SelectField.create(1L, null));
+ }
+
+ @Test
+ public void create_fourArgNullFieldName_throwsNullPointerException() {
+ assertThrows(NullPointerException.class, () -> SelectField.create(1L, null, 9, null));
+ }
+
+ @Test
+ public void create_fieldNumberBelowMinimum_throwsIllegalArgumentException() {
+ IllegalArgumentException thrown =
+ assertThrows(IllegalArgumentException.class, () -> SelectField.create(0L, "foo"));
+
+ assertThat(thrown).hasMessageThat().contains("Field number out of protobuf range: 0");
+ }
+
+ @Test
+ public void create_fieldNumberNegative_throwsIllegalArgumentException() {
+ IllegalArgumentException thrown =
+ assertThrows(IllegalArgumentException.class, () -> SelectField.create(-1L, "foo"));
+
+ assertThat(thrown).hasMessageThat().contains("Field number out of protobuf range: -1");
+ }
+
+ @Test
+ public void create_fieldNumberAboveMaximum_throwsIllegalArgumentException() {
+ IllegalArgumentException thrown =
+ assertThrows(IllegalArgumentException.class, () -> SelectField.create(536870912L, "foo"));
+
+ assertThat(thrown).hasMessageThat().contains("Field number out of protobuf range: 536870912");
+ }
+
+ @Test
+ public void create_typeCodeZero_throwsIllegalArgumentException() {
+ IllegalArgumentException thrown =
+ assertThrows(IllegalArgumentException.class, () -> SelectField.create(1L, "foo", 0, null));
+
+ assertThat(thrown).hasMessageThat().contains("Invalid protobuf type code: 0");
+ }
+
+ @Test
+ public void create_typeCodeAboveMaximum_throwsIllegalArgumentException() {
+ IllegalArgumentException thrown =
+ assertThrows(IllegalArgumentException.class, () -> SelectField.create(1L, "foo", 19, null));
+
+ assertThat(thrown).hasMessageThat().contains("Invalid protobuf type code: 19");
+ }
+
+ @Test
+ public void create_typeCodeBelowSentinel_throwsIllegalArgumentException() {
+ IllegalArgumentException thrown =
+ assertThrows(IllegalArgumentException.class, () -> SelectField.create(1L, "foo", -2, null));
+
+ assertThat(thrown).hasMessageThat().contains("Invalid protobuf type code: -2");
+ }
+
+ @Test
+ public void create_typeCodeGroupProto_throwsIllegalArgumentException() {
+ IllegalArgumentException thrown =
+ assertThrows(IllegalArgumentException.class, () -> SelectField.create(1L, "foo", 10, null));
+
+ assertThat(thrown).hasMessageThat().contains("Invalid protobuf type code: 10");
+ }
+
+ @Test
+ public void equalsAndHashCode_testedProperly() {
+ new EqualsTester()
+ .addEqualityGroup(SelectField.create(1L, "foo"), SelectField.create(1L, "foo"))
+ .addEqualityGroup(SelectField.create(2L, "foo"), SelectField.create(2L, "foo"))
+ .addEqualityGroup(SelectField.create(1L, "bar"), SelectField.create(1L, "bar"))
+ .addEqualityGroup(
+ SelectField.create(1L, "foo", 9, "default"),
+ SelectField.create(1L, "foo", 9, "default"))
+ .addEqualityGroup(SelectField.create(1L, "foo", 9, "other_default"))
+ .testEquals();
+ }
+}
diff --git a/common/values/BUILD.bazel b/common/values/BUILD.bazel
index 9853289a9..192f01de8 100644
--- a/common/values/BUILD.bazel
+++ b/common/values/BUILD.bazel
@@ -126,3 +126,39 @@ cel_android_library(
name = "base_proto_message_value_provider_android",
exports = ["//common/src/main/java/dev/cel/common/values:base_proto_message_value_provider_android"],
)
+
+java_library(
+ name = "select_field",
+ visibility = ["//:internal"],
+ exports = ["//common/src/main/java/dev/cel/common/values:select_field"],
+)
+
+cel_android_library(
+ name = "select_field_android",
+ visibility = ["//:internal"],
+ exports = ["//common/src/main/java/dev/cel/common/values:select_field_android"],
+)
+
+java_library(
+ name = "optimized_selectable",
+ visibility = ["//:internal"],
+ exports = ["//common/src/main/java/dev/cel/common/values:optimized_selectable"],
+)
+
+cel_android_library(
+ name = "optimized_selectable_android",
+ visibility = ["//:internal"],
+ exports = ["//common/src/main/java/dev/cel/common/values:optimized_selectable_android"],
+)
+
+java_library(
+ name = "optimized_select_traversal",
+ visibility = ["//:internal"],
+ exports = ["//common/src/main/java/dev/cel/common/values:optimized_select_traversal"],
+)
+
+cel_android_library(
+ name = "optimized_select_traversal_android",
+ visibility = ["//:internal"],
+ exports = ["//common/src/main/java/dev/cel/common/values:optimized_select_traversal_android"],
+)