|
17 | 17 | import static com.google.common.base.Preconditions.checkNotNull; |
18 | 18 | import static com.google.common.base.Preconditions.checkState; |
19 | 19 | import static com.google.common.collect.ImmutableList.toImmutableList; |
| 20 | +import static com.google.common.collect.ImmutableSet.toImmutableSet; |
20 | 21 |
|
21 | 22 | import com.google.auto.value.AutoValue; |
22 | 23 | import com.google.common.annotations.VisibleForTesting; |
|
25 | 26 | import com.google.common.collect.ImmutableSet; |
26 | 27 | import com.google.errorprone.annotations.CanIgnoreReturnValue; |
27 | 28 | import com.google.errorprone.annotations.CheckReturnValue; |
| 29 | +import dev.cel.checker.CelStandardDeclarations; |
| 30 | +import dev.cel.checker.CelStandardDeclarations.StandardFunction; |
28 | 31 | import dev.cel.common.CelFunctionDecl; |
29 | 32 | import dev.cel.common.CelOptions; |
30 | 33 | import dev.cel.common.CelOverloadDecl; |
|
41 | 44 | import dev.cel.compiler.CelCompilerBuilder; |
42 | 45 | import dev.cel.extensions.CelExtensions; |
43 | 46 | import dev.cel.extensions.CelOptionalLibrary; |
| 47 | +import dev.cel.parser.CelStandardMacro; |
44 | 48 | import dev.cel.runtime.CelRuntimeBuilder; |
45 | 49 | import java.util.Arrays; |
46 | 50 | import java.util.Optional; |
@@ -97,6 +101,9 @@ public abstract class CelEnvironment { |
97 | 101 | /** New function declarations to add in the compilation environment. */ |
98 | 102 | public abstract ImmutableSet<FunctionDecl> functions(); |
99 | 103 |
|
| 104 | + /** Standard library subset (which macros, functions to include/exclude) */ |
| 105 | + public abstract Optional<LibrarySubset> standardLibrarySubset(); |
| 106 | + |
100 | 107 | /** Builder for {@link CelEnvironment}. */ |
101 | 108 | @AutoValue.Builder |
102 | 109 | public abstract static class Builder { |
@@ -141,6 +148,8 @@ public Builder setFunctions(FunctionDecl... functions) { |
141 | 148 |
|
142 | 149 | public abstract Builder setFunctions(ImmutableSet<FunctionDecl> functions); |
143 | 150 |
|
| 151 | + public abstract Builder setStandardLibrarySubset(Optional<LibrarySubset> stdLibrarySubset); |
| 152 | + |
144 | 153 | @CheckReturnValue |
145 | 154 | public abstract CelEnvironment build(); |
146 | 155 | } |
@@ -180,6 +189,8 @@ public CelCompiler extend(CelCompiler celCompiler, CelOptions celOptions) |
180 | 189 |
|
181 | 190 | addAllCompilerExtensions(compilerBuilder, celOptions); |
182 | 191 |
|
| 192 | + applyStandardLibrarySubset(compilerBuilder); |
| 193 | + |
183 | 194 | return compilerBuilder.build(); |
184 | 195 | } catch (RuntimeException e) { |
185 | 196 | throw new CelEnvironmentException(e.getMessage(), e); |
@@ -218,6 +229,75 @@ private void addAllRuntimeExtensions(CelRuntimeBuilder celRuntimeBuilder, CelOpt |
218 | 229 | } |
219 | 230 | } |
220 | 231 |
|
| 232 | + private void applyStandardLibrarySubset(CelCompilerBuilder compilerBuilder) { |
| 233 | + if (!standardLibrarySubset().isPresent()) { |
| 234 | + return; |
| 235 | + } |
| 236 | + |
| 237 | + LibrarySubset librarySubset = standardLibrarySubset().get(); |
| 238 | + if (librarySubset.disabled()) { |
| 239 | + compilerBuilder.setStandardEnvironmentEnabled(false); |
| 240 | + return; |
| 241 | + } |
| 242 | + |
| 243 | + compilerBuilder.setStandardEnvironmentEnabled(true); |
| 244 | + |
| 245 | + if (librarySubset.macrosDisabled()) { |
| 246 | + compilerBuilder.setStandardMacros(ImmutableList.of()); |
| 247 | + } else if (!librarySubset.includedMacros().isEmpty()) { |
| 248 | + compilerBuilder.setStandardMacros( |
| 249 | + librarySubset.includedMacros().stream() |
| 250 | + .map(name -> getStandardMacroOrThrow(name)) |
| 251 | + .toList()); |
| 252 | + } else if (!librarySubset.excludedMacros().isEmpty()) { |
| 253 | + ImmutableSet<CelStandardMacro> set = |
| 254 | + librarySubset.excludedMacros().stream() |
| 255 | + .map(name -> getStandardMacroOrThrow(name)) |
| 256 | + .collect(toImmutableSet()); |
| 257 | + compilerBuilder.setStandardMacros( |
| 258 | + CelStandardMacro.STANDARD_MACROS.stream().filter(macro -> !set.contains(macro)).toList()); |
| 259 | + } |
| 260 | + |
| 261 | + if (!librarySubset.includedFunctions().isEmpty()) { |
| 262 | + compilerBuilder.setStandardEnvironmentEnabled(false); |
| 263 | + compilerBuilder.setStandardDeclarations( |
| 264 | + CelStandardDeclarations.newBuilder() |
| 265 | + .includeFunctions( |
| 266 | + librarySubset.includedFunctions().stream() |
| 267 | + .map(name -> getStandardFunctionOrThrow(name)) |
| 268 | + .toList()) |
| 269 | + .build()); |
| 270 | + } else if (!librarySubset.excludedFunctions().isEmpty()) { |
| 271 | + compilerBuilder.setStandardEnvironmentEnabled(false); |
| 272 | + compilerBuilder.setStandardDeclarations( |
| 273 | + CelStandardDeclarations.newBuilder() |
| 274 | + .excludeFunctions( |
| 275 | + librarySubset.excludedFunctions().stream() |
| 276 | + .map(name -> getStandardFunctionOrThrow(name)) |
| 277 | + .toList()) |
| 278 | + .build()); |
| 279 | + |
| 280 | + } |
| 281 | + } |
| 282 | + |
| 283 | + private static CelStandardMacro getStandardMacroOrThrow(String macroName) { |
| 284 | + for (CelStandardMacro macro : CelStandardMacro.STANDARD_MACROS) { |
| 285 | + if (macro.getFunction().equals(macroName)) { |
| 286 | + return macro; |
| 287 | + } |
| 288 | + } |
| 289 | + throw new IllegalArgumentException("unrecognized standard macro `" + macroName + "'"); |
| 290 | + } |
| 291 | + |
| 292 | + private static StandardFunction getStandardFunctionOrThrow(String functionName) { |
| 293 | + for (StandardFunction function : StandardFunction.values()) { |
| 294 | + if (function.functionName().equals(functionName)) { |
| 295 | + return function; |
| 296 | + } |
| 297 | + } |
| 298 | + throw new IllegalArgumentException("unrecognized standard function `" + functionName + "'"); |
| 299 | + } |
| 300 | + |
221 | 301 | private static CanonicalCelExtension getExtensionOrThrow(String extensionName) { |
222 | 302 | CanonicalCelExtension extension = CEL_EXTENSION_CONFIG_MAP.get(extensionName); |
223 | 303 | if (extension == null) { |
@@ -624,4 +704,76 @@ void addRuntimeExtension(CelRuntimeBuilder runtimeBuilder, CelOptions options) { |
624 | 704 | this.runtimeExtensionApplier = runtimeExtensionApplier; |
625 | 705 | } |
626 | 706 | } |
| 707 | + |
| 708 | + /** |
| 709 | + * LibrarySubset indicates a subset of the macros and function supported by a subsettable |
| 710 | + * library. |
| 711 | + */ |
| 712 | + @AutoValue |
| 713 | + public abstract static class LibrarySubset { |
| 714 | + |
| 715 | + /** |
| 716 | + * Disabled indicates whether the library has been disabled, typically only used for |
| 717 | + * default-enabled libraries like stdlib. |
| 718 | + */ |
| 719 | + public abstract boolean disabled(); |
| 720 | + |
| 721 | + /** DisableMacros disables macros for the given library. */ |
| 722 | + public abstract boolean macrosDisabled(); |
| 723 | + |
| 724 | + /** IncludeMacros specifies a set of macro function names to include in the subset. */ |
| 725 | + public abstract ImmutableSet<String> includedMacros(); |
| 726 | + |
| 727 | + /** |
| 728 | + * ExcludeMacros specifies a set of macro function names to exclude from the subset. |
| 729 | + * |
| 730 | + * <p>Note: if IncludedMacros is non-empty, then ExcludedMacros is ignored. |
| 731 | + */ |
| 732 | + public abstract ImmutableSet<String> excludedMacros(); |
| 733 | + |
| 734 | + /** |
| 735 | + * IncludeFunctions specifies a set of functions to include in the subset. |
| 736 | + * |
| 737 | + * <p>Note: the overloads specified in the subset need only specify their ID. |
| 738 | + * <p>Note: if IncludedFunctions is non-empty, then ExcludedFunctions is ignored. |
| 739 | + */ |
| 740 | + public abstract ImmutableSet<String> includedFunctions(); |
| 741 | + |
| 742 | + /** |
| 743 | + * ExcludeFunctions specifies the set of functions to exclude from the subset. |
| 744 | + * |
| 745 | + * <p>Note: the overloads specified in the subset need only specify their ID. |
| 746 | + */ |
| 747 | + public abstract ImmutableSet<String> excludedFunctions(); |
| 748 | + |
| 749 | + public static Builder newBuilder() { |
| 750 | + return new AutoValue_CelEnvironment_LibrarySubset.Builder() |
| 751 | + .setDisabled(true) |
| 752 | + .setMacrosDisabled(false) |
| 753 | + .setIncludedMacros(ImmutableSet.of()) |
| 754 | + .setExcludedMacros(ImmutableSet.of()) |
| 755 | + .setIncludedFunctions(ImmutableSet.of()) |
| 756 | + .setExcludedFunctions(ImmutableSet.of()); |
| 757 | + } |
| 758 | + |
| 759 | + /** Builder for {@link LibrarySubset}. */ |
| 760 | + @AutoValue.Builder |
| 761 | + public abstract static class Builder { |
| 762 | + |
| 763 | + public abstract Builder setDisabled(boolean disabled); |
| 764 | + |
| 765 | + public abstract Builder setMacrosDisabled(boolean disabled); |
| 766 | + |
| 767 | + public abstract Builder setIncludedMacros(ImmutableSet<String> includedMacros); |
| 768 | + |
| 769 | + public abstract Builder setExcludedMacros(ImmutableSet<String> excludedMacros); |
| 770 | + |
| 771 | + public abstract Builder setIncludedFunctions(ImmutableSet<String> includedFunctions); |
| 772 | + |
| 773 | + public abstract Builder setExcludedFunctions(ImmutableSet<String> excludedFunctions); |
| 774 | + |
| 775 | + @CheckReturnValue |
| 776 | + public abstract LibrarySubset build(); |
| 777 | + } |
| 778 | + } |
627 | 779 | } |
0 commit comments