5353import dev .cel .runtime .CelRuntimeLibrary ;
5454import java .util .Arrays ;
5555import java .util .Optional ;
56+ import java .util .function .ObjIntConsumer ;
5657
5758/**
5859 * CelEnvironment is a native representation of a CEL environment for compiler and runtime. This
@@ -74,6 +75,24 @@ public abstract class CelEnvironment {
7475 "strings" , CanonicalCelExtension .STRINGS ,
7576 "comprehensions" , CanonicalCelExtension .COMPREHENSIONS );
7677
78+ private static final ImmutableMap <String , ObjIntConsumer <CelOptions .Builder >> LIMIT_HANDLERS =
79+ ImmutableMap .of (
80+ "cel.limit.expression_code_points" ,
81+ (options , value ) -> options .maxExpressionCodePointSize (value ),
82+ "cel.limit.parse_error_recovery" ,
83+ (options , value ) -> options .maxParseErrorRecoveryLimit (value ),
84+ "cel.limit.parse_recursion_depth" ,
85+ (options , value ) -> options .maxParseRecursionDepth (value ));
86+
87+ private static final ImmutableMap <String , BooleanOptionConsumer > FEATURE_HANDLERS =
88+ ImmutableMap .of (
89+ "cel.feature.macro_call_tracking" ,
90+ (options , enabled ) -> options .populateMacroCalls (enabled ),
91+ "cel.feature.backtick_escape_syntax" ,
92+ (options , enabled ) -> options .enableQuotedIdentifierSyntax (enabled ),
93+ "cel.feature.cross_type_numeric_comparisons" ,
94+ (options , enabled ) -> options .enableHeterogeneousNumericComparisons (enabled ));
95+
7796 /** Environment source in textual format (ex: textproto, YAML). */
7897 public abstract Optional <Source > source ();
7998
@@ -112,6 +131,9 @@ public abstract class CelEnvironment {
112131 /** Feature flags to enable in the environment. */
113132 public abstract ImmutableSet <FeatureFlag > features ();
114133
134+ /** Limits to set in the environment. */
135+ public abstract ImmutableSet <Limit > limits ();
136+
115137 /** Builder for {@link CelEnvironment}. */
116138 @ AutoValue .Builder
117139 public abstract static class Builder {
@@ -168,7 +190,14 @@ public Builder setFeatures(FeatureFlag... featureFlags) {
168190 return setFeatures (ImmutableSet .copyOf (featureFlags ));
169191 }
170192
171- public abstract Builder setFeatures (ImmutableSet <FeatureFlag > macros );
193+ public abstract Builder setFeatures (ImmutableSet <FeatureFlag > featureFlags );
194+
195+ @ CanIgnoreReturnValue
196+ public Builder setLimits (Limit ... limits ) {
197+ return setLimits (ImmutableSet .copyOf (limits ));
198+ }
199+
200+ public abstract Builder setLimits (ImmutableSet <Limit > limits );
172201
173202 abstract CelEnvironment autoBuild ();
174203
@@ -200,13 +229,14 @@ public static Builder newBuilder() {
200229 .setContainer (CelContainer .ofName ("" ))
201230 .setVariables (ImmutableSet .of ())
202231 .setFunctions (ImmutableSet .of ())
203- .setFeatures (ImmutableSet .of ());
232+ .setFeatures (ImmutableSet .of ())
233+ .setLimits (ImmutableSet .of ());
204234 }
205235
206236 /** Extends the provided {@link CelCompiler} environment with this configuration. */
207237 public CelCompiler extend (CelCompiler celCompiler , CelOptions celOptions )
208238 throws CelEnvironmentException {
209- celOptions = applyFeatureFlags (celOptions );
239+ celOptions = applyEnvironmentOptions (celOptions );
210240 try {
211241 CelTypeProvider celTypeProvider = celCompiler .getTypeProvider ();
212242 CelCompilerBuilder compilerBuilder =
@@ -236,7 +266,7 @@ public CelCompiler extend(CelCompiler celCompiler, CelOptions celOptions)
236266
237267 /** Extends the provided {@link Cel} environment with this configuration. */
238268 public Cel extend (Cel cel , CelOptions celOptions ) throws CelEnvironmentException {
239- celOptions = applyFeatureFlags (celOptions );
269+ celOptions = applyEnvironmentOptions (celOptions );
240270 try {
241271 // Casting is necessary to only extend the compiler here
242272 CelCompiler celCompiler = extend ((CelCompiler ) cel , celOptions );
@@ -249,18 +279,22 @@ public Cel extend(Cel cel, CelOptions celOptions) throws CelEnvironmentException
249279 }
250280 }
251281
252- private CelOptions applyFeatureFlags (CelOptions celOptions ) {
282+ private CelOptions applyEnvironmentOptions (CelOptions celOptions ) {
253283 CelOptions .Builder optionsBuilder = celOptions .toBuilder ();
254284 for (FeatureFlag featureFlag : features ()) {
255- if (featureFlag .name ().equals ("cel.feature.macro_call_tracking" )) {
256- optionsBuilder .populateMacroCalls (featureFlag .enabled ());
257- } else if (featureFlag .name ().equals ("cel.feature.backtick_escape_syntax" )) {
258- optionsBuilder .enableQuotedIdentifierSyntax (featureFlag .enabled ());
259- } else if (featureFlag .name ().equals ("cel.feature.cross_type_numeric_comparisons" )) {
260- optionsBuilder .enableHeterogeneousNumericComparisons (featureFlag .enabled ());
261- } else {
285+ BooleanOptionConsumer consumer = FEATURE_HANDLERS .get (featureFlag .name ());
286+ if (consumer == null ) {
262287 throw new IllegalArgumentException ("Unknown feature flag: " + featureFlag .name ());
263288 }
289+ consumer .accept (optionsBuilder , featureFlag .enabled ());
290+ }
291+ for (Limit limit : limits ()) {
292+ int value = limit .value () < 0 ? -1 : limit .value ();
293+ ObjIntConsumer <CelOptions .Builder > consumer = LIMIT_HANDLERS .get (limit .name ());
294+ if (consumer == null ) {
295+ throw new IllegalArgumentException ("Unknown limit: " + limit .name ());
296+ }
297+ consumer .accept (optionsBuilder , value );
264298 }
265299 return optionsBuilder .build ();
266300 }
@@ -672,6 +706,25 @@ public static FeatureFlag create(String name, boolean enabled) {
672706 }
673707 }
674708
709+ /**
710+ * Represents a configurable limit in the environment.
711+ *
712+ * <p>A negative value indicates no limit. If not specified, the limit should be set to the
713+ * library default.
714+ */
715+ @ AutoValue
716+ public abstract static class Limit {
717+ /** Normalized name of the limit (e.g. cel.limit.expression_code_points */
718+ public abstract String name ();
719+
720+ /** The value of the limit, -1 means no limit. */
721+ public abstract int value ();
722+
723+ public static Limit create (String name , int value ) {
724+ return new AutoValue_CelEnvironment_Limit (name , value );
725+ }
726+ }
727+
675728 /**
676729 * Represents a configuration for a canonical CEL extension that can be enabled in the
677730 * environment.
@@ -995,4 +1048,9 @@ public static OverloadSelector.Builder newBuilder() {
9951048 }
9961049 }
9971050 }
1051+
1052+ @ FunctionalInterface
1053+ private static interface BooleanOptionConsumer {
1054+ void accept (CelOptions .Builder options , boolean value );
1055+ }
9981056}
0 commit comments