Merged
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
3 changes: 2 additions & 1 deletion bundle/src/test/java/dev/cel/bundle/BUILD.bazel
Original file line numberDiff line numberDiff line change
Expand Up@@ -41,6 +41,8 @@ java_library(
"//common/types:cel_proto_types",
"//common/types:message_type_provider",
"//common/types:type_providers",
"//common/values",
"//common/values:cel_byte_string",
"//compiler",
"//compiler:compiler_builder",
"//extensions",
Expand All@@ -64,7 +66,6 @@ java_library(
"@maven//:com_google_truth_extensions_truth_proto_extension",
"@maven//:junit_junit",
"@maven//:org_jspecify_jspecify",
"@maven_android//:com_google_protobuf_protobuf_javalite",
],
)

Expand Down
40 changes: 35 additions & 5 deletions bundle/src/test/java/dev/cel/bundle/CelImplTest.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -48,7 +48,6 @@
import com.google.protobuf.Empty;
import com.google.protobuf.FieldMask;
import com.google.protobuf.Message;
import com.google.protobuf.NullValue;
import com.google.protobuf.Struct;
import com.google.protobuf.TextFormat;
import com.google.protobuf.Timestamp;
Expand DownExpand Up@@ -86,6 +85,8 @@
import dev.cel.common.types.ProtoMessageTypeProvider;
import dev.cel.common.types.SimpleType;
import dev.cel.common.types.StructTypeReference;
import dev.cel.common.values.CelByteString;
import dev.cel.common.values.NullValue;
import dev.cel.compiler.CelCompiler;
import dev.cel.compiler.CelCompilerFactory;
import dev.cel.compiler.CelCompilerImpl;
Expand All@@ -108,6 +109,7 @@
import dev.cel.runtime.UnknownContext;
import dev.cel.testing.testdata.proto3.StandaloneGlobalEnum;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
Expand DownExpand Up@@ -1019,7 +1021,10 @@ public void program_enumTypeReferenceResolution(boolean resolveTypeDependencies)
Cel cel =
standardCelBuilderWithMacros()
.setOptions(
CelOptions.current().resolveTypeDependencies(resolveTypeDependencies).build())
CelOptions.current()
.evaluateCanonicalTypesToNativeValues(true)
.resolveTypeDependencies(resolveTypeDependencies)
.build())
.addMessageTypes(Struct.getDescriptor())
.setResultType(StructTypeReference.create("google.protobuf.NullValue"))
.setContainer(CelContainer.ofName("google.protobuf"))
Expand All@@ -1037,7 +1042,11 @@ public void program_enumTypeReferenceResolution(boolean resolveTypeDependencies)
public void program_enumTypeTransitiveResolution() throws Exception {
Cel cel =
standardCelBuilderWithMacros()
.setOptions(CelOptions.current().resolveTypeDependencies(true).build())
.setOptions(
CelOptions.current()
.evaluateCanonicalTypesToNativeValues(true)
.resolveTypeDependencies(true)
.build())
.addMessageTypes(Proto2ExtensionScopedMessage.getDescriptor())
.setResultType(StructTypeReference.create("google.protobuf.NullValue"))
.setContainer(CelContainer.ofName("google.protobuf"))
Expand DownExpand Up@@ -1626,7 +1635,11 @@ public void programAdvanceEvaluation_indexOnUnknownContainer() throws Exception
public void programAdvanceEvaluation_unsupportedIndexIgnored() throws Exception {
Cel cel =
standardCelBuilderWithMacros()
.setOptions(CelOptions.current().enableUnknownTracking(true).build())
.setOptions(
CelOptions.current()
.evaluateCanonicalTypesToNativeValues(true)
.enableUnknownTracking(true)
.build())
.addVar("unk", MapType.create(SimpleType.STRING, SimpleType.BOOL))
.setContainer(CelContainer.ofName(""))
.addFunctionBindings()
Expand DownExpand Up@@ -1654,7 +1667,7 @@ public void programAdvanceEvaluation_unsupportedIndexIgnored() throws Exception
UnknownContext.create(
fromMap(
ImmutableMap.of(
"unk", ImmutableMap.of(ByteString.copyFromUtf8("a"), false))),
"unk", ImmutableMap.of(CelByteString.copyFromUtf8("a"), false))),
ImmutableList.of())))
.isEqualTo(false);
}
Expand DownExpand Up@@ -2077,6 +2090,23 @@ public void program_regexProgramSizeExceedsLimit_throws() throws Exception {
assertThat(e.getErrorCode()).isEqualTo(CelErrorCode.INVALID_ARGUMENT);
}

@Test
@SuppressWarnings("unchecked") // test only
public void program_evaluateCanonicalTypesToNativeTypesDisabled_producesProtoValues()
throws Exception {
Cel cel =
standardCelBuilderWithMacros()
.setOptions(CelOptions.current().evaluateCanonicalTypesToNativeValues(false).build())
.build();
CelAbstractSyntaxTree ast = cel.compile("[null, {b'abc': null}]").getAst();
Map<ByteString, Object> expectedNestedMap = new LinkedHashMap<>();
expectedNestedMap.put(ByteString.copyFromUtf8("abc"), com.google.protobuf.NullValue.NULL_VALUE);

List<Object> result = (List<Object>) cel.createProgram(ast).eval();

assertThat(result).containsExactly(com.google.protobuf.NullValue.NULL_VALUE, expectedNestedMap);
}

