Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 86 additions & 0 deletions common/src/main/java/dev/cel/common/values/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,8 @@ java_library(
],
deps = [
":base_proto_cel_value_converter",
":optimized_selectable",
":select_field",
":values",
"//:auto_value",
"//common/annotations",
Expand Down Expand Up @@ -351,6 +353,8 @@ cel_android_library(
],
deps = [
":base_proto_cel_value_converter_android",
":optimized_selectable_android",
":select_field_android",
":values_android",
"//:auto_value",
"//common/annotations",
Expand Down Expand Up @@ -434,3 +438,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",
],
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
// 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}.
*
* <p>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<SelectField> 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.
*
* <p>Absence of any intermediate field short-circuits to {@code false}.
*/
public static boolean hasField(Object target, ImmutableList<SelectField> fields) {
if (fields.isEmpty()) {
return false;
}
Object current = target;
int terminalIndex = fields.size() - 1;
for (int i = 0; i < terminalIndex; i++) {
Optional<Object> 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<String> selectable = (SelectableValue<String>) 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<Object> 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<String>) 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<String>) target).find(field.fieldName()).isPresent();
}
throw CelAttributeNotFoundException.forFieldResolution(field.fieldName());
}

private OptimizedSelectTraversal() {}
}
Original file line number Diff line number Diff line change
@@ -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.
*
* <p>Implementations resolve individual field selections against themselves by protobuf field
* number. Walking the chain across multiple fields and heterogeneous values belongs to {@link
* OptimizedSelectTraversal}.
*
* <p>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<Object> findByFieldNumber(SelectField field);
}
Loading
Loading