@Test
public void toBuilder_isImmutable() {
CelBuilder celBuilder = CelFactory.standardCelBuilder();
Expand Down
2 changes: 2 additions & 0 deletions common/src/main/java/dev/cel/common/BUILD.bazel
Original file line numberDiff line numberDiff line change
Expand Up@@ -206,6 +206,8 @@ java_library(
],
deps = [
"//common/internal:proto_time_utils",
"//common/values",
"//common/values:cel_byte_string",
"@maven//:com_google_errorprone_error_prone_annotations",
"@maven//:com_google_guava_guava",
"@maven//:com_google_protobuf_protobuf_java",
Expand Down
16 changes: 16 additions & 0 deletions common/src/main/java/dev/cel/common/CelOptions.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -109,6 +109,8 @@ public enum ProtoUnsetFieldOptions {

public abstract int comprehensionMaxIterations();

public abstract boolean evaluateCanonicalTypesToNativeValues();

public abstract boolean unwrapWellKnownTypesOnFunctionDispatch();

public abstract ProtoUnsetFieldOptions fromProtoUnsetFieldOption();
Expand DownExpand Up@@ -150,6 +152,7 @@ public static Builder newBuilder() {
.enableNamespacedDeclarations(true)
// Evaluation options
.disableCelStandardEquality(true)
.evaluateCanonicalTypesToNativeValues(false)
.enableShortCircuiting(true)
.enableRegexPartialMatch(false)
.enableUnsignedComparisonAndArithmeticIsUnsigned(false)
Expand DownExpand Up@@ -450,6 +453,19 @@ public abstract static class Builder {
*/
public abstract Builder comprehensionMaxIterations(int value);

/**
* If set, canonical CEL types such as bytes and CEL null will return their native value
* equivalents instead of protobuf based values. Specifically:
*
* <ul>
* <li>Bytes: {@code dev.cel.common.values.CelByteString} instead of {@code
* com.google.protobuf.ByteString}.
* <li>CEL null: {@code dev.cel.common.values.NullValue} instead of {@code
* com.google.protobuf.NullValue}.
* </ul>
*/
public abstract Builder evaluateCanonicalTypesToNativeValues(boolean value);

/**
* If disabled, CEL runtime will no longer adapt the function dispatch results for protobuf's
* well known types to other types. This option is enabled by default.
Expand Down
8 changes: 4 additions & 4 deletions common/src/main/java/dev/cel/common/CelProtoJsonAdapter.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -18,7 +18,6 @@
import com.google.common.base.Joiner;
import com.google.common.primitives.UnsignedLong;
import com.google.errorprone.annotations.Immutable;
import com.google.protobuf.ByteString;
import com.google.protobuf.Duration;
import com.google.protobuf.Empty;
import com.google.protobuf.FieldMask;
Expand All@@ -28,6 +27,7 @@
import com.google.protobuf.Timestamp;
import com.google.protobuf.Value;
import dev.cel.common.internal.ProtoTimeUtils;
import dev.cel.common.values.CelByteString;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
Expand DownExpand Up@@ -71,7 +71,7 @@ public static <K extends String, V> Struct adaptToJsonStructValue(Map<K, V> map)
@SuppressWarnings("unchecked")
public static Value adaptValueToJsonValue(Object value) {
Value.Builder json = Value.newBuilder();
if (value == null || value instanceof NullValue) {
if (value == null || value instanceof dev.cel.common.values.NullValue) {
return json.setNullValue(NullValue.NULL_VALUE).build();
}
if (value instanceof Boolean) {
Expand All@@ -93,9 +93,9 @@ public static Value adaptValueToJsonValue(Object value) {
if (value instanceof Float || value instanceof Double) {
return json.setNumberValue(((Number) value).doubleValue()).build();
}
if (value instanceof ByteString) {
if (value instanceof CelByteString) {
return json.setStringValue(
Base64.getEncoder().encodeToString(((ByteString) value).toByteArray()))
Base64.getEncoder().encodeToString(((CelByteString) value).toByteArray()))
.build();
}
if (value instanceof String) {
Expand Down
15 changes: 14 additions & 1 deletion common/src/main/java/dev/cel/common/ast/BUILD.bazel
Original file line numberDiff line numberDiff line change
Expand Up@@ -49,6 +49,8 @@ java_library(
deps = [
"//:auto_value",
"//common/annotations",
"//common/values",
"//common/values:cel_byte_string",
"@maven//:com_google_errorprone_error_prone_annotations",
"@maven//:com_google_guava_guava",
"@maven//:com_google_protobuf_protobuf_java",
Expand All@@ -62,9 +64,12 @@ java_library(
],
deps = [
":ast",
"//common/values",
"//common/values:cel_byte_string",
"@cel_spec//proto/cel/expr:checked_java_proto",
"@cel_spec//proto/cel/expr:syntax_java_proto",
"@maven//:com_google_guava_guava",
"@maven//:com_google_protobuf_protobuf_java",
],
)

Expand All@@ -75,9 +80,12 @@ cel_android_library(
],
deps = [
":ast_android",
"//common/values:cel_byte_string",
"//common/values:values_android",
"@cel_spec//proto/cel/expr:checked_java_proto_lite",
"@cel_spec//proto/cel/expr:syntax_java_proto_lite",
"@maven_android//:com_google_guava_guava",
"@maven_android//:com_google_protobuf_protobuf_javalite",
],
)

Expand All@@ -88,8 +96,11 @@ java_library(
],
deps = [
":ast",
"//common/values",
"//common/values:cel_byte_string",
"@com_google_googleapis//google/api/expr/v1alpha1:expr_java_proto",
"@maven//:com_google_guava_guava",
"@maven//:com_google_protobuf_protobuf_java",
],
)

Expand All@@ -112,8 +123,8 @@ java_library(
deps = [
":ast",
"//common/annotations",
"//common/values:cel_byte_string",
"@maven//:com_google_guava_guava",
"@maven//:com_google_protobuf_protobuf_java",
],
)

Expand All@@ -136,6 +147,8 @@ cel_android_library(
deps = [
"//:auto_value",
"//common/annotations",
"//common/values:cel_byte_string",
"//common/values:values_android",
"@maven//:com_google_errorprone_error_prone_annotations",
"@maven_android//:com_google_guava_guava",
"@maven_android//:com_google_protobuf_protobuf_javalite",
Expand Down
66 changes: 44 additions & 22 deletions common/src/main/java/dev/cel/common/ast/CelConstant.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -19,11 +19,13 @@
import com.google.common.collect.ImmutableSet;
import com.google.common.primitives.UnsignedLong;
import com.google.errorprone.annotations.Immutable;
import com.google.errorprone.annotations.InlineMe;
import com.google.protobuf.ByteString;
import com.google.protobuf.Duration;
import com.google.protobuf.NullValue;
import com.google.protobuf.Timestamp;
import dev.cel.common.annotations.Internal;
import dev.cel.common.values.CelByteString;
import dev.cel.common.values.NullValue;

/**
* Represents a primitive literal.
Expand All@@ -42,7 +44,7 @@ public abstract class CelConstant {
UnsignedLong.class,
Double.class,
String.class,
ByteString.class);
CelByteString.class);

/** Represents the type of the Constant */
public enum Kind {
Expand DownExpand Up@@ -92,7 +94,7 @@ public abstract static class CelConstantNotSet {}

public abstract String stringValue();

public abstract ByteString bytesValue();
public abstract CelByteString bytesValue();

/**
* @deprecated Do not use. Timestamp is no longer built-in CEL type.
Expand DownExpand Up@@ -134,10 +136,46 @@ public static CelConstant ofValue(String value) {
return AutoOneOf_CelConstant.stringValue(value);
}

public static CelConstant ofValue(ByteString value) {
public static CelConstant ofValue(CelByteString value) {
return AutoOneOf_CelConstant.bytesValue(value);
}

/**
* @deprecated Use native type equivalent {@link #ofValue(NullValue)} instead.
*/
@InlineMe(
replacement = "CelConstant.ofValue(NullValue.NULL_VALUE)",
imports = {"dev.cel.common.ast.CelConstant", "dev.cel.common.values.NullValue"})
@Deprecated
public static CelConstant ofValue(com.google.protobuf.NullValue unused) {
return ofValue(NullValue.NULL_VALUE);
}

/**
* @deprecated Use native type equivalent {@link #ofValue(CelByteString)} instead.
*/
@Deprecated
public static CelConstant ofValue(ByteString value) {
CelByteString celByteString = CelByteString.of(value.toByteArray());
return ofValue(celByteString);
}

/**
* @deprecated Do not use. Duration is no longer built-in CEL type.
*/
@Deprecated
public static CelConstant ofValue(Duration value) {
return AutoOneOf_CelConstant.durationValue(value);
}

/**
* @deprecated Do not use. Timestamp is no longer built-in CEL type.
*/
@Deprecated
public static CelConstant ofValue(Timestamp value) {
return AutoOneOf_CelConstant.timestampValue(value);
}

/** Checks whether the provided Java object is a valid CelConstant value. */
public static boolean isConstantValue(Object value) {
return CONSTANT_CLASSES.contains(value.getClass());
Expand All@@ -163,26 +201,10 @@ public static CelConstant ofObjectValue(Object value) {
return ofValue((double) value);
} else if (value instanceof String) {
return ofValue((String) value);
} else if (value instanceof ByteString) {
return ofValue((ByteString) value);
} else if (value instanceof CelByteString) {
return ofValue((CelByteString) value);
}

throw new IllegalArgumentException("Value is not a CelConstant: " + value);
}

/**
* @deprecated Do not use. Duration is no longer built-in CEL type.
*/
@Deprecated
public static CelConstant ofValue(Duration value) {
return AutoOneOf_CelConstant.durationValue(value);
}

/**
* @deprecated Do not use. Timestamp is no longer built-in CEL type.
*/
@Deprecated
public static CelConstant ofValue(Timestamp value) {
return AutoOneOf_CelConstant.timestampValue(value);
}
}
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content
Merged
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
3 changes: 2 additions & 1 deletion bundle/src/test/java/dev/cel/bundle/BUILD.bazel
Original file line numberDiff line numberDiff line change
Expand Up@@ -41,6 +41,8 @@ java_library(
"//common/types:cel_proto_types",
"//common/types:message_type_provider",
"//common/types:type_providers",
"//common/values",
"//common/values:cel_byte_string",
"//compiler",
"//compiler:compiler_builder",
"//extensions",
Expand All@@ -64,7 +66,6 @@ java_library(
"@maven//:com_google_truth_extensions_truth_proto_extension",
"@maven//:junit_junit",
"@maven//:org_jspecify_jspecify",
"@maven_android//:com_google_protobuf_protobuf_javalite",
],
)

Expand Down
40 changes: 35 additions & 5 deletions bundle/src/test/java/dev/cel/bundle/CelImplTest.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -48,7 +48,6 @@
import com.google.protobuf.Empty;
import com.google.protobuf.FieldMask;
import com.google.protobuf.Message;
import com.google.protobuf.NullValue;
import com.google.protobuf.Struct;
import com.google.protobuf.TextFormat;
import com.google.protobuf.Timestamp;
Expand DownExpand Up@@ -86,6 +85,8 @@
import dev.cel.common.types.ProtoMessageTypeProvider;
import dev.cel.common.types.SimpleType;
import dev.cel.common.types.StructTypeReference;
import dev.cel.common.values.CelByteString;
import dev.cel.common.values.NullValue;
import dev.cel.compiler.CelCompiler;
import dev.cel.compiler.CelCompilerFactory;
import dev.cel.compiler.CelCompilerImpl;
Expand All@@ -108,6 +109,7 @@
import dev.cel.runtime.UnknownContext;
import dev.cel.testing.testdata.proto3.StandaloneGlobalEnum;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
Expand DownExpand Up@@ -1019,7 +1021,10 @@ public void program_enumTypeReferenceResolution(boolean resolveTypeDependencies)
Cel cel =
standardCelBuilderWithMacros()
.setOptions(
CelOptions.current().resolveTypeDependencies(resolveTypeDependencies).build())
CelOptions.current()
.evaluateCanonicalTypesToNativeValues(true)
.resolveTypeDependencies(resolveTypeDependencies)
.build())
.addMessageTypes(Struct.getDescriptor())
.setResultType(StructTypeReference.create("google.protobuf.NullValue"))
.setContainer(CelContainer.ofName("google.protobuf"))
Expand All@@ -1037,7 +1042,11 @@ public void program_enumTypeReferenceResolution(boolean resolveTypeDependencies)
public void program_enumTypeTransitiveResolution() throws Exception {
Cel cel =
standardCelBuilderWithMacros()
.setOptions(CelOptions.current().resolveTypeDependencies(true).build())
.setOptions(
CelOptions.current()
.evaluateCanonicalTypesToNativeValues(true)
.resolveTypeDependencies(true)
.build())
.addMessageTypes(Proto2ExtensionScopedMessage.getDescriptor())
.setResultType(StructTypeReference.create("google.protobuf.NullValue"))
.setContainer(CelContainer.ofName("google.protobuf"))
Expand DownExpand Up@@ -1626,7 +1635,11 @@ public void programAdvanceEvaluation_indexOnUnknownContainer() throws Exception
public void programAdvanceEvaluation_unsupportedIndexIgnored() throws Exception {
Cel cel =
standardCelBuilderWithMacros()
.setOptions(CelOptions.current().enableUnknownTracking(true).build())
.setOptions(
CelOptions.current()
.evaluateCanonicalTypesToNativeValues(true)
.enableUnknownTracking(true)
.build())
.addVar("unk", MapType.create(SimpleType.STRING, SimpleType.BOOL))
.setContainer(CelContainer.ofName(""))
.addFunctionBindings()
Expand DownExpand Up@@ -1654,7 +1667,7 @@ public void programAdvanceEvaluation_unsupportedIndexIgnored() throws Exception
UnknownContext.create(
fromMap(
ImmutableMap.of(
"unk", ImmutableMap.of(ByteString.copyFromUtf8("a"), false))),
"unk", ImmutableMap.of(CelByteString.copyFromUtf8("a"), false))),
ImmutableList.of())))
.isEqualTo(false);
}
Expand DownExpand Up@@ -2077,6 +2090,23 @@ public void program_regexProgramSizeExceedsLimit_throws() throws Exception {
assertThat(e.getErrorCode()).isEqualTo(CelErrorCode.INVALID_ARGUMENT);
}

@Test
@SuppressWarnings("unchecked") // test only
public void program_evaluateCanonicalTypesToNativeTypesDisabled_producesProtoValues()
throws Exception {
Cel cel =
standardCelBuilderWithMacros()
.setOptions(CelOptions.current().evaluateCanonicalTypesToNativeValues(false).build())
.build();
CelAbstractSyntaxTree ast = cel.compile("[null, {b'abc': null}]").getAst();
Map<ByteString, Object> expectedNestedMap = new LinkedHashMap<>();
expectedNestedMap.put(ByteString.copyFromUtf8("abc"), com.google.protobuf.NullValue.NULL_VALUE);

List<Object> result = (List<Object>) cel.createProgram(ast).eval();

assertThat(result).containsExactly(com.google.protobuf.NullValue.NULL_VALUE, expectedNestedMap);
}

@Test
public void toBuilder_isImmutable() {
CelBuilder celBuilder = CelFactory.standardCelBuilder();
Expand Down
2 changes: 2 additions & 0 deletions common/src/main/java/dev/cel/common/BUILD.bazel
Original file line numberDiff line numberDiff line change
Expand Up@@ -206,6 +206,8 @@ java_library(
],
deps = [
"//common/internal:proto_time_utils",
"//common/values",
"//common/values:cel_byte_string",
"@maven//:com_google_errorprone_error_prone_annotations",
"@maven//:com_google_guava_guava",
"@maven//:com_google_protobuf_protobuf_java",
Expand Down
16 changes: 16 additions & 0 deletions common/src/main/java/dev/cel/common/CelOptions.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -109,6 +109,8 @@ public enum ProtoUnsetFieldOptions {

public abstract int comprehensionMaxIterations();

public abstract boolean evaluateCanonicalTypesToNativeValues();

public abstract boolean unwrapWellKnownTypesOnFunctionDispatch();

public abstract ProtoUnsetFieldOptions fromProtoUnsetFieldOption();
Expand DownExpand Up@@ -150,6 +152,7 @@ public static Builder newBuilder() {
.enableNamespacedDeclarations(true)
// Evaluation options
.disableCelStandardEquality(true)
.evaluateCanonicalTypesToNativeValues(false)
.enableShortCircuiting(true)
.enableRegexPartialMatch(false)
.enableUnsignedComparisonAndArithmeticIsUnsigned(false)
Expand DownExpand Up@@ -450,6 +453,19 @@ public abstract static class Builder {
*/
public abstract Builder comprehensionMaxIterations(int value);

/**
* If set, canonical CEL types such as bytes and CEL null will return their native value
* equivalents instead of protobuf based values. Specifically:
*
* <ul>
* <li>Bytes: {@code dev.cel.common.values.CelByteString} instead of {@code
* com.google.protobuf.ByteString}.
* <li>CEL null: {@code dev.cel.common.values.NullValue} instead of {@code
* com.google.protobuf.NullValue}.
* </ul>
*/
public abstract Builder evaluateCanonicalTypesToNativeValues(boolean value);

/**
* If disabled, CEL runtime will no longer adapt the function dispatch results for protobuf's
* well known types to other types. This option is enabled by default.
Expand Down
8 changes: 4 additions & 4 deletions common/src/main/java/dev/cel/common/CelProtoJsonAdapter.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -18,7 +18,6 @@
import com.google.common.base.Joiner;
import com.google.common.primitives.UnsignedLong;
import com.google.errorprone.annotations.Immutable;
import com.google.protobuf.ByteString;
import com.google.protobuf.Duration;
import com.google.protobuf.Empty;
import com.google.protobuf.FieldMask;
Expand All@@ -28,6 +27,7 @@
import com.google.protobuf.Timestamp;
import com.google.protobuf.Value;
import dev.cel.common.internal.ProtoTimeUtils;
import dev.cel.common.values.CelByteString;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
Expand DownExpand Up@@ -71,7 +71,7 @@ public static <K extends String, V> Struct adaptToJsonStructValue(Map<K, V> map)
@SuppressWarnings("unchecked")
public static Value adaptValueToJsonValue(Object value) {
Value.Builder json = Value.newBuilder();
if (value == null || value instanceof NullValue) {
if (value == null || value instanceof dev.cel.common.values.NullValue) {
return json.setNullValue(NullValue.NULL_VALUE).build();
}
if (value instanceof Boolean) {
Expand All@@ -93,9 +93,9 @@ public static Value adaptValueToJsonValue(Object value) {
if (value instanceof Float || value instanceof Double) {
return json.setNumberValue(((Number) value).doubleValue()).build();
}
if (value instanceof ByteString) {
if (value instanceof CelByteString) {
return json.setStringValue(
Base64.getEncoder().encodeToString(((ByteString) value).toByteArray()))
Base64.getEncoder().encodeToString(((CelByteString) value).toByteArray()))
.build();
}
if (value instanceof String) {
Expand Down
15 changes: 14 additions & 1 deletion common/src/main/java/dev/cel/common/ast/BUILD.bazel
Original file line numberDiff line numberDiff line change
Expand Up@@ -49,6 +49,8 @@ java_library(
deps = [
"//:auto_value",
"//common/annotations",
"//common/values",
"//common/values:cel_byte_string",
"@maven//:com_google_errorprone_error_prone_annotations",
"@maven//:com_google_guava_guava",
"@maven//:com_google_protobuf_protobuf_java",
Expand All@@ -62,9 +64,12 @@ java_library(
],
deps = [
":ast",
"//common/values",
"//common/values:cel_byte_string",
"@cel_spec//proto/cel/expr:checked_java_proto",
"@cel_spec//proto/cel/expr:syntax_java_proto",
"@maven//:com_google_guava_guava",
"@maven//:com_google_protobuf_protobuf_java",
],
)

Expand All@@ -75,9 +80,12 @@ cel_android_library(
],
deps = [
":ast_android",
"//common/values:cel_byte_string",
"//common/values:values_android",
"@cel_spec//proto/cel/expr:checked_java_proto_lite",
"@cel_spec//proto/cel/expr:syntax_java_proto_lite",
"@maven_android//:com_google_guava_guava",
"@maven_android//:com_google_protobuf_protobuf_javalite",
],
)

Expand All@@ -88,8 +96,11 @@ java_library(
],
deps = [
":ast",
"//common/values",
"//common/values:cel_byte_string",
"@com_google_googleapis//google/api/expr/v1alpha1:expr_java_proto",
"@maven//:com_google_guava_guava",
"@maven//:com_google_protobuf_protobuf_java",
],
)

Expand All@@ -112,8 +123,8 @@ java_library(
deps = [
":ast",
"//common/annotations",
"//common/values:cel_byte_string",
"@maven//:com_google_guava_guava",
"@maven//:com_google_protobuf_protobuf_java",
],
)

Expand All@@ -136,6 +147,8 @@ cel_android_library(
deps = [
"//:auto_value",
"//common/annotations",
"//common/values:cel_byte_string",
"//common/values:values_android",
"@maven//:com_google_errorprone_error_prone_annotations",
"@maven_android//:com_google_guava_guava",
"@maven_android//:com_google_protobuf_protobuf_javalite",
Expand Down
66 changes: 44 additions & 22 deletions common/src/main/java/dev/cel/common/ast/CelConstant.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -19,11 +19,13 @@
import com.google.common.collect.ImmutableSet;
import com.google.common.primitives.UnsignedLong;
import com.google.errorprone.annotations.Immutable;
import com.google.errorprone.annotations.InlineMe;
import com.google.protobuf.ByteString;
import com.google.protobuf.Duration;
import com.google.protobuf.NullValue;
import com.google.protobuf.Timestamp;
import dev.cel.common.annotations.Internal;
import dev.cel.common.values.CelByteString;
import dev.cel.common.values.NullValue;

/**
* Represents a primitive literal.
Expand All@@ -42,7 +44,7 @@ public abstract class CelConstant {
UnsignedLong.class,
Double.class,
String.class,
ByteString.class);
CelByteString.class);

/** Represents the type of the Constant */
public enum Kind {
Expand DownExpand Up@@ -92,7 +94,7 @@ public abstract static class CelConstantNotSet {}

public abstract String stringValue();

public abstract ByteString bytesValue();
public abstract CelByteString bytesValue();

/**
* @deprecated Do not use. Timestamp is no longer built-in CEL type.
Expand DownExpand Up@@ -134,10 +136,46 @@ public static CelConstant ofValue(String value) {
return AutoOneOf_CelConstant.stringValue(value);
}

public static CelConstant ofValue(ByteString value) {
public static CelConstant ofValue(CelByteString value) {
return AutoOneOf_CelConstant.bytesValue(value);
}

/**
* @deprecated Use native type equivalent {@link #ofValue(NullValue)} instead.
*/
@InlineMe(
replacement = "CelConstant.ofValue(NullValue.NULL_VALUE)",
imports = {"dev.cel.common.ast.CelConstant", "dev.cel.common.values.NullValue"})
@Deprecated
public static CelConstant ofValue(com.google.protobuf.NullValue unused) {
return ofValue(NullValue.NULL_VALUE);
}

/**
* @deprecated Use native type equivalent {@link #ofValue(CelByteString)} instead.
*/
@Deprecated
public static CelConstant ofValue(ByteString value) {
CelByteString celByteString = CelByteString.of(value.toByteArray());
return ofValue(celByteString);
}

/**
* @deprecated Do not use. Duration is no longer built-in CEL type.
*/
@Deprecated
public static CelConstant ofValue(Duration value) {
return AutoOneOf_CelConstant.durationValue(value);
}

/**
* @deprecated Do not use. Timestamp is no longer built-in CEL type.
*/
@Deprecated
public static CelConstant ofValue(Timestamp value) {
return AutoOneOf_CelConstant.timestampValue(value);
}

/** Checks whether the provided Java object is a valid CelConstant value. */
public static boolean isConstantValue(Object value) {
return CONSTANT_CLASSES.contains(value.getClass());
Expand All@@ -163,26 +201,10 @@ public static CelConstant ofObjectValue(Object value) {
return ofValue((double) value);
} else if (value instanceof String) {
return ofValue((String) value);
} else if (value instanceof ByteString) {
return ofValue((ByteString) value);
} else if (value instanceof CelByteString) {
return ofValue((CelByteString) value);
}

throw new IllegalArgumentException("Value is not a CelConstant: " + value);
}

/**
* @deprecated Do not use. Duration is no longer built-in CEL type.
*/
@Deprecated
public static CelConstant ofValue(Duration value) {
return AutoOneOf_CelConstant.durationValue(value);
}

/**
* @deprecated Do not use. Timestamp is no longer built-in CEL type.
*/
@Deprecated
public static CelConstant ofValue(Timestamp value) {
return AutoOneOf_CelConstant.timestampValue(value);
}
}
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
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
3 changes: 2 additions & 1 deletion bundle/src/test/java/dev/cel/bundle/BUILD.bazel
Original file line numberDiff line numberDiff line change
Expand Up@@ -41,6 +41,8 @@ java_library(
"//common/types:cel_proto_types",
"//common/types:message_type_provider",
"//common/types:type_providers",
"//common/values",
"//common/values:cel_byte_string",
"//compiler",
"//compiler:compiler_builder",
"//extensions",
Expand All@@ -64,7 +66,6 @@ java_library(
"@maven//:com_google_truth_extensions_truth_proto_extension",
"@maven//:junit_junit",
"@maven//:org_jspecify_jspecify",
"@maven_android//:com_google_protobuf_protobuf_javalite",
],
)

Expand Down
40 changes: 35 additions & 5 deletions bundle/src/test/java/dev/cel/bundle/CelImplTest.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -48,7 +48,6 @@
import com.google.protobuf.Empty;
import com.google.protobuf.FieldMask;
import com.google.protobuf.Message;
import com.google.protobuf.NullValue;
import com.google.protobuf.Struct;
import com.google.protobuf.TextFormat;
import com.google.protobuf.Timestamp;
Expand DownExpand Up@@ -86,6 +85,8 @@
import dev.cel.common.types.ProtoMessageTypeProvider;
import dev.cel.common.types.SimpleType;
import dev.cel.common.types.StructTypeReference;
import dev.cel.common.values.CelByteString;
import dev.cel.common.values.NullValue;
import dev.cel.compiler.CelCompiler;
import dev.cel.compiler.CelCompilerFactory;
import dev.cel.compiler.CelCompilerImpl;
Expand All@@ -108,6 +109,7 @@
import dev.cel.runtime.UnknownContext;
import dev.cel.testing.testdata.proto3.StandaloneGlobalEnum;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
Expand DownExpand Up@@ -1019,7 +1021,10 @@ public void program_enumTypeReferenceResolution(boolean resolveTypeDependencies)
Cel cel =
standardCelBuilderWithMacros()
.setOptions(
CelOptions.current().resolveTypeDependencies(resolveTypeDependencies).build())
CelOptions.current()
.evaluateCanonicalTypesToNativeValues(true)
.resolveTypeDependencies(resolveTypeDependencies)
.build())
.addMessageTypes(Struct.getDescriptor())
.setResultType(StructTypeReference.create("google.protobuf.NullValue"))
.setContainer(CelContainer.ofName("google.protobuf"))
Expand All@@ -1037,7 +1042,11 @@ public void program_enumTypeReferenceResolution(boolean resolveTypeDependencies)
public void program_enumTypeTransitiveResolution() throws Exception {
Cel cel =
standardCelBuilderWithMacros()
.setOptions(CelOptions.current().resolveTypeDependencies(true).build())
.setOptions(
CelOptions.current()
.evaluateCanonicalTypesToNativeValues(true)
.resolveTypeDependencies(true)
.build())
.addMessageTypes(Proto2ExtensionScopedMessage.getDescriptor())
.setResultType(StructTypeReference.create("google.protobuf.NullValue"))
.setContainer(CelContainer.ofName("google.protobuf"))
Expand DownExpand Up@@ -1626,7 +1635,11 @@ public void programAdvanceEvaluation_indexOnUnknownContainer() throws Exception
public void programAdvanceEvaluation_unsupportedIndexIgnored() throws Exception {
Cel cel =
standardCelBuilderWithMacros()
.setOptions(CelOptions.current().enableUnknownTracking(true).build())
.setOptions(
CelOptions.current()
.evaluateCanonicalTypesToNativeValues(true)
.enableUnknownTracking(true)
.build())
.addVar("unk", MapType.create(SimpleType.STRING, SimpleType.BOOL))
.setContainer(CelContainer.ofName(""))
.addFunctionBindings()
Expand DownExpand Up@@ -1654,7 +1667,7 @@ public void programAdvanceEvaluation_unsupportedIndexIgnored() throws Exception
UnknownContext.create(
fromMap(
ImmutableMap.of(
"unk", ImmutableMap.of(ByteString.copyFromUtf8("a"), false))),
"unk", ImmutableMap.of(CelByteString.copyFromUtf8("a"), false))),
ImmutableList.of())))
.isEqualTo(false);
}
Expand DownExpand Up@@ -2077,6 +2090,23 @@ public void program_regexProgramSizeExceedsLimit_throws() throws Exception {
assertThat(e.getErrorCode()).isEqualTo(CelErrorCode.INVALID_ARGUMENT);
}

@Test
@SuppressWarnings("unchecked") // test only
public void program_evaluateCanonicalTypesToNativeTypesDisabled_producesProtoValues()
throws Exception {
Cel cel =
standardCelBuilderWithMacros()
.setOptions(CelOptions.current().evaluateCanonicalTypesToNativeValues(false).build())
.build();
CelAbstractSyntaxTree ast = cel.compile("[null, {b'abc': null}]").getAst();
Map<ByteString, Object> expectedNestedMap = new LinkedHashMap<>();
expectedNestedMap.put(ByteString.copyFromUtf8("abc"), com.google.protobuf.NullValue.NULL_VALUE);

List<Object> result = (List<Object>) cel.createProgram(ast).eval();

assertThat(result).containsExactly(com.google.protobuf.NullValue.NULL_VALUE, expectedNestedMap);
}

@Test
public void toBuilder_isImmutable() {
CelBuilder celBuilder = CelFactory.standardCelBuilder();
Expand Down
2 changes: 2 additions & 0 deletions common/src/main/java/dev/cel/common/BUILD.bazel
Original file line numberDiff line numberDiff line change
Expand Up@@ -206,6 +206,8 @@ java_library(
],
deps = [
"//common/internal:proto_time_utils",
"//common/values",
"//common/values:cel_byte_string",
"@maven//:com_google_errorprone_error_prone_annotations",
"@maven//:com_google_guava_guava",
"@maven//:com_google_protobuf_protobuf_java",
Expand Down
16 changes: 16 additions & 0 deletions common/src/main/java/dev/cel/common/CelOptions.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -109,6 +109,8 @@ public enum ProtoUnsetFieldOptions {

public abstract int comprehensionMaxIterations();

public abstract boolean evaluateCanonicalTypesToNativeValues();

public abstract boolean unwrapWellKnownTypesOnFunctionDispatch();

public abstract ProtoUnsetFieldOptions fromProtoUnsetFieldOption();
Expand DownExpand Up@@ -150,6 +152,7 @@ public static Builder newBuilder() {
.enableNamespacedDeclarations(true)
// Evaluation options
.disableCelStandardEquality(true)
.evaluateCanonicalTypesToNativeValues(false)
.enableShortCircuiting(true)
.enableRegexPartialMatch(false)
.enableUnsignedComparisonAndArithmeticIsUnsigned(false)
Expand DownExpand Up@@ -450,6 +453,19 @@ public abstract static class Builder {
*/
public abstract Builder comprehensionMaxIterations(int value);

/**
* If set, canonical CEL types such as bytes and CEL null will return their native value
* equivalents instead of protobuf based values. Specifically:
*
* <ul>
* <li>Bytes: {@code dev.cel.common.values.CelByteString} instead of {@code
* com.google.protobuf.ByteString}.
* <li>CEL null: {@code dev.cel.common.values.NullValue} instead of {@code
* com.google.protobuf.NullValue}.
* </ul>
*/
public abstract Builder evaluateCanonicalTypesToNativeValues(boolean value);

/**
* If disabled, CEL runtime will no longer adapt the function dispatch results for protobuf's
* well known types to other types. This option is enabled by default.
Expand Down
8 changes: 4 additions & 4 deletions common/src/main/java/dev/cel/common/CelProtoJsonAdapter.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -18,7 +18,6 @@
import com.google.common.base.Joiner;
import com.google.common.primitives.UnsignedLong;
import com.google.errorprone.annotations.Immutable;
import com.google.protobuf.ByteString;
import com.google.protobuf.Duration;
import com.google.protobuf.Empty;
import com.google.protobuf.FieldMask;
Expand All@@ -28,6 +27,7 @@
import com.google.protobuf.Timestamp;
import com.google.protobuf.Value;
import dev.cel.common.internal.ProtoTimeUtils;
import dev.cel.common.values.CelByteString;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
Expand DownExpand Up@@ -71,7 +71,7 @@ public static <K extends String, V> Struct adaptToJsonStructValue(Map<K, V> map)
@SuppressWarnings("unchecked")
public static Value adaptValueToJsonValue(Object value) {
Value.Builder json = Value.newBuilder();
if (value == null || value instanceof NullValue) {
if (value == null || value instanceof dev.cel.common.values.NullValue) {
return json.setNullValue(NullValue.NULL_VALUE).build();
}
if (value instanceof Boolean) {
Expand All@@ -93,9 +93,9 @@ public static Value adaptValueToJsonValue(Object value) {
if (value instanceof Float || value instanceof Double) {
return json.setNumberValue(((Number) value).doubleValue()).build();
}
if (value instanceof ByteString) {
if (value instanceof CelByteString) {
return json.setStringValue(
Base64.getEncoder().encodeToString(((ByteString) value).toByteArray()))
Base64.getEncoder().encodeToString(((CelByteString) value).toByteArray()))
.build();
}
if (value instanceof String) {
Expand Down
15 changes: 14 additions & 1 deletion common/src/main/java/dev/cel/common/ast/BUILD.bazel
Original file line numberDiff line numberDiff line change
Expand Up@@ -49,6 +49,8 @@ java_library(
deps = [
"//:auto_value",
"//common/annotations",
"//common/values",
"//common/values:cel_byte_string",
"@maven//:com_google_errorprone_error_prone_annotations",
"@maven//:com_google_guava_guava",
"@maven//:com_google_protobuf_protobuf_java",
Expand All@@ -62,9 +64,12 @@ java_library(
],
deps = [
":ast",
"//common/values",
"//common/values:cel_byte_string",
"@cel_spec//proto/cel/expr:checked_java_proto",
"@cel_spec//proto/cel/expr:syntax_java_proto",
"@maven//:com_google_guava_guava",
"@maven//:com_google_protobuf_protobuf_java",
],
)

Expand All@@ -75,9 +80,12 @@ cel_android_library(
],
deps = [
":ast_android",
"//common/values:cel_byte_string",
"//common/values:values_android",
"@cel_spec//proto/cel/expr:checked_java_proto_lite",
"@cel_spec//proto/cel/expr:syntax_java_proto_lite",
"@maven_android//:com_google_guava_guava",
"@maven_android//:com_google_protobuf_protobuf_javalite",
],
)

Expand All@@ -88,8 +96,11 @@ java_library(
],
deps = [
":ast",
"//common/values",
"//common/values:cel_byte_string",
"@com_google_googleapis//google/api/expr/v1alpha1:expr_java_proto",
"@maven//:com_google_guava_guava",
"@maven//:com_google_protobuf_protobuf_java",
],
)

Expand All@@ -112,8 +123,8 @@ java_library(
deps = [
":ast",
"//common/annotations",
"//common/values:cel_byte_string",
"@maven//:com_google_guava_guava",
"@maven//:com_google_protobuf_protobuf_java",
],
)

Expand All@@ -136,6 +147,8 @@ cel_android_library(
deps = [
"//:auto_value",
"//common/annotations",
"//common/values:cel_byte_string",
"//common/values:values_android",
"@maven//:com_google_errorprone_error_prone_annotations",
"@maven_android//:com_google_guava_guava",
"@maven_android//:com_google_protobuf_protobuf_javalite",
Expand Down
66 changes: 44 additions & 22 deletions common/src/main/java/dev/cel/common/ast/CelConstant.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -19,11 +19,13 @@
import com.google.common.collect.ImmutableSet;
import com.google.common.primitives.UnsignedLong;
import com.google.errorprone.annotations.Immutable;
import com.google.errorprone.annotations.InlineMe;
import com.google.protobuf.ByteString;
import com.google.protobuf.Duration;
import com.google.protobuf.NullValue;
import com.google.protobuf.Timestamp;
import dev.cel.common.annotations.Internal;
import dev.cel.common.values.CelByteString;
import dev.cel.common.values.NullValue;

/**
* Represents a primitive literal.
Expand All@@ -42,7 +44,7 @@ public abstract class CelConstant {
UnsignedLong.class,
Double.class,
String.class,
ByteString.class);
CelByteString.class);

/** Represents the type of the Constant */
public enum Kind {
Expand DownExpand Up@@ -92,7 +94,7 @@ public abstract static class CelConstantNotSet {}

public abstract String stringValue();

public abstract ByteString bytesValue();
public abstract CelByteString bytesValue();

/**
* @deprecated Do not use. Timestamp is no longer built-in CEL type.
Expand DownExpand Up@@ -134,10 +136,46 @@ public static CelConstant ofValue(String value) {
return AutoOneOf_CelConstant.stringValue(value);
}

public static CelConstant ofValue(ByteString value) {
public static CelConstant ofValue(CelByteString value) {
return AutoOneOf_CelConstant.bytesValue(value);
}

/**
* @deprecated Use native type equivalent {@link #ofValue(NullValue)} instead.
*/
@InlineMe(
replacement = "CelConstant.ofValue(NullValue.NULL_VALUE)",
imports = {"dev.cel.common.ast.CelConstant", "dev.cel.common.values.NullValue"})
@Deprecated
public static CelConstant ofValue(com.google.protobuf.NullValue unused) {
return ofValue(NullValue.NULL_VALUE);
}

/**
* @deprecated Use native type equivalent {@link #ofValue(CelByteString)} instead.
*/
@Deprecated
public static CelConstant ofValue(ByteString value) {
CelByteString celByteString = CelByteString.of(value.toByteArray());
return ofValue(celByteString);
}

/**
* @deprecated Do not use. Duration is no longer built-in CEL type.
*/
@Deprecated
public static CelConstant ofValue(Duration value) {
return AutoOneOf_CelConstant.durationValue(value);
}

/**
* @deprecated Do not use. Timestamp is no longer built-in CEL type.
*/
@Deprecated
public static CelConstant ofValue(Timestamp value) {
return AutoOneOf_CelConstant.timestampValue(value);
}

/** Checks whether the provided Java object is a valid CelConstant value. */
public static boolean isConstantValue(Object value) {
return CONSTANT_CLASSES.contains(value.getClass());
Expand All@@ -163,26 +201,10 @@ public static CelConstant ofObjectValue(Object value) {
return ofValue((double) value);
} else if (value instanceof String) {
return ofValue((String) value);
} else if (value instanceof ByteString) {
return ofValue((ByteString) value);
} else if (value instanceof CelByteString) {
return ofValue((CelByteString) value);
}

throw new IllegalArgumentException("Value is not a CelConstant: " + value);
}

/**
* @deprecated Do not use. Duration is no longer built-in CEL type.
*/
@Deprecated
public static CelConstant ofValue(Duration value) {
return AutoOneOf_CelConstant.durationValue(value);
}

/**
* @deprecated Do not use. Timestamp is no longer built-in CEL type.
*/
@Deprecated
public static CelConstant ofValue(Timestamp value) {
return AutoOneOf_CelConstant.timestampValue(value);
}
}
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
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
3 changes: 2 additions & 1 deletion bundle/src/test/java/dev/cel/bundle/BUILD.bazel
Original file line numberDiff line numberDiff line change
Expand Up@@ -41,6 +41,8 @@ java_library(
"//common/types:cel_proto_types",
"//common/types:message_type_provider",
"//common/types:type_providers",
"//common/values",
"//common/values:cel_byte_string",
"//compiler",
"//compiler:compiler_builder",
"//extensions",
Expand All@@ -64,7 +66,6 @@ java_library(
"@maven//:com_google_truth_extensions_truth_proto_extension",
"@maven//:junit_junit",
"@maven//:org_jspecify_jspecify",
"@maven_android//:com_google_protobuf_protobuf_javalite",
],
)

Expand Down
40 changes: 35 additions & 5 deletions bundle/src/test/java/dev/cel/bundle/CelImplTest.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -48,7 +48,6 @@
import com.google.protobuf.Empty;
import com.google.protobuf.FieldMask;
import com.google.protobuf.Message;
import com.google.protobuf.NullValue;
import com.google.protobuf.Struct;
import com.google.protobuf.TextFormat;
import com.google.protobuf.Timestamp;
Expand DownExpand Up@@ -86,6 +85,8 @@
import dev.cel.common.types.ProtoMessageTypeProvider;
import dev.cel.common.types.SimpleType;
import dev.cel.common.types.StructTypeReference;
import dev.cel.common.values.CelByteString;
import dev.cel.common.values.NullValue;
import dev.cel.compiler.CelCompiler;
import dev.cel.compiler.CelCompilerFactory;
import dev.cel.compiler.CelCompilerImpl;
Expand All@@ -108,6 +109,7 @@
import dev.cel.runtime.UnknownContext;
import dev.cel.testing.testdata.proto3.StandaloneGlobalEnum;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
Expand DownExpand Up@@ -1019,7 +1021,10 @@ public void program_enumTypeReferenceResolution(boolean resolveTypeDependencies)
Cel cel =
standardCelBuilderWithMacros()
.setOptions(
CelOptions.current().resolveTypeDependencies(resolveTypeDependencies).build())
CelOptions.current()
.evaluateCanonicalTypesToNativeValues(true)
.resolveTypeDependencies(resolveTypeDependencies)
.build())
.addMessageTypes(Struct.getDescriptor())
.setResultType(StructTypeReference.create("google.protobuf.NullValue"))
.setContainer(CelContainer.ofName("google.protobuf"))
Expand All@@ -1037,7 +1042,11 @@ public void program_enumTypeReferenceResolution(boolean resolveTypeDependencies)
public void program_enumTypeTransitiveResolution() throws Exception {
Cel cel =
standardCelBuilderWithMacros()
.setOptions(CelOptions.current().resolveTypeDependencies(true).build())
.setOptions(
CelOptions.current()
.evaluateCanonicalTypesToNativeValues(true)
.resolveTypeDependencies(true)
.build())
.addMessageTypes(Proto2ExtensionScopedMessage.getDescriptor())
.setResultType(StructTypeReference.create("google.protobuf.NullValue"))
.setContainer(CelContainer.ofName("google.protobuf"))
Expand DownExpand Up@@ -1626,7 +1635,11 @@ public void programAdvanceEvaluation_indexOnUnknownContainer() throws Exception
public void programAdvanceEvaluation_unsupportedIndexIgnored() throws Exception {
Cel cel =
standardCelBuilderWithMacros()
.setOptions(CelOptions.current().enableUnknownTracking(true).build())
.setOptions(
CelOptions.current()
.evaluateCanonicalTypesToNativeValues(true)
.enableUnknownTracking(true)
.build())
.addVar("unk", MapType.create(SimpleType.STRING, SimpleType.BOOL))
.setContainer(CelContainer.ofName(""))
.addFunctionBindings()
Expand DownExpand Up@@ -1654,7 +1667,7 @@ public void programAdvanceEvaluation_unsupportedIndexIgnored() throws Exception
UnknownContext.create(
fromMap(
ImmutableMap.of(
"unk", ImmutableMap.of(ByteString.copyFromUtf8("a"), false))),
"unk", ImmutableMap.of(CelByteString.copyFromUtf8("a"), false))),
ImmutableList.of())))
.isEqualTo(false);
}
Expand DownExpand Up@@ -2077,6 +2090,23 @@ public void program_regexProgramSizeExceedsLimit_throws() throws Exception {
assertThat(e.getErrorCode()).isEqualTo(CelErrorCode.INVALID_ARGUMENT);
}

@Test
@SuppressWarnings("unchecked") // test only
public void program_evaluateCanonicalTypesToNativeTypesDisabled_producesProtoValues()
throws Exception {
Cel cel =
standardCelBuilderWithMacros()
.setOptions(CelOptions.current().evaluateCanonicalTypesToNativeValues(false).build())
.build();
CelAbstractSyntaxTree ast = cel.compile("[null, {b'abc': null}]").getAst();
Map<ByteString, Object> expectedNestedMap = new LinkedHashMap<>();
expectedNestedMap.put(ByteString.copyFromUtf8("abc"), com.google.protobuf.NullValue.NULL_VALUE);

List<Object> result = (List<Object>) cel.createProgram(ast).eval();

assertThat(result).containsExactly(com.google.protobuf.NullValue.NULL_VALUE, expectedNestedMap);
}

@Test
public void toBuilder_isImmutable() {
CelBuilder celBuilder = CelFactory.standardCelBuilder();
Expand Down
2 changes: 2 additions & 0 deletions common/src/main/java/dev/cel/common/BUILD.bazel
Original file line numberDiff line numberDiff line change
Expand Up@@ -206,6 +206,8 @@ java_library(
],
deps = [
"//common/internal:proto_time_utils",
"//common/values",
"//common/values:cel_byte_string",
"@maven//:com_google_errorprone_error_prone_annotations",
"@maven//:com_google_guava_guava",
"@maven//:com_google_protobuf_protobuf_java",
Expand Down
16 changes: 16 additions & 0 deletions common/src/main/java/dev/cel/common/CelOptions.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -109,6 +109,8 @@ public enum ProtoUnsetFieldOptions {

public abstract int comprehensionMaxIterations();

public abstract boolean evaluateCanonicalTypesToNativeValues();

public abstract boolean unwrapWellKnownTypesOnFunctionDispatch();

public abstract ProtoUnsetFieldOptions fromProtoUnsetFieldOption();
Expand DownExpand Up@@ -150,6 +152,7 @@ public static Builder newBuilder() {
.enableNamespacedDeclarations(true)
// Evaluation options
.disableCelStandardEquality(true)
.evaluateCanonicalTypesToNativeValues(false)
.enableShortCircuiting(true)
.enableRegexPartialMatch(false)
.enableUnsignedComparisonAndArithmeticIsUnsigned(false)
Expand DownExpand Up@@ -450,6 +453,19 @@ public abstract static class Builder {
*/
public abstract Builder comprehensionMaxIterations(int value);

/**
* If set, canonical CEL types such as bytes and CEL null will return their native value
* equivalents instead of protobuf based values. Specifically:
*
* <ul>
* <li>Bytes: {@code dev.cel.common.values.CelByteString} instead of {@code
* com.google.protobuf.ByteString}.
* <li>CEL null: {@code dev.cel.common.values.NullValue} instead of {@code
* com.google.protobuf.NullValue}.
* </ul>
*/
public abstract Builder evaluateCanonicalTypesToNativeValues(boolean value);

/**
* If disabled, CEL runtime will no longer adapt the function dispatch results for protobuf's
* well known types to other types. This option is enabled by default.
Expand Down
8 changes: 4 additions & 4 deletions common/src/main/java/dev/cel/common/CelProtoJsonAdapter.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -18,7 +18,6 @@
import com.google.common.base.Joiner;
import com.google.common.primitives.UnsignedLong;
import com.google.errorprone.annotations.Immutable;
import com.google.protobuf.ByteString;
import com.google.protobuf.Duration;
import com.google.protobuf.Empty;
import com.google.protobuf.FieldMask;
Expand All@@ -28,6 +27,7 @@
import com.google.protobuf.Timestamp;
import com.google.protobuf.Value;
import dev.cel.common.internal.ProtoTimeUtils;
import dev.cel.common.values.CelByteString;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
Expand DownExpand Up@@ -71,7 +71,7 @@ public static <K extends String, V> Struct adaptToJsonStructValue(Map<K, V> map)
@SuppressWarnings("unchecked")
public static Value adaptValueToJsonValue(Object value) {
Value.Builder json = Value.newBuilder();
if (value == null || value instanceof NullValue) {
if (value == null || value instanceof dev.cel.common.values.NullValue) {
return json.setNullValue(NullValue.NULL_VALUE).build();
}
if (value instanceof Boolean) {
Expand All@@ -93,9 +93,9 @@ public static Value adaptValueToJsonValue(Object value) {
if (value instanceof Float || value instanceof Double) {
return json.setNumberValue(((Number) value).doubleValue()).build();
}
if (value instanceof ByteString) {
if (value instanceof CelByteString) {
return json.setStringValue(
Base64.getEncoder().encodeToString(((ByteString) value).toByteArray()))
Base64.getEncoder().encodeToString(((CelByteString) value).toByteArray()))
.build();
}
if (value instanceof String) {
Expand Down
15 changes: 14 additions & 1 deletion common/src/main/java/dev/cel/common/ast/BUILD.bazel
Original file line numberDiff line numberDiff line change
Expand Up@@ -49,6 +49,8 @@ java_library(
deps = [
"//:auto_value",
"//common/annotations",
"//common/values",
"//common/values:cel_byte_string",
"@maven//:com_google_errorprone_error_prone_annotations",
"@maven//:com_google_guava_guava",
"@maven//:com_google_protobuf_protobuf_java",
Expand All@@ -62,9 +64,12 @@ java_library(
],
deps = [
":ast",
"//common/values",
"//common/values:cel_byte_string",
"@cel_spec//proto/cel/expr:checked_java_proto",
"@cel_spec//proto/cel/expr:syntax_java_proto",
"@maven//:com_google_guava_guava",
"@maven//:com_google_protobuf_protobuf_java",
],
)

Expand All@@ -75,9 +80,12 @@ cel_android_library(
],
deps = [
":ast_android",
"//common/values:cel_byte_string",
"//common/values:values_android",
"@cel_spec//proto/cel/expr:checked_java_proto_lite",
"@cel_spec//proto/cel/expr:syntax_java_proto_lite",
"@maven_android//:com_google_guava_guava",
"@maven_android//:com_google_protobuf_protobuf_javalite",
],
)

Expand All@@ -88,8 +96,11 @@ java_library(
],
deps = [
":ast",
"//common/values",
"//common/values:cel_byte_string",
"@com_google_googleapis//google/api/expr/v1alpha1:expr_java_proto",
"@maven//:com_google_guava_guava",
"@maven//:com_google_protobuf_protobuf_java",
],
)

Expand All@@ -112,8 +123,8 @@ java_library(
deps = [
":ast",
"//common/annotations",
"//common/values:cel_byte_string",
"@maven//:com_google_guava_guava",
"@maven//:com_google_protobuf_protobuf_java",
],
)

Expand All@@ -136,6 +147,8 @@ cel_android_library(
deps = [
"//:auto_value",
"//common/annotations",
"//common/values:cel_byte_string",
"//common/values:values_android",
"@maven//:com_google_errorprone_error_prone_annotations",
"@maven_android//:com_google_guava_guava",
"@maven_android//:com_google_protobuf_protobuf_javalite",
Expand Down
66 changes: 44 additions & 22 deletions common/src/main/java/dev/cel/common/ast/CelConstant.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -19,11 +19,13 @@
import com.google.common.collect.ImmutableSet;
import com.google.common.primitives.UnsignedLong;
import com.google.errorprone.annotations.Immutable;
import com.google.errorprone.annotations.InlineMe;
import com.google.protobuf.ByteString;
import com.google.protobuf.Duration;
import com.google.protobuf.NullValue;
import com.google.protobuf.Timestamp;
import dev.cel.common.annotations.Internal;
import dev.cel.common.values.CelByteString;
import dev.cel.common.values.NullValue;

/**
* Represents a primitive literal.
Expand All@@ -42,7 +44,7 @@ public abstract class CelConstant {
UnsignedLong.class,
Double.class,
String.class,
ByteString.class);
CelByteString.class);

/** Represents the type of the Constant */
public enum Kind {
Expand DownExpand Up@@ -92,7 +94,7 @@ public abstract static class CelConstantNotSet {}

public abstract String stringValue();

public abstract ByteString bytesValue();
public abstract CelByteString bytesValue();

/**
* @deprecated Do not use. Timestamp is no longer built-in CEL type.
Expand DownExpand Up@@ -134,10 +136,46 @@ public static CelConstant ofValue(String value) {
return AutoOneOf_CelConstant.stringValue(value);
}

public static CelConstant ofValue(ByteString value) {
public static CelConstant ofValue(CelByteString value) {
return AutoOneOf_CelConstant.bytesValue(value);
}

/**
* @deprecated Use native type equivalent {@link #ofValue(NullValue)} instead.
*/
@InlineMe(
replacement = "CelConstant.ofValue(NullValue.NULL_VALUE)",
imports = {"dev.cel.common.ast.CelConstant", "dev.cel.common.values.NullValue"})
@Deprecated
public static CelConstant ofValue(com.google.protobuf.NullValue unused) {
return ofValue(NullValue.NULL_VALUE);
}

/**
* @deprecated Use native type equivalent {@link #ofValue(CelByteString)} instead.
*/
@Deprecated
public static CelConstant ofValue(ByteString value) {
CelByteString celByteString = CelByteString.of(value.toByteArray());
return ofValue(celByteString);
}

/**
* @deprecated Do not use. Duration is no longer built-in CEL type.
*/
@Deprecated
public static CelConstant ofValue(Duration value) {
return AutoOneOf_CelConstant.durationValue(value);
}

/**
* @deprecated Do not use. Timestamp is no longer built-in CEL type.
*/
@Deprecated
public static CelConstant ofValue(Timestamp value) {
return AutoOneOf_CelConstant.timestampValue(value);
}

/** Checks whether the provided Java object is a valid CelConstant value. */
public static boolean isConstantValue(Object value) {
return CONSTANT_CLASSES.contains(value.getClass());
Expand All@@ -163,26 +201,10 @@ public static CelConstant ofObjectValue(Object value) {
return ofValue((double) value);
} else if (value instanceof String) {
return ofValue((String) value);
} else if (value instanceof ByteString) {
return ofValue((ByteString) value);
} else if (value instanceof CelByteString) {
return ofValue((CelByteString) value);
}

throw new IllegalArgumentException("Value is not a CelConstant: " + value);
}

/**
* @deprecated Do not use. Duration is no longer built-in CEL type.
*/
@Deprecated
public static CelConstant ofValue(Duration value) {
return AutoOneOf_CelConstant.durationValue(value);
}

/**
* @deprecated Do not use. Timestamp is no longer built-in CEL type.
*/
@Deprecated
public static CelConstant ofValue(Timestamp value) {
return AutoOneOf_CelConstant.timestampValue(value);
}
}
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content
Merged
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
3 changes: 2 additions & 1 deletion bundle/src/test/java/dev/cel/bundle/BUILD.bazel
Original file line numberDiff line numberDiff line change
Expand Up@@ -41,6 +41,8 @@ java_library(
"//common/types:cel_proto_types",
"//common/types:message_type_provider",
"//common/types:type_providers",
"//common/values",
"//common/values:cel_byte_string",
"//compiler",
"//compiler:compiler_builder",
"//extensions",
Expand All@@ -64,7 +66,6 @@ java_library(
"@maven//:com_google_truth_extensions_truth_proto_extension",
"@maven//:junit_junit",
"@maven//:org_jspecify_jspecify",
"@maven_android//:com_google_protobuf_protobuf_javalite",
],
)

Expand Down
40 changes: 35 additions & 5 deletions bundle/src/test/java/dev/cel/bundle/CelImplTest.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -48,7 +48,6 @@
import com.google.protobuf.Empty;
import com.google.protobuf.FieldMask;
import com.google.protobuf.Message;
import com.google.protobuf.NullValue;
import com.google.protobuf.Struct;
import com.google.protobuf.TextFormat;
import com.google.protobuf.Timestamp;
Expand DownExpand Up@@ -86,6 +85,8 @@
import dev.cel.common.types.ProtoMessageTypeProvider;
import dev.cel.common.types.SimpleType;
import dev.cel.common.types.StructTypeReference;
import dev.cel.common.values.CelByteString;
import dev.cel.common.values.NullValue;
import dev.cel.compiler.CelCompiler;
import dev.cel.compiler.CelCompilerFactory;
import dev.cel.compiler.CelCompilerImpl;
Expand All@@ -108,6 +109,7 @@
import dev.cel.runtime.UnknownContext;
import dev.cel.testing.testdata.proto3.StandaloneGlobalEnum;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
Expand DownExpand Up@@ -1019,7 +1021,10 @@ public void program_enumTypeReferenceResolution(boolean resolveTypeDependencies)
Cel cel =
standardCelBuilderWithMacros()
.setOptions(
CelOptions.current().resolveTypeDependencies(resolveTypeDependencies).build())
CelOptions.current()
.evaluateCanonicalTypesToNativeValues(true)
.resolveTypeDependencies(resolveTypeDependencies)
.build())
.addMessageTypes(Struct.getDescriptor())
.setResultType(StructTypeReference.create("google.protobuf.NullValue"))
.setContainer(CelContainer.ofName("google.protobuf"))
Expand All@@ -1037,7 +1042,11 @@ public void program_enumTypeReferenceResolution(boolean resolveTypeDependencies)
public void program_enumTypeTransitiveResolution() throws Exception {
Cel cel =
standardCelBuilderWithMacros()
.setOptions(CelOptions.current().resolveTypeDependencies(true).build())
.setOptions(
CelOptions.current()
.evaluateCanonicalTypesToNativeValues(true)
.resolveTypeDependencies(true)
.build())
.addMessageTypes(Proto2ExtensionScopedMessage.getDescriptor())
.setResultType(StructTypeReference.create("google.protobuf.NullValue"))
.setContainer(CelContainer.ofName("google.protobuf"))
Expand DownExpand Up@@ -1626,7 +1635,11 @@ public void programAdvanceEvaluation_indexOnUnknownContainer() throws Exception
public void programAdvanceEvaluation_unsupportedIndexIgnored() throws Exception {
Cel cel =
standardCelBuilderWithMacros()
.setOptions(CelOptions.current().enableUnknownTracking(true).build())
.setOptions(
CelOptions.current()
.evaluateCanonicalTypesToNativeValues(true)
.enableUnknownTracking(true)
.build())
.addVar("unk", MapType.create(SimpleType.STRING, SimpleType.BOOL))
.setContainer(CelContainer.ofName(""))
.addFunctionBindings()
Expand DownExpand Up@@ -1654,7 +1667,7 @@ public void programAdvanceEvaluation_unsupportedIndexIgnored() throws Exception
UnknownContext.create(
fromMap(
ImmutableMap.of(
"unk", ImmutableMap.of(ByteString.copyFromUtf8("a"), false))),
"unk", ImmutableMap.of(CelByteString.copyFromUtf8("a"), false))),
ImmutableList.of())))
.isEqualTo(false);
}
Expand DownExpand Up@@ -2077,6 +2090,23 @@ public void program_regexProgramSizeExceedsLimit_throws() throws Exception {
assertThat(e.getErrorCode()).isEqualTo(CelErrorCode.INVALID_ARGUMENT);
}

@Test
@SuppressWarnings("unchecked") // test only
public void program_evaluateCanonicalTypesToNativeTypesDisabled_producesProtoValues()
throws Exception {
Cel cel =
standardCelBuilderWithMacros()
.setOptions(CelOptions.current().evaluateCanonicalTypesToNativeValues(false).build())
.build();
CelAbstractSyntaxTree ast = cel.compile("[null, {b'abc': null}]").getAst();
Map<ByteString, Object> expectedNestedMap = new LinkedHashMap<>();
expectedNestedMap.put(ByteString.copyFromUtf8("abc"), com.google.protobuf.NullValue.NULL_VALUE);

List<Object> result = (List<Object>) cel.createProgram(ast).eval();

assertThat(result).containsExactly(com.google.protobuf.NullValue.NULL_VALUE, expectedNestedMap);
}

@Test
public void toBuilder_isImmutable() {
CelBuilder celBuilder = CelFactory.standardCelBuilder();
Expand Down
2 changes: 2 additions & 0 deletions common/src/main/java/dev/cel/common/BUILD.bazel
Original file line numberDiff line numberDiff line change
Expand Up@@ -206,6 +206,8 @@ java_library(
],
deps = [
"//common/internal:proto_time_utils",
"//common/values",
"//common/values:cel_byte_string",
"@maven//:com_google_errorprone_error_prone_annotations",
"@maven//:com_google_guava_guava",
"@maven//:com_google_protobuf_protobuf_java",
Expand Down
16 changes: 16 additions & 0 deletions common/src/main/java/dev/cel/common/CelOptions.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -109,6 +109,8 @@ public enum ProtoUnsetFieldOptions {

public abstract int comprehensionMaxIterations();

public abstract boolean evaluateCanonicalTypesToNativeValues();

public abstract boolean unwrapWellKnownTypesOnFunctionDispatch();

public abstract ProtoUnsetFieldOptions fromProtoUnsetFieldOption();
Expand DownExpand Up@@ -150,6 +152,7 @@ public static Builder newBuilder() {
.enableNamespacedDeclarations(true)
// Evaluation options
.disableCelStandardEquality(true)
.evaluateCanonicalTypesToNativeValues(false)
.enableShortCircuiting(true)
.enableRegexPartialMatch(false)
.enableUnsignedComparisonAndArithmeticIsUnsigned(false)
Expand DownExpand Up@@ -450,6 +453,19 @@ public abstract static class Builder {
*/
public abstract Builder comprehensionMaxIterations(int value);

/**
* If set, canonical CEL types such as bytes and CEL null will return their native value
* equivalents instead of protobuf based values. Specifically:
*
* <ul>
* <li>Bytes: {@code dev.cel.common.values.CelByteString} instead of {@code
* com.google.protobuf.ByteString}.
* <li>CEL null: {@code dev.cel.common.values.NullValue} instead of {@code
* com.google.protobuf.NullValue}.
* </ul>
*/
public abstract Builder evaluateCanonicalTypesToNativeValues(boolean value);

/**
* If disabled, CEL runtime will no longer adapt the function dispatch results for protobuf's
* well known types to other types. This option is enabled by default.
Expand Down
8 changes: 4 additions & 4 deletions common/src/main/java/dev/cel/common/CelProtoJsonAdapter.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -18,7 +18,6 @@
import com.google.common.base.Joiner;
import com.google.common.primitives.UnsignedLong;
import com.google.errorprone.annotations.Immutable;
import com.google.protobuf.ByteString;
import com.google.protobuf.Duration;
import com.google.protobuf.Empty;
import com.google.protobuf.FieldMask;
Expand All@@ -28,6 +27,7 @@
import com.google.protobuf.Timestamp;
import com.google.protobuf.Value;
import dev.cel.common.internal.ProtoTimeUtils;
import dev.cel.common.values.CelByteString;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
Expand DownExpand Up@@ -71,7 +71,7 @@ public static <K extends String, V> Struct adaptToJsonStructValue(Map<K, V> map)
@SuppressWarnings("unchecked")
public static Value adaptValueToJsonValue(Object value) {
Value.Builder json = Value.newBuilder();
if (value == null || value instanceof NullValue) {
if (value == null || value instanceof dev.cel.common.values.NullValue) {
return json.setNullValue(NullValue.NULL_VALUE).build();
}
if (value instanceof Boolean) {
Expand All@@ -93,9 +93,9 @@ public static Value adaptValueToJsonValue(Object value) {
if (value instanceof Float || value instanceof Double) {
return json.setNumberValue(((Number) value).doubleValue()).build();
}
if (value instanceof ByteString) {
if (value instanceof CelByteString) {
return json.setStringValue(
Base64.getEncoder().encodeToString(((ByteString) value).toByteArray()))
Base64.getEncoder().encodeToString(((CelByteString) value).toByteArray()))
.build();
}
if (value instanceof String) {
Expand Down
15 changes: 14 additions & 1 deletion common/src/main/java/dev/cel/common/ast/BUILD.bazel
Original file line numberDiff line numberDiff line change
Expand Up@@ -49,6 +49,8 @@ java_library(
deps = [
"//:auto_value",
"//common/annotations",
"//common/values",
"//common/values:cel_byte_string",
"@maven//:com_google_errorprone_error_prone_annotations",
"@maven//:com_google_guava_guava",
"@maven//:com_google_protobuf_protobuf_java",
Expand All@@ -62,9 +64,12 @@ java_library(
],
deps = [
":ast",
"//common/values",
"//common/values:cel_byte_string",
"@cel_spec//proto/cel/expr:checked_java_proto",
"@cel_spec//proto/cel/expr:syntax_java_proto",
"@maven//:com_google_guava_guava",
"@maven//:com_google_protobuf_protobuf_java",
],
)

Expand All@@ -75,9 +80,12 @@ cel_android_library(
],
deps = [
":ast_android",
"//common/values:cel_byte_string",
"//common/values:values_android",
"@cel_spec//proto/cel/expr:checked_java_proto_lite",
"@cel_spec//proto/cel/expr:syntax_java_proto_lite",
"@maven_android//:com_google_guava_guava",
"@maven_android//:com_google_protobuf_protobuf_javalite",
],
)

Expand All@@ -88,8 +96,11 @@ java_library(
],
deps = [
":ast",
"//common/values",
"//common/values:cel_byte_string",
"@com_google_googleapis//google/api/expr/v1alpha1:expr_java_proto",
"@maven//:com_google_guava_guava",
"@maven//:com_google_protobuf_protobuf_java",
],
)

Expand All@@ -112,8 +123,8 @@ java_library(
deps = [
":ast",
"//common/annotations",
"//common/values:cel_byte_string",
"@maven//:com_google_guava_guava",
"@maven//:com_google_protobuf_protobuf_java",
],
)

Expand All@@ -136,6 +147,8 @@ cel_android_library(
deps = [
"//:auto_value",
"//common/annotations",
"//common/values:cel_byte_string",
"//common/values:values_android",
"@maven//:com_google_errorprone_error_prone_annotations",
"@maven_android//:com_google_guava_guava",
"@maven_android//:com_google_protobuf_protobuf_javalite",
Expand Down
66 changes: 44 additions & 22 deletions common/src/main/java/dev/cel/common/ast/CelConstant.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -19,11 +19,13 @@
import com.google.common.collect.ImmutableSet;
import com.google.common.primitives.UnsignedLong;
import com.google.errorprone.annotations.Immutable;
import com.google.errorprone.annotations.InlineMe;
import com.google.protobuf.ByteString;
import com.google.protobuf.Duration;
import com.google.protobuf.NullValue;
import com.google.protobuf.Timestamp;
import dev.cel.common.annotations.Internal;
import dev.cel.common.values.CelByteString;
import dev.cel.common.values.NullValue;

/**
* Represents a primitive literal.
Expand All@@ -42,7 +44,7 @@ public abstract class CelConstant {
UnsignedLong.class,
Double.class,
String.class,
ByteString.class);
CelByteString.class);

/** Represents the type of the Constant */
public enum Kind {
Expand DownExpand Up@@ -92,7 +94,7 @@ public abstract static class CelConstantNotSet {}

public abstract String stringValue();

public abstract ByteString bytesValue();
public abstract CelByteString bytesValue();

/**
* @deprecated Do not use. Timestamp is no longer built-in CEL type.
Expand DownExpand Up@@ -134,10 +136,46 @@ public static CelConstant ofValue(String value) {
return AutoOneOf_CelConstant.stringValue(value);
}

public static CelConstant ofValue(ByteString value) {
public static CelConstant ofValue(CelByteString value) {
return AutoOneOf_CelConstant.bytesValue(value);
}

/**
* @deprecated Use native type equivalent {@link #ofValue(NullValue)} instead.
*/
@InlineMe(
replacement = "CelConstant.ofValue(NullValue.NULL_VALUE)",
imports = {"dev.cel.common.ast.CelConstant", "dev.cel.common.values.NullValue"})
@Deprecated
public static CelConstant ofValue(com.google.protobuf.NullValue unused) {
return ofValue(NullValue.NULL_VALUE);
}

/**
* @deprecated Use native type equivalent {@link #ofValue(CelByteString)} instead.
*/
@Deprecated
public static CelConstant ofValue(ByteString value) {
CelByteString celByteString = CelByteString.of(value.toByteArray());
return ofValue(celByteString);
}

/**
* @deprecated Do not use. Duration is no longer built-in CEL type.
*/
@Deprecated
public static CelConstant ofValue(Duration value) {
return AutoOneOf_CelConstant.durationValue(value);
}

/**
* @deprecated Do not use. Timestamp is no longer built-in CEL type.
*/
@Deprecated
public static CelConstant ofValue(Timestamp value) {
return AutoOneOf_CelConstant.timestampValue(value);
}

/** Checks whether the provided Java object is a valid CelConstant value. */
public static boolean isConstantValue(Object value) {
return CONSTANT_CLASSES.contains(value.getClass());
Expand All@@ -163,26 +201,10 @@ public static CelConstant ofObjectValue(Object value) {
return ofValue((double) value);
} else if (value instanceof String) {
return ofValue((String) value);
} else if (value instanceof ByteString) {
return ofValue((ByteString) value);
} else if (value instanceof CelByteString) {
return ofValue((CelByteString) value);
}

throw new IllegalArgumentException("Value is not a CelConstant: " + value);
}

/**
* @deprecated Do not use. Duration is no longer built-in CEL type.
*/
@Deprecated
public static CelConstant ofValue(Duration value) {
return AutoOneOf_CelConstant.durationValue(value);
}

/**
* @deprecated Do not use. Timestamp is no longer built-in CEL type.
*/
@Deprecated
public static CelConstant ofValue(Timestamp value) {
return AutoOneOf_CelConstant.timestampValue(value);
}
}
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
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
3 changes: 2 additions & 1 deletion bundle/src/test/java/dev/cel/bundle/BUILD.bazel
Original file line numberDiff line numberDiff line change
Expand Up@@ -41,6 +41,8 @@ java_library(
"//common/types:cel_proto_types",
"//common/types:message_type_provider",
"//common/types:type_providers",
"//common/values",
"//common/values:cel_byte_string",
"//compiler",
"//compiler:compiler_builder",
"//extensions",
Expand All@@ -64,7 +66,6 @@ java_library(
"@maven//:com_google_truth_extensions_truth_proto_extension",
"@maven//:junit_junit",
"@maven//:org_jspecify_jspecify",
"@maven_android//:com_google_protobuf_protobuf_javalite",
],
)

Expand Down
40 changes: 35 additions & 5 deletions bundle/src/test/java/dev/cel/bundle/CelImplTest.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -48,7 +48,6 @@
import com.google.protobuf.Empty;
import com.google.protobuf.FieldMask;
import com.google.protobuf.Message;
import com.google.protobuf.NullValue;
import com.google.protobuf.Struct;
import com.google.protobuf.TextFormat;
import com.google.protobuf.Timestamp;
Expand DownExpand Up@@ -86,6 +85,8 @@
import dev.cel.common.types.ProtoMessageTypeProvider;
import dev.cel.common.types.SimpleType;
import dev.cel.common.types.StructTypeReference;
import dev.cel.common.values.CelByteString;
import dev.cel.common.values.NullValue;
import dev.cel.compiler.CelCompiler;
import dev.cel.compiler.CelCompilerFactory;
import dev.cel.compiler.CelCompilerImpl;
Expand All@@ -108,6 +109,7 @@
import dev.cel.runtime.UnknownContext;
import dev.cel.testing.testdata.proto3.StandaloneGlobalEnum;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
Expand DownExpand Up@@ -1019,7 +1021,10 @@ public void program_enumTypeReferenceResolution(boolean resolveTypeDependencies)
Cel cel =
standardCelBuilderWithMacros()
.setOptions(
CelOptions.current().resolveTypeDependencies(resolveTypeDependencies).build())
CelOptions.current()
.evaluateCanonicalTypesToNativeValues(true)
.resolveTypeDependencies(resolveTypeDependencies)
.build())
.addMessageTypes(Struct.getDescriptor())
.setResultType(StructTypeReference.create("google.protobuf.NullValue"))
.setContainer(CelContainer.ofName("google.protobuf"))
Expand All@@ -1037,7 +1042,11 @@ public void program_enumTypeReferenceResolution(boolean resolveTypeDependencies)
public void program_enumTypeTransitiveResolution() throws Exception {
Cel cel =
standardCelBuilderWithMacros()
.setOptions(CelOptions.current().resolveTypeDependencies(true).build())
.setOptions(
CelOptions.current()
.evaluateCanonicalTypesToNativeValues(true)
.resolveTypeDependencies(true)
.build())
.addMessageTypes(Proto2ExtensionScopedMessage.getDescriptor())
.setResultType(StructTypeReference.create("google.protobuf.NullValue"))
.setContainer(CelContainer.ofName("google.protobuf"))
Expand DownExpand Up@@ -1626,7 +1635,11 @@ public void programAdvanceEvaluation_indexOnUnknownContainer() throws Exception
public void programAdvanceEvaluation_unsupportedIndexIgnored() throws Exception {
Cel cel =
standardCelBuilderWithMacros()
.setOptions(CelOptions.current().enableUnknownTracking(true).build())
.setOptions(
CelOptions.current()
.evaluateCanonicalTypesToNativeValues(true)
.enableUnknownTracking(true)
.build())
.addVar("unk", MapType.create(SimpleType.STRING, SimpleType.BOOL))
.setContainer(CelContainer.ofName(""))
.addFunctionBindings()
Expand DownExpand Up@@ -1654,7 +1667,7 @@ public void programAdvanceEvaluation_unsupportedIndexIgnored() throws Exception
UnknownContext.create(
fromMap(
ImmutableMap.of(
"unk", ImmutableMap.of(ByteString.copyFromUtf8("a"), false))),
"unk", ImmutableMap.of(CelByteString.copyFromUtf8("a"), false))),
ImmutableList.of())))
.isEqualTo(false);
}
Expand DownExpand Up@@ -2077,6 +2090,23 @@ public void program_regexProgramSizeExceedsLimit_throws() throws Exception {
assertThat(e.getErrorCode()).isEqualTo(CelErrorCode.INVALID_ARGUMENT);
}

@Test
@SuppressWarnings("unchecked") // test only
public void program_evaluateCanonicalTypesToNativeTypesDisabled_producesProtoValues()
throws Exception {
Cel cel =
standardCelBuilderWithMacros()
.setOptions(CelOptions.current().evaluateCanonicalTypesToNativeValues(false).build())
.build();
CelAbstractSyntaxTree ast = cel.compile("[null, {b'abc': null}]").getAst();
Map<ByteString, Object> expectedNestedMap = new LinkedHashMap<>();
expectedNestedMap.put(ByteString.copyFromUtf8("abc"), com.google.protobuf.NullValue.NULL_VALUE);

List<Object> result = (List<Object>) cel.createProgram(ast).eval();

assertThat(result).containsExactly(com.google.protobuf.NullValue.NULL_VALUE, expectedNestedMap);
}

@Test
public void toBuilder_isImmutable() {
CelBuilder celBuilder = CelFactory.standardCelBuilder();
Expand Down
2 changes: 2 additions & 0 deletions common/src/main/java/dev/cel/common/BUILD.bazel
Original file line numberDiff line numberDiff line change
Expand Up@@ -206,6 +206,8 @@ java_library(
],
deps = [
"//common/internal:proto_time_utils",
"//common/values",
"//common/values:cel_byte_string",
"@maven//:com_google_errorprone_error_prone_annotations",
"@maven//:com_google_guava_guava",
"@maven//:com_google_protobuf_protobuf_java",
Expand Down
16 changes: 16 additions & 0 deletions common/src/main/java/dev/cel/common/CelOptions.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -109,6 +109,8 @@ public enum ProtoUnsetFieldOptions {

public abstract int comprehensionMaxIterations();

public abstract boolean evaluateCanonicalTypesToNativeValues();

public abstract boolean unwrapWellKnownTypesOnFunctionDispatch();

public abstract ProtoUnsetFieldOptions fromProtoUnsetFieldOption();
Expand DownExpand Up@@ -150,6 +152,7 @@ public static Builder newBuilder() {
.enableNamespacedDeclarations(true)
// Evaluation options
.disableCelStandardEquality(true)
.evaluateCanonicalTypesToNativeValues(false)
.enableShortCircuiting(true)
.enableRegexPartialMatch(false)
.enableUnsignedComparisonAndArithmeticIsUnsigned(false)
Expand DownExpand Up@@ -450,6 +453,19 @@ public abstract static class Builder {
*/
public abstract Builder comprehensionMaxIterations(int value);

/**
* If set, canonical CEL types such as bytes and CEL null will return their native value
* equivalents instead of protobuf based values. Specifically:
*
* <ul>
* <li>Bytes: {@code dev.cel.common.values.CelByteString} instead of {@code
* com.google.protobuf.ByteString}.
* <li>CEL null: {@code dev.cel.common.values.NullValue} instead of {@code
* com.google.protobuf.NullValue}.
* </ul>
*/
public abstract Builder evaluateCanonicalTypesToNativeValues(boolean value);

/**
* If disabled, CEL runtime will no longer adapt the function dispatch results for protobuf's
* well known types to other types. This option is enabled by default.
Expand Down
8 changes: 4 additions & 4 deletions common/src/main/java/dev/cel/common/CelProtoJsonAdapter.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -18,7 +18,6 @@
import com.google.common.base.Joiner;
import com.google.common.primitives.UnsignedLong;
import com.google.errorprone.annotations.Immutable;
import com.google.protobuf.ByteString;
import com.google.protobuf.Duration;
import com.google.protobuf.Empty;
import com.google.protobuf.FieldMask;
Expand All@@ -28,6 +27,7 @@
import com.google.protobuf.Timestamp;
import com.google.protobuf.Value;
import dev.cel.common.internal.ProtoTimeUtils;
import dev.cel.common.values.CelByteString;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
Expand DownExpand Up@@ -71,7 +71,7 @@ public static <K extends String, V> Struct adaptToJsonStructValue(Map<K, V> map)
@SuppressWarnings("unchecked")
public static Value adaptValueToJsonValue(Object value) {
Value.Builder json = Value.newBuilder();
if (value == null || value instanceof NullValue) {
if (value == null || value instanceof dev.cel.common.values.NullValue) {
return json.setNullValue(NullValue.NULL_VALUE).build();
}
if (value instanceof Boolean) {
Expand All@@ -93,9 +93,9 @@ public static Value adaptValueToJsonValue(Object value) {
if (value instanceof Float || value instanceof Double) {
return json.setNumberValue(((Number) value).doubleValue()).build();
}
if (value instanceof ByteString) {
if (value instanceof CelByteString) {
return json.setStringValue(
Base64.getEncoder().encodeToString(((ByteString) value).toByteArray()))
Base64.getEncoder().encodeToString(((CelByteString) value).toByteArray()))
.build();
}
if (value instanceof String) {
Expand Down
15 changes: 14 additions & 1 deletion common/src/main/java/dev/cel/common/ast/BUILD.bazel
Original file line numberDiff line numberDiff line change
Expand Up@@ -49,6 +49,8 @@ java_library(
deps = [
"//:auto_value",
"//common/annotations",
"//common/values",
"//common/values:cel_byte_string",
"@maven//:com_google_errorprone_error_prone_annotations",
"@maven//:com_google_guava_guava",
"@maven//:com_google_protobuf_protobuf_java",
Expand All@@ -62,9 +64,12 @@ java_library(
],
deps = [
":ast",
"//common/values",
"//common/values:cel_byte_string",
"@cel_spec//proto/cel/expr:checked_java_proto",
"@cel_spec//proto/cel/expr:syntax_java_proto",
"@maven//:com_google_guava_guava",
"@maven//:com_google_protobuf_protobuf_java",
],
)

Expand All@@ -75,9 +80,12 @@ cel_android_library(
],
deps = [
":ast_android",
"//common/values:cel_byte_string",
"//common/values:values_android",
"@cel_spec//proto/cel/expr:checked_java_proto_lite",
"@cel_spec//proto/cel/expr:syntax_java_proto_lite",
"@maven_android//:com_google_guava_guava",
"@maven_android//:com_google_protobuf_protobuf_javalite",
],
)

Expand All@@ -88,8 +96,11 @@ java_library(
],
deps = [
":ast",
"//common/values",
"//common/values:cel_byte_string",
"@com_google_googleapis//google/api/expr/v1alpha1:expr_java_proto",
"@maven//:com_google_guava_guava",
"@maven//:com_google_protobuf_protobuf_java",
],
)

Expand All@@ -112,8 +123,8 @@ java_library(
deps = [
":ast",
"//common/annotations",
"//common/values:cel_byte_string",
"@maven//:com_google_guava_guava",
"@maven//:com_google_protobuf_protobuf_java",
],
)

Expand All@@ -136,6 +147,8 @@ cel_android_library(
deps = [
"//:auto_value",
"//common/annotations",
"//common/values:cel_byte_string",
"//common/values:values_android",
"@maven//:com_google_errorprone_error_prone_annotations",
"@maven_android//:com_google_guava_guava",
"@maven_android//:com_google_protobuf_protobuf_javalite",
Expand Down
66 changes: 44 additions & 22 deletions common/src/main/java/dev/cel/common/ast/CelConstant.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -19,11 +19,13 @@
import com.google.common.collect.ImmutableSet;
import com.google.common.primitives.UnsignedLong;
import com.google.errorprone.annotations.Immutable;
import com.google.errorprone.annotations.InlineMe;
import com.google.protobuf.ByteString;
import com.google.protobuf.Duration;
import com.google.protobuf.NullValue;
import com.google.protobuf.Timestamp;
import dev.cel.common.annotations.Internal;
import dev.cel.common.values.CelByteString;
import dev.cel.common.values.NullValue;

/**
* Represents a primitive literal.
Expand All@@ -42,7 +44,7 @@ public abstract class CelConstant {
UnsignedLong.class,
Double.class,
String.class,
ByteString.class);
CelByteString.class);

/** Represents the type of the Constant */
public enum Kind {
Expand DownExpand Up@@ -92,7 +94,7 @@ public abstract static class CelConstantNotSet {}

public abstract String stringValue();

public abstract ByteString bytesValue();
public abstract CelByteString bytesValue();

/**
* @deprecated Do not use. Timestamp is no longer built-in CEL type.
Expand DownExpand Up@@ -134,10 +136,46 @@ public static CelConstant ofValue(String value) {
return AutoOneOf_CelConstant.stringValue(value);
}

public static CelConstant ofValue(ByteString value) {
public static CelConstant ofValue(CelByteString value) {
return AutoOneOf_CelConstant.bytesValue(value);
}

/**
* @deprecated Use native type equivalent {@link #ofValue(NullValue)} instead.
*/
@InlineMe(
replacement = "CelConstant.ofValue(NullValue.NULL_VALUE)",
imports = {"dev.cel.common.ast.CelConstant", "dev.cel.common.values.NullValue"})
@Deprecated
public static CelConstant ofValue(com.google.protobuf.NullValue unused) {
return ofValue(NullValue.NULL_VALUE);
}

/**
* @deprecated Use native type equivalent {@link #ofValue(CelByteString)} instead.
*/
@Deprecated
public static CelConstant ofValue(ByteString value) {
CelByteString celByteString = CelByteString.of(value.toByteArray());
return ofValue(celByteString);
}

/**
* @deprecated Do not use. Duration is no longer built-in CEL type.
*/
@Deprecated
public static CelConstant ofValue(Duration value) {
return AutoOneOf_CelConstant.durationValue(value);
}

/**
* @deprecated Do not use. Timestamp is no longer built-in CEL type.
*/
@Deprecated
public static CelConstant ofValue(Timestamp value) {
return AutoOneOf_CelConstant.timestampValue(value);
}

/** Checks whether the provided Java object is a valid CelConstant value. */
public static boolean isConstantValue(Object value) {
return CONSTANT_CLASSES.contains(value.getClass());
Expand All@@ -163,26 +201,10 @@ public static CelConstant ofObjectValue(Object value) {
return ofValue((double) value);
} else if (value instanceof String) {
return ofValue((String) value);
} else if (value instanceof ByteString) {
return ofValue((ByteString) value);
} else if (value instanceof CelByteString) {
return ofValue((CelByteString) value);
}

throw new IllegalArgumentException("Value is not a CelConstant: " + value);
}

/**
* @deprecated Do not use. Duration is no longer built-in CEL type.
*/
@Deprecated
public static CelConstant ofValue(Duration value) {
return AutoOneOf_CelConstant.durationValue(value);
}

/**
* @deprecated Do not use. Timestamp is no longer built-in CEL type.
*/
@Deprecated
public static CelConstant ofValue(Timestamp value) {
return AutoOneOf_CelConstant.timestampValue(value);
}
}
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
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
3 changes: 2 additions & 1 deletion bundle/src/test/java/dev/cel/bundle/BUILD.bazel
Original file line numberDiff line numberDiff line change
Expand Up@@ -41,6 +41,8 @@ java_library(
"//common/types:cel_proto_types",
"//common/types:message_type_provider",
"//common/types:type_providers",
"//common/values",
"//common/values:cel_byte_string",
"//compiler",
"//compiler:compiler_builder",
"//extensions",
Expand All@@ -64,7 +66,6 @@ java_library(
"@maven//:com_google_truth_extensions_truth_proto_extension",
"@maven//:junit_junit",
"@maven//:org_jspecify_jspecify",
"@maven_android//:com_google_protobuf_protobuf_javalite",
],
)

Expand Down
40 changes: 35 additions & 5 deletions bundle/src/test/java/dev/cel/bundle/CelImplTest.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -48,7 +48,6 @@
import com.google.protobuf.Empty;
import com.google.protobuf.FieldMask;
import com.google.protobuf.Message;
import com.google.protobuf.NullValue;
import com.google.protobuf.Struct;
import com.google.protobuf.TextFormat;
import com.google.protobuf.Timestamp;
Expand DownExpand Up@@ -86,6 +85,8 @@
import dev.cel.common.types.ProtoMessageTypeProvider;
import dev.cel.common.types.SimpleType;
import dev.cel.common.types.StructTypeReference;
import dev.cel.common.values.CelByteString;
import dev.cel.common.values.NullValue;
import dev.cel.compiler.CelCompiler;
import dev.cel.compiler.CelCompilerFactory;
import dev.cel.compiler.CelCompilerImpl;
Expand All@@ -108,6 +109,7 @@
import dev.cel.runtime.UnknownContext;
import dev.cel.testing.testdata.proto3.StandaloneGlobalEnum;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
Expand DownExpand Up@@ -1019,7 +1021,10 @@ public void program_enumTypeReferenceResolution(boolean resolveTypeDependencies)
Cel cel =
standardCelBuilderWithMacros()
.setOptions(
CelOptions.current().resolveTypeDependencies(resolveTypeDependencies).build())
CelOptions.current()
.evaluateCanonicalTypesToNativeValues(true)
.resolveTypeDependencies(resolveTypeDependencies)
.build())
.addMessageTypes(Struct.getDescriptor())
.setResultType(StructTypeReference.create("google.protobuf.NullValue"))
.setContainer(CelContainer.ofName("google.protobuf"))
Expand All@@ -1037,7 +1042,11 @@ public void program_enumTypeReferenceResolution(boolean resolveTypeDependencies)
public void program_enumTypeTransitiveResolution() throws Exception {
Cel cel =
standardCelBuilderWithMacros()
.setOptions(CelOptions.current().resolveTypeDependencies(true).build())
.setOptions(
CelOptions.current()
.evaluateCanonicalTypesToNativeValues(true)
.resolveTypeDependencies(true)
.build())
.addMessageTypes(Proto2ExtensionScopedMessage.getDescriptor())
.setResultType(StructTypeReference.create("google.protobuf.NullValue"))
.setContainer(CelContainer.ofName("google.protobuf"))
Expand DownExpand Up@@ -1626,7 +1635,11 @@ public void programAdvanceEvaluation_indexOnUnknownContainer() throws Exception
public void programAdvanceEvaluation_unsupportedIndexIgnored() throws Exception {
Cel cel =
standardCelBuilderWithMacros()
.setOptions(CelOptions.current().enableUnknownTracking(true).build())
.setOptions(
CelOptions.current()
.evaluateCanonicalTypesToNativeValues(true)
.enableUnknownTracking(true)
.build())
.addVar("unk", MapType.create(SimpleType.STRING, SimpleType.BOOL))
.setContainer(CelContainer.ofName(""))
.addFunctionBindings()
Expand DownExpand Up@@ -1654,7 +1667,7 @@ public void programAdvanceEvaluation_unsupportedIndexIgnored() throws Exception
UnknownContext.create(
fromMap(
ImmutableMap.of(
"unk", ImmutableMap.of(ByteString.copyFromUtf8("a"), false))),
"unk", ImmutableMap.of(CelByteString.copyFromUtf8("a"), false))),
ImmutableList.of())))
.isEqualTo(false);
}
Expand DownExpand Up@@ -2077,6 +2090,23 @@ public void program_regexProgramSizeExceedsLimit_throws() throws Exception {
assertThat(e.getErrorCode()).isEqualTo(CelErrorCode.INVALID_ARGUMENT);
}

@Test
@SuppressWarnings("unchecked") // test only
public void program_evaluateCanonicalTypesToNativeTypesDisabled_producesProtoValues()
throws Exception {
Cel cel =
standardCelBuilderWithMacros()
.setOptions(CelOptions.current().evaluateCanonicalTypesToNativeValues(false).build())
.build();
CelAbstractSyntaxTree ast = cel.compile("[null, {b'abc': null}]").getAst();
Map<ByteString, Object> expectedNestedMap = new LinkedHashMap<>();
expectedNestedMap.put(ByteString.copyFromUtf8("abc"), com.google.protobuf.NullValue.NULL_VALUE);

List<Object> result = (List<Object>) cel.createProgram(ast).eval();

assertThat(result).containsExactly(com.google.protobuf.NullValue.NULL_VALUE, expectedNestedMap);
}

@Test
public void toBuilder_isImmutable() {
CelBuilder celBuilder = CelFactory.standardCelBuilder();
Expand Down
2 changes: 2 additions & 0 deletions common/src/main/java/dev/cel/common/BUILD.bazel
Original file line numberDiff line numberDiff line change
Expand Up@@ -206,6 +206,8 @@ java_library(
],
deps = [
"//common/internal:proto_time_utils",
"//common/values",
"//common/values:cel_byte_string",
"@maven//:com_google_errorprone_error_prone_annotations",
"@maven//:com_google_guava_guava",
"@maven//:com_google_protobuf_protobuf_java",
Expand Down
16 changes: 16 additions & 0 deletions common/src/main/java/dev/cel/common/CelOptions.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -109,6 +109,8 @@ public enum ProtoUnsetFieldOptions {

public abstract int comprehensionMaxIterations();

public abstract boolean evaluateCanonicalTypesToNativeValues();

public abstract boolean unwrapWellKnownTypesOnFunctionDispatch();

public abstract ProtoUnsetFieldOptions fromProtoUnsetFieldOption();
Expand DownExpand Up@@ -150,6 +152,7 @@ public static Builder newBuilder() {
.enableNamespacedDeclarations(true)
// Evaluation options
.disableCelStandardEquality(true)
.evaluateCanonicalTypesToNativeValues(false)
.enableShortCircuiting(true)
.enableRegexPartialMatch(false)
.enableUnsignedComparisonAndArithmeticIsUnsigned(false)
Expand DownExpand Up@@ -450,6 +453,19 @@ public abstract static class Builder {
*/
public abstract Builder comprehensionMaxIterations(int value);

/**
* If set, canonical CEL types such as bytes and CEL null will return their native value
* equivalents instead of protobuf based values. Specifically:
*
* <ul>
* <li>Bytes: {@code dev.cel.common.values.CelByteString} instead of {@code
* com.google.protobuf.ByteString}.
* <li>CEL null: {@code dev.cel.common.values.NullValue} instead of {@code
* com.google.protobuf.NullValue}.
* </ul>
*/
public abstract Builder evaluateCanonicalTypesToNativeValues(boolean value);

/**
* If disabled, CEL runtime will no longer adapt the function dispatch results for protobuf's
* well known types to other types. This option is enabled by default.
Expand Down
8 changes: 4 additions & 4 deletions common/src/main/java/dev/cel/common/CelProtoJsonAdapter.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -18,7 +18,6 @@
import com.google.common.base.Joiner;
import com.google.common.primitives.UnsignedLong;
import com.google.errorprone.annotations.Immutable;
import com.google.protobuf.ByteString;
import com.google.protobuf.Duration;
import com.google.protobuf.Empty;
import com.google.protobuf.FieldMask;
Expand All@@ -28,6 +27,7 @@
import com.google.protobuf.Timestamp;
import com.google.protobuf.Value;
import dev.cel.common.internal.ProtoTimeUtils;
import dev.cel.common.values.CelByteString;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
Expand DownExpand Up@@ -71,7 +71,7 @@ public static <K extends String, V> Struct adaptToJsonStructValue(Map<K, V> map)
@SuppressWarnings("unchecked")
public static Value adaptValueToJsonValue(Object value) {
Value.Builder json = Value.newBuilder();
if (value == null || value instanceof NullValue) {
if (value == null || value instanceof dev.cel.common.values.NullValue) {
return json.setNullValue(NullValue.NULL_VALUE).build();
}
if (value instanceof Boolean) {
Expand All@@ -93,9 +93,9 @@ public static Value adaptValueToJsonValue(Object value) {
if (value instanceof Float || value instanceof Double) {
return json.setNumberValue(((Number) value).doubleValue()).build();
}
if (value instanceof ByteString) {
if (value instanceof CelByteString) {
return json.setStringValue(
Base64.getEncoder().encodeToString(((ByteString) value).toByteArray()))
Base64.getEncoder().encodeToString(((CelByteString) value).toByteArray()))
.build();
}
if (value instanceof String) {
Expand Down
15 changes: 14 additions & 1 deletion common/src/main/java/dev/cel/common/ast/BUILD.bazel
Original file line numberDiff line numberDiff line change
Expand Up@@ -49,6 +49,8 @@ java_library(
deps = [
"//:auto_value",
"//common/annotations",
"//common/values",
"//common/values:cel_byte_string",
"@maven//:com_google_errorprone_error_prone_annotations",
"@maven//:com_google_guava_guava",
"@maven//:com_google_protobuf_protobuf_java",
Expand All@@ -62,9 +64,12 @@ java_library(
],
deps = [
":ast",
"//common/values",
"//common/values:cel_byte_string",
"@cel_spec//proto/cel/expr:checked_java_proto",
"@cel_spec//proto/cel/expr:syntax_java_proto",
"@maven//:com_google_guava_guava",
"@maven//:com_google_protobuf_protobuf_java",
],
)

Expand All@@ -75,9 +80,12 @@ cel_android_library(
],
deps = [
":ast_android",
"//common/values:cel_byte_string",
"//common/values:values_android",
"@cel_spec//proto/cel/expr:checked_java_proto_lite",
"@cel_spec//proto/cel/expr:syntax_java_proto_lite",
"@maven_android//:com_google_guava_guava",
"@maven_android//:com_google_protobuf_protobuf_javalite",
],
)

Expand All@@ -88,8 +96,11 @@ java_library(
],
deps = [
":ast",
"//common/values",
"//common/values:cel_byte_string",
"@com_google_googleapis//google/api/expr/v1alpha1:expr_java_proto",
"@maven//:com_google_guava_guava",
"@maven//:com_google_protobuf_protobuf_java",
],
)

Expand All@@ -112,8 +123,8 @@ java_library(
deps = [
":ast",
"//common/annotations",
"//common/values:cel_byte_string",
"@maven//:com_google_guava_guava",
"@maven//:com_google_protobuf_protobuf_java",
],
)

Expand All@@ -136,6 +147,8 @@ cel_android_library(
deps = [
"//:auto_value",
"//common/annotations",
"//common/values:cel_byte_string",
"//common/values:values_android",
"@maven//:com_google_errorprone_error_prone_annotations",
"@maven_android//:com_google_guava_guava",
"@maven_android//:com_google_protobuf_protobuf_javalite",
Expand Down
66 changes: 44 additions & 22 deletions common/src/main/java/dev/cel/common/ast/CelConstant.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -19,11 +19,13 @@
import com.google.common.collect.ImmutableSet;
import com.google.common.primitives.UnsignedLong;
import com.google.errorprone.annotations.Immutable;
import com.google.errorprone.annotations.InlineMe;
import com.google.protobuf.ByteString;
import com.google.protobuf.Duration;
import com.google.protobuf.NullValue;
import com.google.protobuf.Timestamp;
import dev.cel.common.annotations.Internal;
import dev.cel.common.values.CelByteString;
import dev.cel.common.values.NullValue;

/**
* Represents a primitive literal.
Expand All@@ -42,7 +44,7 @@ public abstract class CelConstant {
UnsignedLong.class,
Double.class,
String.class,
ByteString.class);
CelByteString.class);

/** Represents the type of the Constant */
public enum Kind {
Expand DownExpand Up@@ -92,7 +94,7 @@ public abstract static class CelConstantNotSet {}

public abstract String stringValue();

public abstract ByteString bytesValue();
public abstract CelByteString bytesValue();

/**
* @deprecated Do not use. Timestamp is no longer built-in CEL type.
Expand DownExpand Up@@ -134,10 +136,46 @@ public static CelConstant ofValue(String value) {
return AutoOneOf_CelConstant.stringValue(value);
}

public static CelConstant ofValue(ByteString value) {
public static CelConstant ofValue(CelByteString value) {
return AutoOneOf_CelConstant.bytesValue(value);
}

/**
* @deprecated Use native type equivalent {@link #ofValue(NullValue)} instead.
*/
@InlineMe(
replacement = "CelConstant.ofValue(NullValue.NULL_VALUE)",
imports = {"dev.cel.common.ast.CelConstant", "dev.cel.common.values.NullValue"})
@Deprecated
public static CelConstant ofValue(com.google.protobuf.NullValue unused) {
return ofValue(NullValue.NULL_VALUE);
}

/**
* @deprecated Use native type equivalent {@link #ofValue(CelByteString)} instead.
*/
@Deprecated
public static CelConstant ofValue(ByteString value) {
CelByteString celByteString = CelByteString.of(value.toByteArray());
return ofValue(celByteString);
}

/**
* @deprecated Do not use. Duration is no longer built-in CEL type.
*/
@Deprecated
public static CelConstant ofValue(Duration value) {
return AutoOneOf_CelConstant.durationValue(value);
}

/**
* @deprecated Do not use. Timestamp is no longer built-in CEL type.
*/
@Deprecated
public static CelConstant ofValue(Timestamp value) {
return AutoOneOf_CelConstant.timestampValue(value);
}

/** Checks whether the provided Java object is a valid CelConstant value. */
public static boolean isConstantValue(Object value) {
return CONSTANT_CLASSES.contains(value.getClass());
Expand All@@ -163,26 +201,10 @@ public static CelConstant ofObjectValue(Object value) {
return ofValue((double) value);
} else if (value instanceof String) {
return ofValue((String) value);
} else if (value instanceof ByteString) {
return ofValue((ByteString) value);
} else if (value instanceof CelByteString) {
return ofValue((CelByteString) value);
}

throw new IllegalArgumentException("Value is not a CelConstant: " + value);
}

/**
* @deprecated Do not use. Duration is no longer built-in CEL type.
*/
@Deprecated
public static CelConstant ofValue(Duration value) {
return AutoOneOf_CelConstant.durationValue(value);
}

/**
* @deprecated Do not use. Timestamp is no longer built-in CEL type.
*/
@Deprecated
public static CelConstant ofValue(Timestamp value) {
return AutoOneOf_CelConstant.timestampValue(value);
}
}
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content
Merged
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
3 changes: 2 additions & 1 deletion bundle/src/test/java/dev/cel/bundle/BUILD.bazel
Original file line numberDiff line numberDiff line change
Expand Up@@ -41,6 +41,8 @@ java_library(
"//common/types:cel_proto_types",
"//common/types:message_type_provider",
"//common/types:type_providers",
"//common/values",
"//common/values:cel_byte_string",
"//compiler",
"//compiler:compiler_builder",
"//extensions",
Expand All@@ -64,7 +66,6 @@ java_library(
"@maven//:com_google_truth_extensions_truth_proto_extension",
"@maven//:junit_junit",
"@maven//:org_jspecify_jspecify",
"@maven_android//:com_google_protobuf_protobuf_javalite",
],
)

Expand Down
40 changes: 35 additions & 5 deletions bundle/src/test/java/dev/cel/bundle/CelImplTest.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -48,7 +48,6 @@
import com.google.protobuf.Empty;
import com.google.protobuf.FieldMask;
import com.google.protobuf.Message;
import com.google.protobuf.NullValue;
import com.google.protobuf.Struct;
import com.google.protobuf.TextFormat;
import com.google.protobuf.Timestamp;
Expand DownExpand Up@@ -86,6 +85,8 @@
import dev.cel.common.types.ProtoMessageTypeProvider;
import dev.cel.common.types.SimpleType;
import dev.cel.common.types.StructTypeReference;
import dev.cel.common.values.CelByteString;
import dev.cel.common.values.NullValue;
import dev.cel.compiler.CelCompiler;
import dev.cel.compiler.CelCompilerFactory;
import dev.cel.compiler.CelCompilerImpl;
Expand All@@ -108,6 +109,7 @@
import dev.cel.runtime.UnknownContext;
import dev.cel.testing.testdata.proto3.StandaloneGlobalEnum;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
Expand DownExpand Up@@ -1019,7 +1021,10 @@ public void program_enumTypeReferenceResolution(boolean resolveTypeDependencies)
Cel cel =
standardCelBuilderWithMacros()
.setOptions(
CelOptions.current().resolveTypeDependencies(resolveTypeDependencies).build())
CelOptions.current()
.evaluateCanonicalTypesToNativeValues(true)
.resolveTypeDependencies(resolveTypeDependencies)
.build())
.addMessageTypes(Struct.getDescriptor())
.setResultType(StructTypeReference.create("google.protobuf.NullValue"))
.setContainer(CelContainer.ofName("google.protobuf"))
Expand All@@ -1037,7 +1042,11 @@ public void program_enumTypeReferenceResolution(boolean resolveTypeDependencies)
public void program_enumTypeTransitiveResolution() throws Exception {
Cel cel =
standardCelBuilderWithMacros()
.setOptions(CelOptions.current().resolveTypeDependencies(true).build())
.setOptions(
CelOptions.current()
.evaluateCanonicalTypesToNativeValues(true)
.resolveTypeDependencies(true)
.build())
.addMessageTypes(Proto2ExtensionScopedMessage.getDescriptor())
.setResultType(StructTypeReference.create("google.protobuf.NullValue"))
.setContainer(CelContainer.ofName("google.protobuf"))
Expand DownExpand Up@@ -1626,7 +1635,11 @@ public void programAdvanceEvaluation_indexOnUnknownContainer() throws Exception
public void programAdvanceEvaluation_unsupportedIndexIgnored() throws Exception {
Cel cel =
standardCelBuilderWithMacros()
.setOptions(CelOptions.current().enableUnknownTracking(true).build())
.setOptions(
CelOptions.current()
.evaluateCanonicalTypesToNativeValues(true)
.enableUnknownTracking(true)
.build())
.addVar("unk", MapType.create(SimpleType.STRING, SimpleType.BOOL))
.setContainer(CelContainer.ofName(""))
.addFunctionBindings()
Expand DownExpand Up@@ -1654,7 +1667,7 @@ public void programAdvanceEvaluation_unsupportedIndexIgnored() throws Exception
UnknownContext.create(
fromMap(
ImmutableMap.of(
"unk", ImmutableMap.of(ByteString.copyFromUtf8("a"), false))),
"unk", ImmutableMap.of(CelByteString.copyFromUtf8("a"), false))),
ImmutableList.of())))
.isEqualTo(false);
}
Expand DownExpand Up@@ -2077,6 +2090,23 @@ public void program_regexProgramSizeExceedsLimit_throws() throws Exception {
assertThat(e.getErrorCode()).isEqualTo(CelErrorCode.INVALID_ARGUMENT);
}

@Test
@SuppressWarnings("unchecked") // test only
public void program_evaluateCanonicalTypesToNativeTypesDisabled_producesProtoValues()
throws Exception {
Cel cel =
standardCelBuilderWithMacros()
.setOptions(CelOptions.current().evaluateCanonicalTypesToNativeValues(false).build())
.build();
CelAbstractSyntaxTree ast = cel.compile("[null, {b'abc': null}]").getAst();
Map<ByteString, Object> expectedNestedMap = new LinkedHashMap<>();
expectedNestedMap.put(ByteString.copyFromUtf8("abc"), com.google.protobuf.NullValue.NULL_VALUE);

List<Object> result = (List<Object>) cel.createProgram(ast).eval();

assertThat(result).containsExactly(com.google.protobuf.NullValue.NULL_VALUE, expectedNestedMap);
}

@Test
public void toBuilder_isImmutable() {
CelBuilder celBuilder = CelFactory.standardCelBuilder();
Expand Down
2 changes: 2 additions & 0 deletions common/src/main/java/dev/cel/common/BUILD.bazel
Original file line numberDiff line numberDiff line change
Expand Up@@ -206,6 +206,8 @@ java_library(
],
deps = [
"//common/internal:proto_time_utils",
"//common/values",
"//common/values:cel_byte_string",
"@maven//:com_google_errorprone_error_prone_annotations",
"@maven//:com_google_guava_guava",
"@maven//:com_google_protobuf_protobuf_java",
Expand Down
16 changes: 16 additions & 0 deletions common/src/main/java/dev/cel/common/CelOptions.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -109,6 +109,8 @@ public enum ProtoUnsetFieldOptions {

public abstract int comprehensionMaxIterations();

public abstract boolean evaluateCanonicalTypesToNativeValues();

public abstract boolean unwrapWellKnownTypesOnFunctionDispatch();

public abstract ProtoUnsetFieldOptions fromProtoUnsetFieldOption();
Expand DownExpand Up@@ -150,6 +152,7 @@ public static Builder newBuilder() {
.enableNamespacedDeclarations(true)
// Evaluation options
.disableCelStandardEquality(true)
.evaluateCanonicalTypesToNativeValues(false)
.enableShortCircuiting(true)
.enableRegexPartialMatch(false)
.enableUnsignedComparisonAndArithmeticIsUnsigned(false)
Expand DownExpand Up@@ -450,6 +453,19 @@ public abstract static class Builder {
*/
public abstract Builder comprehensionMaxIterations(int value);

/**
* If set, canonical CEL types such as bytes and CEL null will return their native value
* equivalents instead of protobuf based values. Specifically:
*
* <ul>
* <li>Bytes: {@code dev.cel.common.values.CelByteString} instead of {@code
* com.google.protobuf.ByteString}.
* <li>CEL null: {@code dev.cel.common.values.NullValue} instead of {@code
* com.google.protobuf.NullValue}.
* </ul>
*/
public abstract Builder evaluateCanonicalTypesToNativeValues(boolean value);

/**
* If disabled, CEL runtime will no longer adapt the function dispatch results for protobuf's
* well known types to other types. This option is enabled by default.
Expand Down
8 changes: 4 additions & 4 deletions common/src/main/java/dev/cel/common/CelProtoJsonAdapter.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -18,7 +18,6 @@
import com.google.common.base.Joiner;
import com.google.common.primitives.UnsignedLong;
import com.google.errorprone.annotations.Immutable;
import com.google.protobuf.ByteString;
import com.google.protobuf.Duration;
import com.google.protobuf.Empty;
import com.google.protobuf.FieldMask;
Expand All@@ -28,6 +27,7 @@
import com.google.protobuf.Timestamp;
import com.google.protobuf.Value;
import dev.cel.common.internal.ProtoTimeUtils;
import dev.cel.common.values.CelByteString;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
Expand DownExpand Up@@ -71,7 +71,7 @@ public static <K extends String, V> Struct adaptToJsonStructValue(Map<K, V> map)
@SuppressWarnings("unchecked")
public static Value adaptValueToJsonValue(Object value) {
Value.Builder json = Value.newBuilder();
if (value == null || value instanceof NullValue) {
if (value == null || value instanceof dev.cel.common.values.NullValue) {
return json.setNullValue(NullValue.NULL_VALUE).build();
}
if (value instanceof Boolean) {
Expand All@@ -93,9 +93,9 @@ public static Value adaptValueToJsonValue(Object value) {
if (value instanceof Float || value instanceof Double) {
return json.setNumberValue(((Number) value).doubleValue()).build();
}
if (value instanceof ByteString) {
if (value instanceof CelByteString) {
return json.setStringValue(
Base64.getEncoder().encodeToString(((ByteString) value).toByteArray()))
Base64.getEncoder().encodeToString(((CelByteString) value).toByteArray()))
.build();
}
if (value instanceof String) {
Expand Down
15 changes: 14 additions & 1 deletion common/src/main/java/dev/cel/common/ast/BUILD.bazel
Original file line numberDiff line numberDiff line change
Expand Up@@ -49,6 +49,8 @@ java_library(
deps = [
"//:auto_value",
"//common/annotations",
"//common/values",
"//common/values:cel_byte_string",
"@maven//:com_google_errorprone_error_prone_annotations",
"@maven//:com_google_guava_guava",
"@maven//:com_google_protobuf_protobuf_java",
Expand All@@ -62,9 +64,12 @@ java_library(
],
deps = [
":ast",
"//common/values",
"//common/values:cel_byte_string",
"@cel_spec//proto/cel/expr:checked_java_proto",
"@cel_spec//proto/cel/expr:syntax_java_proto",
"@maven//:com_google_guava_guava",
"@maven//:com_google_protobuf_protobuf_java",
],
)

Expand All@@ -75,9 +80,12 @@ cel_android_library(
],
deps = [
":ast_android",
"//common/values:cel_byte_string",
"//common/values:values_android",
"@cel_spec//proto/cel/expr:checked_java_proto_lite",
"@cel_spec//proto/cel/expr:syntax_java_proto_lite",
"@maven_android//:com_google_guava_guava",
"@maven_android//:com_google_protobuf_protobuf_javalite",
],
)

Expand All@@ -88,8 +96,11 @@ java_library(
],
deps = [
":ast",
"//common/values",
"//common/values:cel_byte_string",
"@com_google_googleapis//google/api/expr/v1alpha1:expr_java_proto",
"@maven//:com_google_guava_guava",
"@maven//:com_google_protobuf_protobuf_java",
],
)

Expand All@@ -112,8 +123,8 @@ java_library(
deps = [
":ast",
"//common/annotations",
"//common/values:cel_byte_string",
"@maven//:com_google_guava_guava",
"@maven//:com_google_protobuf_protobuf_java",
],
)

Expand All@@ -136,6 +147,8 @@ cel_android_library(
deps = [
"//:auto_value",
"//common/annotations",
"//common/values:cel_byte_string",
"//common/values:values_android",
"@maven//:com_google_errorprone_error_prone_annotations",
"@maven_android//:com_google_guava_guava",
"@maven_android//:com_google_protobuf_protobuf_javalite",
Expand Down
66 changes: 44 additions & 22 deletions common/src/main/java/dev/cel/common/ast/CelConstant.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -19,11 +19,13 @@
import com.google.common.collect.ImmutableSet;
import com.google.common.primitives.UnsignedLong;
import com.google.errorprone.annotations.Immutable;
import com.google.errorprone.annotations.InlineMe;
import com.google.protobuf.ByteString;
import com.google.protobuf.Duration;
import com.google.protobuf.NullValue;
import com.google.protobuf.Timestamp;
import dev.cel.common.annotations.Internal;
import dev.cel.common.values.CelByteString;
import dev.cel.common.values.NullValue;

/**
* Represents a primitive literal.
Expand All@@ -42,7 +44,7 @@ public abstract class CelConstant {
UnsignedLong.class,
Double.class,
String.class,
ByteString.class);
CelByteString.class);

/** Represents the type of the Constant */
public enum Kind {
Expand DownExpand Up@@ -92,7 +94,7 @@ public abstract static class CelConstantNotSet {}

public abstract String stringValue();

public abstract ByteString bytesValue();
public abstract CelByteString bytesValue();

/**
* @deprecated Do not use. Timestamp is no longer built-in CEL type.
Expand DownExpand Up@@ -134,10 +136,46 @@ public static CelConstant ofValue(String value) {
return AutoOneOf_CelConstant.stringValue(value);
}

public static CelConstant ofValue(ByteString value) {
public static CelConstant ofValue(CelByteString value) {
return AutoOneOf_CelConstant.bytesValue(value);
}

/**
* @deprecated Use native type equivalent {@link #ofValue(NullValue)} instead.
*/
@InlineMe(
replacement = "CelConstant.ofValue(NullValue.NULL_VALUE)",
imports = {"dev.cel.common.ast.CelConstant", "dev.cel.common.values.NullValue"})
@Deprecated
public static CelConstant ofValue(com.google.protobuf.NullValue unused) {
return ofValue(NullValue.NULL_VALUE);
}

/**
* @deprecated Use native type equivalent {@link #ofValue(CelByteString)} instead.
*/
@Deprecated
public static CelConstant ofValue(ByteString value) {
CelByteString celByteString = CelByteString.of(value.toByteArray());
return ofValue(celByteString);
}

/**
* @deprecated Do not use. Duration is no longer built-in CEL type.
*/
@Deprecated
public static CelConstant ofValue(Duration value) {
return AutoOneOf_CelConstant.durationValue(value);
}

/**
* @deprecated Do not use. Timestamp is no longer built-in CEL type.
*/
@Deprecated
public static CelConstant ofValue(Timestamp value) {
return AutoOneOf_CelConstant.timestampValue(value);
}

/** Checks whether the provided Java object is a valid CelConstant value. */
public static boolean isConstantValue(Object value) {
return CONSTANT_CLASSES.contains(value.getClass());
Expand All@@ -163,26 +201,10 @@ public static CelConstant ofObjectValue(Object value) {
return ofValue((double) value);
} else if (value instanceof String) {
return ofValue((String) value);
} else if (value instanceof ByteString) {
return ofValue((ByteString) value);
} else if (value instanceof CelByteString) {
return ofValue((CelByteString) value);
}

throw new IllegalArgumentException("Value is not a CelConstant: " + value);
}

/**
* @deprecated Do not use. Duration is no longer built-in CEL type.
*/
@Deprecated
public static CelConstant ofValue(Duration value) {
return AutoOneOf_CelConstant.durationValue(value);
}

/**
* @deprecated Do not use. Timestamp is no longer built-in CEL type.
*/
@Deprecated
public static CelConstant ofValue(Timestamp value) {
return AutoOneOf_CelConstant.timestampValue(value);
}
}
Loading
Loading