From 8a6a10d3f63b8ebb50ad95bbe6e49b73c6067ff4 Mon Sep 17 00:00:00 2001
From: Piyush Garg
Date: Tue, 29 Aug 2023 13:21:44 +0530
Subject: [PATCH] Bump triggers to v0.25.0
---
go.mod | 12 +-
go.sum | 21 +-
pkg/cmd/eventlistener/describe_test.go | 11 +-
.../antlr4/runtime/Go/antlr/{ => v4}/LICENSE | 0
.../antlr4/runtime/Go/antlr/v4/antlrdoc.go | 68 +
.../antlr4/runtime/Go/antlr/{ => v4}/atn.go | 27 +-
.../runtime/Go/antlr/{ => v4}/atn_config.go | 54 +-
.../Go/antlr/{ => v4}/atn_config_set.go | 80 +-
.../{ => v4}/atn_deserialization_options.go | 2 +-
.../Go/antlr/{ => v4}/atn_deserializer.go | 2 +-
.../Go/antlr/{ => v4}/atn_simulator.go | 2 +-
.../runtime/Go/antlr/{ => v4}/atn_state.go | 9 +-
.../runtime/Go/antlr/{ => v4}/atn_type.go | 2 +-
.../runtime/Go/antlr/{ => v4}/char_stream.go | 2 +-
.../Go/antlr/{ => v4}/common_token_factory.go | 2 +-
.../Go/antlr/{ => v4}/common_token_stream.go | 6 +-
.../antlr4/runtime/Go/antlr/v4/comparators.go | 147 +
.../antlr4/runtime/Go/antlr/{ => v4}/dfa.go | 54 +-
.../Go/antlr/{ => v4}/dfa_serializer.go | 2 +-
.../runtime/Go/antlr/{ => v4}/dfa_state.go | 54 +-
.../{ => v4}/diagnostic_error_listener.go | 4 +-
.../Go/antlr/{ => v4}/error_listener.go | 6 +-
.../Go/antlr/{ => v4}/error_strategy.go | 38 +-
.../runtime/Go/antlr/{ => v4}/errors.go | 5 +-
.../runtime/Go/antlr/{ => v4}/file_stream.go | 2 +-
.../runtime/Go/antlr/{ => v4}/input_stream.go | 2 +-
.../runtime/Go/antlr/{ => v4}/int_stream.go | 2 +-
.../runtime/Go/antlr/{ => v4}/interval_set.go | 6 +-
.../antlr4/runtime/Go/antlr/v4/jcollect.go | 198 +
.../antlr4/runtime/Go/antlr/{ => v4}/lexer.go | 6 +-
.../runtime/Go/antlr/{ => v4}/lexer_action.go | 44 +-
.../antlr/{ => v4}/lexer_action_executor.go | 27 +-
.../Go/antlr/{ => v4}/lexer_atn_simulator.go | 17 +-
.../runtime/Go/antlr/{ => v4}/ll1_analyzer.go | 30 +-
.../runtime/Go/antlr/{ => v4}/parser.go | 14 +-
.../Go/antlr/{ => v4}/parser_atn_simulator.go | 153 +-
.../Go/antlr/{ => v4}/parser_rule_context.go | 4 +-
.../Go/antlr/{ => v4}/prediction_context.go | 161 +-
.../Go/antlr/{ => v4}/prediction_mode.go | 48 +-
.../runtime/Go/antlr/{ => v4}/recognizer.go | 19 +-
.../runtime/Go/antlr/{ => v4}/rule_context.go | 2 +-
.../Go/antlr/{ => v4}/semantic_context.go | 81 +-
.../antlr4/runtime/Go/antlr/{ => v4}/token.go | 3 +-
.../runtime/Go/antlr/{ => v4}/token_source.go | 2 +-
.../runtime/Go/antlr/{ => v4}/token_stream.go | 2 +-
.../Go/antlr/{ => v4}/tokenstream_rewriter.go | 420 +--
.../Go/antlr/{ => v4}/trace_listener.go | 2 +-
.../runtime/Go/antlr/{ => v4}/transition.go | 2 +-
.../antlr4/runtime/Go/antlr/{ => v4}/tree.go | 5 +-
.../antlr4/runtime/Go/antlr/{ => v4}/trees.go | 9 +-
.../antlr4/runtime/Go/antlr/{ => v4}/utils.go | 21 +-
.../runtime/Go/antlr/{ => v4}/utils_set.go | 34 +-
.../github.com/google/cel-go/cel/BUILD.bazel | 12 +-
vendor/github.com/google/cel-go/cel/decls.go | 1088 +-----
vendor/github.com/google/cel-go/cel/env.go | 412 ++-
vendor/github.com/google/cel-go/cel/io.go | 46 +-
.../github.com/google/cel-go/cel/library.go | 299 +-
vendor/github.com/google/cel-go/cel/macro.go | 11 +-
.../github.com/google/cel-go/cel/options.go | 169 +-
.../github.com/google/cel-go/cel/program.go | 81 +-
.../github.com/google/cel-go/cel/validator.go | 388 ++
.../google/cel-go/checker/BUILD.bazel | 10 +-
.../google/cel-go/checker/checker.go | 433 ++-
.../github.com/google/cel-go/checker/cost.go | 107 +-
.../google/cel-go/checker/decls/BUILD.bazel | 3 +-
.../github.com/google/cel-go/checker/env.go | 239 +-
.../google/cel-go/checker/errors.go | 94 +-
.../google/cel-go/checker/format.go | 216 ++
.../google/cel-go/checker/mapping.go | 14 +-
.../google/cel-go/checker/options.go | 13 +-
.../google/cel-go/checker/printer.go | 3 +
.../cel-go/checker/{decls => }/scopes.go | 38 +-
.../google/cel-go/checker/standard.go | 481 +--
.../github.com/google/cel-go/checker/types.go | 404 +--
.../google/cel-go/common/BUILD.bazel | 2 +-
.../google/cel-go/common/ast/BUILD.bazel | 52 +
.../google/cel-go/common/ast/ast.go | 226 ++
.../google/cel-go/common/ast/expr.go | 709 ++++
.../cel-go/common/containers/BUILD.bazel | 4 +-
.../google/cel-go/common/debug/BUILD.bazel | 2 +-
.../google/cel-go/common/decls/BUILD.bazel | 39 +
.../google/cel-go/common/decls/decls.go | 843 +++++
.../github.com/google/cel-go/common/error.go | 8 +-
.../github.com/google/cel-go/common/errors.go | 16 +-
.../cel-go/common/functions/BUILD.bazel | 17 +
.../cel-go/common/functions/functions.go | 61 +
.../cel-go/common/overloads/overloads.go | 10 +
.../github.com/google/cel-go/common/source.go | 3 -
.../google/cel-go/common/stdlib/BUILD.bazel | 25 +
.../google/cel-go/common/stdlib/standard.go | 661 ++++
.../google/cel-go/common/types/BUILD.bazel | 11 +-
.../google/cel-go/common/types/bool.go | 6 -
.../google/cel-go/common/types/bytes.go | 7 -
.../google/cel-go/common/types/double.go | 14 +-
.../google/cel-go/common/types/duration.go | 76 +-
.../google/cel-go/common/types/err.go | 17 +-
.../google/cel-go/common/types/int.go | 25 +-
.../google/cel-go/common/types/iterator.go | 2 +-
.../google/cel-go/common/types/list.go | 90 +-
.../google/cel-go/common/types/map.go | 87 +-
.../google/cel-go/common/types/null.go | 2 -
.../google/cel-go/common/types/object.go | 18 +-
.../google/cel-go/common/types/optional.go | 2 +-
.../google/cel-go/common/types/pb/BUILD.bazel | 2 +-
.../google/cel-go/common/types/pb/type.go | 23 +-
.../google/cel-go/common/types/provider.go | 244 +-
.../cel-go/common/types/ref/BUILD.bazel | 2 +-
.../cel-go/common/types/ref/provider.go | 37 +-
.../cel-go/common/types/ref/reference.go | 11 +-
.../google/cel-go/common/types/string.go | 44 +-
.../google/cel-go/common/types/timestamp.go | 20 +-
.../google/cel-go/common/types/type.go | 102 -
.../google/cel-go/common/types/types.go | 806 +++++
.../google/cel-go/common/types/uint.go | 22 +-
.../google/cel-go/common/types/unknown.go | 290 +-
.../google/cel-go/common/types/util.go | 2 +-
.../github.com/google/cel-go/ext/BUILD.bazel | 68 +
vendor/github.com/google/cel-go/ext/README.md | 416 +++
.../github.com/google/cel-go/ext/bindings.go | 96 +
.../github.com/google/cel-go/ext/encoders.go | 87 +
vendor/github.com/google/cel-go/ext/guards.go | 64 +
vendor/github.com/google/cel-go/ext/lists.go | 94 +
vendor/github.com/google/cel-go/ext/math.go | 373 ++
vendor/github.com/google/cel-go/ext/native.go | 574 +++
vendor/github.com/google/cel-go/ext/protos.go | 141 +
vendor/github.com/google/cel-go/ext/sets.go | 138 +
.../github.com/google/cel-go/ext/strings.go | 1095 ++++++
.../google/cel-go/interpreter/BUILD.bazel | 15 +-
.../google/cel-go/interpreter/activation.go | 2 +-
.../cel-go/interpreter/attribute_patterns.go | 42 +-
.../google/cel-go/interpreter/attributes.go | 198 +-
.../google/cel-go/interpreter/coster.go | 35 -
.../google/cel-go/interpreter/decorators.go | 21 +-
.../google/cel-go/interpreter/dispatcher.go | 2 +-
.../google/cel-go/interpreter/evalstate.go | 6 +-
.../google/cel-go/interpreter/formatting.go | 383 ++
.../cel-go/interpreter/functions/BUILD.bazel | 9 +-
.../cel-go/interpreter/functions/functions.go | 33 +-
.../cel-go/interpreter/functions/standard.go | 270 --
.../cel-go/interpreter/interpretable.go | 680 ++--
.../google/cel-go/interpreter/interpreter.go | 28 +-
.../google/cel-go/interpreter/planner.go | 125 +-
.../google/cel-go/interpreter/prune.go | 374 +-
.../google/cel-go/interpreter/runtimecost.go | 72 +-
.../google/cel-go/parser/BUILD.bazel | 6 +-
.../github.com/google/cel-go/parser/errors.go | 17 +-
.../google/cel-go/parser/gen/BUILD.bazel | 2 +-
.../google/cel-go/parser/gen/CEL.g4 | 28 +-
.../google/cel-go/parser/gen/CEL.interp | 9 +-
.../google/cel-go/parser/gen/CEL.tokens | 132 +-
.../google/cel-go/parser/gen/CELLexer.interp | 8 +-
.../google/cel-go/parser/gen/CELLexer.tokens | 132 +-
.../cel-go/parser/gen/cel_base_listener.go | 18 +-
.../cel-go/parser/gen/cel_base_visitor.go | 10 +-
.../google/cel-go/parser/gen/cel_lexer.go | 483 ++-
.../google/cel-go/parser/gen/cel_listener.go | 18 +-
.../google/cel-go/parser/gen/cel_parser.go | 1276 ++++---
.../google/cel-go/parser/gen/cel_visitor.go | 11 +-
.../google/cel-go/parser/gen/generate.sh | 2 +-
.../github.com/google/cel-go/parser/helper.go | 127 +-
.../github.com/google/cel-go/parser/input.go | 2 +-
.../github.com/google/cel-go/parser/macro.go | 17 +-
.../google/cel-go/parser/options.go | 29 +-
.../github.com/google/cel-go/parser/parser.go | 118 +-
.../google/cel-go/parser/unparser.go | 56 +-
.../v1alpha1/event_listener_validation.go | 22 +-
.../v1beta1/event_listener_validation.go | 22 +-
.../triggers/v1beta1/openapi_generated.go | 307 +-
.../pkg/apis/triggers/v1beta1/swagger.json | 22 +-
.../apis/triggers/v1beta1/trigger_types.go | 69 -
.../triggers/v1beta1/zz_generated.deepcopy.go | 180 -
.../triggers/pkg/interceptors/cel/cel.go | 253 ++
.../triggers/pkg/interceptors/cel/triggers.go | 365 ++
.../triggers/pkg/interceptors/interceptors.go | 145 +
.../triggers/pkg/interceptors/interface.go | 1 +
.../pkg/interceptors/secret_getter.go | 85 +
.../eventlistener/resources/deployment.go | 43 +-
.../eventlistener/resources/service.go | 9 +-
.../triggers/test/e2e-tests-examples.sh | 9 +-
.../tektoncd/triggers/test/resources.go | 12 +
vendor/github.com/tidwall/gjson/LICENSE | 20 +
vendor/github.com/tidwall/gjson/README.md | 490 +++
vendor/github.com/tidwall/gjson/SYNTAX.md | 339 ++
vendor/github.com/tidwall/gjson/gjson.go | 3214 +++++++++++++++++
vendor/github.com/tidwall/gjson/logo.png | Bin 0 -> 15936 bytes
vendor/github.com/tidwall/match/LICENSE | 20 +
vendor/github.com/tidwall/match/README.md | 29 +
vendor/github.com/tidwall/match/match.go | 237 ++
vendor/github.com/tidwall/pretty/LICENSE | 20 +
vendor/github.com/tidwall/pretty/README.md | 122 +
vendor/github.com/tidwall/pretty/pretty.go | 674 ++++
vendor/github.com/tidwall/sjson/LICENSE | 21 +
vendor/github.com/tidwall/sjson/README.md | 278 ++
vendor/github.com/tidwall/sjson/logo.png | Bin 0 -> 16874 bytes
vendor/github.com/tidwall/sjson/sjson.go | 737 ++++
.../x/text/feature/plural/common.go | 70 +
.../x/text/feature/plural/message.go | 244 ++
.../x/text/feature/plural/plural.go | 262 ++
.../x/text/feature/plural/tables.go | 552 +++
.../x/text/internal/catmsg/catmsg.go | 417 +++
.../x/text/internal/catmsg/codec.go | 407 +++
.../x/text/internal/catmsg/varint.go | 62 +
.../x/text/internal/format/format.go | 41 +
.../x/text/internal/format/parser.go | 358 ++
.../x/text/internal/number/common.go | 55 +
.../x/text/internal/number/decimal.go | 500 +++
.../x/text/internal/number/format.go | 535 +++
.../x/text/internal/number/number.go | 152 +
.../x/text/internal/number/pattern.go | 485 +++
.../internal/number/roundingmode_string.go | 30 +
.../x/text/internal/number/tables.go | 1219 +++++++
.../x/text/internal/stringset/set.go | 86 +
vendor/golang.org/x/text/message/catalog.go | 36 +
.../x/text/message/catalog/catalog.go | 365 ++
.../golang.org/x/text/message/catalog/dict.go | 129 +
.../golang.org/x/text/message/catalog/go19.go | 16 +
.../x/text/message/catalog/gopre19.go | 24 +
vendor/golang.org/x/text/message/doc.go | 99 +
vendor/golang.org/x/text/message/format.go | 510 +++
vendor/golang.org/x/text/message/message.go | 193 +
vendor/golang.org/x/text/message/print.go | 984 +++++
vendor/modules.txt | 38 +-
222 files changed, 28449 insertions(+), 6234 deletions(-)
rename vendor/github.com/antlr/antlr4/runtime/Go/antlr/{ => v4}/LICENSE (100%)
create mode 100644 vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/antlrdoc.go
rename vendor/github.com/antlr/antlr4/runtime/Go/antlr/{ => v4}/atn.go (72%)
rename vendor/github.com/antlr/antlr4/runtime/Go/antlr/{ => v4}/atn_config.go (84%)
rename vendor/github.com/antlr/antlr4/runtime/Go/antlr/{ => v4}/atn_config_set.go (81%)
rename vendor/github.com/antlr/antlr4/runtime/Go/antlr/{ => v4}/atn_deserialization_options.go (96%)
rename vendor/github.com/antlr/antlr4/runtime/Go/antlr/{ => v4}/atn_deserializer.go (99%)
rename vendor/github.com/antlr/antlr4/runtime/Go/antlr/{ => v4}/atn_simulator.go (94%)
rename vendor/github.com/antlr/antlr4/runtime/Go/antlr/{ => v4}/atn_state.go (97%)
rename vendor/github.com/antlr/antlr4/runtime/Go/antlr/{ => v4}/atn_type.go (79%)
rename vendor/github.com/antlr/antlr4/runtime/Go/antlr/{ => v4}/char_stream.go (82%)
rename vendor/github.com/antlr/antlr4/runtime/Go/antlr/{ => v4}/common_token_factory.go (96%)
rename vendor/github.com/antlr/antlr4/runtime/Go/antlr/{ => v4}/common_token_stream.go (98%)
create mode 100644 vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/comparators.go
rename vendor/github.com/antlr/antlr4/runtime/Go/antlr/{ => v4}/dfa.go (80%)
rename vendor/github.com/antlr/antlr4/runtime/Go/antlr/{ => v4}/dfa_serializer.go (97%)
rename vendor/github.com/antlr/antlr4/runtime/Go/antlr/{ => v4}/dfa_state.go (90%)
rename vendor/github.com/antlr/antlr4/runtime/Go/antlr/{ => v4}/diagnostic_error_listener.go (98%)
rename vendor/github.com/antlr/antlr4/runtime/Go/antlr/{ => v4}/error_listener.go (98%)
rename vendor/github.com/antlr/antlr4/runtime/Go/antlr/{ => v4}/error_strategy.go (99%)
rename vendor/github.com/antlr/antlr4/runtime/Go/antlr/{ => v4}/errors.go (98%)
rename vendor/github.com/antlr/antlr4/runtime/Go/antlr/{ => v4}/file_stream.go (92%)
rename vendor/github.com/antlr/antlr4/runtime/Go/antlr/{ => v4}/input_stream.go (96%)
rename vendor/github.com/antlr/antlr4/runtime/Go/antlr/{ => v4}/int_stream.go (82%)
rename vendor/github.com/antlr/antlr4/runtime/Go/antlr/{ => v4}/interval_set.go (98%)
create mode 100644 vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/jcollect.go
rename vendor/github.com/antlr/antlr4/runtime/Go/antlr/{ => v4}/lexer.go (98%)
rename vendor/github.com/antlr/antlr4/runtime/Go/antlr/{ => v4}/lexer_action.go (91%)
rename vendor/github.com/antlr/antlr4/runtime/Go/antlr/{ => v4}/lexer_action_executor.go (88%)
rename vendor/github.com/antlr/antlr4/runtime/Go/antlr/{ => v4}/lexer_atn_simulator.go (98%)
rename vendor/github.com/antlr/antlr4/runtime/Go/antlr/{ => v4}/ll1_analyzer.go (87%)
rename vendor/github.com/antlr/antlr4/runtime/Go/antlr/{ => v4}/parser.go (99%)
rename vendor/github.com/antlr/antlr4/runtime/Go/antlr/{ => v4}/parser_atn_simulator.go (94%)
rename vendor/github.com/antlr/antlr4/runtime/Go/antlr/{ => v4}/parser_rule_context.go (98%)
rename vendor/github.com/antlr/antlr4/runtime/Go/antlr/{ => v4}/prediction_context.go (81%)
rename vendor/github.com/antlr/antlr4/runtime/Go/antlr/{ => v4}/prediction_mode.go (95%)
rename vendor/github.com/antlr/antlr4/runtime/Go/antlr/{ => v4}/recognizer.go (92%)
rename vendor/github.com/antlr/antlr4/runtime/Go/antlr/{ => v4}/rule_context.go (97%)
rename vendor/github.com/antlr/antlr4/runtime/Go/antlr/{ => v4}/semantic_context.go (85%)
rename vendor/github.com/antlr/antlr4/runtime/Go/antlr/{ => v4}/token.go (98%)
rename vendor/github.com/antlr/antlr4/runtime/Go/antlr/{ => v4}/token_source.go (85%)
rename vendor/github.com/antlr/antlr4/runtime/Go/antlr/{ => v4}/token_stream.go (87%)
rename vendor/github.com/antlr/antlr4/runtime/Go/antlr/{ => v4}/tokenstream_rewriter.go (58%)
rename vendor/github.com/antlr/antlr4/runtime/Go/antlr/{ => v4}/trace_listener.go (93%)
rename vendor/github.com/antlr/antlr4/runtime/Go/antlr/{ => v4}/transition.go (99%)
rename vendor/github.com/antlr/antlr4/runtime/Go/antlr/{ => v4}/tree.go (98%)
rename vendor/github.com/antlr/antlr4/runtime/Go/antlr/{ => v4}/trees.go (93%)
rename vendor/github.com/antlr/antlr4/runtime/Go/antlr/{ => v4}/utils.go (94%)
rename vendor/github.com/antlr/antlr4/runtime/Go/antlr/{ => v4}/utils_set.go (80%)
create mode 100644 vendor/github.com/google/cel-go/cel/validator.go
create mode 100644 vendor/github.com/google/cel-go/checker/format.go
rename vendor/github.com/google/cel-go/checker/{decls => }/scopes.go (81%)
create mode 100644 vendor/github.com/google/cel-go/common/ast/BUILD.bazel
create mode 100644 vendor/github.com/google/cel-go/common/ast/ast.go
create mode 100644 vendor/github.com/google/cel-go/common/ast/expr.go
create mode 100644 vendor/github.com/google/cel-go/common/decls/BUILD.bazel
create mode 100644 vendor/github.com/google/cel-go/common/decls/decls.go
create mode 100644 vendor/github.com/google/cel-go/common/functions/BUILD.bazel
create mode 100644 vendor/github.com/google/cel-go/common/functions/functions.go
create mode 100644 vendor/github.com/google/cel-go/common/stdlib/BUILD.bazel
create mode 100644 vendor/github.com/google/cel-go/common/stdlib/standard.go
delete mode 100644 vendor/github.com/google/cel-go/common/types/type.go
create mode 100644 vendor/github.com/google/cel-go/common/types/types.go
create mode 100644 vendor/github.com/google/cel-go/ext/BUILD.bazel
create mode 100644 vendor/github.com/google/cel-go/ext/README.md
create mode 100644 vendor/github.com/google/cel-go/ext/bindings.go
create mode 100644 vendor/github.com/google/cel-go/ext/encoders.go
create mode 100644 vendor/github.com/google/cel-go/ext/guards.go
create mode 100644 vendor/github.com/google/cel-go/ext/lists.go
create mode 100644 vendor/github.com/google/cel-go/ext/math.go
create mode 100644 vendor/github.com/google/cel-go/ext/native.go
create mode 100644 vendor/github.com/google/cel-go/ext/protos.go
create mode 100644 vendor/github.com/google/cel-go/ext/sets.go
create mode 100644 vendor/github.com/google/cel-go/ext/strings.go
delete mode 100644 vendor/github.com/google/cel-go/interpreter/coster.go
create mode 100644 vendor/github.com/google/cel-go/interpreter/formatting.go
delete mode 100644 vendor/github.com/google/cel-go/interpreter/functions/standard.go
create mode 100644 vendor/github.com/tektoncd/triggers/pkg/interceptors/cel/cel.go
create mode 100644 vendor/github.com/tektoncd/triggers/pkg/interceptors/cel/triggers.go
create mode 100644 vendor/github.com/tektoncd/triggers/pkg/interceptors/interceptors.go
create mode 100644 vendor/github.com/tektoncd/triggers/pkg/interceptors/interface.go
create mode 100644 vendor/github.com/tektoncd/triggers/pkg/interceptors/secret_getter.go
create mode 100644 vendor/github.com/tidwall/gjson/LICENSE
create mode 100644 vendor/github.com/tidwall/gjson/README.md
create mode 100644 vendor/github.com/tidwall/gjson/SYNTAX.md
create mode 100644 vendor/github.com/tidwall/gjson/gjson.go
create mode 100644 vendor/github.com/tidwall/gjson/logo.png
create mode 100644 vendor/github.com/tidwall/match/LICENSE
create mode 100644 vendor/github.com/tidwall/match/README.md
create mode 100644 vendor/github.com/tidwall/match/match.go
create mode 100644 vendor/github.com/tidwall/pretty/LICENSE
create mode 100644 vendor/github.com/tidwall/pretty/README.md
create mode 100644 vendor/github.com/tidwall/pretty/pretty.go
create mode 100644 vendor/github.com/tidwall/sjson/LICENSE
create mode 100644 vendor/github.com/tidwall/sjson/README.md
create mode 100644 vendor/github.com/tidwall/sjson/logo.png
create mode 100644 vendor/github.com/tidwall/sjson/sjson.go
create mode 100644 vendor/golang.org/x/text/feature/plural/common.go
create mode 100644 vendor/golang.org/x/text/feature/plural/message.go
create mode 100644 vendor/golang.org/x/text/feature/plural/plural.go
create mode 100644 vendor/golang.org/x/text/feature/plural/tables.go
create mode 100644 vendor/golang.org/x/text/internal/catmsg/catmsg.go
create mode 100644 vendor/golang.org/x/text/internal/catmsg/codec.go
create mode 100644 vendor/golang.org/x/text/internal/catmsg/varint.go
create mode 100644 vendor/golang.org/x/text/internal/format/format.go
create mode 100644 vendor/golang.org/x/text/internal/format/parser.go
create mode 100644 vendor/golang.org/x/text/internal/number/common.go
create mode 100644 vendor/golang.org/x/text/internal/number/decimal.go
create mode 100644 vendor/golang.org/x/text/internal/number/format.go
create mode 100644 vendor/golang.org/x/text/internal/number/number.go
create mode 100644 vendor/golang.org/x/text/internal/number/pattern.go
create mode 100644 vendor/golang.org/x/text/internal/number/roundingmode_string.go
create mode 100644 vendor/golang.org/x/text/internal/number/tables.go
create mode 100644 vendor/golang.org/x/text/internal/stringset/set.go
create mode 100644 vendor/golang.org/x/text/message/catalog.go
create mode 100644 vendor/golang.org/x/text/message/catalog/catalog.go
create mode 100644 vendor/golang.org/x/text/message/catalog/dict.go
create mode 100644 vendor/golang.org/x/text/message/catalog/go19.go
create mode 100644 vendor/golang.org/x/text/message/catalog/gopre19.go
create mode 100644 vendor/golang.org/x/text/message/doc.go
create mode 100644 vendor/golang.org/x/text/message/format.go
create mode 100644 vendor/golang.org/x/text/message/message.go
create mode 100644 vendor/golang.org/x/text/message/print.go
diff --git a/go.mod b/go.mod
index ce8390e66..60c3385cb 100644
--- a/go.mod
+++ b/go.mod
@@ -25,9 +25,9 @@ require (
github.com/spf13/pflag v1.0.5
github.com/tektoncd/chains v0.17.0
github.com/tektoncd/hub v1.13.0
- github.com/tektoncd/pipeline v0.50.0
+ github.com/tektoncd/pipeline v0.50.1
github.com/tektoncd/plumbing v0.0.0-20221102182345-5dbcfda657d7
- github.com/tektoncd/triggers v0.24.1
+ github.com/tektoncd/triggers v0.25.0
github.com/theupdateframework/go-tuf v0.6.1
go.opencensus.io v0.24.0
go.uber.org/multierr v1.11.0
@@ -86,7 +86,7 @@ require (
github.com/alibabacloud-go/tea-utils v1.4.4 // indirect
github.com/alibabacloud-go/tea-xml v1.1.2 // indirect
github.com/aliyun/credentials-go v1.2.3 // indirect
- github.com/antlr/antlr4/runtime/Go/antlr v1.4.10 // indirect
+ github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230305170008-8188dc5388df // indirect
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
github.com/aws/aws-sdk-go v1.44.303 // indirect
github.com/aws/aws-sdk-go-v2 v1.19.0 // indirect
@@ -162,7 +162,7 @@ require (
github.com/golang/protobuf v1.5.3 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/google/btree v1.1.2 // indirect
- github.com/google/cel-go v0.13.0 // indirect
+ github.com/google/cel-go v0.17.1 // indirect
github.com/google/certificate-transparency-go v1.1.6 // indirect
github.com/google/gnostic v0.6.9 // indirect
github.com/google/go-containerregistry/pkg/authn/k8schain v0.0.0-20230625233257-b8504803389b // indirect
@@ -272,6 +272,10 @@ require (
github.com/subosito/gotenv v1.4.2 // indirect
github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect
github.com/thales-e-security/pool v0.0.2 // indirect
+ github.com/tidwall/gjson v1.12.1 // indirect
+ github.com/tidwall/match v1.1.1 // indirect
+ github.com/tidwall/pretty v1.2.0 // indirect
+ github.com/tidwall/sjson v1.2.4 // indirect
github.com/titanous/rocacheck v0.0.0-20171023193734-afe73141d399 // indirect
github.com/tjfoc/gmsm v1.3.2 // indirect
github.com/transparency-dev/merkle v0.0.2 // indirect
diff --git a/go.sum b/go.sum
index dd202efe6..67425ad5b 100644
--- a/go.sum
+++ b/go.sum
@@ -886,8 +886,8 @@ github.com/antihax/optional v0.0.0-20180407024304-ca021399b1a6/go.mod h1:V8iCPQY
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20210826220005-b48c857c3a0e/go.mod h1:F7bn7fEU90QkQ3tnmaTx3LTKLEDqnwWODIYppRQ5hnY=
github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20211221011931-643d94fcab96/go.mod h1:F7bn7fEU90QkQ3tnmaTx3LTKLEDqnwWODIYppRQ5hnY=
-github.com/antlr/antlr4/runtime/Go/antlr v1.4.10 h1:yL7+Jz0jTC6yykIK/Wh74gnTJnrGr5AyrNMXuA0gves=
-github.com/antlr/antlr4/runtime/Go/antlr v1.4.10/go.mod h1:F7bn7fEU90QkQ3tnmaTx3LTKLEDqnwWODIYppRQ5hnY=
+github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230305170008-8188dc5388df h1:7RFfzj4SSt6nnvCPbCqijJi1nWCd+TqAT3bYCStRC18=
+github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230305170008-8188dc5388df/go.mod h1:pSwJ0fSY5KhvocuWSx4fz3BA8OrA1bQn+K1Eli3BRwM=
github.com/aokoli/goutils v1.0.1/go.mod h1:SijmP0QR8LtwsmDs8Yii5Z/S4trXFGFC2oO5g9DP+DQ=
github.com/apache/arrow/go/v10 v10.0.1/go.mod h1:YvhnlEePVnBS4+0z3fhPfUy7W1Ikj0Ih0vcRo/gZ1M0=
github.com/apache/arrow/go/v11 v11.0.0/go.mod h1:Eg5OsL5H+e299f7u5ssuXsuHQVEGC4xei5aX110hRiI=
@@ -1737,8 +1737,8 @@ github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9
github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU=
github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
github.com/google/cel-go v0.9.0/go.mod h1:U7ayypeSkw23szu4GaQTPJGx66c20mx8JklMSxrmI1w=
-github.com/google/cel-go v0.13.0 h1:z+8OBOcmh7IeKyqwT/6IlnMvy621fYUqnTVPEdegGlU=
-github.com/google/cel-go v0.13.0/go.mod h1:K2hpQgEjDp18J76a2DKFRlPBPpgRZgi6EbnpDgIhJ8s=
+github.com/google/cel-go v0.17.1 h1:s2151PDGy/eqpCI80/8dl4VL3xTkqI/YubXLXCFw0mw=
+github.com/google/cel-go v0.17.1/go.mod h1:HXZKzB0LXqer5lHHgfWAnlYwJaQBDKMjxjulNQzhwhY=
github.com/google/cel-spec v0.6.0/go.mod h1:Nwjgxy5CbjlPrtCWjeDjUyKMl8w41YBYGjsyDdqk0xA=
github.com/google/certificate-transparency-go v1.0.21/go.mod h1:QeJfpSbVSfYc7RgB3gJFj9cbuQMMchQxrWXz8Ruopmg=
github.com/google/certificate-transparency-go v1.1.1/go.mod h1:FDKqPvSXawb2ecErVRrD+nfy23RCzyl7eqVCEmlT1Zs=
@@ -1778,6 +1778,7 @@ github.com/google/go-containerregistry/pkg/authn/kubernetes v0.0.0-2022011015105
github.com/google/go-containerregistry/pkg/authn/kubernetes v0.0.0-20230516205744-dbecb1de8cfa h1:+MG+Q2Q7mtW6kCIbUPZ9ZMrj7xOWDKI1hhy1qp0ygI0=
github.com/google/go-containerregistry/pkg/authn/kubernetes v0.0.0-20230516205744-dbecb1de8cfa/go.mod h1:KdL98/Va8Dy1irB6lTxIRIQ7bQj4lbrlvqUzKEQ+ZBU=
github.com/google/go-github/v27 v27.0.6/go.mod h1:/0Gr8pJ55COkmv+S/yPKCczSkUPIM/LnFyubufRNIS0=
+github.com/google/go-github/v31 v31.0.0 h1:JJUxlP9lFK+ziXKimTCprajMApV1ecWD4NB6CCb0plo=
github.com/google/go-github/v50 v50.2.0 h1:j2FyongEHlO9nxXLc+LP3wuBSVU9mVxfpdYUexMpIfk=
github.com/google/go-github/v50 v50.2.0/go.mod h1:VBY8FB6yPIjrtKhozXv4FQupxKLS6H4m6xFZlT43q8Q=
github.com/google/go-licenses v0.0.0-20200602185517-f29a4c695c3d/go.mod h1:g1VOUGKZYIqe8lDq2mL7plhAWXqrEaGUs7eIjthN1sk=
@@ -2879,12 +2880,12 @@ github.com/tektoncd/chains v0.17.0 h1:iUcZA6ZMtuKmigcbJ/GqoKWR1YTCHZjGlREMAo5kg8
github.com/tektoncd/chains v0.17.0/go.mod h1:xnn91ocomJeb4QNMFr4Rw5nrQ8MuJqWrvivINFhjJJI=
github.com/tektoncd/hub v1.13.0 h1:WJF9JMQzdBxfiQILtDT2lgAXxBc+y9v5U4qwavUO5pE=
github.com/tektoncd/hub v1.13.0/go.mod h1:9n47cu03gbNVB5n922jKjc602sRpe/ihgQ3SvHNijQ4=
-github.com/tektoncd/pipeline v0.50.0 h1:bH04XChFOYCwr7Gm6f2NiDkieHUiGohKCGsLe0fxYf0=
-github.com/tektoncd/pipeline v0.50.0/go.mod h1:OjhCfhPQbVvK6GUmIseL2ipjaQ8ILcUerMk4P4sCcHA=
+github.com/tektoncd/pipeline v0.50.1 h1:Asdfn1MxUSTlfzmr0PV4BPIEH7K4QLGym33nLgQlPCQ=
+github.com/tektoncd/pipeline v0.50.1/go.mod h1:OjhCfhPQbVvK6GUmIseL2ipjaQ8ILcUerMk4P4sCcHA=
github.com/tektoncd/plumbing v0.0.0-20221102182345-5dbcfda657d7 h1:YsjQ83UBIIq4k/s2PzQ6pqe4tpPtm1hia3oyNBDDrDU=
github.com/tektoncd/plumbing v0.0.0-20221102182345-5dbcfda657d7/go.mod h1:uJBaI0AL/kjPThiMYZcWRujEz7D401v643d6s/21GAg=
-github.com/tektoncd/triggers v0.24.1 h1:JOQonXtnsIar4P2/N1bAvUCX9561PCwh3oA1Bd6O64k=
-github.com/tektoncd/triggers v0.24.1/go.mod h1:yQcliUXLfIp0YijT30R0t/4hItCsznTpOxOlSIrKF78=
+github.com/tektoncd/triggers v0.25.0 h1:HaHZ0w8RpeIvB/7DoIZz+KhIOAVzPiFIPZOrDtvEPbM=
+github.com/tektoncd/triggers v0.25.0/go.mod h1:yIxJZ4rLqZmLidFgyhR882BEy3gaW3gQkSsofP1KlRM=
github.com/tenntenn/modver v1.0.1/go.mod h1:bePIyQPb7UeioSRkw3Q0XeMhYZSMx9B8ePqg6SAMGH0=
github.com/tenntenn/text/transform v0.0.0-20200319021203-7eef512accb3/go.mod h1:ON8b8w4BN/kE1EOhwT0o+d62W65a6aPw1nouo9LMgyY=
github.com/tetafro/godot v1.4.11/go.mod h1:LR3CJpxDVGlYOWn3ZZg1PgNZdTUvzsZWu8xaEohUpn8=
@@ -2893,10 +2894,14 @@ github.com/thales-e-security/pool v0.0.2/go.mod h1:qtpMm2+thHtqhLzTwgDBj/OuNnMpu
github.com/theupdateframework/go-tuf v0.6.1 h1:6J89fGjQf7s0mLmTG7p7pO/MbKOg+bIXhaLyQdmbKuE=
github.com/theupdateframework/go-tuf v0.6.1/go.mod h1:LAFusuQsFNBnEyYoTuA5zZrF7iaQ4TEgBXm8lb6Vj18=
github.com/tidwall/gjson v1.12.1 h1:ikuZsLdhr8Ws0IdROXUS1Gi4v9Z4pGqpX/CvJkxvfpo=
+github.com/tidwall/gjson v1.12.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
+github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
+github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tidwall/sjson v1.2.4 h1:cuiLzLnaMeBhRmEv00Lpk3tkYrcxpmbU81tAY4Dw0tc=
+github.com/tidwall/sjson v1.2.4/go.mod h1:098SZ494YoMWPmMO6ct4dcFnqxwj9r/gF0Etp19pSNM=
github.com/timakin/bodyclose v0.0.0-20200424151742-cb6215831a94/go.mod h1:Qimiffbc6q9tBWlVV6x0P9sat/ao1xEkREYPPj9hphk=
github.com/titanous/rocacheck v0.0.0-20171023193734-afe73141d399 h1:e/5i7d4oYZ+C1wj2THlRK+oAhjeS/TRQwMfkIuet3w0=
github.com/titanous/rocacheck v0.0.0-20171023193734-afe73141d399/go.mod h1:LdwHTNJT99C5fTAzDz0ud328OgXz+gierycbcIx2fRs=
diff --git a/pkg/cmd/eventlistener/describe_test.go b/pkg/cmd/eventlistener/describe_test.go
index 29dd68ed1..31836806c 100644
--- a/pkg/cmd/eventlistener/describe_test.go
+++ b/pkg/cmd/eventlistener/describe_test.go
@@ -23,6 +23,7 @@ import (
testDynamic "github.com/tektoncd/cli/pkg/test/dynamic"
"github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1"
triggersv1beta1 "github.com/tektoncd/triggers/pkg/apis/triggers/v1beta1"
+ "github.com/tektoncd/triggers/pkg/interceptors/cel"
triggertest "github.com/tektoncd/triggers/test"
"gotest.tools/v3/golden"
corev1 "k8s.io/api/core/v1"
@@ -713,7 +714,7 @@ func TestEventListenerDescribe_WithCELInterceptors(t *testing.T) {
},
{
Name: "overlays",
- Value: triggertest.ToV1JSON(t, []triggersv1beta1.CELOverlay{{
+ Value: triggertest.ToV1JSON(t, []cel.Overlay{{
Key: "value",
Expression: "'testing'",
}}),
@@ -783,7 +784,7 @@ func TestEventListenerDescribe_WithMultipleBindingAndInterceptors(t *testing.T)
},
{
Name: "overlays",
- Value: triggertest.ToV1JSON(t, []triggersv1beta1.CELOverlay{{
+ Value: triggertest.ToV1JSON(t, []cel.Overlay{{
Key: "value",
Expression: "'testing'",
}}),
@@ -834,7 +835,7 @@ func TestEventListenerDescribe_WithMultipleBindingAndInterceptors(t *testing.T)
},
{
Name: "overlays",
- Value: triggertest.ToV1JSON(t, []triggersv1beta1.CELOverlay{{
+ Value: triggertest.ToV1JSON(t, []cel.Overlay{{
Key: "value",
Expression: "'testing'",
}}),
@@ -898,7 +899,7 @@ func TestEventListenerDescribe_OutputYAMLWithMultipleBindingAndInterceptors(t *t
},
{
Name: "overlays",
- Value: triggertest.ToV1JSON(t, []triggersv1beta1.CELOverlay{{
+ Value: triggertest.ToV1JSON(t, []cel.Overlay{{
Key: "value",
Expression: "'testing'",
}}),
@@ -949,7 +950,7 @@ func TestEventListenerDescribe_OutputYAMLWithMultipleBindingAndInterceptors(t *t
},
{
Name: "overlays",
- Value: triggertest.ToV1JSON(t, []triggersv1beta1.CELOverlay{{
+ Value: triggertest.ToV1JSON(t, []cel.Overlay{{
Key: "value",
Expression: "'testing'",
}}),
diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/LICENSE b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/LICENSE
similarity index 100%
rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/LICENSE
rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/LICENSE
diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/antlrdoc.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/antlrdoc.go
new file mode 100644
index 000000000..ab5121267
--- /dev/null
+++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/antlrdoc.go
@@ -0,0 +1,68 @@
+/*
+Package antlr implements the Go version of the ANTLR 4 runtime.
+
+# The ANTLR Tool
+
+ANTLR (ANother Tool for Language Recognition) is a powerful parser generator for reading, processing, executing,
+or translating structured text or binary files. It's widely used to build languages, tools, and frameworks.
+From a grammar, ANTLR generates a parser that can build parse trees and also generates a listener interface
+(or visitor) that makes it easy to respond to the recognition of phrases of interest.
+
+# Code Generation
+
+ANTLR supports the generation of code in a number of [target languages], and the generated code is supported by a
+runtime library, written specifically to support the generated code in the target language. This library is the
+runtime for the Go target.
+
+To generate code for the go target, it is generally recommended to place the source grammar files in a package of
+their own, and use the `.sh` script method of generating code, using the go generate directive. In that same directory
+it is usual, though not required, to place the antlr tool that should be used to generate the code. That does mean
+that the antlr tool JAR file will be checked in to your source code control though, so you are free to use any other
+way of specifying the version of the ANTLR tool to use, such as aliasing in `.zshrc` or equivalent, or a profile in
+your IDE, or configuration in your CI system.
+
+Here is a general template for an ANTLR based recognizer in Go:
+
+ .
+ ├── myproject
+ ├── parser
+ │ ├── mygrammar.g4
+ │ ├── antlr-4.12.0-complete.jar
+ │ ├── error_listeners.go
+ │ ├── generate.go
+ │ ├── generate.sh
+ ├── go.mod
+ ├── go.sum
+ ├── main.go
+ └── main_test.go
+
+Make sure that the package statement in your grammar file(s) reflects the go package they exist in.
+The generate.go file then looks like this:
+
+ package parser
+
+ //go:generate ./generate.sh
+
+And the generate.sh file will look similar to this:
+
+ #!/bin/sh
+
+ alias antlr4='java -Xmx500M -cp "./antlr4-4.12.0-complete.jar:$CLASSPATH" org.antlr.v4.Tool'
+ antlr4 -Dlanguage=Go -no-visitor -package parser *.g4
+
+depending on whether you want visitors or listeners or any other ANTLR options.
+
+From the command line at the root of your package “myproject” you can then simply issue the command:
+
+ go generate ./...
+
+# Copyright Notice
+
+Copyright (c) 2012-2022 The ANTLR Project. All rights reserved.
+
+Use of this file is governed by the BSD 3-clause license, which can be found in the [LICENSE.txt] file in the project root.
+
+[target languages]: https://github.com/antlr/antlr4/tree/master/runtime
+[LICENSE.txt]: https://github.com/antlr/antlr4/blob/master/LICENSE.txt
+*/
+package antlr
diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/atn.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/atn.go
similarity index 72%
rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/atn.go
rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/atn.go
index a4e2079e6..98010d2e6 100644
--- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/atn.go
+++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/atn.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
+// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved.
// Use of this file is governed by the BSD 3-clause license that
// can be found in the LICENSE.txt file in the project root.
@@ -6,11 +6,24 @@ package antlr
import "sync"
+// ATNInvalidAltNumber is used to represent an ALT number that has yet to be calculated or
+// which is invalid for a particular struct such as [*antlr.BaseRuleContext]
var ATNInvalidAltNumber int
+// ATN represents an “[Augmented Transition Network]”, though general in ANTLR the term
+// “Augmented Recursive Transition Network” though there are some descriptions of “[Recursive Transition Network]”
+// in existence.
+//
+// ATNs represent the main networks in the system and are serialized by the code generator and support [ALL(*)].
+//
+// [Augmented Transition Network]: https://en.wikipedia.org/wiki/Augmented_transition_network
+// [ALL(*)]: https://www.antlr.org/papers/allstar-techreport.pdf
+// [Recursive Transition Network]: https://en.wikipedia.org/wiki/Recursive_transition_network
type ATN struct {
// DecisionToState is the decision points for all rules, subrules, optional
- // blocks, ()+, ()*, etc. Used to build DFA predictors for them.
+ // blocks, ()+, ()*, etc. Each subrule/rule is a decision point, and we must track them so we
+ // can go back later and build DFA predictors for them. This includes
+ // all the rules, subrules, optional blocks, ()+, ()* etc...
DecisionToState []DecisionState
// grammarType is the ATN type and is used for deserializing ATNs from strings.
@@ -45,6 +58,8 @@ type ATN struct {
edgeMu sync.RWMutex
}
+// NewATN returns a new ATN struct representing the given grammarType and is used
+// for runtime deserialization of ATNs from the code generated by the ANTLR tool
func NewATN(grammarType int, maxTokenType int) *ATN {
return &ATN{
grammarType: grammarType,
@@ -53,7 +68,7 @@ func NewATN(grammarType int, maxTokenType int) *ATN {
}
}
-// NextTokensInContext computes the set of valid tokens that can occur starting
+// NextTokensInContext computes and returns the set of valid tokens that can occur starting
// in state s. If ctx is nil, the set of tokens will not include what can follow
// the rule surrounding s. In other words, the set will be restricted to tokens
// reachable staying within the rule of s.
@@ -61,8 +76,8 @@ func (a *ATN) NextTokensInContext(s ATNState, ctx RuleContext) *IntervalSet {
return NewLL1Analyzer(a).Look(s, nil, ctx)
}
-// NextTokensNoContext computes the set of valid tokens that can occur starting
-// in s and staying in same rule. Token.EPSILON is in set if we reach end of
+// NextTokensNoContext computes and returns the set of valid tokens that can occur starting
+// in state s and staying in same rule. [antlr.Token.EPSILON] is in set if we reach end of
// rule.
func (a *ATN) NextTokensNoContext(s ATNState) *IntervalSet {
a.mu.Lock()
@@ -76,6 +91,8 @@ func (a *ATN) NextTokensNoContext(s ATNState) *IntervalSet {
return iset
}
+// NextTokens computes and returns the set of valid tokens starting in state s, by
+// calling either [NextTokensNoContext] (ctx == nil) or [NextTokensInContext] (ctx != nil).
func (a *ATN) NextTokens(s ATNState, ctx RuleContext) *IntervalSet {
if ctx == nil {
return a.NextTokensNoContext(s)
diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/atn_config.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/atn_config.go
similarity index 84%
rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/atn_config.go
rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/atn_config.go
index 97ba417f7..7619fa172 100644
--- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/atn_config.go
+++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/atn_config.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
+// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved.
// Use of this file is governed by the BSD 3-clause license that
// can be found in the LICENSE.txt file in the project root.
@@ -8,19 +8,14 @@ import (
"fmt"
)
-type comparable interface {
- equals(other interface{}) bool
-}
-
// ATNConfig is a tuple: (ATN state, predicted alt, syntactic, semantic
// context). The syntactic context is a graph-structured stack node whose
// path(s) to the root is the rule invocation(s) chain used to arrive at the
// state. The semantic context is the tree of semantic predicates encountered
// before reaching an ATN state.
type ATNConfig interface {
- comparable
-
- hash() int
+ Equals(o Collectable[ATNConfig]) bool
+ Hash() int
GetState() ATNState
GetAlt() int
@@ -47,7 +42,7 @@ type BaseATNConfig struct {
reachesIntoOuterContext int
}
-func NewBaseATNConfig7(old *BaseATNConfig) *BaseATNConfig { // TODO: Dup
+func NewBaseATNConfig7(old *BaseATNConfig) ATNConfig { // TODO: Dup
return &BaseATNConfig{
state: old.state,
alt: old.alt,
@@ -135,11 +130,16 @@ func (b *BaseATNConfig) SetReachesIntoOuterContext(v int) {
b.reachesIntoOuterContext = v
}
+// Equals is the default comparison function for an ATNConfig when no specialist implementation is required
+// for a collection.
+//
// An ATN configuration is equal to another if both have the same state, they
// predict the same alternative, and syntactic/semantic contexts are the same.
-func (b *BaseATNConfig) equals(o interface{}) bool {
+func (b *BaseATNConfig) Equals(o Collectable[ATNConfig]) bool {
if b == o {
return true
+ } else if o == nil {
+ return false
}
var other, ok = o.(*BaseATNConfig)
@@ -153,30 +153,32 @@ func (b *BaseATNConfig) equals(o interface{}) bool {
if b.context == nil {
equal = other.context == nil
} else {
- equal = b.context.equals(other.context)
+ equal = b.context.Equals(other.context)
}
var (
nums = b.state.GetStateNumber() == other.state.GetStateNumber()
alts = b.alt == other.alt
- cons = b.semanticContext.equals(other.semanticContext)
+ cons = b.semanticContext.Equals(other.semanticContext)
sups = b.precedenceFilterSuppressed == other.precedenceFilterSuppressed
)
return nums && alts && cons && sups && equal
}
-func (b *BaseATNConfig) hash() int {
+// Hash is the default hash function for BaseATNConfig, when no specialist hash function
+// is required for a collection
+func (b *BaseATNConfig) Hash() int {
var c int
if b.context != nil {
- c = b.context.hash()
+ c = b.context.Hash()
}
h := murmurInit(7)
h = murmurUpdate(h, b.state.GetStateNumber())
h = murmurUpdate(h, b.alt)
h = murmurUpdate(h, c)
- h = murmurUpdate(h, b.semanticContext.hash())
+ h = murmurUpdate(h, b.semanticContext.Hash())
return murmurFinish(h, 4)
}
@@ -243,7 +245,9 @@ func NewLexerATNConfig1(state ATNState, alt int, context PredictionContext) *Lex
return &LexerATNConfig{BaseATNConfig: NewBaseATNConfig5(state, alt, context, SemanticContextNone)}
}
-func (l *LexerATNConfig) hash() int {
+// Hash is the default hash function for LexerATNConfig objects, it can be used directly or via
+// the default comparator [ObjEqComparator].
+func (l *LexerATNConfig) Hash() int {
var f int
if l.passedThroughNonGreedyDecision {
f = 1
@@ -253,15 +257,20 @@ func (l *LexerATNConfig) hash() int {
h := murmurInit(7)
h = murmurUpdate(h, l.state.GetStateNumber())
h = murmurUpdate(h, l.alt)
- h = murmurUpdate(h, l.context.hash())
- h = murmurUpdate(h, l.semanticContext.hash())
+ h = murmurUpdate(h, l.context.Hash())
+ h = murmurUpdate(h, l.semanticContext.Hash())
h = murmurUpdate(h, f)
- h = murmurUpdate(h, l.lexerActionExecutor.hash())
+ h = murmurUpdate(h, l.lexerActionExecutor.Hash())
h = murmurFinish(h, 6)
return h
}
-func (l *LexerATNConfig) equals(other interface{}) bool {
+// Equals is the default comparison function for LexerATNConfig objects, it can be used directly or via
+// the default comparator [ObjEqComparator].
+func (l *LexerATNConfig) Equals(other Collectable[ATNConfig]) bool {
+ if l == other {
+ return true
+ }
var othert, ok = other.(*LexerATNConfig)
if l == other {
@@ -275,7 +284,7 @@ func (l *LexerATNConfig) equals(other interface{}) bool {
var b bool
if l.lexerActionExecutor != nil {
- b = !l.lexerActionExecutor.equals(othert.lexerActionExecutor)
+ b = !l.lexerActionExecutor.Equals(othert.lexerActionExecutor)
} else {
b = othert.lexerActionExecutor != nil
}
@@ -284,10 +293,9 @@ func (l *LexerATNConfig) equals(other interface{}) bool {
return false
}
- return l.BaseATNConfig.equals(othert.BaseATNConfig)
+ return l.BaseATNConfig.Equals(othert.BaseATNConfig)
}
-
func checkNonGreedyDecision(source *LexerATNConfig, target ATNState) bool {
var ds, ok = target.(DecisionState)
diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/atn_config_set.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/atn_config_set.go
similarity index 81%
rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/atn_config_set.go
rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/atn_config_set.go
index 49ad4a719..43e9b33f3 100644
--- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/atn_config_set.go
+++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/atn_config_set.go
@@ -1,24 +1,25 @@
-// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
+// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved.
// Use of this file is governed by the BSD 3-clause license that
// can be found in the LICENSE.txt file in the project root.
package antlr
-import "fmt"
+import (
+ "fmt"
+)
type ATNConfigSet interface {
- hash() int
+ Hash() int
+ Equals(o Collectable[ATNConfig]) bool
Add(ATNConfig, *DoubleDict) bool
AddAll([]ATNConfig) bool
- GetStates() Set
+ GetStates() *JStore[ATNState, Comparator[ATNState]]
GetPredicates() []SemanticContext
GetItems() []ATNConfig
OptimizeConfigs(interpreter *BaseATNSimulator)
- Equals(other interface{}) bool
-
Length() int
IsEmpty() bool
Contains(ATNConfig) bool
@@ -57,7 +58,7 @@ type BaseATNConfigSet struct {
// effectively doubles the number of objects associated with ATNConfigs. All
// keys are hashed by (s, i, _, pi), not including the context. Wiped out when
// read-only because a set becomes a DFA state.
- configLookup Set
+ configLookup *JStore[ATNConfig, Comparator[ATNConfig]]
// configs is the added elements.
configs []ATNConfig
@@ -83,7 +84,7 @@ type BaseATNConfigSet struct {
// readOnly is whether it is read-only. Do not
// allow any code to manipulate the set if true because DFA states will point at
- // sets and those must not change. It not protect other fields; conflictingAlts
+ // sets and those must not change. It not, protect other fields; conflictingAlts
// in particular, which is assigned after readOnly.
readOnly bool
@@ -104,7 +105,7 @@ func (b *BaseATNConfigSet) Alts() *BitSet {
func NewBaseATNConfigSet(fullCtx bool) *BaseATNConfigSet {
return &BaseATNConfigSet{
cachedHash: -1,
- configLookup: newArray2DHashSetWithCap(hashATNConfig, equalATNConfigs, 16, 2),
+ configLookup: NewJStore[ATNConfig, Comparator[ATNConfig]](aConfCompInst),
fullCtx: fullCtx,
}
}
@@ -126,9 +127,11 @@ func (b *BaseATNConfigSet) Add(config ATNConfig, mergeCache *DoubleDict) bool {
b.dipsIntoOuterContext = true
}
- existing := b.configLookup.Add(config).(ATNConfig)
+ existing, present := b.configLookup.Put(config)
- if existing == config {
+ // The config was not already in the set
+ //
+ if !present {
b.cachedHash = -1
b.configs = append(b.configs, config) // Track order here
return true
@@ -154,11 +157,14 @@ func (b *BaseATNConfigSet) Add(config ATNConfig, mergeCache *DoubleDict) bool {
return true
}
-func (b *BaseATNConfigSet) GetStates() Set {
- states := newArray2DHashSet(nil, nil)
+func (b *BaseATNConfigSet) GetStates() *JStore[ATNState, Comparator[ATNState]] {
+
+ // states uses the standard comparator provided by the ATNState instance
+ //
+ states := NewJStore[ATNState, Comparator[ATNState]](aStateEqInst)
for i := 0; i < len(b.configs); i++ {
- states.Add(b.configs[i].GetState())
+ states.Put(b.configs[i].GetState())
}
return states
@@ -214,7 +220,34 @@ func (b *BaseATNConfigSet) AddAll(coll []ATNConfig) bool {
return false
}
-func (b *BaseATNConfigSet) Equals(other interface{}) bool {
+// Compare is a hack function just to verify that adding DFAstares to the known
+// set works, so long as comparison of ATNConfigSet s works. For that to work, we
+// need to make sure that the set of ATNConfigs in two sets are equivalent. We can't
+// know the order, so we do this inefficient hack. If this proves the point, then
+// we can change the config set to a better structure.
+func (b *BaseATNConfigSet) Compare(bs *BaseATNConfigSet) bool {
+ if len(b.configs) != len(bs.configs) {
+ return false
+ }
+
+ for _, c := range b.configs {
+ found := false
+ for _, c2 := range bs.configs {
+ if c.Equals(c2) {
+ found = true
+ break
+ }
+ }
+
+ if !found {
+ return false
+ }
+
+ }
+ return true
+}
+
+func (b *BaseATNConfigSet) Equals(other Collectable[ATNConfig]) bool {
if b == other {
return true
} else if _, ok := other.(*BaseATNConfigSet); !ok {
@@ -224,15 +257,15 @@ func (b *BaseATNConfigSet) Equals(other interface{}) bool {
other2 := other.(*BaseATNConfigSet)
return b.configs != nil &&
- // TODO: b.configs.equals(other2.configs) && // TODO: Is b necessary?
b.fullCtx == other2.fullCtx &&
b.uniqueAlt == other2.uniqueAlt &&
b.conflictingAlts == other2.conflictingAlts &&
b.hasSemanticContext == other2.hasSemanticContext &&
- b.dipsIntoOuterContext == other2.dipsIntoOuterContext
+ b.dipsIntoOuterContext == other2.dipsIntoOuterContext &&
+ b.Compare(other2)
}
-func (b *BaseATNConfigSet) hash() int {
+func (b *BaseATNConfigSet) Hash() int {
if b.readOnly {
if b.cachedHash == -1 {
b.cachedHash = b.hashCodeConfigs()
@@ -247,7 +280,7 @@ func (b *BaseATNConfigSet) hash() int {
func (b *BaseATNConfigSet) hashCodeConfigs() int {
h := 1
for _, config := range b.configs {
- h = 31*h + config.hash()
+ h = 31*h + config.Hash()
}
return h
}
@@ -283,7 +316,7 @@ func (b *BaseATNConfigSet) Clear() {
b.configs = make([]ATNConfig, 0)
b.cachedHash = -1
- b.configLookup = newArray2DHashSet(nil, equalATNConfigs)
+ b.configLookup = NewJStore[ATNConfig, Comparator[ATNConfig]](atnConfCompInst)
}
func (b *BaseATNConfigSet) FullContext() bool {
@@ -365,7 +398,8 @@ type OrderedATNConfigSet struct {
func NewOrderedATNConfigSet() *OrderedATNConfigSet {
b := NewBaseATNConfigSet(false)
- b.configLookup = newArray2DHashSet(nil, nil)
+ // This set uses the standard Hash() and Equals() from ATNConfig
+ b.configLookup = NewJStore[ATNConfig, Comparator[ATNConfig]](aConfEqInst)
return &OrderedATNConfigSet{BaseATNConfigSet: b}
}
@@ -375,7 +409,7 @@ func hashATNConfig(i interface{}) int {
hash := 7
hash = 31*hash + o.GetState().GetStateNumber()
hash = 31*hash + o.GetAlt()
- hash = 31*hash + o.GetSemanticContext().hash()
+ hash = 31*hash + o.GetSemanticContext().Hash()
return hash
}
@@ -403,5 +437,5 @@ func equalATNConfigs(a, b interface{}) bool {
return false
}
- return ai.GetSemanticContext().equals(bi.GetSemanticContext())
+ return ai.GetSemanticContext().Equals(bi.GetSemanticContext())
}
diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/atn_deserialization_options.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/atn_deserialization_options.go
similarity index 96%
rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/atn_deserialization_options.go
rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/atn_deserialization_options.go
index cb8eafb0b..3c975ec7b 100644
--- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/atn_deserialization_options.go
+++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/atn_deserialization_options.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
+// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved.
// Use of this file is governed by the BSD 3-clause license that
// can be found in the LICENSE.txt file in the project root.
diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/atn_deserializer.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/atn_deserializer.go
similarity index 99%
rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/atn_deserializer.go
rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/atn_deserializer.go
index aea9bbfa9..3888856b4 100644
--- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/atn_deserializer.go
+++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/atn_deserializer.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
+// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved.
// Use of this file is governed by the BSD 3-clause license that
// can be found in the LICENSE.txt file in the project root.
diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/atn_simulator.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/atn_simulator.go
similarity index 94%
rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/atn_simulator.go
rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/atn_simulator.go
index d5454d6d5..41529115f 100644
--- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/atn_simulator.go
+++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/atn_simulator.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
+// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved.
// Use of this file is governed by the BSD 3-clause license that
// can be found in the LICENSE.txt file in the project root.
diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/atn_state.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/atn_state.go
similarity index 97%
rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/atn_state.go
rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/atn_state.go
index 3835bb2e9..1f2a56bc3 100644
--- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/atn_state.go
+++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/atn_state.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
+// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved.
// Use of this file is governed by the BSD 3-clause license that
// can be found in the LICENSE.txt file in the project root.
@@ -49,7 +49,8 @@ type ATNState interface {
AddTransition(Transition, int)
String() string
- hash() int
+ Hash() int
+ Equals(Collectable[ATNState]) bool
}
type BaseATNState struct {
@@ -123,7 +124,7 @@ func (as *BaseATNState) SetNextTokenWithinRule(v *IntervalSet) {
as.NextTokenWithinRule = v
}
-func (as *BaseATNState) hash() int {
+func (as *BaseATNState) Hash() int {
return as.stateNumber
}
@@ -131,7 +132,7 @@ func (as *BaseATNState) String() string {
return strconv.Itoa(as.stateNumber)
}
-func (as *BaseATNState) equals(other interface{}) bool {
+func (as *BaseATNState) Equals(other Collectable[ATNState]) bool {
if ot, ok := other.(ATNState); ok {
return as.stateNumber == ot.GetStateNumber()
}
diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/atn_type.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/atn_type.go
similarity index 79%
rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/atn_type.go
rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/atn_type.go
index a7b48976b..3a515a145 100644
--- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/atn_type.go
+++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/atn_type.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
+// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved.
// Use of this file is governed by the BSD 3-clause license that
// can be found in the LICENSE.txt file in the project root.
diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/char_stream.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/char_stream.go
similarity index 82%
rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/char_stream.go
rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/char_stream.go
index 70c1207f7..c33f0adb5 100644
--- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/char_stream.go
+++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/char_stream.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
+// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved.
// Use of this file is governed by the BSD 3-clause license that
// can be found in the LICENSE.txt file in the project root.
diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/common_token_factory.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/common_token_factory.go
similarity index 96%
rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/common_token_factory.go
rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/common_token_factory.go
index 330ff8f31..1bb0314ea 100644
--- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/common_token_factory.go
+++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/common_token_factory.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
+// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved.
// Use of this file is governed by the BSD 3-clause license that
// can be found in the LICENSE.txt file in the project root.
diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/common_token_stream.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/common_token_stream.go
similarity index 98%
rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/common_token_stream.go
rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/common_token_stream.go
index c90e9b890..c6c9485a2 100644
--- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/common_token_stream.go
+++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/common_token_stream.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
+// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved.
// Use of this file is governed by the BSD 3-clause license that
// can be found in the LICENSE.txt file in the project root.
@@ -331,10 +331,12 @@ func (c *CommonTokenStream) GetTextFromRuleContext(interval RuleContext) string
func (c *CommonTokenStream) GetTextFromInterval(interval *Interval) string {
c.lazyInit()
- c.Fill()
if interval == nil {
+ c.Fill()
interval = NewInterval(0, len(c.tokens)-1)
+ } else {
+ c.Sync(interval.Stop)
}
start := interval.Start
diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/comparators.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/comparators.go
new file mode 100644
index 000000000..9ea320053
--- /dev/null
+++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/comparators.go
@@ -0,0 +1,147 @@
+package antlr
+
+// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved.
+// Use of this file is governed by the BSD 3-clause license that
+// can be found in the LICENSE.txt file in the project root.
+
+// This file contains all the implementations of custom comparators used for generic collections when the
+// Hash() and Equals() funcs supplied by the struct objects themselves need to be overridden. Normally, we would
+// put the comparators in the source file for the struct themselves, but given the organization of this code is
+// sorta kinda based upon the Java code, I found it confusing trying to find out which comparator was where and used by
+// which instantiation of a collection. For instance, an Array2DHashSet in the Java source, when used with ATNConfig
+// collections requires three different comparators depending on what the collection is being used for. Collecting - pun intended -
+// all the comparators here, makes it much easier to see which implementation of hash and equals is used by which collection.
+// It also makes it easy to verify that the Hash() and Equals() functions marry up with the Java implementations.
+
+// ObjEqComparator is the equivalent of the Java ObjectEqualityComparator, which is the default instance of
+// Equality comparator. We do not have inheritance in Go, only interfaces, so we use generics to enforce some
+// type safety and avoid having to implement this for every type that we want to perform comparison on.
+//
+// This comparator works by using the standard Hash() and Equals() methods of the type T that is being compared. Which
+// allows us to use it in any collection instance that does nto require a special hash or equals implementation.
+type ObjEqComparator[T Collectable[T]] struct{}
+
+var (
+ aStateEqInst = &ObjEqComparator[ATNState]{}
+ aConfEqInst = &ObjEqComparator[ATNConfig]{}
+ aConfCompInst = &ATNConfigComparator[ATNConfig]{}
+ atnConfCompInst = &BaseATNConfigComparator[ATNConfig]{}
+ dfaStateEqInst = &ObjEqComparator[*DFAState]{}
+ semctxEqInst = &ObjEqComparator[SemanticContext]{}
+ atnAltCfgEqInst = &ATNAltConfigComparator[ATNConfig]{}
+)
+
+// Equals2 delegates to the Equals() method of type T
+func (c *ObjEqComparator[T]) Equals2(o1, o2 T) bool {
+ return o1.Equals(o2)
+}
+
+// Hash1 delegates to the Hash() method of type T
+func (c *ObjEqComparator[T]) Hash1(o T) int {
+
+ return o.Hash()
+}
+
+type SemCComparator[T Collectable[T]] struct{}
+
+// ATNConfigComparator is used as the compartor for the configLookup field of an ATNConfigSet
+// and has a custom Equals() and Hash() implementation, because equality is not based on the
+// standard Hash() and Equals() methods of the ATNConfig type.
+type ATNConfigComparator[T Collectable[T]] struct {
+}
+
+// Equals2 is a custom comparator for ATNConfigs specifically for configLookup
+func (c *ATNConfigComparator[T]) Equals2(o1, o2 ATNConfig) bool {
+
+ // Same pointer, must be equal, even if both nil
+ //
+ if o1 == o2 {
+ return true
+
+ }
+
+ // If either are nil, but not both, then the result is false
+ //
+ if o1 == nil || o2 == nil {
+ return false
+ }
+
+ return o1.GetState().GetStateNumber() == o2.GetState().GetStateNumber() &&
+ o1.GetAlt() == o2.GetAlt() &&
+ o1.GetSemanticContext().Equals(o2.GetSemanticContext())
+}
+
+// Hash1 is custom hash implementation for ATNConfigs specifically for configLookup
+func (c *ATNConfigComparator[T]) Hash1(o ATNConfig) int {
+ hash := 7
+ hash = 31*hash + o.GetState().GetStateNumber()
+ hash = 31*hash + o.GetAlt()
+ hash = 31*hash + o.GetSemanticContext().Hash()
+ return hash
+}
+
+// ATNAltConfigComparator is used as the comparator for mapping configs to Alt Bitsets
+type ATNAltConfigComparator[T Collectable[T]] struct {
+}
+
+// Equals2 is a custom comparator for ATNConfigs specifically for configLookup
+func (c *ATNAltConfigComparator[T]) Equals2(o1, o2 ATNConfig) bool {
+
+ // Same pointer, must be equal, even if both nil
+ //
+ if o1 == o2 {
+ return true
+
+ }
+
+ // If either are nil, but not both, then the result is false
+ //
+ if o1 == nil || o2 == nil {
+ return false
+ }
+
+ return o1.GetState().GetStateNumber() == o2.GetState().GetStateNumber() &&
+ o1.GetContext().Equals(o2.GetContext())
+}
+
+// Hash1 is custom hash implementation for ATNConfigs specifically for configLookup
+func (c *ATNAltConfigComparator[T]) Hash1(o ATNConfig) int {
+ h := murmurInit(7)
+ h = murmurUpdate(h, o.GetState().GetStateNumber())
+ h = murmurUpdate(h, o.GetContext().Hash())
+ return murmurFinish(h, 2)
+}
+
+// BaseATNConfigComparator is used as the comparator for the configLookup field of a BaseATNConfigSet
+// and has a custom Equals() and Hash() implementation, because equality is not based on the
+// standard Hash() and Equals() methods of the ATNConfig type.
+type BaseATNConfigComparator[T Collectable[T]] struct {
+}
+
+// Equals2 is a custom comparator for ATNConfigs specifically for baseATNConfigSet
+func (c *BaseATNConfigComparator[T]) Equals2(o1, o2 ATNConfig) bool {
+
+ // Same pointer, must be equal, even if both nil
+ //
+ if o1 == o2 {
+ return true
+
+ }
+
+ // If either are nil, but not both, then the result is false
+ //
+ if o1 == nil || o2 == nil {
+ return false
+ }
+
+ return o1.GetState().GetStateNumber() == o2.GetState().GetStateNumber() &&
+ o1.GetAlt() == o2.GetAlt() &&
+ o1.GetSemanticContext().Equals(o2.GetSemanticContext())
+}
+
+// Hash1 is custom hash implementation for ATNConfigs specifically for configLookup, but in fact just
+// delegates to the standard Hash() method of the ATNConfig type.
+func (c *BaseATNConfigComparator[T]) Hash1(o ATNConfig) int {
+
+ return o.Hash()
+}
diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/dfa.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/dfa.go
similarity index 80%
rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/dfa.go
rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/dfa.go
index d55a2a87d..bfd43e1f7 100644
--- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/dfa.go
+++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/dfa.go
@@ -1,13 +1,9 @@
-// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
+// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved.
// Use of this file is governed by the BSD 3-clause license that
// can be found in the LICENSE.txt file in the project root.
package antlr
-import (
- "sort"
-)
-
type DFA struct {
// atnStartState is the ATN state in which this was created
atnStartState DecisionState
@@ -15,8 +11,15 @@ type DFA struct {
decision int
// states is all the DFA states. Use Map to get the old state back; Set can only
- // indicate whether it is there.
- states map[int]*DFAState
+ // indicate whether it is there. Go maps implement key hash collisions and so on and are very
+ // good, but the DFAState is an object and can't be used directly as the key as it can in say JAva
+ // amd C#, whereby if the hashcode is the same for two objects, then Equals() is called against them
+ // to see if they really are the same object.
+ //
+ //
+ states *JStore[*DFAState, *ObjEqComparator[*DFAState]]
+
+ numstates int
s0 *DFAState
@@ -29,7 +32,7 @@ func NewDFA(atnStartState DecisionState, decision int) *DFA {
dfa := &DFA{
atnStartState: atnStartState,
decision: decision,
- states: make(map[int]*DFAState),
+ states: NewJStore[*DFAState, *ObjEqComparator[*DFAState]](dfaStateEqInst),
}
if s, ok := atnStartState.(*StarLoopEntryState); ok && s.precedenceRuleDecision {
dfa.precedenceDfa = true
@@ -92,7 +95,8 @@ func (d *DFA) getPrecedenceDfa() bool {
// true or nil otherwise, and d.precedenceDfa is updated.
func (d *DFA) setPrecedenceDfa(precedenceDfa bool) {
if d.getPrecedenceDfa() != precedenceDfa {
- d.setStates(make(map[int]*DFAState))
+ d.states = NewJStore[*DFAState, *ObjEqComparator[*DFAState]](dfaStateEqInst)
+ d.numstates = 0
if precedenceDfa {
precedenceState := NewDFAState(-1, NewBaseATNConfigSet(false))
@@ -117,38 +121,12 @@ func (d *DFA) setS0(s *DFAState) {
d.s0 = s
}
-func (d *DFA) getState(hash int) (*DFAState, bool) {
- s, ok := d.states[hash]
- return s, ok
-}
-
-func (d *DFA) setStates(states map[int]*DFAState) {
- d.states = states
-}
-
-func (d *DFA) setState(hash int, state *DFAState) {
- d.states[hash] = state
-}
-
-func (d *DFA) numStates() int {
- return len(d.states)
-}
-
-type dfaStateList []*DFAState
-
-func (d dfaStateList) Len() int { return len(d) }
-func (d dfaStateList) Less(i, j int) bool { return d[i].stateNumber < d[j].stateNumber }
-func (d dfaStateList) Swap(i, j int) { d[i], d[j] = d[j], d[i] }
-
// sortedStates returns the states in d sorted by their state number.
func (d *DFA) sortedStates() []*DFAState {
- vs := make([]*DFAState, 0, len(d.states))
-
- for _, v := range d.states {
- vs = append(vs, v)
- }
- sort.Sort(dfaStateList(vs))
+ vs := d.states.SortedSlice(func(i, j *DFAState) bool {
+ return i.stateNumber < j.stateNumber
+ })
return vs
}
diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/dfa_serializer.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/dfa_serializer.go
similarity index 97%
rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/dfa_serializer.go
rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/dfa_serializer.go
index bf2ccc06c..84d0a31e5 100644
--- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/dfa_serializer.go
+++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/dfa_serializer.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
+// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved.
// Use of this file is governed by the BSD 3-clause license that
// can be found in the LICENSE.txt file in the project root.
diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/dfa_state.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/dfa_state.go
similarity index 90%
rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/dfa_state.go
rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/dfa_state.go
index 970ed1986..c90dec55c 100644
--- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/dfa_state.go
+++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/dfa_state.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
+// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved.
// Use of this file is governed by the BSD 3-clause license that
// can be found in the LICENSE.txt file in the project root.
@@ -90,16 +90,16 @@ func NewDFAState(stateNumber int, configs ATNConfigSet) *DFAState {
}
// GetAltSet gets the set of all alts mentioned by all ATN configurations in d.
-func (d *DFAState) GetAltSet() Set {
- alts := newArray2DHashSet(nil, nil)
+func (d *DFAState) GetAltSet() []int {
+ var alts []int
if d.configs != nil {
for _, c := range d.configs.GetItems() {
- alts.Add(c.GetAlt())
+ alts = append(alts, c.GetAlt())
}
}
- if alts.Len() == 0 {
+ if len(alts) == 0 {
return nil
}
@@ -130,27 +130,6 @@ func (d *DFAState) setPrediction(v int) {
d.prediction = v
}
-// equals returns whether d equals other. Two DFAStates are equal if their ATN
-// configuration sets are the same. This method is used to see if a state
-// already exists.
-//
-// Because the number of alternatives and number of ATN configurations are
-// finite, there is a finite number of DFA states that can be processed. This is
-// necessary to show that the algorithm terminates.
-//
-// Cannot test the DFA state numbers here because in
-// ParserATNSimulator.addDFAState we need to know if any other state exists that
-// has d exact set of ATN configurations. The stateNumber is irrelevant.
-func (d *DFAState) equals(other interface{}) bool {
- if d == other {
- return true
- } else if _, ok := other.(*DFAState); !ok {
- return false
- }
-
- return d.configs.Equals(other.(*DFAState).configs)
-}
-
func (d *DFAState) String() string {
var s string
if d.isAcceptState {
@@ -164,8 +143,27 @@ func (d *DFAState) String() string {
return fmt.Sprintf("%d:%s%s", d.stateNumber, fmt.Sprint(d.configs), s)
}
-func (d *DFAState) hash() int {
+func (d *DFAState) Hash() int {
h := murmurInit(7)
- h = murmurUpdate(h, d.configs.hash())
+ h = murmurUpdate(h, d.configs.Hash())
return murmurFinish(h, 1)
}
+
+// Equals returns whether d equals other. Two DFAStates are equal if their ATN
+// configuration sets are the same. This method is used to see if a state
+// already exists.
+//
+// Because the number of alternatives and number of ATN configurations are
+// finite, there is a finite number of DFA states that can be processed. This is
+// necessary to show that the algorithm terminates.
+//
+// Cannot test the DFA state numbers here because in
+// ParserATNSimulator.addDFAState we need to know if any other state exists that
+// has d exact set of ATN configurations. The stateNumber is irrelevant.
+func (d *DFAState) Equals(o Collectable[*DFAState]) bool {
+ if d == o {
+ return true
+ }
+
+ return d.configs.Equals(o.(*DFAState).configs)
+}
diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/diagnostic_error_listener.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/diagnostic_error_listener.go
similarity index 98%
rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/diagnostic_error_listener.go
rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/diagnostic_error_listener.go
index 1fec43d9d..c55bcc19b 100644
--- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/diagnostic_error_listener.go
+++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/diagnostic_error_listener.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
+// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved.
// Use of this file is governed by the BSD 3-clause license that
// can be found in the LICENSE.txt file in the project root.
@@ -87,7 +87,6 @@ func (d *DiagnosticErrorListener) getDecisionDescription(recognizer Parser, dfa
return strconv.Itoa(decision) + " (" + ruleName + ")"
}
-//
// Computes the set of conflicting or ambiguous alternatives from a
// configuration set, if that information was not already provided by the
// parser.
@@ -97,7 +96,6 @@ func (d *DiagnosticErrorListener) getDecisionDescription(recognizer Parser, dfa
// @param configs The conflicting or ambiguous configuration set.
// @return Returns {@code ReportedAlts} if it is not {@code nil}, otherwise
// returns the set of alternatives represented in {@code configs}.
-//
func (d *DiagnosticErrorListener) getConflictingAlts(ReportedAlts *BitSet, set ATNConfigSet) *BitSet {
if ReportedAlts != nil {
return ReportedAlts
diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/error_listener.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/error_listener.go
similarity index 98%
rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/error_listener.go
rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/error_listener.go
index 028e1a9d7..f679f0dcd 100644
--- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/error_listener.go
+++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/error_listener.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
+// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved.
// Use of this file is governed by the BSD 3-clause license that
// can be found in the LICENSE.txt file in the project root.
@@ -48,12 +48,9 @@ func NewConsoleErrorListener() *ConsoleErrorListener {
return new(ConsoleErrorListener)
}
-//
// Provides a default instance of {@link ConsoleErrorListener}.
-//
var ConsoleErrorListenerINSTANCE = NewConsoleErrorListener()
-//
// {@inheritDoc}
//
//
@@ -64,7 +61,6 @@ var ConsoleErrorListenerINSTANCE = NewConsoleErrorListener()
//
// line line:charPositionInLine msg
//
-//
func (c *ConsoleErrorListener) SyntaxError(recognizer Recognizer, offendingSymbol interface{}, line, column int, msg string, e RecognitionException) {
fmt.Fprintln(os.Stderr, "line "+strconv.Itoa(line)+":"+strconv.Itoa(column)+" "+msg)
}
diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/error_strategy.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/error_strategy.go
similarity index 99%
rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/error_strategy.go
rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/error_strategy.go
index c4080dbfd..5c0a637ba 100644
--- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/error_strategy.go
+++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/error_strategy.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
+// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved.
// Use of this file is governed by the BSD 3-clause license that
// can be found in the LICENSE.txt file in the project root.
@@ -23,7 +23,6 @@ type ErrorStrategy interface {
// This is the default implementation of {@link ANTLRErrorStrategy} used for
// error Reporting and recovery in ANTLR parsers.
-//
type DefaultErrorStrategy struct {
errorRecoveryMode bool
lastErrorIndex int
@@ -61,12 +60,10 @@ func (d *DefaultErrorStrategy) reset(recognizer Parser) {
d.endErrorCondition(recognizer)
}
-//
// This method is called to enter error recovery mode when a recognition
// exception is Reported.
//
// @param recognizer the parser instance
-//
func (d *DefaultErrorStrategy) beginErrorCondition(recognizer Parser) {
d.errorRecoveryMode = true
}
@@ -75,28 +72,23 @@ func (d *DefaultErrorStrategy) InErrorRecoveryMode(recognizer Parser) bool {
return d.errorRecoveryMode
}
-//
// This method is called to leave error recovery mode after recovering from
// a recognition exception.
//
// @param recognizer
-//
func (d *DefaultErrorStrategy) endErrorCondition(recognizer Parser) {
d.errorRecoveryMode = false
d.lastErrorStates = nil
d.lastErrorIndex = -1
}
-//
// {@inheritDoc}
//
// The default implementation simply calls {@link //endErrorCondition}.
-//
func (d *DefaultErrorStrategy) ReportMatch(recognizer Parser) {
d.endErrorCondition(recognizer)
}
-//
// {@inheritDoc}
//
// The default implementation returns immediately if the handler is already
@@ -114,7 +106,6 @@ func (d *DefaultErrorStrategy) ReportMatch(recognizer Parser) {
//
All other types: calls {@link Parser//NotifyErrorListeners} to Report
// the exception
//
-//
func (d *DefaultErrorStrategy) ReportError(recognizer Parser, e RecognitionException) {
// if we've already Reported an error and have not Matched a token
// yet successfully, don't Report any errors.
@@ -142,7 +133,6 @@ func (d *DefaultErrorStrategy) ReportError(recognizer Parser, e RecognitionExcep
// The default implementation reSynchronizes the parser by consuming tokens
// until we find one in the reSynchronization set--loosely the set of tokens
// that can follow the current rule.
-//
func (d *DefaultErrorStrategy) Recover(recognizer Parser, e RecognitionException) {
if d.lastErrorIndex == recognizer.GetInputStream().Index() &&
@@ -206,7 +196,6 @@ func (d *DefaultErrorStrategy) Recover(recognizer Parser, e RecognitionException
// compare token set at the start of the loop and at each iteration. If for
// some reason speed is suffering for you, you can turn off d
// functionality by simply overriding d method as a blank { }.
-//
func (d *DefaultErrorStrategy) Sync(recognizer Parser) {
// If already recovering, don't try to Sync
if d.InErrorRecoveryMode(recognizer) {
@@ -247,7 +236,6 @@ func (d *DefaultErrorStrategy) Sync(recognizer Parser) {
//
// @param recognizer the parser instance
// @param e the recognition exception
-//
func (d *DefaultErrorStrategy) ReportNoViableAlternative(recognizer Parser, e *NoViableAltException) {
tokens := recognizer.GetTokenStream()
var input string
@@ -264,7 +252,6 @@ func (d *DefaultErrorStrategy) ReportNoViableAlternative(recognizer Parser, e *N
recognizer.NotifyErrorListeners(msg, e.offendingToken, e)
}
-//
// This is called by {@link //ReportError} when the exception is an
// {@link InputMisMatchException}.
//
@@ -272,14 +259,12 @@ func (d *DefaultErrorStrategy) ReportNoViableAlternative(recognizer Parser, e *N
//
// @param recognizer the parser instance
// @param e the recognition exception
-//
func (this *DefaultErrorStrategy) ReportInputMisMatch(recognizer Parser, e *InputMisMatchException) {
msg := "mismatched input " + this.GetTokenErrorDisplay(e.offendingToken) +
" expecting " + e.getExpectedTokens().StringVerbose(recognizer.GetLiteralNames(), recognizer.GetSymbolicNames(), false)
recognizer.NotifyErrorListeners(msg, e.offendingToken, e)
}
-//
// This is called by {@link //ReportError} when the exception is a
// {@link FailedPredicateException}.
//
@@ -287,7 +272,6 @@ func (this *DefaultErrorStrategy) ReportInputMisMatch(recognizer Parser, e *Inpu
//
// @param recognizer the parser instance
// @param e the recognition exception
-//
func (d *DefaultErrorStrategy) ReportFailedPredicate(recognizer Parser, e *FailedPredicateException) {
ruleName := recognizer.GetRuleNames()[recognizer.GetParserRuleContext().GetRuleIndex()]
msg := "rule " + ruleName + " " + e.message
@@ -310,7 +294,6 @@ func (d *DefaultErrorStrategy) ReportFailedPredicate(recognizer Parser, e *Faile
// {@link Parser//NotifyErrorListeners}.
//
// @param recognizer the parser instance
-//
func (d *DefaultErrorStrategy) ReportUnwantedToken(recognizer Parser) {
if d.InErrorRecoveryMode(recognizer) {
return
@@ -339,7 +322,6 @@ func (d *DefaultErrorStrategy) ReportUnwantedToken(recognizer Parser) {
// {@link Parser//NotifyErrorListeners}.
//
// @param recognizer the parser instance
-//
func (d *DefaultErrorStrategy) ReportMissingToken(recognizer Parser) {
if d.InErrorRecoveryMode(recognizer) {
return
@@ -392,15 +374,14 @@ func (d *DefaultErrorStrategy) ReportMissingToken(recognizer Parser) {
// derivation:
//
//
-// => ID '=' '(' INT ')' ('+' atom)* ''
+// => ID '=' '(' INT ')' ('+' atom)* ”
// ^
//
//
-// The attempt to Match {@code ')'} will fail when it sees {@code ''} and
-// call {@link //recoverInline}. To recover, it sees that {@code LA(1)==''}
+// The attempt to Match {@code ')'} will fail when it sees {@code ”} and
+// call {@link //recoverInline}. To recover, it sees that {@code LA(1)==”}
// is in the set of tokens that can follow the {@code ')'} token reference
// in rule {@code atom}. It can assume that you forgot the {@code ')'}.
-//
func (d *DefaultErrorStrategy) RecoverInline(recognizer Parser) Token {
// SINGLE TOKEN DELETION
MatchedSymbol := d.SingleTokenDeletion(recognizer)
@@ -418,7 +399,6 @@ func (d *DefaultErrorStrategy) RecoverInline(recognizer Parser) Token {
panic(NewInputMisMatchException(recognizer))
}
-//
// This method implements the single-token insertion inline error recovery
// strategy. It is called by {@link //recoverInline} if the single-token
// deletion strategy fails to recover from the mismatched input. If this
@@ -434,7 +414,6 @@ func (d *DefaultErrorStrategy) RecoverInline(recognizer Parser) Token {
// @param recognizer the parser instance
// @return {@code true} if single-token insertion is a viable recovery
// strategy for the current mismatched input, otherwise {@code false}
-//
func (d *DefaultErrorStrategy) SingleTokenInsertion(recognizer Parser) bool {
currentSymbolType := recognizer.GetTokenStream().LA(1)
// if current token is consistent with what could come after current
@@ -469,7 +448,6 @@ func (d *DefaultErrorStrategy) SingleTokenInsertion(recognizer Parser) bool {
// @return the successfully Matched {@link Token} instance if single-token
// deletion successfully recovers from the mismatched input, otherwise
// {@code nil}
-//
func (d *DefaultErrorStrategy) SingleTokenDeletion(recognizer Parser) Token {
NextTokenType := recognizer.GetTokenStream().LA(2)
expecting := d.GetExpectedTokens(recognizer)
@@ -507,7 +485,6 @@ func (d *DefaultErrorStrategy) SingleTokenDeletion(recognizer Parser) Token {
// a CommonToken of the appropriate type. The text will be the token.
// If you change what tokens must be created by the lexer,
// override d method to create the appropriate tokens.
-//
func (d *DefaultErrorStrategy) GetMissingSymbol(recognizer Parser) Token {
currentSymbol := recognizer.GetCurrentToken()
expecting := d.GetExpectedTokens(recognizer)
@@ -546,7 +523,6 @@ func (d *DefaultErrorStrategy) GetExpectedTokens(recognizer Parser) *IntervalSet
// the token). This is better than forcing you to override a method in
// your token objects because you don't have to go modify your lexer
// so that it creates a NewJava type.
-//
func (d *DefaultErrorStrategy) GetTokenErrorDisplay(t Token) string {
if t == nil {
return ""
@@ -578,7 +554,7 @@ func (d *DefaultErrorStrategy) escapeWSAndQuote(s string) string {
// from within the rule i.e., the FIRST computation done by
// ANTLR stops at the end of a rule.
//
-// EXAMPLE
+// # EXAMPLE
//
// When you find a "no viable alt exception", the input is not
// consistent with any of the alternatives for rule r. The best
@@ -597,7 +573,6 @@ func (d *DefaultErrorStrategy) escapeWSAndQuote(s string) string {
// c : ID
// | INT
//
-//
// At each rule invocation, the set of tokens that could follow
// that rule is pushed on a stack. Here are the various
// context-sensitive follow sets:
@@ -660,7 +635,6 @@ func (d *DefaultErrorStrategy) escapeWSAndQuote(s string) string {
//
// Like Grosch I implement context-sensitive FOLLOW sets that are combined
// at run-time upon error to avoid overhead during parsing.
-//
func (d *DefaultErrorStrategy) getErrorRecoverySet(recognizer Parser) *IntervalSet {
atn := recognizer.GetInterpreter().atn
ctx := recognizer.GetParserRuleContext()
@@ -733,7 +707,6 @@ func NewBailErrorStrategy() *BailErrorStrategy {
// in a {@link ParseCancellationException} so it is not caught by the
// rule func catches. Use {@link Exception//getCause()} to get the
// original {@link RecognitionException}.
-//
func (b *BailErrorStrategy) Recover(recognizer Parser, e RecognitionException) {
context := recognizer.GetParserRuleContext()
for context != nil {
@@ -749,7 +722,6 @@ func (b *BailErrorStrategy) Recover(recognizer Parser, e RecognitionException) {
// Make sure we don't attempt to recover inline if the parser
// successfully recovers, it won't panic an exception.
-//
func (b *BailErrorStrategy) RecoverInline(recognizer Parser) Token {
b.Recover(recognizer, NewInputMisMatchException(recognizer))
diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/errors.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/errors.go
similarity index 98%
rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/errors.go
rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/errors.go
index 2ef74926e..3954c1378 100644
--- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/errors.go
+++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/errors.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
+// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved.
// Use of this file is governed by the BSD 3-clause license that
// can be found in the LICENSE.txt file in the project root.
@@ -74,7 +74,6 @@ func (b *BaseRecognitionException) GetInputStream() IntStream {
// If the state number is not known, b method returns -1.
-//
// Gets the set of input symbols which could potentially follow the
// previously Matched symbol at the time b exception was panicn.
//
@@ -136,7 +135,6 @@ type NoViableAltException struct {
// to take based upon the remaining input. It tracks the starting token
// of the offending input and also knows where the parser was
// in the various paths when the error. Reported by ReportNoViableAlternative()
-//
func NewNoViableAltException(recognizer Parser, input TokenStream, startToken Token, offendingToken Token, deadEndConfigs ATNConfigSet, ctx ParserRuleContext) *NoViableAltException {
if ctx == nil {
@@ -177,7 +175,6 @@ type InputMisMatchException struct {
// This signifies any kind of mismatched input exceptions such as
// when the current input does not Match the expected token.
-//
func NewInputMisMatchException(recognizer Parser) *InputMisMatchException {
i := new(InputMisMatchException)
diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/file_stream.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/file_stream.go
similarity index 92%
rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/file_stream.go
rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/file_stream.go
index 842170c08..bd6ad5efe 100644
--- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/file_stream.go
+++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/file_stream.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
+// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved.
// Use of this file is governed by the BSD 3-clause license that
// can be found in the LICENSE.txt file in the project root.
diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/input_stream.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/input_stream.go
similarity index 96%
rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/input_stream.go
rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/input_stream.go
index 5ff270f53..a8b889ced 100644
--- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/input_stream.go
+++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/input_stream.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
+// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved.
// Use of this file is governed by the BSD 3-clause license that
// can be found in the LICENSE.txt file in the project root.
diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/int_stream.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/int_stream.go
similarity index 82%
rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/int_stream.go
rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/int_stream.go
index 438e0ea6e..4778878bd 100644
--- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/int_stream.go
+++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/int_stream.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
+// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved.
// Use of this file is governed by the BSD 3-clause license that
// can be found in the LICENSE.txt file in the project root.
diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/interval_set.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/interval_set.go
similarity index 98%
rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/interval_set.go
rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/interval_set.go
index 1e9393adb..c1e155e81 100644
--- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/interval_set.go
+++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/interval_set.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
+// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved.
// Use of this file is governed by the BSD 3-clause license that
// can be found in the LICENSE.txt file in the project root.
@@ -223,6 +223,10 @@ func (i *IntervalSet) StringVerbose(literalNames []string, symbolicNames []strin
return i.toIndexString()
}
+func (i *IntervalSet) GetIntervals() []*Interval {
+ return i.intervals
+}
+
func (i *IntervalSet) toCharString() string {
names := make([]string, len(i.intervals))
diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/jcollect.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/jcollect.go
new file mode 100644
index 000000000..e5a74f0c6
--- /dev/null
+++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/jcollect.go
@@ -0,0 +1,198 @@
+package antlr
+
+// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved.
+// Use of this file is governed by the BSD 3-clause license that
+// can be found in the LICENSE.txt file in the project root.
+
+import (
+ "sort"
+)
+
+// Collectable is an interface that a struct should implement if it is to be
+// usable as a key in these collections.
+type Collectable[T any] interface {
+ Hash() int
+ Equals(other Collectable[T]) bool
+}
+
+type Comparator[T any] interface {
+ Hash1(o T) int
+ Equals2(T, T) bool
+}
+
+// JStore implements a container that allows the use of a struct to calculate the key
+// for a collection of values akin to map. This is not meant to be a full-blown HashMap but just
+// serve the needs of the ANTLR Go runtime.
+//
+// For ease of porting the logic of the runtime from the master target (Java), this collection
+// operates in a similar way to Java, in that it can use any struct that supplies a Hash() and Equals()
+// function as the key. The values are stored in a standard go map which internally is a form of hashmap
+// itself, the key for the go map is the hash supplied by the key object. The collection is able to deal with
+// hash conflicts by using a simple slice of values associated with the hash code indexed bucket. That isn't
+// particularly efficient, but it is simple, and it works. As this is specifically for the ANTLR runtime, and
+// we understand the requirements, then this is fine - this is not a general purpose collection.
+type JStore[T any, C Comparator[T]] struct {
+ store map[int][]T
+ len int
+ comparator Comparator[T]
+}
+
+func NewJStore[T any, C Comparator[T]](comparator Comparator[T]) *JStore[T, C] {
+
+ if comparator == nil {
+ panic("comparator cannot be nil")
+ }
+
+ s := &JStore[T, C]{
+ store: make(map[int][]T, 1),
+ comparator: comparator,
+ }
+ return s
+}
+
+// Put will store given value in the collection. Note that the key for storage is generated from
+// the value itself - this is specifically because that is what ANTLR needs - this would not be useful
+// as any kind of general collection.
+//
+// If the key has a hash conflict, then the value will be added to the slice of values associated with the
+// hash, unless the value is already in the slice, in which case the existing value is returned. Value equivalence is
+// tested by calling the equals() method on the key.
+//
+// # If the given value is already present in the store, then the existing value is returned as v and exists is set to true
+//
+// If the given value is not present in the store, then the value is added to the store and returned as v and exists is set to false.
+func (s *JStore[T, C]) Put(value T) (v T, exists bool) { //nolint:ireturn
+
+ kh := s.comparator.Hash1(value)
+
+ for _, v1 := range s.store[kh] {
+ if s.comparator.Equals2(value, v1) {
+ return v1, true
+ }
+ }
+ s.store[kh] = append(s.store[kh], value)
+ s.len++
+ return value, false
+}
+
+// Get will return the value associated with the key - the type of the key is the same type as the value
+// which would not generally be useful, but this is a specific thing for ANTLR where the key is
+// generated using the object we are going to store.
+func (s *JStore[T, C]) Get(key T) (T, bool) { //nolint:ireturn
+
+ kh := s.comparator.Hash1(key)
+
+ for _, v := range s.store[kh] {
+ if s.comparator.Equals2(key, v) {
+ return v, true
+ }
+ }
+ return key, false
+}
+
+// Contains returns true if the given key is present in the store
+func (s *JStore[T, C]) Contains(key T) bool { //nolint:ireturn
+
+ _, present := s.Get(key)
+ return present
+}
+
+func (s *JStore[T, C]) SortedSlice(less func(i, j T) bool) []T {
+ vs := make([]T, 0, len(s.store))
+ for _, v := range s.store {
+ vs = append(vs, v...)
+ }
+ sort.Slice(vs, func(i, j int) bool {
+ return less(vs[i], vs[j])
+ })
+
+ return vs
+}
+
+func (s *JStore[T, C]) Each(f func(T) bool) {
+ for _, e := range s.store {
+ for _, v := range e {
+ f(v)
+ }
+ }
+}
+
+func (s *JStore[T, C]) Len() int {
+ return s.len
+}
+
+func (s *JStore[T, C]) Values() []T {
+ vs := make([]T, 0, len(s.store))
+ for _, e := range s.store {
+ for _, v := range e {
+ vs = append(vs, v)
+ }
+ }
+ return vs
+}
+
+type entry[K, V any] struct {
+ key K
+ val V
+}
+
+type JMap[K, V any, C Comparator[K]] struct {
+ store map[int][]*entry[K, V]
+ len int
+ comparator Comparator[K]
+}
+
+func NewJMap[K, V any, C Comparator[K]](comparator Comparator[K]) *JMap[K, V, C] {
+ return &JMap[K, V, C]{
+ store: make(map[int][]*entry[K, V], 1),
+ comparator: comparator,
+ }
+}
+
+func (m *JMap[K, V, C]) Put(key K, val V) {
+ kh := m.comparator.Hash1(key)
+
+ m.store[kh] = append(m.store[kh], &entry[K, V]{key, val})
+ m.len++
+}
+
+func (m *JMap[K, V, C]) Values() []V {
+ vs := make([]V, 0, len(m.store))
+ for _, e := range m.store {
+ for _, v := range e {
+ vs = append(vs, v.val)
+ }
+ }
+ return vs
+}
+
+func (m *JMap[K, V, C]) Get(key K) (V, bool) {
+
+ var none V
+ kh := m.comparator.Hash1(key)
+ for _, e := range m.store[kh] {
+ if m.comparator.Equals2(e.key, key) {
+ return e.val, true
+ }
+ }
+ return none, false
+}
+
+func (m *JMap[K, V, C]) Len() int {
+ return len(m.store)
+}
+
+func (m *JMap[K, V, C]) Delete(key K) {
+ kh := m.comparator.Hash1(key)
+ for i, e := range m.store[kh] {
+ if m.comparator.Equals2(e.key, key) {
+ m.store[kh] = append(m.store[kh][:i], m.store[kh][i+1:]...)
+ m.len--
+ return
+ }
+ }
+}
+
+func (m *JMap[K, V, C]) Clear() {
+ m.store = make(map[int][]*entry[K, V])
+}
diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/lexer.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/lexer.go
similarity index 98%
rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/lexer.go
rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/lexer.go
index b04f04572..6533f0516 100644
--- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/lexer.go
+++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/lexer.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
+// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved.
// Use of this file is governed by the BSD 3-clause license that
// can be found in the LICENSE.txt file in the project root.
@@ -232,8 +232,6 @@ func (b *BaseLexer) NextToken() Token {
}
return b.token
}
-
- return nil
}
// Instruct the lexer to Skip creating a token for current lexer rule
@@ -342,7 +340,7 @@ func (b *BaseLexer) GetCharIndex() int {
}
// Return the text Matched so far for the current token or any text override.
-//Set the complete text of l token it wipes any previous changes to the text.
+// Set the complete text of l token it wipes any previous changes to the text.
func (b *BaseLexer) GetText() string {
if b.text != "" {
return b.text
diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/lexer_action.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/lexer_action.go
similarity index 91%
rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/lexer_action.go
rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/lexer_action.go
index 5a325be13..111656c29 100644
--- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/lexer_action.go
+++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/lexer_action.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
+// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved.
// Use of this file is governed by the BSD 3-clause license that
// can be found in the LICENSE.txt file in the project root.
@@ -21,8 +21,8 @@ type LexerAction interface {
getActionType() int
getIsPositionDependent() bool
execute(lexer Lexer)
- hash() int
- equals(other LexerAction) bool
+ Hash() int
+ Equals(other LexerAction) bool
}
type BaseLexerAction struct {
@@ -51,15 +51,14 @@ func (b *BaseLexerAction) getIsPositionDependent() bool {
return b.isPositionDependent
}
-func (b *BaseLexerAction) hash() int {
+func (b *BaseLexerAction) Hash() int {
return b.actionType
}
-func (b *BaseLexerAction) equals(other LexerAction) bool {
+func (b *BaseLexerAction) Equals(other LexerAction) bool {
return b == other
}
-//
// Implements the {@code Skip} lexer action by calling {@link Lexer//Skip}.
//
// The {@code Skip} command does not have any parameters, so l action is
@@ -85,7 +84,8 @@ func (l *LexerSkipAction) String() string {
return "skip"
}
-// Implements the {@code type} lexer action by calling {@link Lexer//setType}
+// Implements the {@code type} lexer action by calling {@link Lexer//setType}
+//
// with the assigned type.
type LexerTypeAction struct {
*BaseLexerAction
@@ -104,14 +104,14 @@ func (l *LexerTypeAction) execute(lexer Lexer) {
lexer.SetType(l.thetype)
}
-func (l *LexerTypeAction) hash() int {
+func (l *LexerTypeAction) Hash() int {
h := murmurInit(0)
h = murmurUpdate(h, l.actionType)
h = murmurUpdate(h, l.thetype)
return murmurFinish(h, 2)
}
-func (l *LexerTypeAction) equals(other LexerAction) bool {
+func (l *LexerTypeAction) Equals(other LexerAction) bool {
if l == other {
return true
} else if _, ok := other.(*LexerTypeAction); !ok {
@@ -148,14 +148,14 @@ func (l *LexerPushModeAction) execute(lexer Lexer) {
lexer.PushMode(l.mode)
}
-func (l *LexerPushModeAction) hash() int {
+func (l *LexerPushModeAction) Hash() int {
h := murmurInit(0)
h = murmurUpdate(h, l.actionType)
h = murmurUpdate(h, l.mode)
return murmurFinish(h, 2)
}
-func (l *LexerPushModeAction) equals(other LexerAction) bool {
+func (l *LexerPushModeAction) Equals(other LexerAction) bool {
if l == other {
return true
} else if _, ok := other.(*LexerPushModeAction); !ok {
@@ -245,14 +245,14 @@ func (l *LexerModeAction) execute(lexer Lexer) {
lexer.SetMode(l.mode)
}
-func (l *LexerModeAction) hash() int {
+func (l *LexerModeAction) Hash() int {
h := murmurInit(0)
h = murmurUpdate(h, l.actionType)
h = murmurUpdate(h, l.mode)
return murmurFinish(h, 2)
}
-func (l *LexerModeAction) equals(other LexerAction) bool {
+func (l *LexerModeAction) Equals(other LexerAction) bool {
if l == other {
return true
} else if _, ok := other.(*LexerModeAction); !ok {
@@ -303,7 +303,7 @@ func (l *LexerCustomAction) execute(lexer Lexer) {
lexer.Action(nil, l.ruleIndex, l.actionIndex)
}
-func (l *LexerCustomAction) hash() int {
+func (l *LexerCustomAction) Hash() int {
h := murmurInit(0)
h = murmurUpdate(h, l.actionType)
h = murmurUpdate(h, l.ruleIndex)
@@ -311,13 +311,14 @@ func (l *LexerCustomAction) hash() int {
return murmurFinish(h, 3)
}
-func (l *LexerCustomAction) equals(other LexerAction) bool {
+func (l *LexerCustomAction) Equals(other LexerAction) bool {
if l == other {
return true
} else if _, ok := other.(*LexerCustomAction); !ok {
return false
} else {
- return l.ruleIndex == other.(*LexerCustomAction).ruleIndex && l.actionIndex == other.(*LexerCustomAction).actionIndex
+ return l.ruleIndex == other.(*LexerCustomAction).ruleIndex &&
+ l.actionIndex == other.(*LexerCustomAction).actionIndex
}
}
@@ -344,14 +345,14 @@ func (l *LexerChannelAction) execute(lexer Lexer) {
lexer.SetChannel(l.channel)
}
-func (l *LexerChannelAction) hash() int {
+func (l *LexerChannelAction) Hash() int {
h := murmurInit(0)
h = murmurUpdate(h, l.actionType)
h = murmurUpdate(h, l.channel)
return murmurFinish(h, 2)
}
-func (l *LexerChannelAction) equals(other LexerAction) bool {
+func (l *LexerChannelAction) Equals(other LexerAction) bool {
if l == other {
return true
} else if _, ok := other.(*LexerChannelAction); !ok {
@@ -412,10 +413,10 @@ func (l *LexerIndexedCustomAction) execute(lexer Lexer) {
l.lexerAction.execute(lexer)
}
-func (l *LexerIndexedCustomAction) hash() int {
+func (l *LexerIndexedCustomAction) Hash() int {
h := murmurInit(0)
h = murmurUpdate(h, l.offset)
- h = murmurUpdate(h, l.lexerAction.hash())
+ h = murmurUpdate(h, l.lexerAction.Hash())
return murmurFinish(h, 2)
}
@@ -425,6 +426,7 @@ func (l *LexerIndexedCustomAction) equals(other LexerAction) bool {
} else if _, ok := other.(*LexerIndexedCustomAction); !ok {
return false
} else {
- return l.offset == other.(*LexerIndexedCustomAction).offset && l.lexerAction == other.(*LexerIndexedCustomAction).lexerAction
+ return l.offset == other.(*LexerIndexedCustomAction).offset &&
+ l.lexerAction.Equals(other.(*LexerIndexedCustomAction).lexerAction)
}
}
diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/lexer_action_executor.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/lexer_action_executor.go
similarity index 88%
rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/lexer_action_executor.go
rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/lexer_action_executor.go
index 056941dd6..be1ba7a7e 100644
--- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/lexer_action_executor.go
+++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/lexer_action_executor.go
@@ -1,9 +1,11 @@
-// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
+// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved.
// Use of this file is governed by the BSD 3-clause license that
// can be found in the LICENSE.txt file in the project root.
package antlr
+import "golang.org/x/exp/slices"
+
// Represents an executor for a sequence of lexer actions which traversed during
// the Matching operation of a lexer rule (token).
//
@@ -12,8 +14,8 @@ package antlr
// not cause bloating of the {@link DFA} created for the lexer.
type LexerActionExecutor struct {
- lexerActions []LexerAction
- cachedHash int
+ lexerActions []LexerAction
+ cachedHash int
}
func NewLexerActionExecutor(lexerActions []LexerAction) *LexerActionExecutor {
@@ -30,7 +32,7 @@ func NewLexerActionExecutor(lexerActions []LexerAction) *LexerActionExecutor {
// of the performance-critical {@link LexerATNConfig//hashCode} operation.
l.cachedHash = murmurInit(57)
for _, a := range lexerActions {
- l.cachedHash = murmurUpdate(l.cachedHash, a.hash())
+ l.cachedHash = murmurUpdate(l.cachedHash, a.Hash())
}
return l
@@ -151,14 +153,17 @@ func (l *LexerActionExecutor) execute(lexer Lexer, input CharStream, startIndex
}
}
-func (l *LexerActionExecutor) hash() int {
+func (l *LexerActionExecutor) Hash() int {
if l == nil {
+ // TODO: Why is this here? l should not be nil
return 61
}
+
+ // TODO: This is created from the action itself when the struct is created - will this be an issue at some point? Java uses the runtime assign hashcode
return l.cachedHash
}
-func (l *LexerActionExecutor) equals(other interface{}) bool {
+func (l *LexerActionExecutor) Equals(other interface{}) bool {
if l == other {
return true
}
@@ -169,5 +174,13 @@ func (l *LexerActionExecutor) equals(other interface{}) bool {
if othert == nil {
return false
}
- return l.cachedHash == othert.cachedHash && &l.lexerActions == &othert.lexerActions
+ if l.cachedHash != othert.cachedHash {
+ return false
+ }
+ if len(l.lexerActions) != len(othert.lexerActions) {
+ return false
+ }
+ return slices.EqualFunc(l.lexerActions, othert.lexerActions, func(i, j LexerAction) bool {
+ return i.Equals(j)
+ })
}
diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/lexer_atn_simulator.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/lexer_atn_simulator.go
similarity index 98%
rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/lexer_atn_simulator.go
rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/lexer_atn_simulator.go
index dc05153ea..c573b7521 100644
--- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/lexer_atn_simulator.go
+++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/lexer_atn_simulator.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
+// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved.
// Use of this file is governed by the BSD 3-clause license that
// can be found in the LICENSE.txt file in the project root.
@@ -591,19 +591,24 @@ func (l *LexerATNSimulator) addDFAState(configs ATNConfigSet, suppressEdge bool)
proposed.lexerActionExecutor = firstConfigWithRuleStopState.(*LexerATNConfig).lexerActionExecutor
proposed.setPrediction(l.atn.ruleToTokenType[firstConfigWithRuleStopState.GetState().GetRuleIndex()])
}
- hash := proposed.hash()
dfa := l.decisionToDFA[l.mode]
l.atn.stateMu.Lock()
defer l.atn.stateMu.Unlock()
- existing, ok := dfa.getState(hash)
- if ok {
+ existing, present := dfa.states.Get(proposed)
+ if present {
+
+ // This state was already present, so just return it.
+ //
proposed = existing
} else {
- proposed.stateNumber = dfa.numStates()
+
+ // We need to add the new state
+ //
+ proposed.stateNumber = dfa.states.Len()
configs.SetReadOnly(true)
proposed.configs = configs
- dfa.setState(hash, proposed)
+ dfa.states.Put(proposed)
}
if !suppressEdge {
dfa.setS0(proposed)
diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/ll1_analyzer.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/ll1_analyzer.go
similarity index 87%
rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/ll1_analyzer.go
rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/ll1_analyzer.go
index 6ffb37de6..76689615a 100644
--- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/ll1_analyzer.go
+++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/ll1_analyzer.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
+// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved.
// Use of this file is governed by the BSD 3-clause license that
// can be found in the LICENSE.txt file in the project root.
@@ -14,14 +14,15 @@ func NewLL1Analyzer(atn *ATN) *LL1Analyzer {
return la
}
-//* Special value added to the lookahead sets to indicate that we hit
-// a predicate during analysis if {@code seeThruPreds==false}.
-///
+// - Special value added to the lookahead sets to indicate that we hit
+// a predicate during analysis if {@code seeThruPreds==false}.
+//
+// /
const (
LL1AnalyzerHitPred = TokenInvalidType
)
-//*
+// *
// Calculates the SLL(1) expected lookahead set for each outgoing transition
// of an {@link ATNState}. The returned array has one element for each
// outgoing transition in {@code s}. If the closure from transition
@@ -38,7 +39,7 @@ func (la *LL1Analyzer) getDecisionLookahead(s ATNState) []*IntervalSet {
look := make([]*IntervalSet, count)
for alt := 0; alt < count; alt++ {
look[alt] = NewIntervalSet()
- lookBusy := newArray2DHashSet(nil, nil)
+ lookBusy := NewJStore[ATNConfig, Comparator[ATNConfig]](aConfEqInst)
seeThruPreds := false // fail to get lookahead upon pred
la.look1(s.GetTransitions()[alt].getTarget(), nil, BasePredictionContextEMPTY, look[alt], lookBusy, NewBitSet(), seeThruPreds, false)
// Wipe out lookahead for la alternative if we found nothing
@@ -50,7 +51,7 @@ func (la *LL1Analyzer) getDecisionLookahead(s ATNState) []*IntervalSet {
return look
}
-//*
+// *
// Compute set of tokens that can follow {@code s} in the ATN in the
// specified {@code ctx}.
//
@@ -67,7 +68,7 @@ func (la *LL1Analyzer) getDecisionLookahead(s ATNState) []*IntervalSet {
//
// @return The set of tokens that can follow {@code s} in the ATN in the
// specified {@code ctx}.
-///
+// /
func (la *LL1Analyzer) Look(s, stopState ATNState, ctx RuleContext) *IntervalSet {
r := NewIntervalSet()
seeThruPreds := true // ignore preds get all lookahead
@@ -75,7 +76,7 @@ func (la *LL1Analyzer) Look(s, stopState ATNState, ctx RuleContext) *IntervalSet
if ctx != nil {
lookContext = predictionContextFromRuleContext(s.GetATN(), ctx)
}
- la.look1(s, stopState, lookContext, r, newArray2DHashSet(nil, nil), NewBitSet(), seeThruPreds, true)
+ la.look1(s, stopState, lookContext, r, NewJStore[ATNConfig, Comparator[ATNConfig]](aConfEqInst), NewBitSet(), seeThruPreds, true)
return r
}
@@ -109,14 +110,14 @@ func (la *LL1Analyzer) Look(s, stopState ATNState, ctx RuleContext) *IntervalSet
// outermost context is reached. This parameter has no effect if {@code ctx}
// is {@code nil}.
-func (la *LL1Analyzer) look2(s, stopState ATNState, ctx PredictionContext, look *IntervalSet, lookBusy Set, calledRuleStack *BitSet, seeThruPreds, addEOF bool, i int) {
+func (la *LL1Analyzer) look2(s, stopState ATNState, ctx PredictionContext, look *IntervalSet, lookBusy *JStore[ATNConfig, Comparator[ATNConfig]], calledRuleStack *BitSet, seeThruPreds, addEOF bool, i int) {
returnState := la.atn.states[ctx.getReturnState(i)]
la.look1(returnState, stopState, ctx.GetParent(i), look, lookBusy, calledRuleStack, seeThruPreds, addEOF)
}
-func (la *LL1Analyzer) look1(s, stopState ATNState, ctx PredictionContext, look *IntervalSet, lookBusy Set, calledRuleStack *BitSet, seeThruPreds, addEOF bool) {
+func (la *LL1Analyzer) look1(s, stopState ATNState, ctx PredictionContext, look *IntervalSet, lookBusy *JStore[ATNConfig, Comparator[ATNConfig]], calledRuleStack *BitSet, seeThruPreds, addEOF bool) {
c := NewBaseATNConfig6(s, 0, ctx)
@@ -124,8 +125,11 @@ func (la *LL1Analyzer) look1(s, stopState ATNState, ctx PredictionContext, look
return
}
- lookBusy.Add(c)
+ _, present := lookBusy.Put(c)
+ if present {
+ return
+ }
if s == stopState {
if ctx == nil {
look.addOne(TokenEpsilon)
@@ -198,7 +202,7 @@ func (la *LL1Analyzer) look1(s, stopState ATNState, ctx PredictionContext, look
}
}
-func (la *LL1Analyzer) look3(stopState ATNState, ctx PredictionContext, look *IntervalSet, lookBusy Set, calledRuleStack *BitSet, seeThruPreds, addEOF bool, t1 *RuleTransition) {
+func (la *LL1Analyzer) look3(stopState ATNState, ctx PredictionContext, look *IntervalSet, lookBusy *JStore[ATNConfig, Comparator[ATNConfig]], calledRuleStack *BitSet, seeThruPreds, addEOF bool, t1 *RuleTransition) {
newContext := SingletonBasePredictionContextCreate(ctx, t1.followState.GetStateNumber())
diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/parser.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/parser.go
similarity index 99%
rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/parser.go
rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/parser.go
index 2ab2f5605..d26bf0639 100644
--- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/parser.go
+++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/parser.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
+// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved.
// Use of this file is governed by the BSD 3-clause license that
// can be found in the LICENSE.txt file in the project root.
@@ -91,7 +91,6 @@ func NewBaseParser(input TokenStream) *BaseParser {
// bypass alternatives.
//
// @see ATNDeserializationOptions//isGenerateRuleBypassTransitions()
-//
var bypassAltsAtnCache = make(map[string]int)
// reset the parser's state//
@@ -230,7 +229,6 @@ func (p *BaseParser) GetParseListeners() []ParseTreeListener {
// @param listener the listener to add
//
// @panics nilPointerException if {@code} listener is {@code nil}
-//
func (p *BaseParser) AddParseListener(listener ParseTreeListener) {
if listener == nil {
panic("listener")
@@ -241,13 +239,11 @@ func (p *BaseParser) AddParseListener(listener ParseTreeListener) {
p.parseListeners = append(p.parseListeners, listener)
}
-//
// Remove {@code listener} from the list of parse listeners.
//
// If {@code listener} is {@code nil} or has not been added as a parse
// listener, p.method does nothing.
// @param listener the listener to remove
-//
func (p *BaseParser) RemoveParseListener(listener ParseTreeListener) {
if p.parseListeners != nil {
@@ -289,11 +285,9 @@ func (p *BaseParser) TriggerEnterRuleEvent() {
}
}
-//
// Notify any parse listeners of an exit rule event.
//
// @see //addParseListener
-//
func (p *BaseParser) TriggerExitRuleEvent() {
if p.parseListeners != nil {
// reverse order walk of listeners
@@ -330,7 +324,6 @@ func (p *BaseParser) setTokenFactory(factory TokenFactory) {
//
// @panics UnsupportedOperationException if the current parser does not
// implement the {@link //getSerializedATN()} method.
-//
func (p *BaseParser) GetATNWithBypassAlts() {
// TODO
@@ -402,7 +395,6 @@ func (p *BaseParser) SetTokenStream(input TokenStream) {
// Match needs to return the current input symbol, which gets put
// into the label for the associated token ref e.g., x=ID.
-//
func (p *BaseParser) GetCurrentToken() Token {
return p.input.LT(1)
}
@@ -624,7 +616,6 @@ func (p *BaseParser) IsExpectedToken(symbol int) bool {
// respectively.
//
// @see ATN//getExpectedTokens(int, RuleContext)
-//
func (p *BaseParser) GetExpectedTokens() *IntervalSet {
return p.Interpreter.atn.getExpectedTokens(p.state, p.ctx)
}
@@ -686,7 +677,7 @@ func (p *BaseParser) GetDFAStrings() string {
func (p *BaseParser) DumpDFA() {
seenOne := false
for _, dfa := range p.Interpreter.decisionToDFA {
- if dfa.numStates() > 0 {
+ if dfa.states.Len() > 0 {
if seenOne {
fmt.Println()
}
@@ -703,7 +694,6 @@ func (p *BaseParser) GetSourceName() string {
// During a parse is sometimes useful to listen in on the rule entry and exit
// events as well as token Matches. p.is for quick and dirty debugging.
-//
func (p *BaseParser) SetTrace(trace *TraceListener) {
if trace == nil {
p.RemoveParseListener(p.tracer)
diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/parser_atn_simulator.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/parser_atn_simulator.go
similarity index 94%
rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/parser_atn_simulator.go
rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/parser_atn_simulator.go
index 888d51297..8bcc46a0d 100644
--- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/parser_atn_simulator.go
+++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/parser_atn_simulator.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
+// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved.
// Use of this file is governed by the BSD 3-clause license that
// can be found in the LICENSE.txt file in the project root.
@@ -11,11 +11,11 @@ import (
)
var (
- ParserATNSimulatorDebug = false
- ParserATNSimulatorListATNDecisions = false
- ParserATNSimulatorDFADebug = false
- ParserATNSimulatorRetryDebug = false
- TurnOffLRLoopEntryBranchOpt = false
+ ParserATNSimulatorDebug = false
+ ParserATNSimulatorTraceATNSim = false
+ ParserATNSimulatorDFADebug = false
+ ParserATNSimulatorRetryDebug = false
+ TurnOffLRLoopEntryBranchOpt = false
)
type ParserATNSimulator struct {
@@ -70,8 +70,8 @@ func (p *ParserATNSimulator) reset() {
}
func (p *ParserATNSimulator) AdaptivePredict(input TokenStream, decision int, outerContext ParserRuleContext) int {
- if ParserATNSimulatorDebug || ParserATNSimulatorListATNDecisions {
- fmt.Println("AdaptivePredict decision " + strconv.Itoa(decision) +
+ if ParserATNSimulatorDebug || ParserATNSimulatorTraceATNSim {
+ fmt.Println("adaptivePredict decision " + strconv.Itoa(decision) +
" exec LA(1)==" + p.getLookaheadName(input) +
" line " + strconv.Itoa(input.LT(1).GetLine()) + ":" +
strconv.Itoa(input.LT(1).GetColumn()))
@@ -111,15 +111,15 @@ func (p *ParserATNSimulator) AdaptivePredict(input TokenStream, decision int, ou
if s0 == nil {
if outerContext == nil {
- outerContext = RuleContextEmpty
+ outerContext = ParserRuleContextEmpty
}
- if ParserATNSimulatorDebug || ParserATNSimulatorListATNDecisions {
+ if ParserATNSimulatorDebug {
fmt.Println("predictATN decision " + strconv.Itoa(dfa.decision) +
" exec LA(1)==" + p.getLookaheadName(input) +
", outerContext=" + outerContext.String(p.parser.GetRuleNames(), nil))
}
fullCtx := false
- s0Closure := p.computeStartState(dfa.atnStartState, RuleContextEmpty, fullCtx)
+ s0Closure := p.computeStartState(dfa.atnStartState, ParserRuleContextEmpty, fullCtx)
p.atn.stateMu.Lock()
if dfa.getPrecedenceDfa() {
@@ -174,17 +174,18 @@ func (p *ParserATNSimulator) AdaptivePredict(input TokenStream, decision int, ou
// Reporting insufficient predicates
// cover these cases:
-// dead end
-// single alt
-// single alt + preds
-// conflict
-// conflict + preds
//
+// dead end
+// single alt
+// single alt + preds
+// conflict
+// conflict + preds
func (p *ParserATNSimulator) execATN(dfa *DFA, s0 *DFAState, input TokenStream, startIndex int, outerContext ParserRuleContext) int {
- if ParserATNSimulatorDebug || ParserATNSimulatorListATNDecisions {
+ if ParserATNSimulatorDebug || ParserATNSimulatorTraceATNSim {
fmt.Println("execATN decision " + strconv.Itoa(dfa.decision) +
- " exec LA(1)==" + p.getLookaheadName(input) +
+ ", DFA state " + s0.String() +
+ ", LA(1)==" + p.getLookaheadName(input) +
" line " + strconv.Itoa(input.LT(1).GetLine()) + ":" + strconv.Itoa(input.LT(1).GetColumn()))
}
@@ -277,8 +278,6 @@ func (p *ParserATNSimulator) execATN(dfa *DFA, s0 *DFAState, input TokenStream,
t = input.LA(1)
}
}
-
- panic("Should not have reached p state")
}
// Get an existing target state for an edge in the DFA. If the target state
@@ -384,7 +383,7 @@ func (p *ParserATNSimulator) predicateDFAState(dfaState *DFAState, decisionState
// comes back with reach.uniqueAlt set to a valid alt
func (p *ParserATNSimulator) execATNWithFullContext(dfa *DFA, D *DFAState, s0 ATNConfigSet, input TokenStream, startIndex int, outerContext ParserRuleContext) int {
- if ParserATNSimulatorDebug || ParserATNSimulatorListATNDecisions {
+ if ParserATNSimulatorDebug || ParserATNSimulatorTraceATNSim {
fmt.Println("execATNWithFullContext " + s0.String())
}
@@ -492,9 +491,6 @@ func (p *ParserATNSimulator) execATNWithFullContext(dfa *DFA, D *DFAState, s0 AT
}
func (p *ParserATNSimulator) computeReachSet(closure ATNConfigSet, t int, fullCtx bool) ATNConfigSet {
- if ParserATNSimulatorDebug {
- fmt.Println("in computeReachSet, starting closure: " + closure.String())
- }
if p.mergeCache == nil {
p.mergeCache = NewDoubleDict()
}
@@ -570,7 +566,7 @@ func (p *ParserATNSimulator) computeReachSet(closure ATNConfigSet, t int, fullCt
//
if reach == nil {
reach = NewBaseATNConfigSet(fullCtx)
- closureBusy := newArray2DHashSet(nil, nil)
+ closureBusy := NewJStore[ATNConfig, Comparator[ATNConfig]](aConfEqInst)
treatEOFAsEpsilon := t == TokenEOF
amount := len(intermediate.configs)
for k := 0; k < amount; k++ {
@@ -610,6 +606,11 @@ func (p *ParserATNSimulator) computeReachSet(closure ATNConfigSet, t int, fullCt
reach.Add(skippedStopStates[l], p.mergeCache)
}
}
+
+ if ParserATNSimulatorTraceATNSim {
+ fmt.Println("computeReachSet " + closure.String() + " -> " + reach.String())
+ }
+
if len(reach.GetItems()) == 0 {
return nil
}
@@ -617,7 +618,6 @@ func (p *ParserATNSimulator) computeReachSet(closure ATNConfigSet, t int, fullCt
return reach
}
-//
// Return a configuration set containing only the configurations from
// {@code configs} which are in a {@link RuleStopState}. If all
// configurations in {@code configs} are already in a rule stop state, p
@@ -636,7 +636,6 @@ func (p *ParserATNSimulator) computeReachSet(closure ATNConfigSet, t int, fullCt
// @return {@code configs} if all configurations in {@code configs} are in a
// rule stop state, otherwise return a Newconfiguration set containing only
// the configurations from {@code configs} which are in a rule stop state
-//
func (p *ParserATNSimulator) removeAllConfigsNotInRuleStopState(configs ATNConfigSet, lookToEndOfRule bool) ATNConfigSet {
if PredictionModeallConfigsInRuleStopStates(configs) {
return configs
@@ -662,16 +661,20 @@ func (p *ParserATNSimulator) computeStartState(a ATNState, ctx RuleContext, full
// always at least the implicit call to start rule
initialContext := predictionContextFromRuleContext(p.atn, ctx)
configs := NewBaseATNConfigSet(fullCtx)
+ if ParserATNSimulatorDebug || ParserATNSimulatorTraceATNSim {
+ fmt.Println("computeStartState from ATN state " + a.String() +
+ " initialContext=" + initialContext.String())
+ }
+
for i := 0; i < len(a.GetTransitions()); i++ {
target := a.GetTransitions()[i].getTarget()
c := NewBaseATNConfig6(target, i+1, initialContext)
- closureBusy := newArray2DHashSet(nil, nil)
+ closureBusy := NewJStore[ATNConfig, Comparator[ATNConfig]](atnConfCompInst)
p.closure(c, configs, closureBusy, true, fullCtx, false)
}
return configs
}
-//
// This method transforms the start state computed by
// {@link //computeStartState} to the special start state used by a
// precedence DFA for a particular precedence value. The transformation
@@ -726,7 +729,6 @@ func (p *ParserATNSimulator) computeStartState(a ATNState, ctx RuleContext, full
// @return The transformed configuration set representing the start state
// for a precedence DFA at a particular precedence level (determined by
// calling {@link Parser//getPrecedence}).
-//
func (p *ParserATNSimulator) applyPrecedenceFilter(configs ATNConfigSet) ATNConfigSet {
statesFromAlt1 := make(map[int]PredictionContext)
@@ -760,7 +762,7 @@ func (p *ParserATNSimulator) applyPrecedenceFilter(configs ATNConfigSet) ATNConf
// (basically a graph subtraction algorithm).
if !config.getPrecedenceFilterSuppressed() {
context := statesFromAlt1[config.GetState().GetStateNumber()]
- if context != nil && context.equals(config.GetContext()) {
+ if context != nil && context.Equals(config.GetContext()) {
// eliminated
continue
}
@@ -824,7 +826,6 @@ func (p *ParserATNSimulator) getPredicatePredictions(ambigAlts *BitSet, altToPre
return pairs
}
-//
// This method is used to improve the localization of error messages by
// choosing an alternative rather than panicing a
// {@link NoViableAltException} in particular prediction scenarios where the
@@ -869,7 +870,6 @@ func (p *ParserATNSimulator) getPredicatePredictions(ambigAlts *BitSet, altToPre
// @return The value to return from {@link //AdaptivePredict}, or
// {@link ATN//INVALID_ALT_NUMBER} if a suitable alternative was not
// identified and {@link //AdaptivePredict} should Report an error instead.
-//
func (p *ParserATNSimulator) getSynValidOrSemInvalidAltThatFinishedDecisionEntryRule(configs ATNConfigSet, outerContext ParserRuleContext) int {
cfgs := p.splitAccordingToSemanticValidity(configs, outerContext)
semValidConfigs := cfgs[0]
@@ -938,11 +938,11 @@ func (p *ParserATNSimulator) splitAccordingToSemanticValidity(configs ATNConfigS
}
// Look through a list of predicate/alt pairs, returning alts for the
-// pairs that win. A {@code NONE} predicate indicates an alt containing an
-// unpredicated config which behaves as "always true." If !complete
-// then we stop at the first predicate that evaluates to true. This
-// includes pairs with nil predicates.
//
+// pairs that win. A {@code NONE} predicate indicates an alt containing an
+// unpredicated config which behaves as "always true." If !complete
+// then we stop at the first predicate that evaluates to true. This
+// includes pairs with nil predicates.
func (p *ParserATNSimulator) evalSemanticContext(predPredictions []*PredPrediction, outerContext ParserRuleContext, complete bool) *BitSet {
predictions := NewBitSet()
for i := 0; i < len(predPredictions); i++ {
@@ -972,16 +972,16 @@ func (p *ParserATNSimulator) evalSemanticContext(predPredictions []*PredPredicti
return predictions
}
-func (p *ParserATNSimulator) closure(config ATNConfig, configs ATNConfigSet, closureBusy Set, collectPredicates, fullCtx, treatEOFAsEpsilon bool) {
+func (p *ParserATNSimulator) closure(config ATNConfig, configs ATNConfigSet, closureBusy *JStore[ATNConfig, Comparator[ATNConfig]], collectPredicates, fullCtx, treatEOFAsEpsilon bool) {
initialDepth := 0
p.closureCheckingStopState(config, configs, closureBusy, collectPredicates,
fullCtx, initialDepth, treatEOFAsEpsilon)
}
-func (p *ParserATNSimulator) closureCheckingStopState(config ATNConfig, configs ATNConfigSet, closureBusy Set, collectPredicates, fullCtx bool, depth int, treatEOFAsEpsilon bool) {
- if ParserATNSimulatorDebug {
+func (p *ParserATNSimulator) closureCheckingStopState(config ATNConfig, configs ATNConfigSet, closureBusy *JStore[ATNConfig, Comparator[ATNConfig]], collectPredicates, fullCtx bool, depth int, treatEOFAsEpsilon bool) {
+ if ParserATNSimulatorTraceATNSim {
fmt.Println("closure(" + config.String() + ")")
- fmt.Println("configs(" + configs.String() + ")")
+ //fmt.Println("configs(" + configs.String() + ")")
if config.GetReachesIntoOuterContext() > 50 {
panic("problem")
}
@@ -1031,7 +1031,7 @@ func (p *ParserATNSimulator) closureCheckingStopState(config ATNConfig, configs
}
// Do the actual work of walking epsilon edges//
-func (p *ParserATNSimulator) closureWork(config ATNConfig, configs ATNConfigSet, closureBusy Set, collectPredicates, fullCtx bool, depth int, treatEOFAsEpsilon bool) {
+func (p *ParserATNSimulator) closureWork(config ATNConfig, configs ATNConfigSet, closureBusy *JStore[ATNConfig, Comparator[ATNConfig]], collectPredicates, fullCtx bool, depth int, treatEOFAsEpsilon bool) {
state := config.GetState()
// optimization
if !state.GetEpsilonOnlyTransitions() {
@@ -1066,7 +1066,8 @@ func (p *ParserATNSimulator) closureWork(config ATNConfig, configs ATNConfigSet,
c.SetReachesIntoOuterContext(c.GetReachesIntoOuterContext() + 1)
- if closureBusy.Add(c) != c {
+ _, present := closureBusy.Put(c)
+ if present {
// avoid infinite recursion for right-recursive rules
continue
}
@@ -1077,9 +1078,13 @@ func (p *ParserATNSimulator) closureWork(config ATNConfig, configs ATNConfigSet,
fmt.Println("dips into outer ctx: " + c.String())
}
} else {
- if !t.getIsEpsilon() && closureBusy.Add(c) != c {
- // avoid infinite recursion for EOF* and EOF+
- continue
+
+ if !t.getIsEpsilon() {
+ _, present := closureBusy.Put(c)
+ if present {
+ // avoid infinite recursion for EOF* and EOF+
+ continue
+ }
}
if _, ok := t.(*RuleTransition); ok {
// latch when newDepth goes negative - once we step out of the entry context we can't return
@@ -1104,7 +1109,16 @@ func (p *ParserATNSimulator) canDropLoopEntryEdgeInLeftRecursiveRule(config ATNC
// left-recursion elimination. For efficiency, also check if
// the context has an empty stack case. If so, it would mean
// global FOLLOW so we can't perform optimization
- if startLoop, ok := _p.(StarLoopEntryState); !ok || !startLoop.precedenceRuleDecision || config.GetContext().isEmpty() || config.GetContext().hasEmptyPath() {
+ if _p.GetStateType() != ATNStateStarLoopEntry {
+ return false
+ }
+ startLoop, ok := _p.(*StarLoopEntryState)
+ if !ok {
+ return false
+ }
+ if !startLoop.precedenceRuleDecision ||
+ config.GetContext().isEmpty() ||
+ config.GetContext().hasEmptyPath() {
return false
}
@@ -1117,8 +1131,8 @@ func (p *ParserATNSimulator) canDropLoopEntryEdgeInLeftRecursiveRule(config ATNC
return false
}
}
-
- decisionStartState := _p.(BlockStartState).GetTransitions()[0].getTarget().(BlockStartState)
+ x := _p.GetTransitions()[0].getTarget()
+ decisionStartState := x.(BlockStartState)
blockEndStateNum := decisionStartState.getEndState().stateNumber
blockEndState := p.atn.states[blockEndStateNum].(*BlockEndState)
@@ -1355,13 +1369,12 @@ func (p *ParserATNSimulator) GetTokenName(t int) string {
return "EOF"
}
- if p.parser != nil && p.parser.GetLiteralNames() != nil {
- if t >= len(p.parser.GetLiteralNames()) {
- fmt.Println(strconv.Itoa(t) + " ttype out of range: " + strings.Join(p.parser.GetLiteralNames(), ","))
- // fmt.Println(p.parser.GetInputStream().(TokenStream).GetAllText()) // p seems incorrect
- } else {
- return p.parser.GetLiteralNames()[t] + "<" + strconv.Itoa(t) + ">"
- }
+ if p.parser != nil && p.parser.GetLiteralNames() != nil && t < len(p.parser.GetLiteralNames()) {
+ return p.parser.GetLiteralNames()[t] + "<" + strconv.Itoa(t) + ">"
+ }
+
+ if p.parser != nil && p.parser.GetLiteralNames() != nil && t < len(p.parser.GetSymbolicNames()) {
+ return p.parser.GetSymbolicNames()[t] + "<" + strconv.Itoa(t) + ">"
}
return strconv.Itoa(t)
@@ -1372,9 +1385,9 @@ func (p *ParserATNSimulator) getLookaheadName(input TokenStream) string {
}
// Used for debugging in AdaptivePredict around execATN but I cut
-// it out for clarity now that alg. works well. We can leave p
-// "dead" code for a bit.
//
+// it out for clarity now that alg. works well. We can leave p
+// "dead" code for a bit.
func (p *ParserATNSimulator) dumpDeadEndConfigs(nvae *NoViableAltException) {
panic("Not implemented")
@@ -1421,7 +1434,6 @@ func (p *ParserATNSimulator) getUniqueAlt(configs ATNConfigSet) int {
return alt
}
-//
// Add an edge to the DFA, if possible. This method calls
// {@link //addDFAState} to ensure the {@code to} state is present in the
// DFA. If {@code from} is {@code nil}, or if {@code t} is outside the
@@ -1440,7 +1452,6 @@ func (p *ParserATNSimulator) getUniqueAlt(configs ATNConfigSet) int {
// @return If {@code to} is {@code nil}, p method returns {@code nil}
// otherwise p method returns the result of calling {@link //addDFAState}
// on {@code to}
-//
func (p *ParserATNSimulator) addDFAEdge(dfa *DFA, from *DFAState, t int, to *DFAState) *DFAState {
if ParserATNSimulatorDebug {
fmt.Println("EDGE " + from.String() + " -> " + to.String() + " upon " + p.GetTokenName(t))
@@ -1472,7 +1483,6 @@ func (p *ParserATNSimulator) addDFAEdge(dfa *DFA, from *DFAState, t int, to *DFA
return to
}
-//
// Add state {@code D} to the DFA if it is not already present, and return
// the actual instance stored in the DFA. If a state equivalent to {@code D}
// is already in the DFA, the existing state is returned. Otherwise p
@@ -1486,25 +1496,30 @@ func (p *ParserATNSimulator) addDFAEdge(dfa *DFA, from *DFAState, t int, to *DFA
// @return The state stored in the DFA. This will be either the existing
// state if {@code D} is already in the DFA, or {@code D} itself if the
// state was not already present.
-//
func (p *ParserATNSimulator) addDFAState(dfa *DFA, d *DFAState) *DFAState {
if d == ATNSimulatorError {
return d
}
- hash := d.hash()
- existing, ok := dfa.getState(hash)
- if ok {
+ existing, present := dfa.states.Get(d)
+ if present {
+ if ParserATNSimulatorTraceATNSim {
+ fmt.Print("addDFAState " + d.String() + " exists")
+ }
return existing
}
- d.stateNumber = dfa.numStates()
+
+ // The state was not present, so update it with configs
+ //
+ d.stateNumber = dfa.states.Len()
if !d.configs.ReadOnly() {
d.configs.OptimizeConfigs(p.BaseATNSimulator)
d.configs.SetReadOnly(true)
}
- dfa.setState(hash, d)
- if ParserATNSimulatorDebug {
- fmt.Println("adding NewDFA state: " + d.String())
+ dfa.states.Put(d)
+ if ParserATNSimulatorTraceATNSim {
+ fmt.Println("addDFAState new " + d.String())
}
+
return d
}
diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/parser_rule_context.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/parser_rule_context.go
similarity index 98%
rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/parser_rule_context.go
rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/parser_rule_context.go
index 49cd10c5f..1c8cee747 100644
--- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/parser_rule_context.go
+++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/parser_rule_context.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
+// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved.
// Use of this file is governed by the BSD 3-clause license that
// can be found in the LICENSE.txt file in the project root.
@@ -340,7 +340,7 @@ func (prc *BaseParserRuleContext) String(ruleNames []string, stop RuleContext) s
return s
}
-var RuleContextEmpty = NewBaseParserRuleContext(nil, -1)
+var ParserRuleContextEmpty = NewBaseParserRuleContext(nil, -1)
type InterpreterRuleContext interface {
ParserRuleContext
diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/prediction_context.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/prediction_context.go
similarity index 81%
rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/prediction_context.go
rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/prediction_context.go
index 9fdfd52b2..ba62af361 100644
--- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/prediction_context.go
+++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/prediction_context.go
@@ -1,10 +1,12 @@
-// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
+// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved.
// Use of this file is governed by the BSD 3-clause license that
// can be found in the LICENSE.txt file in the project root.
package antlr
import (
+ "fmt"
+ "golang.org/x/exp/slices"
"strconv"
)
@@ -26,10 +28,10 @@ var (
)
type PredictionContext interface {
- hash() int
+ Hash() int
+ Equals(interface{}) bool
GetParent(int) PredictionContext
getReturnState(int) int
- equals(PredictionContext) bool
length() int
isEmpty() bool
hasEmptyPath() bool
@@ -53,7 +55,7 @@ func (b *BasePredictionContext) isEmpty() bool {
func calculateHash(parent PredictionContext, returnState int) int {
h := murmurInit(1)
- h = murmurUpdate(h, parent.hash())
+ h = murmurUpdate(h, parent.Hash())
h = murmurUpdate(h, returnState)
return murmurFinish(h, 2)
}
@@ -86,7 +88,6 @@ func NewPredictionContextCache() *PredictionContextCache {
// Add a context to the cache and return it. If the context already exists,
// return that one instead and do not add a Newcontext to the cache.
// Protect shared cache from unsafe thread access.
-//
func (p *PredictionContextCache) add(ctx PredictionContext) PredictionContext {
if ctx == BasePredictionContextEMPTY {
return BasePredictionContextEMPTY
@@ -160,28 +161,28 @@ func (b *BaseSingletonPredictionContext) hasEmptyPath() bool {
return b.returnState == BasePredictionContextEmptyReturnState
}
-func (b *BaseSingletonPredictionContext) equals(other PredictionContext) bool {
+func (b *BaseSingletonPredictionContext) Hash() int {
+ return b.cachedHash
+}
+
+func (b *BaseSingletonPredictionContext) Equals(other interface{}) bool {
if b == other {
return true
- } else if _, ok := other.(*BaseSingletonPredictionContext); !ok {
+ }
+ if _, ok := other.(*BaseSingletonPredictionContext); !ok {
return false
- } else if b.hash() != other.hash() {
- return false // can't be same if hash is different
}
otherP := other.(*BaseSingletonPredictionContext)
- if b.returnState != other.getReturnState(0) {
+ if b.returnState != otherP.getReturnState(0) {
return false
- } else if b.parentCtx == nil {
+ }
+ if b.parentCtx == nil {
return otherP.parentCtx == nil
}
- return b.parentCtx.equals(otherP.parentCtx)
-}
-
-func (b *BaseSingletonPredictionContext) hash() int {
- return b.cachedHash
+ return b.parentCtx.Equals(otherP.parentCtx)
}
func (b *BaseSingletonPredictionContext) String() string {
@@ -215,7 +216,7 @@ func NewEmptyPredictionContext() *EmptyPredictionContext {
p := new(EmptyPredictionContext)
p.BaseSingletonPredictionContext = NewBaseSingletonPredictionContext(nil, BasePredictionContextEmptyReturnState)
-
+ p.cachedHash = calculateEmptyHash()
return p
}
@@ -231,7 +232,11 @@ func (e *EmptyPredictionContext) getReturnState(index int) int {
return e.returnState
}
-func (e *EmptyPredictionContext) equals(other PredictionContext) bool {
+func (e *EmptyPredictionContext) Hash() int {
+ return e.cachedHash
+}
+
+func (e *EmptyPredictionContext) Equals(other interface{}) bool {
return e == other
}
@@ -254,7 +259,7 @@ func NewArrayPredictionContext(parents []PredictionContext, returnStates []int)
hash := murmurInit(1)
for _, parent := range parents {
- hash = murmurUpdate(hash, parent.hash())
+ hash = murmurUpdate(hash, parent.Hash())
}
for _, returnState := range returnStates {
@@ -298,18 +303,31 @@ func (a *ArrayPredictionContext) getReturnState(index int) int {
return a.returnStates[index]
}
-func (a *ArrayPredictionContext) equals(other PredictionContext) bool {
- if _, ok := other.(*ArrayPredictionContext); !ok {
+// Equals is the default comparison function for ArrayPredictionContext when no specialized
+// implementation is needed for a collection
+func (a *ArrayPredictionContext) Equals(o interface{}) bool {
+ if a == o {
+ return true
+ }
+ other, ok := o.(*ArrayPredictionContext)
+ if !ok {
return false
- } else if a.cachedHash != other.hash() {
+ }
+ if a.cachedHash != other.Hash() {
return false // can't be same if hash is different
- } else {
- otherP := other.(*ArrayPredictionContext)
- return &a.returnStates == &otherP.returnStates && &a.parents == &otherP.parents
}
+
+ // Must compare the actual array elements and not just the array address
+ //
+ return slices.Equal(a.returnStates, other.returnStates) &&
+ slices.EqualFunc(a.parents, other.parents, func(x, y PredictionContext) bool {
+ return x.Equals(y)
+ })
}
-func (a *ArrayPredictionContext) hash() int {
+// Hash is the default hash function for ArrayPredictionContext when no specialized
+// implementation is needed for a collection
+func (a *ArrayPredictionContext) Hash() int {
return a.BasePredictionContext.cachedHash
}
@@ -343,11 +361,11 @@ func (a *ArrayPredictionContext) String() string {
// /
func predictionContextFromRuleContext(a *ATN, outerContext RuleContext) PredictionContext {
if outerContext == nil {
- outerContext = RuleContextEmpty
+ outerContext = ParserRuleContextEmpty
}
// if we are in RuleContext of start rule, s, then BasePredictionContext
// is EMPTY. Nobody called us. (if we are empty, return empty)
- if outerContext.GetParent() == nil || outerContext == RuleContextEmpty {
+ if outerContext.GetParent() == nil || outerContext == ParserRuleContextEmpty {
return BasePredictionContextEMPTY
}
// If we have a parent, convert it to a BasePredictionContext graph
@@ -359,11 +377,20 @@ func predictionContextFromRuleContext(a *ATN, outerContext RuleContext) Predicti
}
func merge(a, b PredictionContext, rootIsWildcard bool, mergeCache *DoubleDict) PredictionContext {
- // share same graph if both same
- if a == b {
+
+ // Share same graph if both same
+ //
+ if a == b || a.Equals(b) {
return a
}
+ // In Java, EmptyPredictionContext inherits from SingletonPredictionContext, and so the test
+ // in java for SingletonPredictionContext will succeed and a new ArrayPredictionContext will be created
+ // from it.
+ // In go, EmptyPredictionContext does not equate to SingletonPredictionContext and so that conversion
+ // will fail. We need to test for both Empty and Singleton and create an ArrayPredictionContext from
+ // either of them.
+
ac, ok1 := a.(*BaseSingletonPredictionContext)
bc, ok2 := b.(*BaseSingletonPredictionContext)
@@ -380,17 +407,32 @@ func merge(a, b PredictionContext, rootIsWildcard bool, mergeCache *DoubleDict)
return b
}
}
- // convert singleton so both are arrays to normalize
- if _, ok := a.(*BaseSingletonPredictionContext); ok {
- a = NewArrayPredictionContext([]PredictionContext{a.GetParent(0)}, []int{a.getReturnState(0)})
+
+ // Convert Singleton or Empty so both are arrays to normalize - We should not use the existing parameters
+ // here.
+ //
+ // TODO: I think that maybe the Prediction Context structs should be redone as there is a chance we will see this mess again - maybe redo the logic here
+
+ var arp, arb *ArrayPredictionContext
+ var ok bool
+ if arp, ok = a.(*ArrayPredictionContext); ok {
+ } else if _, ok = a.(*BaseSingletonPredictionContext); ok {
+ arp = NewArrayPredictionContext([]PredictionContext{a.GetParent(0)}, []int{a.getReturnState(0)})
+ } else if _, ok = a.(*EmptyPredictionContext); ok {
+ arp = NewArrayPredictionContext([]PredictionContext{}, []int{})
}
- if _, ok := b.(*BaseSingletonPredictionContext); ok {
- b = NewArrayPredictionContext([]PredictionContext{b.GetParent(0)}, []int{b.getReturnState(0)})
+
+ if arb, ok = b.(*ArrayPredictionContext); ok {
+ } else if _, ok = b.(*BaseSingletonPredictionContext); ok {
+ arb = NewArrayPredictionContext([]PredictionContext{b.GetParent(0)}, []int{b.getReturnState(0)})
+ } else if _, ok = b.(*EmptyPredictionContext); ok {
+ arb = NewArrayPredictionContext([]PredictionContext{}, []int{})
}
- return mergeArrays(a.(*ArrayPredictionContext), b.(*ArrayPredictionContext), rootIsWildcard, mergeCache)
+
+ // Both arp and arb
+ return mergeArrays(arp, arb, rootIsWildcard, mergeCache)
}
-//
// Merge two {@link SingletonBasePredictionContext} instances.
//
// Stack tops equal, parents merge is same return left graph.
@@ -423,11 +465,11 @@ func merge(a, b PredictionContext, rootIsWildcard bool, mergeCache *DoubleDict)
// /
func mergeSingletons(a, b *BaseSingletonPredictionContext, rootIsWildcard bool, mergeCache *DoubleDict) PredictionContext {
if mergeCache != nil {
- previous := mergeCache.Get(a.hash(), b.hash())
+ previous := mergeCache.Get(a.Hash(), b.Hash())
if previous != nil {
return previous.(PredictionContext)
}
- previous = mergeCache.Get(b.hash(), a.hash())
+ previous = mergeCache.Get(b.Hash(), a.Hash())
if previous != nil {
return previous.(PredictionContext)
}
@@ -436,7 +478,7 @@ func mergeSingletons(a, b *BaseSingletonPredictionContext, rootIsWildcard bool,
rootMerge := mergeRoot(a, b, rootIsWildcard)
if rootMerge != nil {
if mergeCache != nil {
- mergeCache.set(a.hash(), b.hash(), rootMerge)
+ mergeCache.set(a.Hash(), b.Hash(), rootMerge)
}
return rootMerge
}
@@ -456,7 +498,7 @@ func mergeSingletons(a, b *BaseSingletonPredictionContext, rootIsWildcard bool,
// Newjoined parent so create Newsingleton pointing to it, a'
spc := SingletonBasePredictionContextCreate(parent, a.returnState)
if mergeCache != nil {
- mergeCache.set(a.hash(), b.hash(), spc)
+ mergeCache.set(a.Hash(), b.Hash(), spc)
}
return spc
}
@@ -478,7 +520,7 @@ func mergeSingletons(a, b *BaseSingletonPredictionContext, rootIsWildcard bool,
parents := []PredictionContext{singleParent, singleParent}
apc := NewArrayPredictionContext(parents, payloads)
if mergeCache != nil {
- mergeCache.set(a.hash(), b.hash(), apc)
+ mergeCache.set(a.Hash(), b.Hash(), apc)
}
return apc
}
@@ -494,12 +536,11 @@ func mergeSingletons(a, b *BaseSingletonPredictionContext, rootIsWildcard bool,
}
apc := NewArrayPredictionContext(parents, payloads)
if mergeCache != nil {
- mergeCache.set(a.hash(), b.hash(), apc)
+ mergeCache.set(a.Hash(), b.Hash(), apc)
}
return apc
}
-//
// Handle case where at least one of {@code a} or {@code b} is
// {@link //EMPTY}. In the following diagrams, the symbol {@code $} is used
// to represent {@link //EMPTY}.
@@ -561,7 +602,6 @@ func mergeRoot(a, b SingletonPredictionContext, rootIsWildcard bool) PredictionC
return nil
}
-//
// Merge two {@link ArrayBasePredictionContext} instances.
//
//
Different tops, different parents.
@@ -583,12 +623,18 @@ func mergeRoot(a, b SingletonPredictionContext, rootIsWildcard bool) PredictionC
// /
func mergeArrays(a, b *ArrayPredictionContext, rootIsWildcard bool, mergeCache *DoubleDict) PredictionContext {
if mergeCache != nil {
- previous := mergeCache.Get(a.hash(), b.hash())
+ previous := mergeCache.Get(a.Hash(), b.Hash())
if previous != nil {
+ if ParserATNSimulatorTraceATNSim {
+ fmt.Println("mergeArrays a=" + a.String() + ",b=" + b.String() + " -> previous")
+ }
return previous.(PredictionContext)
}
- previous = mergeCache.Get(b.hash(), a.hash())
+ previous = mergeCache.Get(b.Hash(), a.Hash())
if previous != nil {
+ if ParserATNSimulatorTraceATNSim {
+ fmt.Println("mergeArrays a=" + a.String() + ",b=" + b.String() + " -> previous")
+ }
return previous.(PredictionContext)
}
}
@@ -608,7 +654,7 @@ func mergeArrays(a, b *ArrayPredictionContext, rootIsWildcard bool, mergeCache *
payload := a.returnStates[i]
// $+$ = $
bothDollars := payload == BasePredictionContextEmptyReturnState && aParent == nil && bParent == nil
- axAX := (aParent != nil && bParent != nil && aParent == bParent) // ax+ax
+ axAX := aParent != nil && bParent != nil && aParent == bParent // ax+ax
// ->
// ax
if bothDollars || axAX {
@@ -651,7 +697,7 @@ func mergeArrays(a, b *ArrayPredictionContext, rootIsWildcard bool, mergeCache *
if k == 1 { // for just one merged element, return singleton top
pc := SingletonBasePredictionContextCreate(mergedParents[0], mergedReturnStates[0])
if mergeCache != nil {
- mergeCache.set(a.hash(), b.hash(), pc)
+ mergeCache.set(a.Hash(), b.Hash(), pc)
}
return pc
}
@@ -663,27 +709,36 @@ func mergeArrays(a, b *ArrayPredictionContext, rootIsWildcard bool, mergeCache *
// if we created same array as a or b, return that instead
// TODO: track whether this is possible above during merge sort for speed
+ // TODO: In go, I do not think we can just do M == xx as M is a brand new allocation. This could be causing allocation problems
if M == a {
if mergeCache != nil {
- mergeCache.set(a.hash(), b.hash(), a)
+ mergeCache.set(a.Hash(), b.Hash(), a)
+ }
+ if ParserATNSimulatorTraceATNSim {
+ fmt.Println("mergeArrays a=" + a.String() + ",b=" + b.String() + " -> a")
}
return a
}
if M == b {
if mergeCache != nil {
- mergeCache.set(a.hash(), b.hash(), b)
+ mergeCache.set(a.Hash(), b.Hash(), b)
+ }
+ if ParserATNSimulatorTraceATNSim {
+ fmt.Println("mergeArrays a=" + a.String() + ",b=" + b.String() + " -> b")
}
return b
}
combineCommonParents(mergedParents)
if mergeCache != nil {
- mergeCache.set(a.hash(), b.hash(), M)
+ mergeCache.set(a.Hash(), b.Hash(), M)
+ }
+ if ParserATNSimulatorTraceATNSim {
+ fmt.Println("mergeArrays a=" + a.String() + ",b=" + b.String() + " -> " + M.String())
}
return M
}
-//
// Make pass over all M {@code parents} merge any {@code equals()}
// ones.
// /
diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/prediction_mode.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/prediction_mode.go
similarity index 95%
rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/prediction_mode.go
rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/prediction_mode.go
index 15718f912..7b9b72fab 100644
--- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/prediction_mode.go
+++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/prediction_mode.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
+// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved.
// Use of this file is governed by the BSD 3-clause license that
// can be found in the LICENSE.txt file in the project root.
@@ -70,7 +70,6 @@ const (
PredictionModeLLExactAmbigDetection = 2
)
-//
// Computes the SLL prediction termination condition.
//
//
@@ -108,9 +107,9 @@ const (
// The single-alt-state thing lets prediction continue upon rules like
// (otherwise, it would admit defeat too soon):
//
-// {@code [12|1|[], 6|2|[], 12|2|[]]. s : (ID | ID ID?) '' }
+// {@code [12|1|[], 6|2|[], 12|2|[]]. s : (ID | ID ID?) ” }
//
-// When the ATN simulation reaches the state before {@code ''}, it has a
+//
When the ATN simulation reaches the state before {@code ”}, it has a
// DFA state that looks like: {@code [12|1|[], 6|2|[], 12|2|[]]}. Naturally
// {@code 12|1|[]} and {@code 12|2|[]} conflict, but we cannot stop
// processing this node because alternative to has another way to continue,
@@ -152,16 +151,15 @@ const (
//
//
Before testing these configurations against others, we have to merge
// {@code x} and {@code x'} (without modifying the existing configurations).
-// For example, we test {@code (x+x')==x''} when looking for conflicts in
+// For example, we test {@code (x+x')==x”} when looking for conflicts in
// the following configurations.
//
-// {@code (s, 1, x, {}), (s, 1, x', {p}), (s, 2, x'', {})}
+// {@code (s, 1, x, {}), (s, 1, x', {p}), (s, 2, x”, {})}
//
// If the configuration set has predicates (as indicated by
// {@link ATNConfigSet//hasSemanticContext}), this algorithm makes a copy of
// the configurations to strip out all of the predicates so that a standard
// {@link ATNConfigSet} will merge everything ignoring predicates.
-//
func PredictionModehasSLLConflictTerminatingPrediction(mode int, configs ATNConfigSet) bool {
// Configs in rule stop states indicate reaching the end of the decision
// rule (local context) or end of start rule (full context). If all
@@ -229,7 +227,6 @@ func PredictionModeallConfigsInRuleStopStates(configs ATNConfigSet) bool {
return true
}
-//
// Full LL prediction termination.
//
// Can we stop looking ahead during ATN simulation or is there some
@@ -334,7 +331,7 @@ func PredictionModeallConfigsInRuleStopStates(configs ATNConfigSet) bool {
//
//
//
{@code (s, 1, x)}, {@code (s, 2, x)}, {@code (s', 1, y)},
-// {@code (s', 2, y)}, {@code (s'', 1, z)} yields non-conflicting set
+// {@code (s', 2, y)}, {@code (s”, 1, z)} yields non-conflicting set
// {@code {1}} U conflicting sets {@code min({1,2})} U {@code min({1,2})} =
// {@code {1}} => stop and predict 1
//
@@ -369,31 +366,26 @@ func PredictionModeallConfigsInRuleStopStates(configs ATNConfigSet) bool {
// two or one and three so we keep going. We can only stop prediction when
// we need exact ambiguity detection when the sets look like
// {@code A={{1,2}}} or {@code {{1,2},{1,2}}}, etc...
-//
func PredictionModeresolvesToJustOneViableAlt(altsets []*BitSet) int {
return PredictionModegetSingleViableAlt(altsets)
}
-//
// Determines if every alternative subset in {@code altsets} contains more
// than one alternative.
//
// @param altsets a collection of alternative subsets
// @return {@code true} if every {@link BitSet} in {@code altsets} has
// {@link BitSet//cardinality cardinality} > 1, otherwise {@code false}
-//
func PredictionModeallSubsetsConflict(altsets []*BitSet) bool {
return !PredictionModehasNonConflictingAltSet(altsets)
}
-//
// Determines if any single alternative subset in {@code altsets} contains
// exactly one alternative.
//
// @param altsets a collection of alternative subsets
// @return {@code true} if {@code altsets} contains a {@link BitSet} with
// {@link BitSet//cardinality cardinality} 1, otherwise {@code false}
-//
func PredictionModehasNonConflictingAltSet(altsets []*BitSet) bool {
for i := 0; i < len(altsets); i++ {
alts := altsets[i]
@@ -404,14 +396,12 @@ func PredictionModehasNonConflictingAltSet(altsets []*BitSet) bool {
return false
}
-//
// Determines if any single alternative subset in {@code altsets} contains
// more than one alternative.
//
// @param altsets a collection of alternative subsets
// @return {@code true} if {@code altsets} contains a {@link BitSet} with
// {@link BitSet//cardinality cardinality} > 1, otherwise {@code false}
-//
func PredictionModehasConflictingAltSet(altsets []*BitSet) bool {
for i := 0; i < len(altsets); i++ {
alts := altsets[i]
@@ -422,13 +412,11 @@ func PredictionModehasConflictingAltSet(altsets []*BitSet) bool {
return false
}
-//
// Determines if every alternative subset in {@code altsets} is equivalent.
//
// @param altsets a collection of alternative subsets
// @return {@code true} if every member of {@code altsets} is equal to the
// others, otherwise {@code false}
-//
func PredictionModeallSubsetsEqual(altsets []*BitSet) bool {
var first *BitSet
@@ -444,13 +432,11 @@ func PredictionModeallSubsetsEqual(altsets []*BitSet) bool {
return true
}
-//
// Returns the unique alternative predicted by all alternative subsets in
// {@code altsets}. If no such alternative exists, this method returns
// {@link ATN//INVALID_ALT_NUMBER}.
//
// @param altsets a collection of alternative subsets
-//
func PredictionModegetUniqueAlt(altsets []*BitSet) int {
all := PredictionModeGetAlts(altsets)
if all.length() == 1 {
@@ -466,7 +452,6 @@ func PredictionModegetUniqueAlt(altsets []*BitSet) int {
//
// @param altsets a collection of alternative subsets
// @return the set of represented alternatives in {@code altsets}
-//
func PredictionModeGetAlts(altsets []*BitSet) *BitSet {
all := NewBitSet()
for _, alts := range altsets {
@@ -475,44 +460,35 @@ func PredictionModeGetAlts(altsets []*BitSet) *BitSet {
return all
}
-//
-// This func gets the conflicting alt subsets from a configuration set.
+// PredictionModegetConflictingAltSubsets gets the conflicting alt subsets from a configuration set.
// For each configuration {@code c} in {@code configs}:
//
//
// map[c] U= c.{@link ATNConfig//alt alt} // map hash/equals uses s and x, not
// alt and not pred
//
-//
func PredictionModegetConflictingAltSubsets(configs ATNConfigSet) []*BitSet {
- configToAlts := make(map[int]*BitSet)
+ configToAlts := NewJMap[ATNConfig, *BitSet, *ATNAltConfigComparator[ATNConfig]](atnAltCfgEqInst)
for _, c := range configs.GetItems() {
- key := 31 * c.GetState().GetStateNumber() + c.GetContext().hash()
- alts, ok := configToAlts[key]
+ alts, ok := configToAlts.Get(c)
if !ok {
alts = NewBitSet()
- configToAlts[key] = alts
+ configToAlts.Put(c, alts)
}
alts.add(c.GetAlt())
}
- values := make([]*BitSet, 0, 10)
- for _, v := range configToAlts {
- values = append(values, v)
- }
- return values
+ return configToAlts.Values()
}
-//
-// Get a map from state to alt subset from a configuration set. For each
+// PredictionModeGetStateToAltMap gets a map from state to alt subset from a configuration set. For each
// configuration {@code c} in {@code configs}:
//
//
// map[c.{@link ATNConfig//state state}] U= c.{@link ATNConfig//alt alt}
//
-//
func PredictionModeGetStateToAltMap(configs ATNConfigSet) *AltDict {
m := NewAltDict()
diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/recognizer.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/recognizer.go
similarity index 92%
rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/recognizer.go
rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/recognizer.go
index 93efcf355..bfe542d09 100644
--- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/recognizer.go
+++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/recognizer.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
+// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved.
// Use of this file is governed by the BSD 3-clause license that
// can be found in the LICENSE.txt file in the project root.
@@ -49,7 +49,7 @@ var tokenTypeMapCache = make(map[string]int)
var ruleIndexMapCache = make(map[string]int)
func (b *BaseRecognizer) checkVersion(toolVersion string) {
- runtimeVersion := "4.10.1"
+ runtimeVersion := "4.12.0"
if runtimeVersion != toolVersion {
fmt.Println("ANTLR runtime and generated code versions disagree: " + runtimeVersion + "!=" + toolVersion)
}
@@ -108,7 +108,6 @@ func (b *BaseRecognizer) SetState(v int) {
// Get a map from rule names to rule indexes.
//
// Used for XPath and tree pattern compilation.
-//
func (b *BaseRecognizer) GetRuleIndexMap() map[string]int {
panic("Method not defined!")
@@ -171,18 +170,18 @@ func (b *BaseRecognizer) GetErrorHeader(e RecognitionException) string {
}
// How should a token be displayed in an error message? The default
-// is to display just the text, but during development you might
-// want to have a lot of information spit out. Override in that case
-// to use t.String() (which, for CommonToken, dumps everything about
-// the token). This is better than forcing you to override a method in
-// your token objects because you don't have to go modify your lexer
-// so that it creates a NewJava type.
+//
+// is to display just the text, but during development you might
+// want to have a lot of information spit out. Override in that case
+// to use t.String() (which, for CommonToken, dumps everything about
+// the token). This is better than forcing you to override a method in
+// your token objects because you don't have to go modify your lexer
+// so that it creates a NewJava type.
//
// @deprecated This method is not called by the ANTLR 4 Runtime. Specific
// implementations of {@link ANTLRErrorStrategy} may provide a similar
// feature when necessary. For example, see
// {@link DefaultErrorStrategy//GetTokenErrorDisplay}.
-//
func (b *BaseRecognizer) GetTokenErrorDisplay(t Token) string {
if t == nil {
return ""
diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/rule_context.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/rule_context.go
similarity index 97%
rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/rule_context.go
rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/rule_context.go
index 600cf8c06..210699ba2 100644
--- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/rule_context.go
+++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/rule_context.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
+// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved.
// Use of this file is governed by the BSD 3-clause license that
// can be found in the LICENSE.txt file in the project root.
diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/semantic_context.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/semantic_context.go
similarity index 85%
rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/semantic_context.go
rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/semantic_context.go
index 9ada43077..a702e99de 100644
--- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/semantic_context.go
+++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/semantic_context.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
+// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved.
// Use of this file is governed by the BSD 3-clause license that
// can be found in the LICENSE.txt file in the project root.
@@ -18,12 +18,12 @@ import (
//
type SemanticContext interface {
- comparable
+ Equals(other Collectable[SemanticContext]) bool
+ Hash() int
evaluate(parser Recognizer, outerContext RuleContext) bool
evalPrecedence(parser Recognizer, outerContext RuleContext) SemanticContext
- hash() int
String() string
}
@@ -78,7 +78,7 @@ func NewPredicate(ruleIndex, predIndex int, isCtxDependent bool) *Predicate {
//The default {@link SemanticContext}, which is semantically equivalent to
//a predicate of the form {@code {true}?}.
-var SemanticContextNone SemanticContext = NewPredicate(-1, -1, false)
+var SemanticContextNone = NewPredicate(-1, -1, false)
func (p *Predicate) evalPrecedence(parser Recognizer, outerContext RuleContext) SemanticContext {
return p
@@ -95,7 +95,7 @@ func (p *Predicate) evaluate(parser Recognizer, outerContext RuleContext) bool {
return parser.Sempred(localctx, p.ruleIndex, p.predIndex)
}
-func (p *Predicate) equals(other interface{}) bool {
+func (p *Predicate) Equals(other Collectable[SemanticContext]) bool {
if p == other {
return true
} else if _, ok := other.(*Predicate); !ok {
@@ -107,7 +107,7 @@ func (p *Predicate) equals(other interface{}) bool {
}
}
-func (p *Predicate) hash() int {
+func (p *Predicate) Hash() int {
h := murmurInit(0)
h = murmurUpdate(h, p.ruleIndex)
h = murmurUpdate(h, p.predIndex)
@@ -151,17 +151,22 @@ func (p *PrecedencePredicate) compareTo(other *PrecedencePredicate) int {
return p.precedence - other.precedence
}
-func (p *PrecedencePredicate) equals(other interface{}) bool {
- if p == other {
- return true
- } else if _, ok := other.(*PrecedencePredicate); !ok {
+func (p *PrecedencePredicate) Equals(other Collectable[SemanticContext]) bool {
+
+ var op *PrecedencePredicate
+ var ok bool
+ if op, ok = other.(*PrecedencePredicate); !ok {
return false
- } else {
- return p.precedence == other.(*PrecedencePredicate).precedence
}
+
+ if p == op {
+ return true
+ }
+
+ return p.precedence == other.(*PrecedencePredicate).precedence
}
-func (p *PrecedencePredicate) hash() int {
+func (p *PrecedencePredicate) Hash() int {
h := uint32(1)
h = 31*h + uint32(p.precedence)
return int(h)
@@ -171,10 +176,10 @@ func (p *PrecedencePredicate) String() string {
return "{" + strconv.Itoa(p.precedence) + ">=prec}?"
}
-func PrecedencePredicatefilterPrecedencePredicates(set Set) []*PrecedencePredicate {
+func PrecedencePredicatefilterPrecedencePredicates(set *JStore[SemanticContext, Comparator[SemanticContext]]) []*PrecedencePredicate {
result := make([]*PrecedencePredicate, 0)
- set.Each(func(v interface{}) bool {
+ set.Each(func(v SemanticContext) bool {
if c2, ok := v.(*PrecedencePredicate); ok {
result = append(result, c2)
}
@@ -193,21 +198,21 @@ type AND struct {
func NewAND(a, b SemanticContext) *AND {
- operands := newArray2DHashSet(nil, nil)
+ operands := NewJStore[SemanticContext, Comparator[SemanticContext]](semctxEqInst)
if aa, ok := a.(*AND); ok {
for _, o := range aa.opnds {
- operands.Add(o)
+ operands.Put(o)
}
} else {
- operands.Add(a)
+ operands.Put(a)
}
if ba, ok := b.(*AND); ok {
for _, o := range ba.opnds {
- operands.Add(o)
+ operands.Put(o)
}
} else {
- operands.Add(b)
+ operands.Put(b)
}
precedencePredicates := PrecedencePredicatefilterPrecedencePredicates(operands)
if len(precedencePredicates) > 0 {
@@ -220,7 +225,7 @@ func NewAND(a, b SemanticContext) *AND {
}
}
- operands.Add(reduced)
+ operands.Put(reduced)
}
vs := operands.Values()
@@ -235,14 +240,15 @@ func NewAND(a, b SemanticContext) *AND {
return and
}
-func (a *AND) equals(other interface{}) bool {
+func (a *AND) Equals(other Collectable[SemanticContext]) bool {
if a == other {
return true
- } else if _, ok := other.(*AND); !ok {
+ }
+ if _, ok := other.(*AND); !ok {
return false
} else {
for i, v := range other.(*AND).opnds {
- if !a.opnds[i].equals(v) {
+ if !a.opnds[i].Equals(v) {
return false
}
}
@@ -250,13 +256,11 @@ func (a *AND) equals(other interface{}) bool {
}
}
-//
// {@inheritDoc}
//
//
// The evaluation of predicates by a context is short-circuiting, but
// unordered.
-//
func (a *AND) evaluate(parser Recognizer, outerContext RuleContext) bool {
for i := 0; i < len(a.opnds); i++ {
if !a.opnds[i].evaluate(parser, outerContext) {
@@ -304,18 +308,18 @@ func (a *AND) evalPrecedence(parser Recognizer, outerContext RuleContext) Semant
return result
}
-func (a *AND) hash() int {
+func (a *AND) Hash() int {
h := murmurInit(37) // Init with a value different from OR
for _, op := range a.opnds {
- h = murmurUpdate(h, op.hash())
+ h = murmurUpdate(h, op.Hash())
}
return murmurFinish(h, len(a.opnds))
}
-func (a *OR) hash() int {
+func (a *OR) Hash() int {
h := murmurInit(41) // Init with a value different from AND
for _, op := range a.opnds {
- h = murmurUpdate(h, op.hash())
+ h = murmurUpdate(h, op.Hash())
}
return murmurFinish(h, len(a.opnds))
}
@@ -345,21 +349,21 @@ type OR struct {
func NewOR(a, b SemanticContext) *OR {
- operands := newArray2DHashSet(nil, nil)
+ operands := NewJStore[SemanticContext, Comparator[SemanticContext]](semctxEqInst)
if aa, ok := a.(*OR); ok {
for _, o := range aa.opnds {
- operands.Add(o)
+ operands.Put(o)
}
} else {
- operands.Add(a)
+ operands.Put(a)
}
if ba, ok := b.(*OR); ok {
for _, o := range ba.opnds {
- operands.Add(o)
+ operands.Put(o)
}
} else {
- operands.Add(b)
+ operands.Put(b)
}
precedencePredicates := PrecedencePredicatefilterPrecedencePredicates(operands)
if len(precedencePredicates) > 0 {
@@ -372,7 +376,7 @@ func NewOR(a, b SemanticContext) *OR {
}
}
- operands.Add(reduced)
+ operands.Put(reduced)
}
vs := operands.Values()
@@ -388,14 +392,14 @@ func NewOR(a, b SemanticContext) *OR {
return o
}
-func (o *OR) equals(other interface{}) bool {
+func (o *OR) Equals(other Collectable[SemanticContext]) bool {
if o == other {
return true
} else if _, ok := other.(*OR); !ok {
return false
} else {
for i, v := range other.(*OR).opnds {
- if !o.opnds[i].equals(v) {
+ if !o.opnds[i].Equals(v) {
return false
}
}
@@ -406,7 +410,6 @@ func (o *OR) equals(other interface{}) bool {
//
// The evaluation of predicates by o context is short-circuiting, but
// unordered.
-//
func (o *OR) evaluate(parser Recognizer, outerContext RuleContext) bool {
for i := 0; i < len(o.opnds); i++ {
if o.opnds[i].evaluate(parser, outerContext) {
diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/token.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/token.go
similarity index 98%
rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/token.go
rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/token.go
index 2d8e99095..f73b06bc6 100644
--- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/token.go
+++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/token.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
+// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved.
// Use of this file is governed by the BSD 3-clause license that
// can be found in the LICENSE.txt file in the project root.
@@ -158,7 +158,6 @@ func NewCommonToken(source *TokenSourceCharStreamPair, tokenType, channel, start
// {@link Token//GetInputStream}.
//
// @param oldToken The token to copy.
-//
func (c *CommonToken) clone() *CommonToken {
t := NewCommonToken(c.source, c.tokenType, c.channel, c.start, c.stop)
t.tokenIndex = c.GetTokenIndex()
diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/token_source.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/token_source.go
similarity index 85%
rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/token_source.go
rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/token_source.go
index e023978fe..a3f36eaa6 100644
--- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/token_source.go
+++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/token_source.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
+// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved.
// Use of this file is governed by the BSD 3-clause license that
// can be found in the LICENSE.txt file in the project root.
diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/token_stream.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/token_stream.go
similarity index 87%
rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/token_stream.go
rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/token_stream.go
index df92c8147..1527d43f6 100644
--- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/token_stream.go
+++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/token_stream.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
+// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved.
// Use of this file is governed by the BSD 3-clause license that
// can be found in the LICENSE.txt file in the project root.
diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/tokenstream_rewriter.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/tokenstream_rewriter.go
similarity index 58%
rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/tokenstream_rewriter.go
rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/tokenstream_rewriter.go
index 96a03f02a..b3e38af34 100644
--- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/tokenstream_rewriter.go
+++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/tokenstream_rewriter.go
@@ -1,15 +1,15 @@
-// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
+// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved.
// Use of this file is governed by the BSD 3-clause license that
// can be found in the LICENSE.txt file in the project root.
+
package antlr
import (
-"bytes"
-"fmt"
+ "bytes"
+ "fmt"
)
-
-//
+//
// Useful for rewriting out a buffered input token stream after doing some
// augmentation or other manipulations on it.
@@ -85,12 +85,10 @@ import (
// If you don't use named rewrite streams, a "default" stream is used as the
// first example shows.
-
-
-const(
+const (
Default_Program_Name = "default"
- Program_Init_Size = 100
- Min_Token_Index = 0
+ Program_Init_Size = 100
+ Min_Token_Index = 0
)
// Define the rewrite operation hierarchy
@@ -98,13 +96,13 @@ const(
type RewriteOperation interface {
// Execute the rewrite operation by possibly adding to the buffer.
// Return the index of the next token to operate on.
- Execute(buffer *bytes.Buffer) int
- String() string
- GetInstructionIndex() int
- GetIndex() int
- GetText() string
- GetOpName() string
- GetTokens() TokenStream
+ Execute(buffer *bytes.Buffer) int
+ String() string
+ GetInstructionIndex() int
+ GetIndex() int
+ GetText() string
+ GetOpName() string
+ GetTokens() TokenStream
SetInstructionIndex(val int)
SetIndex(int)
SetText(string)
@@ -114,63 +112,62 @@ type RewriteOperation interface {
type BaseRewriteOperation struct {
//Current index of rewrites list
- instruction_index int
+ instruction_index int
//Token buffer index
- index int
+ index int
//Substitution text
- text string
+ text string
//Actual operation name
- op_name string
+ op_name string
//Pointer to token steam
- tokens TokenStream
+ tokens TokenStream
}
-func (op *BaseRewriteOperation)GetInstructionIndex() int{
+func (op *BaseRewriteOperation) GetInstructionIndex() int {
return op.instruction_index
}
-func (op *BaseRewriteOperation)GetIndex() int{
+func (op *BaseRewriteOperation) GetIndex() int {
return op.index
}
-func (op *BaseRewriteOperation)GetText() string{
+func (op *BaseRewriteOperation) GetText() string {
return op.text
}
-func (op *BaseRewriteOperation)GetOpName() string{
+func (op *BaseRewriteOperation) GetOpName() string {
return op.op_name
}
-func (op *BaseRewriteOperation)GetTokens() TokenStream{
+func (op *BaseRewriteOperation) GetTokens() TokenStream {
return op.tokens
}
-func (op *BaseRewriteOperation)SetInstructionIndex(val int){
+func (op *BaseRewriteOperation) SetInstructionIndex(val int) {
op.instruction_index = val
}
-func (op *BaseRewriteOperation)SetIndex(val int) {
+func (op *BaseRewriteOperation) SetIndex(val int) {
op.index = val
}
-func (op *BaseRewriteOperation)SetText(val string){
+func (op *BaseRewriteOperation) SetText(val string) {
op.text = val
}
-func (op *BaseRewriteOperation)SetOpName(val string){
+func (op *BaseRewriteOperation) SetOpName(val string) {
op.op_name = val
}
-func (op *BaseRewriteOperation)SetTokens(val TokenStream) {
+func (op *BaseRewriteOperation) SetTokens(val TokenStream) {
op.tokens = val
}
-
-func (op *BaseRewriteOperation) Execute(buffer *bytes.Buffer) int{
+func (op *BaseRewriteOperation) Execute(buffer *bytes.Buffer) int {
return op.index
}
-func (op *BaseRewriteOperation) String() string {
+func (op *BaseRewriteOperation) String() string {
return fmt.Sprintf("<%s@%d:\"%s\">",
op.op_name,
op.tokens.Get(op.GetIndex()),
@@ -179,26 +176,25 @@ func (op *BaseRewriteOperation) String() string {
}
-
type InsertBeforeOp struct {
BaseRewriteOperation
}
-func NewInsertBeforeOp(index int, text string, stream TokenStream) *InsertBeforeOp{
- return &InsertBeforeOp{BaseRewriteOperation:BaseRewriteOperation{
- index:index,
- text:text,
- op_name:"InsertBeforeOp",
- tokens:stream,
+func NewInsertBeforeOp(index int, text string, stream TokenStream) *InsertBeforeOp {
+ return &InsertBeforeOp{BaseRewriteOperation: BaseRewriteOperation{
+ index: index,
+ text: text,
+ op_name: "InsertBeforeOp",
+ tokens: stream,
}}
}
-func (op *InsertBeforeOp) Execute(buffer *bytes.Buffer) int{
+func (op *InsertBeforeOp) Execute(buffer *bytes.Buffer) int {
buffer.WriteString(op.text)
- if op.tokens.Get(op.index).GetTokenType() != TokenEOF{
+ if op.tokens.Get(op.index).GetTokenType() != TokenEOF {
buffer.WriteString(op.tokens.Get(op.index).GetText())
}
- return op.index+1
+ return op.index + 1
}
func (op *InsertBeforeOp) String() string {
@@ -213,20 +209,20 @@ type InsertAfterOp struct {
BaseRewriteOperation
}
-func NewInsertAfterOp(index int, text string, stream TokenStream) *InsertAfterOp{
- return &InsertAfterOp{BaseRewriteOperation:BaseRewriteOperation{
- index:index+1,
- text:text,
- tokens:stream,
+func NewInsertAfterOp(index int, text string, stream TokenStream) *InsertAfterOp {
+ return &InsertAfterOp{BaseRewriteOperation: BaseRewriteOperation{
+ index: index + 1,
+ text: text,
+ tokens: stream,
}}
}
func (op *InsertAfterOp) Execute(buffer *bytes.Buffer) int {
buffer.WriteString(op.text)
- if op.tokens.Get(op.index).GetTokenType() != TokenEOF{
+ if op.tokens.Get(op.index).GetTokenType() != TokenEOF {
buffer.WriteString(op.tokens.Get(op.index).GetText())
}
- return op.index+1
+ return op.index + 1
}
func (op *InsertAfterOp) String() string {
@@ -235,28 +231,28 @@ func (op *InsertAfterOp) String() string {
// I'm going to try replacing range from x..y with (y-x)+1 ReplaceOp
// instructions.
-type ReplaceOp struct{
+type ReplaceOp struct {
BaseRewriteOperation
LastIndex int
}
-func NewReplaceOp(from, to int, text string, stream TokenStream)*ReplaceOp {
+func NewReplaceOp(from, to int, text string, stream TokenStream) *ReplaceOp {
return &ReplaceOp{
- BaseRewriteOperation:BaseRewriteOperation{
- index:from,
- text:text,
- op_name:"ReplaceOp",
- tokens:stream,
+ BaseRewriteOperation: BaseRewriteOperation{
+ index: from,
+ text: text,
+ op_name: "ReplaceOp",
+ tokens: stream,
},
- LastIndex:to,
+ LastIndex: to,
}
}
-func (op *ReplaceOp)Execute(buffer *bytes.Buffer) int{
- if op.text != ""{
+func (op *ReplaceOp) Execute(buffer *bytes.Buffer) int {
+ if op.text != "" {
buffer.WriteString(op.text)
}
- return op.LastIndex +1
+ return op.LastIndex + 1
}
func (op *ReplaceOp) String() string {
@@ -268,54 +264,54 @@ func (op *ReplaceOp) String() string {
op.tokens.Get(op.index), op.tokens.Get(op.LastIndex), op.text)
}
-
type TokenStreamRewriter struct {
//Our source stream
- tokens TokenStream
+ tokens TokenStream
// You may have multiple, named streams of rewrite operations.
// I'm calling these things "programs."
// Maps String (name) → rewrite (List)
- programs map[string][]RewriteOperation
- last_rewrite_token_indexes map[string]int
+ programs map[string][]RewriteOperation
+ last_rewrite_token_indexes map[string]int
}
-func NewTokenStreamRewriter(tokens TokenStream) *TokenStreamRewriter{
+func NewTokenStreamRewriter(tokens TokenStream) *TokenStreamRewriter {
return &TokenStreamRewriter{
- tokens: tokens,
- programs: map[string][]RewriteOperation{
- Default_Program_Name:make([]RewriteOperation,0, Program_Init_Size),
+ tokens: tokens,
+ programs: map[string][]RewriteOperation{
+ Default_Program_Name: make([]RewriteOperation, 0, Program_Init_Size),
},
- last_rewrite_token_indexes: map[string]int{},
+ last_rewrite_token_indexes: map[string]int{},
}
}
-func (tsr *TokenStreamRewriter) GetTokenStream() TokenStream{
+func (tsr *TokenStreamRewriter) GetTokenStream() TokenStream {
return tsr.tokens
}
-// Rollback the instruction stream for a program so that
-// the indicated instruction (via instructionIndex) is no
-// longer in the stream. UNTESTED!
-func (tsr *TokenStreamRewriter) Rollback(program_name string, instruction_index int){
- is, ok := tsr.programs[program_name]
- if ok{
+// Rollback the instruction stream for a program so that
+// the indicated instruction (via instructionIndex) is no
+// longer in the stream. UNTESTED!
+func (tsr *TokenStreamRewriter) Rollback(program_name string, instruction_index int) {
+ is, ok := tsr.programs[program_name]
+ if ok {
tsr.programs[program_name] = is[Min_Token_Index:instruction_index]
}
}
-func (tsr *TokenStreamRewriter) RollbackDefault(instruction_index int){
+func (tsr *TokenStreamRewriter) RollbackDefault(instruction_index int) {
tsr.Rollback(Default_Program_Name, instruction_index)
}
-//Reset the program so that no instructions exist
-func (tsr *TokenStreamRewriter) DeleteProgram(program_name string){
+
+// Reset the program so that no instructions exist
+func (tsr *TokenStreamRewriter) DeleteProgram(program_name string) {
tsr.Rollback(program_name, Min_Token_Index) //TODO: double test on that cause lower bound is not included
}
-func (tsr *TokenStreamRewriter) DeleteProgramDefault(){
+func (tsr *TokenStreamRewriter) DeleteProgramDefault() {
tsr.DeleteProgram(Default_Program_Name)
}
-func (tsr *TokenStreamRewriter) InsertAfter(program_name string, index int, text string){
+func (tsr *TokenStreamRewriter) InsertAfter(program_name string, index int, text string) {
// to insert after, just insert before next index (even if past end)
var op RewriteOperation = NewInsertAfterOp(index, text, tsr.tokens)
rewrites := tsr.GetProgram(program_name)
@@ -323,31 +319,31 @@ func (tsr *TokenStreamRewriter) InsertAfter(program_name string, index int, text
tsr.AddToProgram(program_name, op)
}
-func (tsr *TokenStreamRewriter) InsertAfterDefault(index int, text string){
+func (tsr *TokenStreamRewriter) InsertAfterDefault(index int, text string) {
tsr.InsertAfter(Default_Program_Name, index, text)
}
-func (tsr *TokenStreamRewriter) InsertAfterToken(program_name string, token Token, text string){
+func (tsr *TokenStreamRewriter) InsertAfterToken(program_name string, token Token, text string) {
tsr.InsertAfter(program_name, token.GetTokenIndex(), text)
}
-func (tsr* TokenStreamRewriter) InsertBefore(program_name string, index int, text string){
+func (tsr *TokenStreamRewriter) InsertBefore(program_name string, index int, text string) {
var op RewriteOperation = NewInsertBeforeOp(index, text, tsr.tokens)
rewrites := tsr.GetProgram(program_name)
op.SetInstructionIndex(len(rewrites))
tsr.AddToProgram(program_name, op)
}
-func (tsr *TokenStreamRewriter) InsertBeforeDefault(index int, text string){
+func (tsr *TokenStreamRewriter) InsertBeforeDefault(index int, text string) {
tsr.InsertBefore(Default_Program_Name, index, text)
}
-func (tsr *TokenStreamRewriter) InsertBeforeToken(program_name string,token Token, text string){
+func (tsr *TokenStreamRewriter) InsertBeforeToken(program_name string, token Token, text string) {
tsr.InsertBefore(program_name, token.GetTokenIndex(), text)
}
-func (tsr *TokenStreamRewriter) Replace(program_name string, from, to int, text string){
- if from > to || from < 0 || to < 0 || to >= tsr.tokens.Size(){
+func (tsr *TokenStreamRewriter) Replace(program_name string, from, to int, text string) {
+ if from > to || from < 0 || to < 0 || to >= tsr.tokens.Size() {
panic(fmt.Sprintf("replace: range invalid: %d..%d(size=%d)",
from, to, tsr.tokens.Size()))
}
@@ -357,207 +353,216 @@ func (tsr *TokenStreamRewriter) Replace(program_name string, from, to int, text
tsr.AddToProgram(program_name, op)
}
-func (tsr *TokenStreamRewriter)ReplaceDefault(from, to int, text string) {
+func (tsr *TokenStreamRewriter) ReplaceDefault(from, to int, text string) {
tsr.Replace(Default_Program_Name, from, to, text)
}
-func (tsr *TokenStreamRewriter)ReplaceDefaultPos(index int, text string){
+func (tsr *TokenStreamRewriter) ReplaceDefaultPos(index int, text string) {
tsr.ReplaceDefault(index, index, text)
}
-func (tsr *TokenStreamRewriter)ReplaceToken(program_name string, from, to Token, text string){
+func (tsr *TokenStreamRewriter) ReplaceToken(program_name string, from, to Token, text string) {
tsr.Replace(program_name, from.GetTokenIndex(), to.GetTokenIndex(), text)
}
-func (tsr *TokenStreamRewriter)ReplaceTokenDefault(from, to Token, text string){
+func (tsr *TokenStreamRewriter) ReplaceTokenDefault(from, to Token, text string) {
tsr.ReplaceToken(Default_Program_Name, from, to, text)
}
-func (tsr *TokenStreamRewriter)ReplaceTokenDefaultPos(index Token, text string){
+func (tsr *TokenStreamRewriter) ReplaceTokenDefaultPos(index Token, text string) {
tsr.ReplaceTokenDefault(index, index, text)
}
-func (tsr *TokenStreamRewriter)Delete(program_name string, from, to int){
- tsr.Replace(program_name, from, to, "" )
+func (tsr *TokenStreamRewriter) Delete(program_name string, from, to int) {
+ tsr.Replace(program_name, from, to, "")
}
-func (tsr *TokenStreamRewriter)DeleteDefault(from, to int){
+func (tsr *TokenStreamRewriter) DeleteDefault(from, to int) {
tsr.Delete(Default_Program_Name, from, to)
}
-func (tsr *TokenStreamRewriter)DeleteDefaultPos(index int){
- tsr.DeleteDefault(index,index)
+func (tsr *TokenStreamRewriter) DeleteDefaultPos(index int) {
+ tsr.DeleteDefault(index, index)
}
-func (tsr *TokenStreamRewriter)DeleteToken(program_name string, from, to Token) {
+func (tsr *TokenStreamRewriter) DeleteToken(program_name string, from, to Token) {
tsr.ReplaceToken(program_name, from, to, "")
}
-func (tsr *TokenStreamRewriter)DeleteTokenDefault(from,to Token){
+func (tsr *TokenStreamRewriter) DeleteTokenDefault(from, to Token) {
tsr.DeleteToken(Default_Program_Name, from, to)
}
-func (tsr *TokenStreamRewriter)GetLastRewriteTokenIndex(program_name string)int {
+func (tsr *TokenStreamRewriter) GetLastRewriteTokenIndex(program_name string) int {
i, ok := tsr.last_rewrite_token_indexes[program_name]
- if !ok{
+ if !ok {
return -1
}
return i
}
-func (tsr *TokenStreamRewriter)GetLastRewriteTokenIndexDefault()int{
+func (tsr *TokenStreamRewriter) GetLastRewriteTokenIndexDefault() int {
return tsr.GetLastRewriteTokenIndex(Default_Program_Name)
}
-func (tsr *TokenStreamRewriter)SetLastRewriteTokenIndex(program_name string, i int){
+func (tsr *TokenStreamRewriter) SetLastRewriteTokenIndex(program_name string, i int) {
tsr.last_rewrite_token_indexes[program_name] = i
}
-func (tsr *TokenStreamRewriter)InitializeProgram(name string)[]RewriteOperation{
+func (tsr *TokenStreamRewriter) InitializeProgram(name string) []RewriteOperation {
is := make([]RewriteOperation, 0, Program_Init_Size)
tsr.programs[name] = is
return is
}
-func (tsr *TokenStreamRewriter)AddToProgram(name string, op RewriteOperation){
+func (tsr *TokenStreamRewriter) AddToProgram(name string, op RewriteOperation) {
is := tsr.GetProgram(name)
is = append(is, op)
tsr.programs[name] = is
}
-func (tsr *TokenStreamRewriter)GetProgram(name string) []RewriteOperation {
+func (tsr *TokenStreamRewriter) GetProgram(name string) []RewriteOperation {
is, ok := tsr.programs[name]
- if !ok{
+ if !ok {
is = tsr.InitializeProgram(name)
}
return is
}
-// Return the text from the original tokens altered per the
-// instructions given to this rewriter.
-func (tsr *TokenStreamRewriter)GetTextDefault() string{
+
+// Return the text from the original tokens altered per the
+// instructions given to this rewriter.
+func (tsr *TokenStreamRewriter) GetTextDefault() string {
return tsr.GetText(
Default_Program_Name,
NewInterval(0, tsr.tokens.Size()-1))
}
-// Return the text from the original tokens altered per the
-// instructions given to this rewriter.
-func (tsr *TokenStreamRewriter)GetText(program_name string, interval *Interval) string {
+
+// Return the text from the original tokens altered per the
+// instructions given to this rewriter.
+func (tsr *TokenStreamRewriter) GetText(program_name string, interval *Interval) string {
rewrites := tsr.programs[program_name]
start := interval.Start
- stop := interval.Stop
+ stop := interval.Stop
// ensure start/end are in range
stop = min(stop, tsr.tokens.Size()-1)
- start = max(start,0)
- if rewrites == nil || len(rewrites) == 0{
+ start = max(start, 0)
+ if rewrites == nil || len(rewrites) == 0 {
return tsr.tokens.GetTextFromInterval(interval) // no instructions to execute
}
buf := bytes.Buffer{}
// First, optimize instruction stream
indexToOp := reduceToSingleOperationPerIndex(rewrites)
// Walk buffer, executing instructions and emitting tokens
- for i:=start; i<=stop && i= tsr.tokens.Size()-1 {buf.WriteString(op.GetText())}
+ for _, op := range indexToOp {
+ if op.GetIndex() >= tsr.tokens.Size()-1 {
+ buf.WriteString(op.GetText())
+ }
}
}
return buf.String()
}
-// We need to combine operations and report invalid operations (like
-// overlapping replaces that are not completed nested). Inserts to
-// same index need to be combined etc... Here are the cases:
+// We need to combine operations and report invalid operations (like
+// overlapping replaces that are not completed nested). Inserts to
+// same index need to be combined etc... Here are the cases:
//
-// I.i.u I.j.v leave alone, nonoverlapping
-// I.i.u I.i.v combine: Iivu
+// I.i.u I.j.v leave alone, nonoverlapping
+// I.i.u I.i.v combine: Iivu
//
-// R.i-j.u R.x-y.v | i-j in x-y delete first R
-// R.i-j.u R.i-j.v delete first R
-// R.i-j.u R.x-y.v | x-y in i-j ERROR
-// R.i-j.u R.x-y.v | boundaries overlap ERROR
+// R.i-j.u R.x-y.v | i-j in x-y delete first R
+// R.i-j.u R.i-j.v delete first R
+// R.i-j.u R.x-y.v | x-y in i-j ERROR
+// R.i-j.u R.x-y.v | boundaries overlap ERROR
//
-// Delete special case of replace (text==null):
-// D.i-j.u D.x-y.v | boundaries overlap combine to max(min)..max(right)
+// Delete special case of replace (text==null):
+// D.i-j.u D.x-y.v | boundaries overlap combine to max(min)..max(right)
//
-// I.i.u R.x-y.v | i in (x+1)-y delete I (since insert before
-// we're not deleting i)
-// I.i.u R.x-y.v | i not in (x+1)-y leave alone, nonoverlapping
-// R.x-y.v I.i.u | i in x-y ERROR
-// R.x-y.v I.x.u R.x-y.uv (combine, delete I)
-// R.x-y.v I.i.u | i not in x-y leave alone, nonoverlapping
+// I.i.u R.x-y.v | i in (x+1)-y delete I (since insert before
+// we're not deleting i)
+// I.i.u R.x-y.v | i not in (x+1)-y leave alone, nonoverlapping
+// R.x-y.v I.i.u | i in x-y ERROR
+// R.x-y.v I.x.u R.x-y.uv (combine, delete I)
+// R.x-y.v I.i.u | i not in x-y leave alone, nonoverlapping
//
-// I.i.u = insert u before op @ index i
-// R.x-y.u = replace x-y indexed tokens with u
+// I.i.u = insert u before op @ index i
+// R.x-y.u = replace x-y indexed tokens with u
//
-// First we need to examine replaces. For any replace op:
+// First we need to examine replaces. For any replace op:
//
-// 1. wipe out any insertions before op within that range.
-// 2. Drop any replace op before that is contained completely within
-// that range.
-// 3. Throw exception upon boundary overlap with any previous replace.
+// 1. wipe out any insertions before op within that range.
+// 2. Drop any replace op before that is contained completely within
+// that range.
+// 3. Throw exception upon boundary overlap with any previous replace.
//
-// Then we can deal with inserts:
+// Then we can deal with inserts:
//
-// 1. for any inserts to same index, combine even if not adjacent.
-// 2. for any prior replace with same left boundary, combine this
-// insert with replace and delete this replace.
-// 3. throw exception if index in same range as previous replace
+// 1. for any inserts to same index, combine even if not adjacent.
+// 2. for any prior replace with same left boundary, combine this
+// insert with replace and delete this replace.
+// 3. throw exception if index in same range as previous replace
//
-// Don't actually delete; make op null in list. Easier to walk list.
-// Later we can throw as we add to index → op map.
+// Don't actually delete; make op null in list. Easier to walk list.
+// Later we can throw as we add to index → op map.
//
-// Note that I.2 R.2-2 will wipe out I.2 even though, technically, the
-// inserted stuff would be before the replace range. But, if you
-// add tokens in front of a method body '{' and then delete the method
-// body, I think the stuff before the '{' you added should disappear too.
+// Note that I.2 R.2-2 will wipe out I.2 even though, technically, the
+// inserted stuff would be before the replace range. But, if you
+// add tokens in front of a method body '{' and then delete the method
+// body, I think the stuff before the '{' you added should disappear too.
//
-// Return a map from token index to operation.
-//
-func reduceToSingleOperationPerIndex(rewrites []RewriteOperation) map[int]RewriteOperation{
+// Return a map from token index to operation.
+func reduceToSingleOperationPerIndex(rewrites []RewriteOperation) map[int]RewriteOperation {
// WALK REPLACES
- for i:=0; i < len(rewrites); i++{
+ for i := 0; i < len(rewrites); i++ {
op := rewrites[i]
- if op == nil{continue}
+ if op == nil {
+ continue
+ }
rop, ok := op.(*ReplaceOp)
- if !ok{continue}
+ if !ok {
+ continue
+ }
// Wipe prior inserts within range
- for j:=0; j rop.index && iop.index <=rop.LastIndex{
+ } else if iop.index > rop.index && iop.index <= rop.LastIndex {
// delete insert as it's a no-op.
rewrites[iop.instruction_index] = nil
}
}
}
// Drop any prior replaces contained within
- for j:=0; j=rop.index && prevop.LastIndex <= rop.LastIndex{
+ for j := 0; j < i && j < len(rewrites); j++ {
+ if prevop, ok := rewrites[j].(*ReplaceOp); ok {
+ if prevop.index >= rop.index && prevop.LastIndex <= rop.LastIndex {
// delete replace as it's a no-op.
rewrites[prevop.instruction_index] = nil
continue
@@ -566,61 +571,67 @@ func reduceToSingleOperationPerIndex(rewrites []RewriteOperation) map[int]Rewrit
disjoint := prevop.LastIndex < rop.index || prevop.index > rop.LastIndex
// Delete special case of replace (text==null):
// D.i-j.u D.x-y.v | boundaries overlap combine to max(min)..max(right)
- if prevop.text == "" && rop.text == "" && !disjoint{
+ if prevop.text == "" && rop.text == "" && !disjoint {
rewrites[prevop.instruction_index] = nil
rop.index = min(prevop.index, rop.index)
rop.LastIndex = max(prevop.LastIndex, rop.LastIndex)
println("new rop" + rop.String()) //TODO: remove console write, taken from Java version
- }else if !disjoint{
+ } else if !disjoint {
panic("replace op boundaries of " + rop.String() + " overlap with previous " + prevop.String())
}
}
}
}
// WALK INSERTS
- for i:=0; i < len(rewrites); i++ {
+ for i := 0; i < len(rewrites); i++ {
op := rewrites[i]
- if op == nil{continue}
+ if op == nil {
+ continue
+ }
//hack to replicate inheritance in composition
_, iok := rewrites[i].(*InsertBeforeOp)
_, aok := rewrites[i].(*InsertAfterOp)
- if !iok && !aok{continue}
+ if !iok && !aok {
+ continue
+ }
iop := rewrites[i]
// combine current insert with prior if any at same index
// deviating a bit from TokenStreamRewriter.java - hard to incorporate inheritance logic
- for j:=0; j= rop.index && iop.GetIndex() <= rop.LastIndex{
- panic("insert op "+iop.String()+" within boundaries of previous "+rop.String())
+ if iop.GetIndex() >= rop.index && iop.GetIndex() <= rop.LastIndex {
+ panic("insert op " + iop.String() + " within boundaries of previous " + rop.String())
}
}
}
}
m := map[int]RewriteOperation{}
- for i:=0; i < len(rewrites); i++{
+ for i := 0; i < len(rewrites); i++ {
op := rewrites[i]
- if op == nil {continue}
- if _, ok := m[op.GetIndex()]; ok{
+ if op == nil {
+ continue
+ }
+ if _, ok := m[op.GetIndex()]; ok {
panic("should only be one op per index")
}
m[op.GetIndex()] = op
@@ -628,22 +639,21 @@ func reduceToSingleOperationPerIndex(rewrites []RewriteOperation) map[int]Rewrit
return m
}
-
/*
Quick fixing Go lack of overloads
- */
+*/
-func max(a,b int)int{
- if a>b{
+func max(a, b int) int {
+ if a > b {
return a
- }else {
+ } else {
return b
}
}
-func min(a,b int)int{
- if a as.threshold {
as.expand()
}
@@ -98,7 +96,7 @@ func (as *array2DHashSet) expand() {
b := as.getBuckets(o)
bucketLength := newBucketLengths[b]
- var newBucket []interface{}
+ var newBucket []Collectable[any]
if bucketLength == 0 {
// new bucket
newBucket = as.createBucket(as.initialBucketCapacity)
@@ -107,7 +105,7 @@ func (as *array2DHashSet) expand() {
newBucket = newTable[b]
if bucketLength == len(newBucket) {
// expand
- newBucketCopy := make([]interface{}, len(newBucket)<<1)
+ newBucketCopy := make([]Collectable[any], len(newBucket)<<1)
copy(newBucketCopy[:bucketLength], newBucket)
newBucket = newBucketCopy
newTable[b] = newBucket
@@ -124,7 +122,7 @@ func (as *array2DHashSet) Len() int {
return as.n
}
-func (as *array2DHashSet) Get(o interface{}) interface{} {
+func (as *array2DHashSet) Get(o Collectable[any]) interface{} {
if o == nil {
return nil
}
@@ -147,7 +145,7 @@ func (as *array2DHashSet) Get(o interface{}) interface{} {
return nil
}
-func (as *array2DHashSet) innerAdd(o interface{}) interface{} {
+func (as *array2DHashSet) innerAdd(o Collectable[any]) interface{} {
b := as.getBuckets(o)
bucket := as.buckets[b]
@@ -178,7 +176,7 @@ func (as *array2DHashSet) innerAdd(o interface{}) interface{} {
// full bucket, expand and add to end
oldLength := len(bucket)
- bucketCopy := make([]interface{}, oldLength<<1)
+ bucketCopy := make([]Collectable[any], oldLength<<1)
copy(bucketCopy[:oldLength], bucket)
bucket = bucketCopy
as.buckets[b] = bucket
@@ -187,22 +185,22 @@ func (as *array2DHashSet) innerAdd(o interface{}) interface{} {
return o
}
-func (as *array2DHashSet) getBuckets(value interface{}) int {
+func (as *array2DHashSet) getBuckets(value Collectable[any]) int {
hash := as.hashcodeFunction(value)
return hash & (len(as.buckets) - 1)
}
-func (as *array2DHashSet) createBuckets(cap int) [][]interface{} {
- return make([][]interface{}, cap)
+func (as *array2DHashSet) createBuckets(cap int) [][]Collectable[any] {
+ return make([][]Collectable[any], cap)
}
-func (as *array2DHashSet) createBucket(cap int) []interface{} {
- return make([]interface{}, cap)
+func (as *array2DHashSet) createBucket(cap int) []Collectable[any] {
+ return make([]Collectable[any], cap)
}
func newArray2DHashSetWithCap(
hashcodeFunction func(interface{}) int,
- equalsFunction func(interface{}, interface{}) bool,
+ equalsFunction func(Collectable[any], Collectable[any]) bool,
initCap int,
initBucketCap int,
) *array2DHashSet {
@@ -231,7 +229,7 @@ func newArray2DHashSetWithCap(
func newArray2DHashSet(
hashcodeFunction func(interface{}) int,
- equalsFunction func(interface{}, interface{}) bool,
+ equalsFunction func(Collectable[any], Collectable[any]) bool,
) *array2DHashSet {
return newArray2DHashSetWithCap(hashcodeFunction, equalsFunction, _initalCapacity, _initalBucketCapacity)
}
diff --git a/vendor/github.com/google/cel-go/cel/BUILD.bazel b/vendor/github.com/google/cel-go/cel/BUILD.bazel
index ddddbd280..0905f6353 100644
--- a/vendor/github.com/google/cel-go/cel/BUILD.bazel
+++ b/vendor/github.com/google/cel-go/cel/BUILD.bazel
@@ -15,6 +15,7 @@ go_library(
"macro.go",
"options.go",
"program.go",
+ "validator.go",
],
importpath = "github.com/google/cel-go/cel",
visibility = ["//visibility:public"],
@@ -22,17 +23,20 @@ go_library(
"//checker:go_default_library",
"//checker/decls:go_default_library",
"//common:go_default_library",
+ "//common/ast:go_default_library",
"//common/containers:go_default_library",
+ "//common/decls:go_default_library",
+ "//common/functions:go_default_library",
"//common/operators:go_default_library",
"//common/overloads:go_default_library",
+ "//common/stdlib:go_default_library",
"//common/types:go_default_library",
"//common/types/pb:go_default_library",
"//common/types/ref:go_default_library",
"//common/types/traits:go_default_library",
"//interpreter:go_default_library",
- "//interpreter/functions:go_default_library",
"//parser:go_default_library",
- "@org_golang_google_genproto//googleapis/api/expr/v1alpha1:go_default_library",
+ "@org_golang_google_genproto_googleapis_api//expr/v1alpha1:go_default_library",
"@org_golang_google_protobuf//proto:go_default_library",
"@org_golang_google_protobuf//reflect/protodesc:go_default_library",
"@org_golang_google_protobuf//reflect/protoreflect:go_default_library",
@@ -70,8 +74,10 @@ go_test(
"//test/proto2pb:go_default_library",
"//test/proto3pb:go_default_library",
"@io_bazel_rules_go//proto/wkt:descriptor_go_proto",
- "@org_golang_google_genproto//googleapis/api/expr/v1alpha1:go_default_library",
+ "@org_golang_google_genproto_googleapis_api//expr/v1alpha1:go_default_library",
"@org_golang_google_protobuf//proto:go_default_library",
+ "@org_golang_google_protobuf//encoding/prototext:go_default_library",
"@org_golang_google_protobuf//types/known/structpb:go_default_library",
+ "@org_golang_google_protobuf//types/known/wrapperspb:go_default_library",
],
)
diff --git a/vendor/github.com/google/cel-go/cel/decls.go b/vendor/github.com/google/cel-go/cel/decls.go
index 8ff690b11..0f9501341 100644
--- a/vendor/github.com/google/cel-go/cel/decls.go
+++ b/vendor/github.com/google/cel-go/cel/decls.go
@@ -16,341 +16,133 @@ package cel
import (
"fmt"
- "strings"
- "github.com/google/cel-go/checker/decls"
+ "github.com/google/cel-go/common/ast"
+ "github.com/google/cel-go/common/decls"
+ "github.com/google/cel-go/common/functions"
"github.com/google/cel-go/common/types"
"github.com/google/cel-go/common/types/ref"
- "github.com/google/cel-go/common/types/traits"
- "github.com/google/cel-go/interpreter/functions"
exprpb "google.golang.org/genproto/googleapis/api/expr/v1alpha1"
)
// Kind indicates a CEL type's kind which is used to differentiate quickly between simple and complex types.
-type Kind uint
+type Kind = types.Kind
const (
// DynKind represents a dynamic type. This kind only exists at type-check time.
- DynKind Kind = iota
+ DynKind Kind = types.DynKind
// AnyKind represents a google.protobuf.Any type. This kind only exists at type-check time.
- AnyKind
+ AnyKind = types.AnyKind
// BoolKind represents a boolean type.
- BoolKind
+ BoolKind = types.BoolKind
// BytesKind represents a bytes type.
- BytesKind
+ BytesKind = types.BytesKind
// DoubleKind represents a double type.
- DoubleKind
+ DoubleKind = types.DoubleKind
// DurationKind represents a CEL duration type.
- DurationKind
+ DurationKind = types.DurationKind
// IntKind represents an integer type.
- IntKind
+ IntKind = types.IntKind
// ListKind represents a list type.
- ListKind
+ ListKind = types.ListKind
// MapKind represents a map type.
- MapKind
+ MapKind = types.MapKind
// NullTypeKind represents a null type.
- NullTypeKind
+ NullTypeKind = types.NullTypeKind
// OpaqueKind represents an abstract type which has no accessible fields.
- OpaqueKind
+ OpaqueKind = types.OpaqueKind
// StringKind represents a string type.
- StringKind
+ StringKind = types.StringKind
// StructKind represents a structured object with typed fields.
- StructKind
+ StructKind = types.StructKind
// TimestampKind represents a a CEL time type.
- TimestampKind
+ TimestampKind = types.TimestampKind
// TypeKind represents the CEL type.
- TypeKind
+ TypeKind = types.TypeKind
// TypeParamKind represents a parameterized type whose type name will be resolved at type-check time, if possible.
- TypeParamKind
+ TypeParamKind = types.TypeParamKind
// UintKind represents a uint type.
- UintKind
+ UintKind = types.UintKind
)
var (
// AnyType represents the google.protobuf.Any type.
- AnyType = &Type{
- kind: AnyKind,
- runtimeType: types.NewTypeValue("google.protobuf.Any"),
- }
+ AnyType = types.AnyType
// BoolType represents the bool type.
- BoolType = &Type{
- kind: BoolKind,
- runtimeType: types.BoolType,
- }
+ BoolType = types.BoolType
// BytesType represents the bytes type.
- BytesType = &Type{
- kind: BytesKind,
- runtimeType: types.BytesType,
- }
+ BytesType = types.BytesType
// DoubleType represents the double type.
- DoubleType = &Type{
- kind: DoubleKind,
- runtimeType: types.DoubleType,
- }
+ DoubleType = types.DoubleType
// DurationType represents the CEL duration type.
- DurationType = &Type{
- kind: DurationKind,
- runtimeType: types.DurationType,
- }
+ DurationType = types.DurationType
// DynType represents a dynamic CEL type whose type will be determined at runtime from context.
- DynType = &Type{
- kind: DynKind,
- runtimeType: types.NewTypeValue("dyn"),
- }
+ DynType = types.DynType
// IntType represents the int type.
- IntType = &Type{
- kind: IntKind,
- runtimeType: types.IntType,
- }
+ IntType = types.IntType
// NullType represents the type of a null value.
- NullType = &Type{
- kind: NullTypeKind,
- runtimeType: types.NullType,
- }
+ NullType = types.NullType
// StringType represents the string type.
- StringType = &Type{
- kind: StringKind,
- runtimeType: types.StringType,
- }
+ StringType = types.StringType
// TimestampType represents the time type.
- TimestampType = &Type{
- kind: TimestampKind,
- runtimeType: types.TimestampType,
- }
+ TimestampType = types.TimestampType
// TypeType represents a CEL type
- TypeType = &Type{
- kind: TypeKind,
- runtimeType: types.TypeType,
- }
- //UintType represents a uint type.
- UintType = &Type{
- kind: UintKind,
- runtimeType: types.UintType,
- }
+ TypeType = types.TypeType
+ // UintType represents a uint type.
+ UintType = types.UintType
+
+ // function references for instantiating new types.
+
+ // ListType creates an instances of a list type value with the provided element type.
+ ListType = types.NewListType
+ // MapType creates an instance of a map type value with the provided key and value types.
+ MapType = types.NewMapType
+ // NullableType creates an instance of a nullable type with the provided wrapped type.
+ //
+ // Note: only primitive types are supported as wrapped types.
+ NullableType = types.NewNullableType
+ // OptionalType creates an abstract parameterized type instance corresponding to CEL's notion of optional.
+ OptionalType = types.NewOptionalType
+ // OpaqueType creates an abstract parameterized type with a given name.
+ OpaqueType = types.NewOpaqueType
+ // ObjectType creates a type references to an externally defined type, e.g. a protobuf message type.
+ ObjectType = types.NewObjectType
+ // TypeParamType creates a parameterized type instance.
+ TypeParamType = types.NewTypeParamType
)
// Type holds a reference to a runtime type with an optional type-checked set of type parameters.
-type Type struct {
- // kind indicates general category of the type.
- kind Kind
-
- // runtimeType is the runtime type of the declaration.
- runtimeType ref.Type
-
- // parameters holds the optional type-checked set of type parameters that are used during static analysis.
- parameters []*Type
-
- // isAssignableType function determines whether one type is assignable to this type.
- // A nil value for the isAssignableType function falls back to equality of kind, runtimeType, and parameters.
- isAssignableType func(other *Type) bool
-
- // isAssignableRuntimeType function determines whether the runtime type (with erasure) is assignable to this type.
- // A nil value for the isAssignableRuntimeType function falls back to the equality of the type or type name.
- isAssignableRuntimeType func(other ref.Val) bool
-}
-
-// IsAssignableType determines whether the current type is type-check assignable from the input fromType.
-func (t *Type) IsAssignableType(fromType *Type) bool {
- if t.isAssignableType != nil {
- return t.isAssignableType(fromType)
- }
- return t.defaultIsAssignableType(fromType)
-}
-
-// IsAssignableRuntimeType determines whether the current type is runtime assignable from the input runtimeType.
-//
-// At runtime, parameterized types are erased and so a function which type-checks to support a map(string, string)
-// will have a runtime assignable type of a map.
-func (t *Type) IsAssignableRuntimeType(val ref.Val) bool {
- if t.isAssignableRuntimeType != nil {
- return t.isAssignableRuntimeType(val)
- }
- return t.defaultIsAssignableRuntimeType(val)
-}
-
-// String returns a human-readable definition of the type name.
-func (t *Type) String() string {
- if len(t.parameters) == 0 {
- return t.runtimeType.TypeName()
- }
- params := make([]string, len(t.parameters))
- for i, p := range t.parameters {
- params[i] = p.String()
- }
- return fmt.Sprintf("%s(%s)", t.runtimeType.TypeName(), strings.Join(params, ", "))
-}
-
-// isDyn indicates whether the type is dynamic in any way.
-func (t *Type) isDyn() bool {
- return t.kind == DynKind || t.kind == AnyKind || t.kind == TypeParamKind
-}
+type Type = types.Type
-// equals indicates whether two types have the same kind, type name, and parameters.
-func (t *Type) equals(other *Type) bool {
- if t.kind != other.kind ||
- t.runtimeType.TypeName() != other.runtimeType.TypeName() ||
- len(t.parameters) != len(other.parameters) {
- return false
- }
- for i, p := range t.parameters {
- if !p.equals(other.parameters[i]) {
- return false
- }
- }
- return true
-}
-
-// defaultIsAssignableType provides the standard definition of what it means for one type to be assignable to another
-// where any of the following may return a true result:
-// - The from types are the same instance
-// - The target type is dynamic
-// - The fromType has the same kind and type name as the target type, and all parameters of the target type
-//
-// are IsAssignableType() from the parameters of the fromType.
-func (t *Type) defaultIsAssignableType(fromType *Type) bool {
- if t == fromType || t.isDyn() {
- return true
- }
- if t.kind != fromType.kind ||
- t.runtimeType.TypeName() != fromType.runtimeType.TypeName() ||
- len(t.parameters) != len(fromType.parameters) {
- return false
- }
- for i, tp := range t.parameters {
- fp := fromType.parameters[i]
- if !tp.IsAssignableType(fp) {
- return false
- }
- }
- return true
-}
-
-// defaultIsAssignableRuntimeType inspects the type and in the case of list and map elements, the key and element types
-// to determine whether a ref.Val is assignable to the declared type for a function signature.
-func (t *Type) defaultIsAssignableRuntimeType(val ref.Val) bool {
- valType := val.Type()
- if !(t.runtimeType == valType || t.isDyn() || t.runtimeType.TypeName() == valType.TypeName()) {
- return false
- }
- switch t.runtimeType {
- case types.ListType:
- elemType := t.parameters[0]
- l := val.(traits.Lister)
- if l.Size() == types.IntZero {
- return true
- }
- it := l.Iterator()
- for it.HasNext() == types.True {
- elemVal := it.Next()
- return elemType.IsAssignableRuntimeType(elemVal)
- }
- case types.MapType:
- keyType := t.parameters[0]
- elemType := t.parameters[1]
- m := val.(traits.Mapper)
- if m.Size() == types.IntZero {
- return true
- }
- it := m.Iterator()
- for it.HasNext() == types.True {
- keyVal := it.Next()
- elemVal := m.Get(keyVal)
- return keyType.IsAssignableRuntimeType(keyVal) && elemType.IsAssignableRuntimeType(elemVal)
- }
- }
- return true
-}
-
-// ListType creates an instances of a list type value with the provided element type.
-func ListType(elemType *Type) *Type {
- return &Type{
- kind: ListKind,
- runtimeType: types.ListType,
- parameters: []*Type{elemType},
- }
-}
-
-// MapType creates an instance of a map type value with the provided key and value types.
-func MapType(keyType, valueType *Type) *Type {
- return &Type{
- kind: MapKind,
- runtimeType: types.MapType,
- parameters: []*Type{keyType, valueType},
- }
-}
-
-// NullableType creates an instance of a nullable type with the provided wrapped type.
-//
-// Note: only primitive types are supported as wrapped types.
-func NullableType(wrapped *Type) *Type {
- return &Type{
- kind: wrapped.kind,
- runtimeType: wrapped.runtimeType,
- parameters: wrapped.parameters,
- isAssignableType: func(other *Type) bool {
- return NullType.IsAssignableType(other) || wrapped.IsAssignableType(other)
- },
- isAssignableRuntimeType: func(other ref.Val) bool {
- return NullType.IsAssignableRuntimeType(other) || wrapped.IsAssignableRuntimeType(other)
- },
- }
-}
-
-// OptionalType creates an abstract parameterized type instance corresponding to CEL's notion of optional.
-func OptionalType(param *Type) *Type {
- return OpaqueType("optional", param)
-}
-
-// OpaqueType creates an abstract parameterized type with a given name.
-func OpaqueType(name string, params ...*Type) *Type {
- return &Type{
- kind: OpaqueKind,
- runtimeType: types.NewTypeValue(name),
- parameters: params,
- }
-}
-
-// ObjectType creates a type references to an externally defined type, e.g. a protobuf message type.
-func ObjectType(typeName string) *Type {
- return &Type{
- kind: StructKind,
- runtimeType: types.NewObjectTypeValue(typeName),
- }
-}
-
-// TypeParamType creates a parameterized type instance.
-func TypeParamType(paramName string) *Type {
- return &Type{
- kind: TypeParamKind,
- runtimeType: types.NewTypeValue(paramName),
+// Constant creates an instances of an identifier declaration with a variable name, type, and value.
+func Constant(name string, t *Type, v ref.Val) EnvOption {
+ return func(e *Env) (*Env, error) {
+ e.variables = append(e.variables, decls.NewConstant(name, t, v))
+ return e, nil
}
}
// Variable creates an instance of a variable declaration with a variable name and type.
func Variable(name string, t *Type) EnvOption {
return func(e *Env) (*Env, error) {
- et, err := TypeToExprType(t)
- if err != nil {
- return nil, err
- }
- e.declarations = append(e.declarations, decls.NewVar(name, et))
+ e.variables = append(e.variables, decls.NewVariable(name, t))
return e, nil
}
}
@@ -386,53 +178,30 @@ func Variable(name string, t *Type) EnvOption {
// overload as CEL can only make inferences by type-name regarding such types.
func Function(name string, opts ...FunctionOpt) EnvOption {
return func(e *Env) (*Env, error) {
- fn := &functionDecl{
- name: name,
- overloads: []*overloadDecl{},
- options: opts,
- }
- err := fn.init()
+ fn, err := decls.NewFunction(name, opts...)
if err != nil {
return nil, err
}
- _, err = functionDeclToExprDecl(fn)
- if err != nil {
- return nil, err
- }
- if existing, found := e.functions[fn.name]; found {
- fn, err = existing.merge(fn)
+ if existing, found := e.functions[fn.Name()]; found {
+ fn, err = existing.Merge(fn)
if err != nil {
return nil, err
}
}
- e.functions[name] = fn
+ e.functions[fn.Name()] = fn
return e, nil
}
}
// FunctionOpt defines a functional option for configuring a function declaration.
-type FunctionOpt func(*functionDecl) (*functionDecl, error)
+type FunctionOpt = decls.FunctionOpt
-// SingletonUnaryBinding creates a singleton function defintion to be used for all function overloads.
+// SingletonUnaryBinding creates a singleton function definition to be used for all function overloads.
//
// Note, this approach works well if operand is expected to have a specific trait which it implements,
// e.g. traits.ContainerType. Otherwise, prefer per-overload function bindings.
func SingletonUnaryBinding(fn functions.UnaryOp, traits ...int) FunctionOpt {
- trait := 0
- for _, t := range traits {
- trait = trait | t
- }
- return func(f *functionDecl) (*functionDecl, error) {
- if f.singleton != nil {
- return nil, fmt.Errorf("function already has a singleton binding: %s", f.name)
- }
- f.singleton = &functions.Overload{
- Operator: f.name,
- Unary: fn,
- OperandTrait: trait,
- }
- return f, nil
- }
+ return decls.SingletonUnaryBinding(fn, traits...)
}
// SingletonBinaryImpl creates a singleton function definition to be used with all function overloads.
@@ -442,7 +211,7 @@ func SingletonUnaryBinding(fn functions.UnaryOp, traits ...int) FunctionOpt {
//
// Deprecated: use SingletonBinaryBinding
func SingletonBinaryImpl(fn functions.BinaryOp, traits ...int) FunctionOpt {
- return SingletonBinaryBinding(fn, traits...)
+ return decls.SingletonBinaryBinding(fn, traits...)
}
// SingletonBinaryBinding creates a singleton function definition to be used with all function overloads.
@@ -450,21 +219,7 @@ func SingletonBinaryImpl(fn functions.BinaryOp, traits ...int) FunctionOpt {
// Note, this approach works well if operand is expected to have a specific trait which it implements,
// e.g. traits.ContainerType. Otherwise, prefer per-overload function bindings.
func SingletonBinaryBinding(fn functions.BinaryOp, traits ...int) FunctionOpt {
- trait := 0
- for _, t := range traits {
- trait = trait | t
- }
- return func(f *functionDecl) (*functionDecl, error) {
- if f.singleton != nil {
- return nil, fmt.Errorf("function already has a singleton binding: %s", f.name)
- }
- f.singleton = &functions.Overload{
- Operator: f.name,
- Binary: fn,
- OperandTrait: trait,
- }
- return f, nil
- }
+ return decls.SingletonBinaryBinding(fn, traits...)
}
// SingletonFunctionImpl creates a singleton function definition to be used with all function overloads.
@@ -474,7 +229,7 @@ func SingletonBinaryBinding(fn functions.BinaryOp, traits ...int) FunctionOpt {
//
// Deprecated: use SingletonFunctionBinding
func SingletonFunctionImpl(fn functions.FunctionOp, traits ...int) FunctionOpt {
- return SingletonFunctionBinding(fn, traits...)
+ return decls.SingletonFunctionBinding(fn, traits...)
}
// SingletonFunctionBinding creates a singleton function definition to be used with all function overloads.
@@ -482,21 +237,13 @@ func SingletonFunctionImpl(fn functions.FunctionOp, traits ...int) FunctionOpt {
// Note, this approach works well if operand is expected to have a specific trait which it implements,
// e.g. traits.ContainerType. Otherwise, prefer per-overload function bindings.
func SingletonFunctionBinding(fn functions.FunctionOp, traits ...int) FunctionOpt {
- trait := 0
- for _, t := range traits {
- trait = trait | t
- }
- return func(f *functionDecl) (*functionDecl, error) {
- if f.singleton != nil {
- return nil, fmt.Errorf("function already has a singleton binding: %s", f.name)
- }
- f.singleton = &functions.Overload{
- Operator: f.name,
- Function: fn,
- OperandTrait: trait,
- }
- return f, nil
- }
+ return decls.SingletonFunctionBinding(fn, traits...)
+}
+
+// DisableDeclaration disables the function signatures, effectively removing them from the type-check
+// environment while preserving the runtime bindings.
+func DisableDeclaration(value bool) FunctionOpt {
+ return decls.DisableDeclaration(value)
}
// Overload defines a new global overload with an overload id, argument types, and result type. Through the
@@ -506,7 +253,7 @@ func SingletonFunctionBinding(fn functions.FunctionOp, traits ...int) FunctionOp
// Note: function bindings should be commonly configured with Overload instances whereas operand traits and
// strict-ness should be rare occurrences.
func Overload(overloadID string, args []*Type, resultType *Type, opts ...OverloadOpt) FunctionOpt {
- return newOverload(overloadID, false, args, resultType, opts...)
+ return decls.Overload(overloadID, args, resultType, opts...)
}
// MemberOverload defines a new receiver-style overload (or member function) with an overload id, argument types,
@@ -516,610 +263,51 @@ func Overload(overloadID string, args []*Type, resultType *Type, opts ...Overloa
// Note: function bindings should be commonly configured with Overload instances whereas operand traits and
// strict-ness should be rare occurrences.
func MemberOverload(overloadID string, args []*Type, resultType *Type, opts ...OverloadOpt) FunctionOpt {
- return newOverload(overloadID, true, args, resultType, opts...)
+ return decls.MemberOverload(overloadID, args, resultType, opts...)
}
// OverloadOpt is a functional option for configuring a function overload.
-type OverloadOpt func(*overloadDecl) (*overloadDecl, error)
+type OverloadOpt = decls.OverloadOpt
// UnaryBinding provides the implementation of a unary overload. The provided function is protected by a runtime
// type-guard which ensures runtime type agreement between the overload signature and runtime argument types.
func UnaryBinding(binding functions.UnaryOp) OverloadOpt {
- return func(o *overloadDecl) (*overloadDecl, error) {
- if o.hasBinding() {
- return nil, fmt.Errorf("overload already has a binding: %s", o.id)
- }
- if len(o.argTypes) != 1 {
- return nil, fmt.Errorf("unary function bound to non-unary overload: %s", o.id)
- }
- o.unaryOp = binding
- return o, nil
- }
+ return decls.UnaryBinding(binding)
}
// BinaryBinding provides the implementation of a binary overload. The provided function is protected by a runtime
// type-guard which ensures runtime type agreement between the overload signature and runtime argument types.
func BinaryBinding(binding functions.BinaryOp) OverloadOpt {
- return func(o *overloadDecl) (*overloadDecl, error) {
- if o.hasBinding() {
- return nil, fmt.Errorf("overload already has a binding: %s", o.id)
- }
- if len(o.argTypes) != 2 {
- return nil, fmt.Errorf("binary function bound to non-binary overload: %s", o.id)
- }
- o.binaryOp = binding
- return o, nil
- }
+ return decls.BinaryBinding(binding)
}
// FunctionBinding provides the implementation of a variadic overload. The provided function is protected by a runtime
// type-guard which ensures runtime type agreement between the overload signature and runtime argument types.
func FunctionBinding(binding functions.FunctionOp) OverloadOpt {
- return func(o *overloadDecl) (*overloadDecl, error) {
- if o.hasBinding() {
- return nil, fmt.Errorf("overload already has a binding: %s", o.id)
- }
- o.functionOp = binding
- return o, nil
- }
+ return decls.FunctionBinding(binding)
}
// OverloadIsNonStrict enables the function to be called with error and unknown argument values.
//
// Note: do not use this option unless absoluately necessary as it should be an uncommon feature.
func OverloadIsNonStrict() OverloadOpt {
- return func(o *overloadDecl) (*overloadDecl, error) {
- o.nonStrict = true
- return o, nil
- }
+ return decls.OverloadIsNonStrict()
}
// OverloadOperandTrait configures a set of traits which the first argument to the overload must implement in order to be
// successfully invoked.
func OverloadOperandTrait(trait int) OverloadOpt {
- return func(o *overloadDecl) (*overloadDecl, error) {
- o.operandTrait = trait
- return o, nil
- }
-}
-
-type functionDecl struct {
- name string
- overloads []*overloadDecl
- options []FunctionOpt
- singleton *functions.Overload
- initialized bool
-}
-
-// init ensures that a function's options have been applied.
-//
-// This function is used in both the environment configuration and internally for function merges.
-func (f *functionDecl) init() error {
- if f.initialized {
- return nil
- }
- f.initialized = true
-
- var err error
- for _, opt := range f.options {
- f, err = opt(f)
- if err != nil {
- return err
- }
- }
- if len(f.overloads) == 0 {
- return fmt.Errorf("function %s must have at least one overload", f.name)
- }
- return nil
-}
-
-// bindings produces a set of function bindings, if any are defined.
-func (f *functionDecl) bindings() ([]*functions.Overload, error) {
- overloads := []*functions.Overload{}
- nonStrict := false
- for _, o := range f.overloads {
- if o.hasBinding() {
- overload := &functions.Overload{
- Operator: o.id,
- Unary: o.guardedUnaryOp(f.name),
- Binary: o.guardedBinaryOp(f.name),
- Function: o.guardedFunctionOp(f.name),
- OperandTrait: o.operandTrait,
- NonStrict: o.nonStrict,
- }
- overloads = append(overloads, overload)
- nonStrict = nonStrict || o.nonStrict
- }
- }
- if f.singleton != nil {
- if len(overloads) != 0 {
- return nil, fmt.Errorf("singleton function incompatible with specialized overloads: %s", f.name)
- }
- return []*functions.Overload{
- {
- Operator: f.name,
- Unary: f.singleton.Unary,
- Binary: f.singleton.Binary,
- Function: f.singleton.Function,
- OperandTrait: f.singleton.OperandTrait,
- },
- }, nil
- }
- if len(overloads) == 0 {
- return overloads, nil
- }
- // Single overload. Replicate an entry for it using the function name as well.
- if len(overloads) == 1 {
- if overloads[0].Operator == f.name {
- return overloads, nil
- }
- return append(overloads, &functions.Overload{
- Operator: f.name,
- Unary: overloads[0].Unary,
- Binary: overloads[0].Binary,
- Function: overloads[0].Function,
- NonStrict: overloads[0].NonStrict,
- OperandTrait: overloads[0].OperandTrait,
- }), nil
- }
- // All of the defined overloads are wrapped into a top-level function which
- // performs dynamic dispatch to the proper overload based on the argument types.
- bindings := append([]*functions.Overload{}, overloads...)
- funcDispatch := func(args ...ref.Val) ref.Val {
- for _, o := range f.overloads {
- if !o.matchesRuntimeSignature(args...) {
- continue
- }
- switch len(args) {
- case 1:
- if o.unaryOp != nil {
- return o.unaryOp(args[0])
- }
- case 2:
- if o.binaryOp != nil {
- return o.binaryOp(args[0], args[1])
- }
- }
- if o.functionOp != nil {
- return o.functionOp(args...)
- }
- // eventually this will fall through to the noSuchOverload below.
- }
- return noSuchOverload(f.name, args...)
- }
- function := &functions.Overload{
- Operator: f.name,
- Function: funcDispatch,
- NonStrict: nonStrict,
- }
- return append(bindings, function), nil
-}
-
-// merge one function declaration with another.
-//
-// If a function is extended, by say adding new overloads to an existing function, then it is merged with the
-// prior definition of the function at which point its overloads must not collide with pre-existing overloads
-// and its bindings (singleton, or per-overload) must not conflict with previous definitions either.
-func (f *functionDecl) merge(other *functionDecl) (*functionDecl, error) {
- if f.name != other.name {
- return nil, fmt.Errorf("cannot merge unrelated functions. %s and %s", f.name, other.name)
- }
- err := f.init()
- if err != nil {
- return nil, err
- }
- err = other.init()
- if err != nil {
- return nil, err
- }
- merged := &functionDecl{
- name: f.name,
- overloads: make([]*overloadDecl, len(f.overloads)),
- options: []FunctionOpt{},
- initialized: true,
- singleton: f.singleton,
- }
- copy(merged.overloads, f.overloads)
- for _, o := range other.overloads {
- err := merged.addOverload(o)
- if err != nil {
- return nil, fmt.Errorf("function declaration merge failed: %v", err)
- }
- }
- if other.singleton != nil {
- if merged.singleton != nil {
- return nil, fmt.Errorf("function already has a binding: %s", f.name)
- }
- merged.singleton = other.singleton
- }
- return merged, nil
-}
-
-// addOverload ensures that the new overload does not collide with an existing overload signature;
-// however, if the function signatures are identical, the implementation may be rewritten as its
-// difficult to compare functions by object identity.
-func (f *functionDecl) addOverload(overload *overloadDecl) error {
- for index, o := range f.overloads {
- if o.id != overload.id && o.signatureOverlaps(overload) {
- return fmt.Errorf("overload signature collision in function %s: %s collides with %s", f.name, o.id, overload.id)
- }
- if o.id == overload.id {
- if o.signatureEquals(overload) && o.nonStrict == overload.nonStrict {
- // Allow redefinition of an overload implementation so long as the signatures match.
- f.overloads[index] = overload
- return nil
- } else {
- return fmt.Errorf("overload redefinition in function. %s: %s has multiple definitions", f.name, o.id)
- }
- }
- }
- f.overloads = append(f.overloads, overload)
- return nil
-}
-
-func noSuchOverload(funcName string, args ...ref.Val) ref.Val {
- argTypes := make([]string, len(args))
- for i, arg := range args {
- argTypes[i] = arg.Type().TypeName()
- }
- signature := strings.Join(argTypes, ", ")
- return types.NewErr("no such overload: %s(%s)", funcName, signature)
-}
-
-// overloadDecl contains all of the relevant information regarding a specific function overload.
-type overloadDecl struct {
- id string
- argTypes []*Type
- resultType *Type
- memberFunction bool
-
- // binding options, optional but encouraged.
- unaryOp functions.UnaryOp
- binaryOp functions.BinaryOp
- functionOp functions.FunctionOp
-
- // behavioral options, uncommon
- nonStrict bool
- operandTrait int
-}
-
-func (o *overloadDecl) hasBinding() bool {
- return o.unaryOp != nil || o.binaryOp != nil || o.functionOp != nil
-}
-
-// guardedUnaryOp creates an invocation guard around the provided unary operator, if one is defined.
-func (o *overloadDecl) guardedUnaryOp(funcName string) functions.UnaryOp {
- if o.unaryOp == nil {
- return nil
- }
- return func(arg ref.Val) ref.Val {
- if !o.matchesRuntimeUnarySignature(arg) {
- return noSuchOverload(funcName, arg)
- }
- return o.unaryOp(arg)
- }
-}
-
-// guardedBinaryOp creates an invocation guard around the provided binary operator, if one is defined.
-func (o *overloadDecl) guardedBinaryOp(funcName string) functions.BinaryOp {
- if o.binaryOp == nil {
- return nil
- }
- return func(arg1, arg2 ref.Val) ref.Val {
- if !o.matchesRuntimeBinarySignature(arg1, arg2) {
- return noSuchOverload(funcName, arg1, arg2)
- }
- return o.binaryOp(arg1, arg2)
- }
-}
-
-// guardedFunctionOp creates an invocation guard around the provided variadic function binding, if one is provided.
-func (o *overloadDecl) guardedFunctionOp(funcName string) functions.FunctionOp {
- if o.functionOp == nil {
- return nil
- }
- return func(args ...ref.Val) ref.Val {
- if !o.matchesRuntimeSignature(args...) {
- return noSuchOverload(funcName, args...)
- }
- return o.functionOp(args...)
- }
-}
-
-// matchesRuntimeUnarySignature indicates whether the argument type is runtime assiganble to the overload's expected argument.
-func (o *overloadDecl) matchesRuntimeUnarySignature(arg ref.Val) bool {
- if o.nonStrict && types.IsUnknownOrError(arg) {
- return true
- }
- return o.argTypes[0].IsAssignableRuntimeType(arg) && (o.operandTrait == 0 || arg.Type().HasTrait(o.operandTrait))
-}
-
-// matchesRuntimeBinarySignature indicates whether the argument types are runtime assiganble to the overload's expected arguments.
-func (o *overloadDecl) matchesRuntimeBinarySignature(arg1, arg2 ref.Val) bool {
- if o.nonStrict {
- if types.IsUnknownOrError(arg1) {
- return types.IsUnknownOrError(arg2) || o.argTypes[1].IsAssignableRuntimeType(arg2)
- }
- } else if !o.argTypes[1].IsAssignableRuntimeType(arg2) {
- return false
- }
- return o.argTypes[0].IsAssignableRuntimeType(arg1) && (o.operandTrait == 0 || arg1.Type().HasTrait(o.operandTrait))
-}
-
-// matchesRuntimeSignature indicates whether the argument types are runtime assiganble to the overload's expected arguments.
-func (o *overloadDecl) matchesRuntimeSignature(args ...ref.Val) bool {
- if len(args) != len(o.argTypes) {
- return false
- }
- if len(args) == 0 {
- return true
- }
- allArgsMatch := true
- for i, arg := range args {
- if o.nonStrict && types.IsUnknownOrError(arg) {
- continue
- }
- allArgsMatch = allArgsMatch && o.argTypes[i].IsAssignableRuntimeType(arg)
- }
-
- arg := args[0]
- return allArgsMatch && (o.operandTrait == 0 || (o.nonStrict && types.IsUnknownOrError(arg)) || arg.Type().HasTrait(o.operandTrait))
-}
-
-// signatureEquals indicates whether one overload has an identical signature to another overload.
-//
-// Providing a duplicate signature is not an issue, but an overloapping signature is problematic.
-func (o *overloadDecl) signatureEquals(other *overloadDecl) bool {
- if o.id != other.id || o.memberFunction != other.memberFunction || len(o.argTypes) != len(other.argTypes) {
- return false
- }
- for i, at := range o.argTypes {
- oat := other.argTypes[i]
- if !at.equals(oat) {
- return false
- }
- }
- return o.resultType.equals(other.resultType)
-}
-
-// signatureOverlaps indicates whether one overload has an overlapping signature with another overload.
-//
-// The 'other' overload must first be checked for equality before determining whether it overlaps in order to be completely accurate.
-func (o *overloadDecl) signatureOverlaps(other *overloadDecl) bool {
- if o.memberFunction != other.memberFunction || len(o.argTypes) != len(other.argTypes) {
- return false
- }
- argsOverlap := true
- for i, argType := range o.argTypes {
- otherArgType := other.argTypes[i]
- argsOverlap = argsOverlap &&
- (argType.IsAssignableType(otherArgType) ||
- otherArgType.IsAssignableType(argType))
- }
- return argsOverlap
-}
-
-func newOverload(overloadID string, memberFunction bool, args []*Type, resultType *Type, opts ...OverloadOpt) FunctionOpt {
- return func(f *functionDecl) (*functionDecl, error) {
- overload := &overloadDecl{
- id: overloadID,
- argTypes: args,
- resultType: resultType,
- memberFunction: memberFunction,
- }
- var err error
- for _, opt := range opts {
- overload, err = opt(overload)
- if err != nil {
- return nil, err
- }
- }
- err = f.addOverload(overload)
- if err != nil {
- return nil, err
- }
- return f, nil
- }
-}
-
-func maybeWrapper(t *Type, pbType *exprpb.Type) *exprpb.Type {
- if t.IsAssignableType(NullType) {
- return decls.NewWrapperType(pbType)
- }
- return pbType
+ return decls.OverloadOperandTrait(trait)
}
// TypeToExprType converts a CEL-native type representation to a protobuf CEL Type representation.
func TypeToExprType(t *Type) (*exprpb.Type, error) {
- switch t.kind {
- case AnyKind:
- return decls.Any, nil
- case BoolKind:
- return maybeWrapper(t, decls.Bool), nil
- case BytesKind:
- return maybeWrapper(t, decls.Bytes), nil
- case DoubleKind:
- return maybeWrapper(t, decls.Double), nil
- case DurationKind:
- return decls.Duration, nil
- case DynKind:
- return decls.Dyn, nil
- case IntKind:
- return maybeWrapper(t, decls.Int), nil
- case ListKind:
- et, err := TypeToExprType(t.parameters[0])
- if err != nil {
- return nil, err
- }
- return decls.NewListType(et), nil
- case MapKind:
- kt, err := TypeToExprType(t.parameters[0])
- if err != nil {
- return nil, err
- }
- vt, err := TypeToExprType(t.parameters[1])
- if err != nil {
- return nil, err
- }
- return decls.NewMapType(kt, vt), nil
- case NullTypeKind:
- return decls.Null, nil
- case OpaqueKind:
- params := make([]*exprpb.Type, len(t.parameters))
- for i, p := range t.parameters {
- pt, err := TypeToExprType(p)
- if err != nil {
- return nil, err
- }
- params[i] = pt
- }
- return decls.NewAbstractType(t.runtimeType.TypeName(), params...), nil
- case StringKind:
- return maybeWrapper(t, decls.String), nil
- case StructKind:
- switch t.runtimeType.TypeName() {
- case "google.protobuf.Any":
- return decls.Any, nil
- case "google.protobuf.Duration":
- return decls.Duration, nil
- case "google.protobuf.Timestamp":
- return decls.Timestamp, nil
- case "google.protobuf.Value":
- return decls.Dyn, nil
- case "google.protobuf.ListValue":
- return decls.NewListType(decls.Dyn), nil
- case "google.protobuf.Struct":
- return decls.NewMapType(decls.String, decls.Dyn), nil
- case "google.protobuf.BoolValue":
- return decls.NewWrapperType(decls.Bool), nil
- case "google.protobuf.BytesValue":
- return decls.NewWrapperType(decls.Bytes), nil
- case "google.protobuf.DoubleValue", "google.protobuf.FloatValue":
- return decls.NewWrapperType(decls.Double), nil
- case "google.protobuf.Int32Value", "google.protobuf.Int64Value":
- return decls.NewWrapperType(decls.Int), nil
- case "google.protobuf.StringValue":
- return decls.NewWrapperType(decls.String), nil
- case "google.protobuf.UInt32Value", "google.protobuf.UInt64Value":
- return decls.NewWrapperType(decls.Uint), nil
- default:
- return decls.NewObjectType(t.runtimeType.TypeName()), nil
- }
- case TimestampKind:
- return decls.Timestamp, nil
- case TypeParamKind:
- return decls.NewTypeParamType(t.runtimeType.TypeName()), nil
- case TypeKind:
- return decls.NewTypeType(decls.Dyn), nil
- case UintKind:
- return maybeWrapper(t, decls.Uint), nil
- }
- return nil, fmt.Errorf("missing type conversion to proto: %v", t)
+ return types.TypeToExprType(t)
}
// ExprTypeToType converts a protobuf CEL type representation to a CEL-native type representation.
func ExprTypeToType(t *exprpb.Type) (*Type, error) {
- switch t.GetTypeKind().(type) {
- case *exprpb.Type_Dyn:
- return DynType, nil
- case *exprpb.Type_AbstractType_:
- paramTypes := make([]*Type, len(t.GetAbstractType().GetParameterTypes()))
- for i, p := range t.GetAbstractType().GetParameterTypes() {
- pt, err := ExprTypeToType(p)
- if err != nil {
- return nil, err
- }
- paramTypes[i] = pt
- }
- return OpaqueType(t.GetAbstractType().GetName(), paramTypes...), nil
- case *exprpb.Type_ListType_:
- et, err := ExprTypeToType(t.GetListType().GetElemType())
- if err != nil {
- return nil, err
- }
- return ListType(et), nil
- case *exprpb.Type_MapType_:
- kt, err := ExprTypeToType(t.GetMapType().GetKeyType())
- if err != nil {
- return nil, err
- }
- vt, err := ExprTypeToType(t.GetMapType().GetValueType())
- if err != nil {
- return nil, err
- }
- return MapType(kt, vt), nil
- case *exprpb.Type_MessageType:
- switch t.GetMessageType() {
- case "google.protobuf.Any":
- return AnyType, nil
- case "google.protobuf.Duration":
- return DurationType, nil
- case "google.protobuf.Timestamp":
- return TimestampType, nil
- case "google.protobuf.Value":
- return DynType, nil
- case "google.protobuf.ListValue":
- return ListType(DynType), nil
- case "google.protobuf.Struct":
- return MapType(StringType, DynType), nil
- case "google.protobuf.BoolValue":
- return NullableType(BoolType), nil
- case "google.protobuf.BytesValue":
- return NullableType(BytesType), nil
- case "google.protobuf.DoubleValue", "google.protobuf.FloatValue":
- return NullableType(DoubleType), nil
- case "google.protobuf.Int32Value", "google.protobuf.Int64Value":
- return NullableType(IntType), nil
- case "google.protobuf.StringValue":
- return NullableType(StringType), nil
- case "google.protobuf.UInt32Value", "google.protobuf.UInt64Value":
- return NullableType(UintType), nil
- default:
- return ObjectType(t.GetMessageType()), nil
- }
- case *exprpb.Type_Null:
- return NullType, nil
- case *exprpb.Type_Primitive:
- switch t.GetPrimitive() {
- case exprpb.Type_BOOL:
- return BoolType, nil
- case exprpb.Type_BYTES:
- return BytesType, nil
- case exprpb.Type_DOUBLE:
- return DoubleType, nil
- case exprpb.Type_INT64:
- return IntType, nil
- case exprpb.Type_STRING:
- return StringType, nil
- case exprpb.Type_UINT64:
- return UintType, nil
- default:
- return nil, fmt.Errorf("unsupported primitive type: %v", t)
- }
- case *exprpb.Type_TypeParam:
- return TypeParamType(t.GetTypeParam()), nil
- case *exprpb.Type_Type:
- return TypeType, nil
- case *exprpb.Type_WellKnown:
- switch t.GetWellKnown() {
- case exprpb.Type_ANY:
- return AnyType, nil
- case exprpb.Type_DURATION:
- return DurationType, nil
- case exprpb.Type_TIMESTAMP:
- return TimestampType, nil
- default:
- return nil, fmt.Errorf("unsupported well-known type: %v", t)
- }
- case *exprpb.Type_Wrapper:
- t, err := ExprTypeToType(&exprpb.Type{TypeKind: &exprpb.Type_Primitive{Primitive: t.GetWrapper()}})
- if err != nil {
- return nil, err
- }
- return NullableType(t), nil
- default:
- return nil, fmt.Errorf("unsupported type: %v", t)
- }
+ return types.ExprTypeToType(t)
}
// ExprDeclToDeclaration converts a protobuf CEL declaration to a CEL-native declaration, either a Variable or Function.
@@ -1131,77 +319,77 @@ func ExprDeclToDeclaration(d *exprpb.Decl) (EnvOption, error) {
for i, o := range overloads {
args := make([]*Type, len(o.GetParams()))
for j, p := range o.GetParams() {
- a, err := ExprTypeToType(p)
+ a, err := types.ExprTypeToType(p)
if err != nil {
return nil, err
}
args[j] = a
}
- res, err := ExprTypeToType(o.GetResultType())
+ res, err := types.ExprTypeToType(o.GetResultType())
if err != nil {
return nil, err
}
- opts[i] = Overload(o.GetOverloadId(), args, res)
+ if o.IsInstanceFunction {
+ opts[i] = decls.MemberOverload(o.GetOverloadId(), args, res)
+ } else {
+ opts[i] = decls.Overload(o.GetOverloadId(), args, res)
+ }
}
return Function(d.GetName(), opts...), nil
case *exprpb.Decl_Ident:
- t, err := ExprTypeToType(d.GetIdent().GetType())
+ t, err := types.ExprTypeToType(d.GetIdent().GetType())
if err != nil {
return nil, err
}
- return Variable(d.GetName(), t), nil
- default:
- return nil, fmt.Errorf("unsupported decl: %v", d)
- }
-
-}
-
-func functionDeclToExprDecl(f *functionDecl) (*exprpb.Decl, error) {
- overloads := make([]*exprpb.Decl_FunctionDecl_Overload, len(f.overloads))
- i := 0
- for _, o := range f.overloads {
- paramNames := map[string]struct{}{}
- argTypes := make([]*exprpb.Type, len(o.argTypes))
- for j, a := range o.argTypes {
- collectParamNames(paramNames, a)
- at, err := TypeToExprType(a)
- if err != nil {
- return nil, err
- }
- argTypes[j] = at
+ if d.GetIdent().GetValue() == nil {
+ return Variable(d.GetName(), t), nil
}
- collectParamNames(paramNames, o.resultType)
- resultType, err := TypeToExprType(o.resultType)
+ val, err := ast.ConstantToVal(d.GetIdent().GetValue())
if err != nil {
return nil, err
}
- if len(paramNames) == 0 {
- if o.memberFunction {
- overloads[i] = decls.NewInstanceOverload(o.id, argTypes, resultType)
- } else {
- overloads[i] = decls.NewOverload(o.id, argTypes, resultType)
- }
- } else {
- params := []string{}
- for pn := range paramNames {
- params = append(params, pn)
- }
- if o.memberFunction {
- overloads[i] = decls.NewParameterizedInstanceOverload(o.id, argTypes, resultType, params)
- } else {
- overloads[i] = decls.NewParameterizedOverload(o.id, argTypes, resultType, params)
- }
- }
- i++
+ return Constant(d.GetName(), t, val), nil
+ default:
+ return nil, fmt.Errorf("unsupported decl: %v", d)
}
- return decls.NewFunction(f.name, overloads...), nil
}
-func collectParamNames(paramNames map[string]struct{}, arg *Type) {
- if arg.kind == TypeParamKind {
- paramNames[arg.runtimeType.TypeName()] = struct{}{}
- }
- for _, param := range arg.parameters {
- collectParamNames(paramNames, param)
+func typeValueToKind(tv ref.Type) (Kind, error) {
+ switch tv {
+ case types.BoolType:
+ return BoolKind, nil
+ case types.DoubleType:
+ return DoubleKind, nil
+ case types.IntType:
+ return IntKind, nil
+ case types.UintType:
+ return UintKind, nil
+ case types.ListType:
+ return ListKind, nil
+ case types.MapType:
+ return MapKind, nil
+ case types.StringType:
+ return StringKind, nil
+ case types.BytesType:
+ return BytesKind, nil
+ case types.DurationType:
+ return DurationKind, nil
+ case types.TimestampType:
+ return TimestampKind, nil
+ case types.NullType:
+ return NullTypeKind, nil
+ case types.TypeType:
+ return TypeKind, nil
+ default:
+ switch tv.TypeName() {
+ case "dyn":
+ return DynKind, nil
+ case "google.protobuf.Any":
+ return AnyKind, nil
+ case "optional":
+ return OpaqueKind, nil
+ default:
+ return 0, fmt.Errorf("no known conversion for type of %s", tv.TypeName())
+ }
}
}
diff --git a/vendor/github.com/google/cel-go/cel/env.go b/vendor/github.com/google/cel-go/cel/env.go
index 1a0b11ec7..5cbb86a75 100644
--- a/vendor/github.com/google/cel-go/cel/env.go
+++ b/vendor/github.com/google/cel-go/cel/env.go
@@ -16,13 +16,14 @@ package cel
import (
"errors"
- "fmt"
"sync"
"github.com/google/cel-go/checker"
- "github.com/google/cel-go/checker/decls"
+ chkdecls "github.com/google/cel-go/checker/decls"
"github.com/google/cel-go/common"
+ celast "github.com/google/cel-go/common/ast"
"github.com/google/cel-go/common/containers"
+ "github.com/google/cel-go/common/decls"
"github.com/google/cel-go/common/types"
"github.com/google/cel-go/common/types/ref"
"github.com/google/cel-go/interpreter"
@@ -40,8 +41,8 @@ type Ast struct {
expr *exprpb.Expr
info *exprpb.SourceInfo
source Source
- refMap map[int64]*exprpb.Reference
- typeMap map[int64]*exprpb.Type
+ refMap map[int64]*celast.ReferenceInfo
+ typeMap map[int64]*types.Type
}
// Expr returns the proto serializable instance of the parsed/checked expression.
@@ -60,21 +61,26 @@ func (ast *Ast) SourceInfo() *exprpb.SourceInfo {
}
// ResultType returns the output type of the expression if the Ast has been type-checked, else
-// returns decls.Dyn as the parse step cannot infer the type.
+// returns chkdecls.Dyn as the parse step cannot infer the type.
//
// Deprecated: use OutputType
func (ast *Ast) ResultType() *exprpb.Type {
if !ast.IsChecked() {
- return decls.Dyn
+ return chkdecls.Dyn
}
- return ast.typeMap[ast.expr.GetId()]
+ out := ast.OutputType()
+ t, err := TypeToExprType(out)
+ if err != nil {
+ return chkdecls.Dyn
+ }
+ return t
}
// OutputType returns the output type of the expression if the Ast has been type-checked, else
// returns cel.DynType as the parse step cannot infer types.
func (ast *Ast) OutputType() *Type {
- t, err := ExprTypeToType(ast.ResultType())
- if err != nil {
+ t, found := ast.typeMap[ast.expr.GetId()]
+ if !found {
return DynType
}
return t
@@ -87,32 +93,43 @@ func (ast *Ast) Source() Source {
}
// FormatType converts a type message into a string representation.
+//
+// Deprecated: prefer FormatCELType
func FormatType(t *exprpb.Type) string {
return checker.FormatCheckedType(t)
}
+// FormatCELType formats a cel.Type value to a string representation.
+//
+// The type formatting is identical to FormatType.
+func FormatCELType(t *Type) string {
+ return checker.FormatCELType(t)
+}
+
// Env encapsulates the context necessary to perform parsing, type checking, or generation of
// evaluable programs for different expressions.
type Env struct {
Container *containers.Container
- functions map[string]*functionDecl
- declarations []*exprpb.Decl
+ variables []*decls.VariableDecl
+ functions map[string]*decls.FunctionDecl
macros []parser.Macro
- adapter ref.TypeAdapter
- provider ref.TypeProvider
+ adapter types.Adapter
+ provider types.Provider
features map[int]bool
appliedFeatures map[int]bool
libraries map[string]bool
+ validators []ASTValidator
// Internal parser representation
prsr *parser.Parser
prsrOpts []parser.Option
// Internal checker representation
- chk *checker.Env
- chkErr error
- chkOnce sync.Once
- chkOpts []checker.Option
+ chkMutex sync.Mutex
+ chk *checker.Env
+ chkErr error
+ chkOnce sync.Once
+ chkOpts []checker.Option
// Program options tied to the environment
progOpts []ProgramOption
@@ -153,8 +170,8 @@ func NewCustomEnv(opts ...EnvOption) (*Env, error) {
return nil, err
}
return (&Env{
- declarations: []*exprpb.Decl{},
- functions: map[string]*functionDecl{},
+ variables: []*decls.VariableDecl{},
+ functions: map[string]*decls.FunctionDecl{},
macros: []parser.Macro{},
Container: containers.DefaultContainer,
adapter: registry,
@@ -162,14 +179,19 @@ func NewCustomEnv(opts ...EnvOption) (*Env, error) {
features: map[int]bool{},
appliedFeatures: map[int]bool{},
libraries: map[string]bool{},
+ validators: []ASTValidator{},
progOpts: []ProgramOption{},
}).configure(opts)
}
// Check performs type-checking on the input Ast and yields a checked Ast and/or set of Issues.
+// If any `ASTValidators` are configured on the environment, they will be applied after a valid
+// type-check result. If any issues are detected, the validators will provide them on the
+// output Issues object.
//
-// Checking has failed if the returned Issues value and its Issues.Err() value are non-nil.
-// Issues should be inspected if they are non-nil, but may not represent a fatal error.
+// Either checking or validation has failed if the returned Issues value and its Issues.Err()
+// value are non-nil. Issues should be inspected if they are non-nil, but may not represent a
+// fatal error.
//
// It is possible to have both non-nil Ast and Issues values returned from this call: however,
// the mere presence of an Ast does not imply that it is valid for use.
@@ -178,25 +200,42 @@ func (e *Env) Check(ast *Ast) (*Ast, *Issues) {
pe, _ := AstToParsedExpr(ast)
// Construct the internal checker env, erroring if there is an issue adding the declarations.
- err := e.initChecker()
+ chk, err := e.initChecker()
if err != nil {
errs := common.NewErrors(ast.Source())
- errs.ReportError(common.NoLocation, e.chkErr.Error())
- return nil, NewIssues(errs)
+ errs.ReportError(common.NoLocation, err.Error())
+ return nil, NewIssuesWithSourceInfo(errs, ast.SourceInfo())
}
- res, errs := checker.Check(pe, ast.Source(), e.chk)
+ res, errs := checker.Check(pe, ast.Source(), chk)
if len(errs.GetErrors()) > 0 {
- return nil, NewIssues(errs)
+ return nil, NewIssuesWithSourceInfo(errs, ast.SourceInfo())
}
// Manually create the Ast to ensure that the Ast source information (which may be more
// detailed than the information provided by Check), is returned to the caller.
- return &Ast{
+ ast = &Ast{
source: ast.Source(),
- expr: res.GetExpr(),
- info: res.GetSourceInfo(),
- refMap: res.GetReferenceMap(),
- typeMap: res.GetTypeMap()}, nil
+ expr: res.Expr,
+ info: res.SourceInfo,
+ refMap: res.ReferenceMap,
+ typeMap: res.TypeMap}
+
+ // Generate a validator configuration from the set of configured validators.
+ vConfig := newValidatorConfig()
+ for _, v := range e.validators {
+ if cv, ok := v.(ASTValidatorConfigurer); ok {
+ cv.Configure(vConfig)
+ }
+ }
+ // Apply additional validators on the type-checked result.
+ iss := NewIssuesWithSourceInfo(errs, ast.SourceInfo())
+ for _, v := range e.validators {
+ v.Validate(e, vConfig, res, iss)
+ }
+ if iss.Err() != nil {
+ return nil, iss
+ }
+ return ast, nil
}
// Compile combines the Parse and Check phases CEL program compilation to produce an Ast and
@@ -239,8 +278,9 @@ func (e *Env) CompileSource(src Source) (*Ast, *Issues) {
// TypeProvider are immutable, or that their underlying implementations are based on the
// ref.TypeRegistry which provides a Copy method which will be invoked by this method.
func (e *Env) Extend(opts ...EnvOption) (*Env, error) {
- if e.chkErr != nil {
- return nil, e.chkErr
+ chk, chkErr := e.getCheckerOrError()
+ if chkErr != nil {
+ return nil, chkErr
}
prsrOptsCopy := make([]parser.Option, len(e.prsrOpts))
@@ -253,16 +293,16 @@ func (e *Env) Extend(opts ...EnvOption) (*Env, error) {
copy(chkOptsCopy, e.chkOpts)
// Copy the declarations if needed.
- decsCopy := []*exprpb.Decl{}
- if e.chk != nil {
+ varsCopy := []*decls.VariableDecl{}
+ if chk != nil {
// If the type-checker has already been instantiated, then the e.declarations have been
- // valdiated within the chk instance.
- chkOptsCopy = append(chkOptsCopy, checker.ValidatedDeclarations(e.chk))
+ // validated within the chk instance.
+ chkOptsCopy = append(chkOptsCopy, checker.ValidatedDeclarations(chk))
} else {
// If the type-checker has not been instantiated, ensure the unvalidated declarations are
// provided to the extended Env instance.
- decsCopy = make([]*exprpb.Decl, len(e.declarations))
- copy(decsCopy, e.declarations)
+ varsCopy = make([]*decls.VariableDecl, len(e.variables))
+ copy(varsCopy, e.variables)
}
// Copy macros and program options
@@ -274,8 +314,8 @@ func (e *Env) Extend(opts ...EnvOption) (*Env, error) {
// Copy the adapter / provider if they appear to be mutable.
adapter := e.adapter
provider := e.provider
- adapterReg, isAdapterReg := e.adapter.(ref.TypeRegistry)
- providerReg, isProviderReg := e.provider.(ref.TypeRegistry)
+ adapterReg, isAdapterReg := e.adapter.(*types.Registry)
+ providerReg, isProviderReg := e.provider.(*types.Registry)
// In most cases the provider and adapter will be a ref.TypeRegistry;
// however, in the rare cases where they are not, they are assumed to
// be immutable. Since it is possible to set the TypeProvider separately
@@ -306,7 +346,7 @@ func (e *Env) Extend(opts ...EnvOption) (*Env, error) {
for k, v := range e.appliedFeatures {
appliedFeaturesCopy[k] = v
}
- funcsCopy := make(map[string]*functionDecl, len(e.functions))
+ funcsCopy := make(map[string]*decls.FunctionDecl, len(e.functions))
for k, v := range e.functions {
funcsCopy[k] = v
}
@@ -314,10 +354,12 @@ func (e *Env) Extend(opts ...EnvOption) (*Env, error) {
for k, v := range e.libraries {
libsCopy[k] = v
}
+ validatorsCopy := make([]ASTValidator, len(e.validators))
+ copy(validatorsCopy, e.validators)
ext := &Env{
Container: e.Container,
- declarations: decsCopy,
+ variables: varsCopy,
functions: funcsCopy,
macros: macsCopy,
progOpts: progOptsCopy,
@@ -325,6 +367,7 @@ func (e *Env) Extend(opts ...EnvOption) (*Env, error) {
features: featuresCopy,
appliedFeatures: appliedFeaturesCopy,
libraries: libsCopy,
+ validators: validatorsCopy,
provider: provider,
chkOpts: chkOptsCopy,
prsrOpts: prsrOptsCopy,
@@ -345,6 +388,16 @@ func (e *Env) HasLibrary(libName string) bool {
return exists && configured
}
+// HasValidator returns whether a specific ASTValidator has been configured in the environment.
+func (e *Env) HasValidator(name string) bool {
+ for _, v := range e.validators {
+ if v.Name() == name {
+ return true
+ }
+ }
+ return false
+}
+
// Parse parses the input expression value `txt` to a Ast and/or a set of Issues.
//
// This form of Parse creates a Source value for the input `txt` and forwards to the
@@ -386,36 +439,64 @@ func (e *Env) Program(ast *Ast, opts ...ProgramOption) (Program, error) {
return newProgram(e, ast, optSet)
}
+// CELTypeAdapter returns the `types.Adapter` configured for the environment.
+func (e *Env) CELTypeAdapter() types.Adapter {
+ return e.adapter
+}
+
+// CELTypeProvider returns the `types.Provider` configured for the environment.
+func (e *Env) CELTypeProvider() types.Provider {
+ return e.provider
+}
+
// TypeAdapter returns the `ref.TypeAdapter` configured for the environment.
+//
+// Deprecated: use CELTypeAdapter()
func (e *Env) TypeAdapter() ref.TypeAdapter {
return e.adapter
}
// TypeProvider returns the `ref.TypeProvider` configured for the environment.
+//
+// Deprecated: use CELTypeProvider()
func (e *Env) TypeProvider() ref.TypeProvider {
- return e.provider
+ if legacyProvider, ok := e.provider.(ref.TypeProvider); ok {
+ return legacyProvider
+ }
+ return &interopLegacyTypeProvider{Provider: e.provider}
}
-// UnknownVars returns an interpreter.PartialActivation which marks all variables
-// declared in the Env as unknown AttributePattern values.
+// UnknownVars returns an interpreter.PartialActivation which marks all variables declared in the
+// Env as unknown AttributePattern values.
//
-// Note, the UnknownVars will behave the same as an interpreter.EmptyActivation
-// unless the PartialAttributes option is provided as a ProgramOption.
+// Note, the UnknownVars will behave the same as an interpreter.EmptyActivation unless the
+// PartialAttributes option is provided as a ProgramOption.
func (e *Env) UnknownVars() interpreter.PartialActivation {
- var unknownPatterns []*interpreter.AttributePattern
- for _, d := range e.declarations {
- switch d.GetDeclKind().(type) {
- case *exprpb.Decl_Ident:
- unknownPatterns = append(unknownPatterns,
- interpreter.NewAttributePattern(d.GetName()))
- }
- }
- part, _ := PartialVars(
- interpreter.EmptyActivation(),
- unknownPatterns...)
+ act := interpreter.EmptyActivation()
+ part, _ := PartialVars(act, e.computeUnknownVars(act)...)
return part
}
+// PartialVars returns an interpreter.PartialActivation where all variables not in the input variable
+// set, but which have been configured in the environment, are marked as unknown.
+//
+// The `vars` value may either be an interpreter.Activation or any valid input to the
+// interpreter.NewActivation call.
+//
+// Note, this is equivalent to calling cel.PartialVars and manually configuring the set of unknown
+// variables. For more advanced use cases of partial state where portions of an object graph, rather
+// than top-level variables, are missing the PartialVars() method may be a more suitable choice.
+//
+// Note, the PartialVars will behave the same as an interpreter.EmptyActivation unless the
+// PartialAttributes option is provided as a ProgramOption.
+func (e *Env) PartialVars(vars any) (interpreter.PartialActivation, error) {
+ act, err := interpreter.NewActivation(vars)
+ if err != nil {
+ return nil, err
+ }
+ return PartialVars(act, e.computeUnknownVars(act)...)
+}
+
// ResidualAst takes an Ast and its EvalDetails to produce a new Ast which only contains the
// attribute references which are unknown.
//
@@ -439,8 +520,8 @@ func (e *Env) UnknownVars() interpreter.PartialActivation {
// TODO: Consider adding an option to generate a Program.Residual to avoid round-tripping to an
// Ast format and then Program again.
func (e *Env) ResidualAst(a *Ast, details *EvalDetails) (*Ast, error) {
- pruned := interpreter.PruneAst(a.Expr(), details.State())
- expr, err := AstToString(ParsedExprToAst(&exprpb.ParsedExpr{Expr: pruned}))
+ pruned := interpreter.PruneAst(a.Expr(), a.SourceInfo().GetMacroCalls(), details.State())
+ expr, err := AstToString(ParsedExprToAst(pruned))
if err != nil {
return nil, err
}
@@ -460,12 +541,14 @@ func (e *Env) ResidualAst(a *Ast, details *EvalDetails) (*Ast, error) {
// EstimateCost estimates the cost of a type checked CEL expression using the length estimates of input data and
// extension functions provided by estimator.
-func (e *Env) EstimateCost(ast *Ast, estimator checker.CostEstimator) (checker.CostEstimate, error) {
- checked, err := AstToCheckedExpr(ast)
- if err != nil {
- return checker.CostEstimate{}, fmt.Errorf("EsimateCost could not inspect Ast: %v", err)
+func (e *Env) EstimateCost(ast *Ast, estimator checker.CostEstimator, opts ...checker.CostOption) (checker.CostEstimate, error) {
+ checked := &celast.CheckedAST{
+ Expr: ast.Expr(),
+ SourceInfo: ast.SourceInfo(),
+ TypeMap: ast.typeMap,
+ ReferenceMap: ast.refMap,
}
- return checker.Cost(checked, estimator), nil
+ return checker.Cost(checked, estimator, opts...)
}
// configure applies a series of EnvOptions to the current environment.
@@ -486,14 +569,6 @@ func (e *Env) configure(opts []EnvOption) (*Env, error) {
return nil, err
}
- // Initialize all of the functions configured within the environment.
- for _, fn := range e.functions {
- err = fn.init()
- if err != nil {
- return nil, err
- }
- }
-
// Configure the parser.
prsrOpts := []parser.Option{}
prsrOpts = append(prsrOpts, e.prsrOpts...)
@@ -502,6 +577,9 @@ func (e *Env) configure(opts []EnvOption) (*Env, error) {
if e.HasFeature(featureEnableMacroCallTracking) {
prsrOpts = append(prsrOpts, parser.PopulateMacroCalls(true))
}
+ if e.HasFeature(featureVariadicLogicalASTs) {
+ prsrOpts = append(prsrOpts, parser.EnableVariadicOperatorASTs(true))
+ }
e.prsr, err = parser.NewParser(prsrOpts...)
if err != nil {
return nil, err
@@ -509,7 +587,7 @@ func (e *Env) configure(opts []EnvOption) (*Env, error) {
// Ensure that the checker init happens eagerly rather than lazily.
if e.HasFeature(featureEagerlyValidateDeclarations) {
- err := e.initChecker()
+ _, err := e.initChecker()
if err != nil {
return nil, err
}
@@ -518,44 +596,55 @@ func (e *Env) configure(opts []EnvOption) (*Env, error) {
return e, nil
}
-func (e *Env) initChecker() error {
+func (e *Env) initChecker() (*checker.Env, error) {
e.chkOnce.Do(func() {
chkOpts := []checker.Option{}
chkOpts = append(chkOpts, e.chkOpts...)
chkOpts = append(chkOpts,
- checker.HomogeneousAggregateLiterals(
- e.HasFeature(featureDisableDynamicAggregateLiterals)),
checker.CrossTypeNumericComparisons(
e.HasFeature(featureCrossTypeNumericComparisons)))
ce, err := checker.NewEnv(e.Container, e.provider, chkOpts...)
if err != nil {
- e.chkErr = err
+ e.setCheckerOrError(nil, err)
return
}
// Add the statically configured declarations.
- err = ce.Add(e.declarations...)
+ err = ce.AddIdents(e.variables...)
if err != nil {
- e.chkErr = err
+ e.setCheckerOrError(nil, err)
return
}
// Add the function declarations which are derived from the FunctionDecl instances.
for _, fn := range e.functions {
- fnDecl, err := functionDeclToExprDecl(fn)
- if err != nil {
- e.chkErr = err
- return
+ if fn.IsDeclarationDisabled() {
+ continue
}
- err = ce.Add(fnDecl)
+ err = ce.AddFunctions(fn)
if err != nil {
- e.chkErr = err
+ e.setCheckerOrError(nil, err)
return
}
}
// Add function declarations here separately.
- e.chk = ce
+ e.setCheckerOrError(ce, nil)
})
- return e.chkErr
+ return e.getCheckerOrError()
+}
+
+// setCheckerOrError sets the checker.Env or error state in a concurrency-safe manner
+func (e *Env) setCheckerOrError(chk *checker.Env, chkErr error) {
+ e.chkMutex.Lock()
+ e.chk = chk
+ e.chkErr = chkErr
+ e.chkMutex.Unlock()
+}
+
+// getCheckerOrError gets the checker.Env or error state in a concurrency-safe manner
+func (e *Env) getCheckerOrError() (*checker.Env, error) {
+ e.chkMutex.Lock()
+ defer e.chkMutex.Unlock()
+ return e.chk, e.chkErr
}
// maybeApplyFeature determines whether the feature-guarded option is enabled, and if so applies
@@ -579,17 +668,43 @@ func (e *Env) maybeApplyFeature(feature int, option EnvOption) (*Env, error) {
return e, nil
}
+// computeUnknownVars determines a set of missing variables based on the input activation and the
+// environment's configured declaration set.
+func (e *Env) computeUnknownVars(vars interpreter.Activation) []*interpreter.AttributePattern {
+ var unknownPatterns []*interpreter.AttributePattern
+ for _, v := range e.variables {
+ varName := v.Name()
+ if _, found := vars.ResolveName(varName); found {
+ continue
+ }
+ unknownPatterns = append(unknownPatterns, interpreter.NewAttributePattern(varName))
+ }
+ return unknownPatterns
+}
+
+// Error type which references an expression id, a location within source, and a message.
+type Error = common.Error
+
// Issues defines methods for inspecting the error details of parse and check calls.
//
// Note: in the future, non-fatal warnings and notices may be inspectable via the Issues struct.
type Issues struct {
errs *common.Errors
+ info *exprpb.SourceInfo
}
// NewIssues returns an Issues struct from a common.Errors object.
func NewIssues(errs *common.Errors) *Issues {
+ return NewIssuesWithSourceInfo(errs, nil)
+}
+
+// NewIssuesWithSourceInfo returns an Issues struct from a common.Errors object with SourceInfo metatata
+// which can be used with the `ReportErrorAtID` method for additional error reports within the context
+// information that's inferred from an expression id.
+func NewIssuesWithSourceInfo(errs *common.Errors, info *exprpb.SourceInfo) *Issues {
return &Issues{
errs: errs,
+ info: info,
}
}
@@ -605,9 +720,9 @@ func (i *Issues) Err() error {
}
// Errors returns the collection of errors encountered in more granular detail.
-func (i *Issues) Errors() []common.Error {
+func (i *Issues) Errors() []*Error {
if i == nil {
- return []common.Error{}
+ return []*Error{}
}
return i.errs.GetErrors()
}
@@ -631,6 +746,37 @@ func (i *Issues) String() string {
return i.errs.ToDisplayString()
}
+// ReportErrorAtID reports an error message with an optional set of formatting arguments.
+//
+// The source metadata for the expression at `id`, if present, is attached to the error report.
+// To ensure that source metadata is attached to error reports, use NewIssuesWithSourceInfo.
+func (i *Issues) ReportErrorAtID(id int64, message string, args ...any) {
+ i.errs.ReportErrorAtID(id, locationByID(id, i.info), message, args...)
+}
+
+// locationByID returns a common.Location given an expression id.
+//
+// TODO: move this functionality into the native SourceInfo and an overhaul of the common.Source
+// as this implementation relies on the abstractions present in the protobuf SourceInfo object,
+// and is replicated in the checker.
+func locationByID(id int64, sourceInfo *exprpb.SourceInfo) common.Location {
+ positions := sourceInfo.GetPositions()
+ var line = 1
+ if offset, found := positions[id]; found {
+ col := int(offset)
+ for _, lineOffset := range sourceInfo.GetLineOffsets() {
+ if lineOffset < offset {
+ line++
+ col = int(offset - lineOffset)
+ } else {
+ break
+ }
+ }
+ return common.NewLocation(line, col)
+ }
+ return common.NoLocation
+}
+
// getStdEnv lazy initializes the CEL standard environment.
func getStdEnv() (*Env, error) {
stdEnvInit.Do(func() {
@@ -639,6 +785,90 @@ func getStdEnv() (*Env, error) {
return stdEnv, stdEnvErr
}
+// interopCELTypeProvider layers support for the types.Provider interface on top of a ref.TypeProvider.
+type interopCELTypeProvider struct {
+ ref.TypeProvider
+}
+
+// FindStructType returns a types.Type instance for the given fully-qualified typeName if one exists.
+//
+// This method proxies to the underyling ref.TypeProvider's FindType method and converts protobuf type
+// into a native type representation. If the conversion fails, the type is listed as not found.
+func (p *interopCELTypeProvider) FindStructType(typeName string) (*types.Type, bool) {
+ if et, found := p.FindType(typeName); found {
+ t, err := types.ExprTypeToType(et)
+ if err != nil {
+ return nil, false
+ }
+ return t, true
+ }
+ return nil, false
+}
+
+// FindStructFieldType returns a types.FieldType instance for the given fully-qualified typeName and field
+// name, if one exists.
+//
+// This method proxies to the underyling ref.TypeProvider's FindFieldType method and converts protobuf type
+// into a native type representation. If the conversion fails, the type is listed as not found.
+func (p *interopCELTypeProvider) FindStructFieldType(structType, fieldName string) (*types.FieldType, bool) {
+ if ft, found := p.FindFieldType(structType, fieldName); found {
+ t, err := types.ExprTypeToType(ft.Type)
+ if err != nil {
+ return nil, false
+ }
+ return &types.FieldType{
+ Type: t,
+ IsSet: ft.IsSet,
+ GetFrom: ft.GetFrom,
+ }, true
+ }
+ return nil, false
+}
+
+// interopLegacyTypeProvider layers support for the ref.TypeProvider interface on top of a types.Provider.
+type interopLegacyTypeProvider struct {
+ types.Provider
+}
+
+// FindType retruns the protobuf Type representation for the input type name if one exists.
+//
+// This method proxies to the underlying types.Provider FindStructType method and converts the types.Type
+// value to a protobuf Type representation.
+//
+// Failure to convert the type will result in the type not being found.
+func (p *interopLegacyTypeProvider) FindType(typeName string) (*exprpb.Type, bool) {
+ if t, found := p.FindStructType(typeName); found {
+ et, err := types.TypeToExprType(t)
+ if err != nil {
+ return nil, false
+ }
+ return et, true
+ }
+ return nil, false
+}
+
+// FindFieldType returns the protobuf-based FieldType representation for the input type name and field,
+// if one exists.
+//
+// This call proxies to the types.Provider FindStructFieldType method and converts the types.FIeldType
+// value to a protobuf-based ref.FieldType representation if found.
+//
+// Failure to convert the FieldType will result in the field not being found.
+func (p *interopLegacyTypeProvider) FindFieldType(structType, fieldName string) (*ref.FieldType, bool) {
+ if cft, found := p.FindStructFieldType(structType, fieldName); found {
+ et, err := types.TypeToExprType(cft.Type)
+ if err != nil {
+ return nil, false
+ }
+ return &ref.FieldType{
+ Type: et,
+ IsSet: cft.IsSet,
+ GetFrom: cft.GetFrom,
+ }, true
+ }
+ return nil, false
+}
+
var (
stdEnvInit sync.Once
stdEnv *Env
diff --git a/vendor/github.com/google/cel-go/cel/io.go b/vendor/github.com/google/cel-go/cel/io.go
index 93ded3cf1..80f63140e 100644
--- a/vendor/github.com/google/cel-go/cel/io.go
+++ b/vendor/github.com/google/cel-go/cel/io.go
@@ -22,6 +22,7 @@ import (
"google.golang.org/protobuf/proto"
"github.com/google/cel-go/common"
+ "github.com/google/cel-go/common/ast"
"github.com/google/cel-go/common/types"
"github.com/google/cel-go/common/types/ref"
"github.com/google/cel-go/common/types/traits"
@@ -33,7 +34,8 @@ import (
// CheckedExprToAst converts a checked expression proto message to an Ast.
func CheckedExprToAst(checkedExpr *exprpb.CheckedExpr) *Ast {
- return CheckedExprToAstWithSource(checkedExpr, nil)
+ checked, _ := CheckedExprToAstWithSource(checkedExpr, nil)
+ return checked
}
// CheckedExprToAstWithSource converts a checked expression proto message to an Ast,
@@ -44,29 +46,18 @@ func CheckedExprToAst(checkedExpr *exprpb.CheckedExpr) *Ast {
// through future calls.
//
// Prefer CheckedExprToAst if loading expressions from storage.
-func CheckedExprToAstWithSource(checkedExpr *exprpb.CheckedExpr, src Source) *Ast {
- refMap := checkedExpr.GetReferenceMap()
- if refMap == nil {
- refMap = map[int64]*exprpb.Reference{}
- }
- typeMap := checkedExpr.GetTypeMap()
- if typeMap == nil {
- typeMap = map[int64]*exprpb.Type{}
- }
- si := checkedExpr.GetSourceInfo()
- if si == nil {
- si = &exprpb.SourceInfo{}
- }
- if src == nil {
- src = common.NewInfoSource(si)
+func CheckedExprToAstWithSource(checkedExpr *exprpb.CheckedExpr, src Source) (*Ast, error) {
+ checkedAST, err := ast.CheckedExprToCheckedAST(checkedExpr)
+ if err != nil {
+ return nil, err
}
return &Ast{
- expr: checkedExpr.GetExpr(),
- info: si,
+ expr: checkedAST.Expr,
+ info: checkedAST.SourceInfo,
source: src,
- refMap: refMap,
- typeMap: typeMap,
- }
+ refMap: checkedAST.ReferenceMap,
+ typeMap: checkedAST.TypeMap,
+ }, nil
}
// AstToCheckedExpr converts an Ast to an protobuf CheckedExpr value.
@@ -76,12 +67,13 @@ func AstToCheckedExpr(a *Ast) (*exprpb.CheckedExpr, error) {
if !a.IsChecked() {
return nil, fmt.Errorf("cannot convert unchecked ast")
}
- return &exprpb.CheckedExpr{
- Expr: a.Expr(),
- SourceInfo: a.SourceInfo(),
+ cAst := &ast.CheckedAST{
+ Expr: a.expr,
+ SourceInfo: a.info,
ReferenceMap: a.refMap,
TypeMap: a.typeMap,
- }, nil
+ }
+ return ast.CheckedASTToCheckedExpr(cAst)
}
// ParsedExprToAst converts a parsed expression proto message to an Ast.
@@ -202,7 +194,7 @@ func RefValueToValue(res ref.Val) (*exprpb.Value, error) {
}
var (
- typeNameToTypeValue = map[string]*types.TypeValue{
+ typeNameToTypeValue = map[string]ref.Val{
"bool": types.BoolType,
"bytes": types.BytesType,
"double": types.DoubleType,
@@ -219,7 +211,7 @@ var (
)
// ValueToRefValue converts between exprpb.Value and ref.Val.
-func ValueToRefValue(adapter ref.TypeAdapter, v *exprpb.Value) (ref.Val, error) {
+func ValueToRefValue(adapter types.Adapter, v *exprpb.Value) (ref.Val, error) {
switch v.Kind.(type) {
case *exprpb.Value_NullValue:
return types.NullValue, nil
diff --git a/vendor/github.com/google/cel-go/cel/library.go b/vendor/github.com/google/cel-go/cel/library.go
index f04fda743..4d232085c 100644
--- a/vendor/github.com/google/cel-go/cel/library.go
+++ b/vendor/github.com/google/cel-go/cel/library.go
@@ -15,19 +15,32 @@
package cel
import (
+ "math"
"strconv"
"strings"
"time"
- "github.com/google/cel-go/checker"
"github.com/google/cel-go/common/operators"
"github.com/google/cel-go/common/overloads"
+ "github.com/google/cel-go/common/stdlib"
"github.com/google/cel-go/common/types"
"github.com/google/cel-go/common/types/ref"
"github.com/google/cel-go/common/types/traits"
"github.com/google/cel-go/interpreter"
- "github.com/google/cel-go/interpreter/functions"
"github.com/google/cel-go/parser"
+
+ exprpb "google.golang.org/genproto/googleapis/api/expr/v1alpha1"
+)
+
+const (
+ optMapMacro = "optMap"
+ optFlatMapMacro = "optFlatMap"
+ hasValueFunc = "hasValue"
+ optionalNoneFunc = "optional.none"
+ optionalOfFunc = "optional.of"
+ optionalOfNonZeroValueFunc = "optional.ofNonZeroValue"
+ valueFunc = "value"
+ unusedIterVar = "#unused"
)
// Library provides a collection of EnvOption and ProgramOption values used to configure a CEL
@@ -93,50 +106,222 @@ func (stdLibrary) LibraryName() string {
return "cel.lib.std"
}
-// EnvOptions returns options for the standard CEL function declarations and macros.
+// CompileOptions returns options for the standard CEL function declarations and macros.
func (stdLibrary) CompileOptions() []EnvOption {
return []EnvOption{
- Declarations(checker.StandardDeclarations()...),
+ func(e *Env) (*Env, error) {
+ var err error
+ for _, fn := range stdlib.Functions() {
+ existing, found := e.functions[fn.Name()]
+ if found {
+ fn, err = existing.Merge(fn)
+ if err != nil {
+ return nil, err
+ }
+ }
+ e.functions[fn.Name()] = fn
+ }
+ return e, nil
+ },
+ func(e *Env) (*Env, error) {
+ e.variables = append(e.variables, stdlib.Types()...)
+ return e, nil
+ },
Macros(StandardMacros...),
}
}
// ProgramOptions returns function implementations for the standard CEL functions.
func (stdLibrary) ProgramOptions() []ProgramOption {
- return []ProgramOption{
- Functions(functions.StandardOverloads()...),
+ return []ProgramOption{}
+}
+
+// OptionalTypes enable support for optional syntax and types in CEL.
+//
+// The optional value type makes it possible to express whether variables have
+// been provided, whether a result has been computed, and in the future whether
+// an object field path, map key value, or list index has a value.
+//
+// # Syntax Changes
+//
+// OptionalTypes are unlike other CEL extensions because they modify the CEL
+// syntax itself, notably through the use of a `?` preceding a field name or
+// index value.
+//
+// ## Field Selection
+//
+// The optional syntax in field selection is denoted as `obj.?field`. In other
+// words, if a field is set, return `optional.of(obj.field)“, else
+// `optional.none()`. The optional field selection is viral in the sense that
+// after the first optional selection all subsequent selections or indices
+// are treated as optional, i.e. the following expressions are equivalent:
+//
+// obj.?field.subfield
+// obj.?field.?subfield
+//
+// ## Indexing
+//
+// Similar to field selection, the optional syntax can be used in index
+// expressions on maps and lists:
+//
+// list[?0]
+// map[?key]
+//
+// ## Optional Field Setting
+//
+// When creating map or message literals, if a field may be optionally set
+// based on its presence, then placing a `?` before the field name or key
+// will ensure the type on the right-hand side must be optional(T) where T
+// is the type of the field or key-value.
+//
+// The following returns a map with the key expression set only if the
+// subfield is present, otherwise an empty map is created:
+//
+// {?key: obj.?field.subfield}
+//
+// ## Optional Element Setting
+//
+// When creating list literals, an element in the list may be optionally added
+// when the element expression is preceded by a `?`:
+//
+// [a, ?b, ?c] // return a list with either [a], [a, b], [a, b, c], or [a, c]
+//
+// # Optional.Of
+//
+// Create an optional(T) value of a given value with type T.
+//
+// optional.of(10)
+//
+// # Optional.OfNonZeroValue
+//
+// Create an optional(T) value of a given value with type T if it is not a
+// zero-value. A zero-value the default empty value for any given CEL type,
+// including empty protobuf message types. If the value is empty, the result
+// of this call will be optional.none().
+//
+// optional.ofNonZeroValue([1, 2, 3]) // optional(list(int))
+// optional.ofNonZeroValue([]) // optional.none()
+// optional.ofNonZeroValue(0) // optional.none()
+// optional.ofNonZeroValue("") // optional.none()
+//
+// # Optional.None
+//
+// Create an empty optional value.
+//
+// # HasValue
+//
+// Determine whether the optional contains a value.
+//
+// optional.of(b'hello').hasValue() // true
+// optional.ofNonZeroValue({}).hasValue() // false
+//
+// # Value
+//
+// Get the value contained by the optional. If the optional does not have a
+// value, the result will be a CEL error.
+//
+// optional.of(b'hello').value() // b'hello'
+// optional.ofNonZeroValue({}).value() // error
+//
+// # Or
+//
+// If the value on the left-hand side is optional.none(), the optional value
+// on the right hand side is returned. If the value on the left-hand set is
+// valued, then it is returned. This operation is short-circuiting and will
+// only evaluate as many links in the `or` chain as are needed to return a
+// non-empty optional value.
+//
+// obj.?field.or(m[?key])
+// l[?index].or(obj.?field.subfield).or(obj.?other)
+//
+// # OrValue
+//
+// Either return the value contained within the optional on the left-hand side
+// or return the alternative value on the right hand side.
+//
+// m[?key].orValue("none")
+//
+// # OptMap
+//
+// Apply a transformation to the optional's underlying value if it is not empty
+// and return an optional typed result based on the transformation. The
+// transformation expression type must return a type T which is wrapped into
+// an optional.
+//
+// msg.?elements.optMap(e, e.size()).orValue(0)
+//
+// # OptFlatMap
+//
+// Introduced in version: 1
+//
+// Apply a transformation to the optional's underlying value if it is not empty
+// and return the result. The transform expression must return an optional(T)
+// rather than type T. This can be useful when dealing with zero values and
+// conditionally generating an empty or non-empty result in ways which cannot
+// be expressed with `optMap`.
+//
+// msg.?elements.optFlatMap(e, e[?0]) // return the first element if present.
+func OptionalTypes(opts ...OptionalTypesOption) EnvOption {
+ lib := &optionalLib{version: math.MaxUint32}
+ for _, opt := range opts {
+ lib = opt(lib)
}
+ return Lib(lib)
+}
+
+type optionalLib struct {
+ version uint32
}
-type optionalLibrary struct{}
+// OptionalTypesOption is a functional interface for configuring the strings library.
+type OptionalTypesOption func(*optionalLib) *optionalLib
+
+// OptionalTypesVersion configures the version of the optional type library.
+//
+// The version limits which functions are available. Only functions introduced
+// below or equal to the given version included in the library. If this option
+// is not set, all functions are available.
+//
+// See the library documentation to determine which version a function was introduced.
+// If the documentation does not state which version a function was introduced, it can
+// be assumed to be introduced at version 0, when the library was first created.
+func OptionalTypesVersion(version uint32) OptionalTypesOption {
+ return func(lib *optionalLib) *optionalLib {
+ lib.version = version
+ return lib
+ }
+}
// LibraryName implements the SingletonLibrary interface method.
-func (optionalLibrary) LibraryName() string {
+func (lib *optionalLib) LibraryName() string {
return "cel.lib.optional"
}
// CompileOptions implements the Library interface method.
-func (optionalLibrary) CompileOptions() []EnvOption {
+func (lib *optionalLib) CompileOptions() []EnvOption {
paramTypeK := TypeParamType("K")
paramTypeV := TypeParamType("V")
optionalTypeV := OptionalType(paramTypeV)
listTypeV := ListType(paramTypeV)
mapTypeKV := MapType(paramTypeK, paramTypeV)
- return []EnvOption{
+ opts := []EnvOption{
// Enable the optional syntax in the parser.
enableOptionalSyntax(),
// Introduce the optional type.
Types(types.OptionalType),
+ // Configure the optMap and optFlatMap macros.
+ Macros(NewReceiverMacro(optMapMacro, 2, optMap)),
+
// Global and member functions for working with optional values.
- Function("optional.of",
+ Function(optionalOfFunc,
Overload("optional_of", []*Type{paramTypeV}, optionalTypeV,
UnaryBinding(func(value ref.Val) ref.Val {
return types.OptionalOf(value)
}))),
- Function("optional.ofNonZeroValue",
+ Function(optionalOfNonZeroValueFunc,
Overload("optional_ofNonZeroValue", []*Type{paramTypeV}, optionalTypeV,
UnaryBinding(func(value ref.Val) ref.Val {
v, isZeroer := value.(traits.Zeroer)
@@ -145,18 +330,18 @@ func (optionalLibrary) CompileOptions() []EnvOption {
}
return types.OptionalNone
}))),
- Function("optional.none",
+ Function(optionalNoneFunc,
Overload("optional_none", []*Type{}, optionalTypeV,
FunctionBinding(func(values ...ref.Val) ref.Val {
return types.OptionalNone
}))),
- Function("value",
+ Function(valueFunc,
MemberOverload("optional_value", []*Type{optionalTypeV}, paramTypeV,
UnaryBinding(func(value ref.Val) ref.Val {
opt := value.(*types.Optional)
return opt.GetValue()
}))),
- Function("hasValue",
+ Function(hasValueFunc,
MemberOverload("optional_hasValue", []*Type{optionalTypeV}, BoolType,
UnaryBinding(func(value ref.Val) ref.Val {
opt := value.(*types.Optional)
@@ -183,20 +368,78 @@ func (optionalLibrary) CompileOptions() []EnvOption {
Overload("map_optindex_optional_value", []*Type{mapTypeKV, paramTypeK}, optionalTypeV),
Overload("optional_map_optindex_optional_value", []*Type{OptionalType(mapTypeKV), paramTypeK}, optionalTypeV)),
- // Index overloads to accomodate using an optional value as the operand.
+ // Index overloads to accommodate using an optional value as the operand.
Function(operators.Index,
Overload("optional_list_index_int", []*Type{OptionalType(listTypeV), IntType}, optionalTypeV),
- Overload("optional_map_index_optional_value", []*Type{OptionalType(mapTypeKV), paramTypeK}, optionalTypeV)),
+ Overload("optional_map_index_value", []*Type{OptionalType(mapTypeKV), paramTypeK}, optionalTypeV)),
}
+ if lib.version >= 1 {
+ opts = append(opts, Macros(NewReceiverMacro(optFlatMapMacro, 2, optFlatMap)))
+ }
+ return opts
}
// ProgramOptions implements the Library interface method.
-func (optionalLibrary) ProgramOptions() []ProgramOption {
+func (lib *optionalLib) ProgramOptions() []ProgramOption {
return []ProgramOption{
CustomDecorator(decorateOptionalOr),
}
}
+func optMap(meh MacroExprHelper, target *exprpb.Expr, args []*exprpb.Expr) (*exprpb.Expr, *Error) {
+ varIdent := args[0]
+ varName := ""
+ switch varIdent.GetExprKind().(type) {
+ case *exprpb.Expr_IdentExpr:
+ varName = varIdent.GetIdentExpr().GetName()
+ default:
+ return nil, meh.NewError(varIdent.GetId(), "optMap() variable name must be a simple identifier")
+ }
+ mapExpr := args[1]
+ return meh.GlobalCall(
+ operators.Conditional,
+ meh.ReceiverCall(hasValueFunc, target),
+ meh.GlobalCall(optionalOfFunc,
+ meh.Fold(
+ unusedIterVar,
+ meh.NewList(),
+ varName,
+ meh.ReceiverCall(valueFunc, target),
+ meh.LiteralBool(false),
+ meh.Ident(varName),
+ mapExpr,
+ ),
+ ),
+ meh.GlobalCall(optionalNoneFunc),
+ ), nil
+}
+
+func optFlatMap(meh MacroExprHelper, target *exprpb.Expr, args []*exprpb.Expr) (*exprpb.Expr, *Error) {
+ varIdent := args[0]
+ varName := ""
+ switch varIdent.GetExprKind().(type) {
+ case *exprpb.Expr_IdentExpr:
+ varName = varIdent.GetIdentExpr().GetName()
+ default:
+ return nil, meh.NewError(varIdent.GetId(), "optFlatMap() variable name must be a simple identifier")
+ }
+ mapExpr := args[1]
+ return meh.GlobalCall(
+ operators.Conditional,
+ meh.ReceiverCall(hasValueFunc, target),
+ meh.Fold(
+ unusedIterVar,
+ meh.NewList(),
+ varName,
+ meh.ReceiverCall(valueFunc, target),
+ meh.LiteralBool(false),
+ meh.Ident(varName),
+ mapExpr,
+ ),
+ meh.GlobalCall(optionalNoneFunc),
+ ), nil
+}
+
func enableOptionalSyntax() EnvOption {
return func(e *Env) (*Env, error) {
e.prsrOpts = append(e.prsrOpts, parser.EnableOptionalSyntax(true))
@@ -311,28 +554,16 @@ var (
timeOverloadDeclarations = []EnvOption{
Function(overloads.TimeGetHours,
MemberOverload(overloads.DurationToHours, []*Type{DurationType}, IntType,
- UnaryBinding(func(dur ref.Val) ref.Val {
- d := dur.(types.Duration)
- return types.Int(d.Hours())
- }))),
+ UnaryBinding(types.DurationGetHours))),
Function(overloads.TimeGetMinutes,
MemberOverload(overloads.DurationToMinutes, []*Type{DurationType}, IntType,
- UnaryBinding(func(dur ref.Val) ref.Val {
- d := dur.(types.Duration)
- return types.Int(d.Minutes())
- }))),
+ UnaryBinding(types.DurationGetMinutes))),
Function(overloads.TimeGetSeconds,
MemberOverload(overloads.DurationToSeconds, []*Type{DurationType}, IntType,
- UnaryBinding(func(dur ref.Val) ref.Val {
- d := dur.(types.Duration)
- return types.Int(d.Seconds())
- }))),
+ UnaryBinding(types.DurationGetSeconds))),
Function(overloads.TimeGetMilliseconds,
MemberOverload(overloads.DurationToMilliseconds, []*Type{DurationType}, IntType,
- UnaryBinding(func(dur ref.Val) ref.Val {
- d := dur.(types.Duration)
- return types.Int(d.Milliseconds())
- }))),
+ UnaryBinding(types.DurationGetMilliseconds))),
Function(overloads.TimeGetFullYear,
MemberOverload(overloads.TimestampToYear, []*Type{TimestampType}, IntType,
UnaryBinding(func(ts ref.Val) ref.Val {
diff --git a/vendor/github.com/google/cel-go/cel/macro.go b/vendor/github.com/google/cel-go/cel/macro.go
index e48c5bf8e..1eb414c8b 100644
--- a/vendor/github.com/google/cel-go/cel/macro.go
+++ b/vendor/github.com/google/cel-go/cel/macro.go
@@ -15,7 +15,6 @@
package cel
import (
- "github.com/google/cel-go/common"
"github.com/google/cel-go/parser"
exprpb "google.golang.org/genproto/googleapis/api/expr/v1alpha1"
@@ -63,21 +62,21 @@ func NewReceiverVarArgMacro(function string, expander MacroExpander) Macro {
}
// HasMacroExpander expands the input call arguments into a presence test, e.g. has(.field)
-func HasMacroExpander(meh MacroExprHelper, target *exprpb.Expr, args []*exprpb.Expr) (*exprpb.Expr, *common.Error) {
+func HasMacroExpander(meh MacroExprHelper, target *exprpb.Expr, args []*exprpb.Expr) (*exprpb.Expr, *Error) {
return parser.MakeHas(meh, target, args)
}
// ExistsMacroExpander expands the input call arguments into a comprehension that returns true if any of the
// elements in the range match the predicate expressions:
// .exists(, )
-func ExistsMacroExpander(meh MacroExprHelper, target *exprpb.Expr, args []*exprpb.Expr) (*exprpb.Expr, *common.Error) {
+func ExistsMacroExpander(meh MacroExprHelper, target *exprpb.Expr, args []*exprpb.Expr) (*exprpb.Expr, *Error) {
return parser.MakeExists(meh, target, args)
}
// ExistsOneMacroExpander expands the input call arguments into a comprehension that returns true if exactly
// one of the elements in the range match the predicate expressions:
// .exists_one(, )
-func ExistsOneMacroExpander(meh MacroExprHelper, target *exprpb.Expr, args []*exprpb.Expr) (*exprpb.Expr, *common.Error) {
+func ExistsOneMacroExpander(meh MacroExprHelper, target *exprpb.Expr, args []*exprpb.Expr) (*exprpb.Expr, *Error) {
return parser.MakeExistsOne(meh, target, args)
}
@@ -91,14 +90,14 @@ func ExistsOneMacroExpander(meh MacroExprHelper, target *exprpb.Expr, args []*ex
//
// In the second form only iterVar values which return true when provided to the predicate expression
// are transformed.
-func MapMacroExpander(meh MacroExprHelper, target *exprpb.Expr, args []*exprpb.Expr) (*exprpb.Expr, *common.Error) {
+func MapMacroExpander(meh MacroExprHelper, target *exprpb.Expr, args []*exprpb.Expr) (*exprpb.Expr, *Error) {
return parser.MakeMap(meh, target, args)
}
// FilterMacroExpander expands the input call arguments into a comprehension which produces a list which contains
// only elements which match the provided predicate expression:
// .filter(, )
-func FilterMacroExpander(meh MacroExprHelper, target *exprpb.Expr, args []*exprpb.Expr) (*exprpb.Expr, *common.Error) {
+func FilterMacroExpander(meh MacroExprHelper, target *exprpb.Expr, args []*exprpb.Expr) (*exprpb.Expr, *Error) {
return parser.MakeFilter(meh, target, args)
}
diff --git a/vendor/github.com/google/cel-go/cel/options.go b/vendor/github.com/google/cel-go/cel/options.go
index 23e5223ed..d47f55d8e 100644
--- a/vendor/github.com/google/cel-go/cel/options.go
+++ b/vendor/github.com/google/cel-go/cel/options.go
@@ -23,12 +23,12 @@ import (
"google.golang.org/protobuf/reflect/protoregistry"
"google.golang.org/protobuf/types/dynamicpb"
- "github.com/google/cel-go/checker/decls"
"github.com/google/cel-go/common/containers"
+ "github.com/google/cel-go/common/functions"
+ "github.com/google/cel-go/common/types"
"github.com/google/cel-go/common/types/pb"
"github.com/google/cel-go/common/types/ref"
"github.com/google/cel-go/interpreter"
- "github.com/google/cel-go/interpreter/functions"
"github.com/google/cel-go/parser"
exprpb "google.golang.org/genproto/googleapis/api/expr/v1alpha1"
@@ -41,13 +41,6 @@ import (
const (
_ = iota
- // Disallow heterogeneous aggregate (list, map) literals.
- // Note, it is still possible to have heterogeneous aggregates when
- // provided as variables to the expression, as well as via conversion
- // of well-known dynamic types, or with unchecked expressions.
- // Affects checking. Provides a subset of standard behavior.
- featureDisableDynamicAggregateLiterals
-
// Enable the tracking of function call expressions replaced by macros.
featureEnableMacroCallTracking
@@ -63,9 +56,10 @@ const (
// is not already in UTC.
featureDefaultUTCTimeZone
- // Enable the use of optional types in the syntax, type-system, type-checking,
- // and runtime.
- featureOptionalTypes
+ // Enable the serialization of logical operator ASTs as variadic calls, thus
+ // compressing the logic graph to a single call when multiple like-operator
+ // expressions occur: e.g. a && b && c && d -> call(_&&_, [a, b, c, d])
+ featureVariadicLogicalASTs
)
// EnvOption is a functional interface for configuring the environment.
@@ -82,23 +76,26 @@ func ClearMacros() EnvOption {
}
}
-// CustomTypeAdapter swaps the default ref.TypeAdapter implementation with a custom one.
+// CustomTypeAdapter swaps the default types.Adapter implementation with a custom one.
//
// Note: This option must be specified before the Types and TypeDescs options when used together.
-func CustomTypeAdapter(adapter ref.TypeAdapter) EnvOption {
+func CustomTypeAdapter(adapter types.Adapter) EnvOption {
return func(e *Env) (*Env, error) {
e.adapter = adapter
return e, nil
}
}
-// CustomTypeProvider swaps the default ref.TypeProvider implementation with a custom one.
+// CustomTypeProvider replaces the types.Provider implementation with a custom one.
+//
+// The `provider` variable type may either be types.Provider or ref.TypeProvider (deprecated)
//
// Note: This option must be specified before the Types and TypeDescs options when used together.
-func CustomTypeProvider(provider ref.TypeProvider) EnvOption {
+func CustomTypeProvider(provider any) EnvOption {
return func(e *Env) (*Env, error) {
- e.provider = provider
- return e, nil
+ var err error
+ e.provider, err = maybeInteropProvider(provider)
+ return e, err
}
}
@@ -108,8 +105,28 @@ func CustomTypeProvider(provider ref.TypeProvider) EnvOption {
// for the environment. The NewEnv call builds on top of the standard CEL declarations. For a
// purely custom set of declarations use NewCustomEnv.
func Declarations(decls ...*exprpb.Decl) EnvOption {
+ declOpts := []EnvOption{}
+ var err error
+ var opt EnvOption
+ // Convert the declarations to `EnvOption` values ahead of time.
+ // Surface any errors in conversion when the options are applied.
+ for _, d := range decls {
+ opt, err = ExprDeclToDeclaration(d)
+ if err != nil {
+ break
+ }
+ declOpts = append(declOpts, opt)
+ }
return func(e *Env) (*Env, error) {
- e.declarations = append(e.declarations, decls...)
+ if err != nil {
+ return nil, err
+ }
+ for _, o := range declOpts {
+ e, err = o(e)
+ if err != nil {
+ return nil, err
+ }
+ }
return e, nil
}
}
@@ -126,14 +143,25 @@ func EagerlyValidateDeclarations(enabled bool) EnvOption {
return features(featureEagerlyValidateDeclarations, enabled)
}
-// HomogeneousAggregateLiterals option ensures that list and map literal entry types must agree
-// during type-checking.
+// HomogeneousAggregateLiterals disables mixed type list and map literal values.
//
// Note, it is still possible to have heterogeneous aggregates when provided as variables to the
// expression, as well as via conversion of well-known dynamic types, or with unchecked
// expressions.
func HomogeneousAggregateLiterals() EnvOption {
- return features(featureDisableDynamicAggregateLiterals, true)
+ return ASTValidators(ValidateHomogeneousAggregateLiterals())
+}
+
+// variadicLogicalOperatorASTs flatten like-operator chained logical expressions into a single
+// variadic call with N-terms. This behavior is useful when serializing to a protocol buffer as
+// it will reduce the number of recursive calls needed to deserialize the AST later.
+//
+// For example, given the following expression the call graph will be rendered accordingly:
+//
+// expression: a && b && c && (d || e)
+// ast: call(_&&_, [a, b, c, call(_||_, [d, e])])
+func variadicLogicalOperatorASTs() EnvOption {
+ return features(featureVariadicLogicalASTs, true)
}
// Macros option extends the macro set configured in the environment.
@@ -226,7 +254,12 @@ func Abbrevs(qualifiedNames ...string) EnvOption {
// Note: This option must be specified after the CustomTypeProvider option when used together.
func Types(addTypes ...any) EnvOption {
return func(e *Env) (*Env, error) {
- reg, isReg := e.provider.(ref.TypeRegistry)
+ var reg ref.TypeRegistry
+ var isReg bool
+ reg, isReg = e.provider.(*types.Registry)
+ if !isReg {
+ reg, isReg = e.provider.(ref.TypeRegistry)
+ }
if !isReg {
return nil, fmt.Errorf("custom types not supported by provider: %T", e.provider)
}
@@ -412,6 +445,9 @@ const (
// OptTrackCost enables the runtime cost calculation while validation and return cost within evalDetails
// cost calculation is available via func ActualCost()
OptTrackCost EvalOption = 1 << iota
+
+ // OptCheckStringFormat enables compile-time checking of string.format calls for syntax/cardinality.
+ OptCheckStringFormat EvalOption = 1 << iota
)
// EvalOptions sets one or more evaluation options which may affect the evaluation or Result.
@@ -454,25 +490,21 @@ func CostLimit(costLimit uint64) ProgramOption {
}
}
-func fieldToCELType(field protoreflect.FieldDescriptor) (*exprpb.Type, error) {
+func fieldToCELType(field protoreflect.FieldDescriptor) (*Type, error) {
if field.Kind() == protoreflect.MessageKind || field.Kind() == protoreflect.GroupKind {
msgName := (string)(field.Message().FullName())
- wellKnownType, found := pb.CheckedWellKnowns[msgName]
- if found {
- return wellKnownType, nil
- }
- return decls.NewObjectType(msgName), nil
+ return ObjectType(msgName), nil
}
- if primitiveType, found := pb.CheckedPrimitives[field.Kind()]; found {
+ if primitiveType, found := types.ProtoCELPrimitives[field.Kind()]; found {
return primitiveType, nil
}
if field.Kind() == protoreflect.EnumKind {
- return decls.Int, nil
+ return IntType, nil
}
return nil, fmt.Errorf("field %s type %s not implemented", field.FullName(), field.Kind().String())
}
-func fieldToDecl(field protoreflect.FieldDescriptor) (*exprpb.Decl, error) {
+func fieldToVariable(field protoreflect.FieldDescriptor) (EnvOption, error) {
name := string(field.Name())
if field.IsMap() {
mapKey := field.MapKey()
@@ -485,20 +517,20 @@ func fieldToDecl(field protoreflect.FieldDescriptor) (*exprpb.Decl, error) {
if err != nil {
return nil, err
}
- return decls.NewVar(name, decls.NewMapType(keyType, valueType)), nil
+ return Variable(name, MapType(keyType, valueType)), nil
}
if field.IsList() {
elemType, err := fieldToCELType(field)
if err != nil {
return nil, err
}
- return decls.NewVar(name, decls.NewListType(elemType)), nil
+ return Variable(name, ListType(elemType)), nil
}
celType, err := fieldToCELType(field)
if err != nil {
return nil, err
}
- return decls.NewVar(name, celType), nil
+ return Variable(name, celType), nil
}
// DeclareContextProto returns an option to extend CEL environment with declarations from the given context proto.
@@ -506,23 +538,51 @@ func fieldToDecl(field protoreflect.FieldDescriptor) (*exprpb.Decl, error) {
// https://github.com/google/cel-spec/blob/master/doc/langdef.md#evaluation-environment
func DeclareContextProto(descriptor protoreflect.MessageDescriptor) EnvOption {
return func(e *Env) (*Env, error) {
- var decls []*exprpb.Decl
fields := descriptor.Fields()
for i := 0; i < fields.Len(); i++ {
field := fields.Get(i)
- decl, err := fieldToDecl(field)
+ variable, err := fieldToVariable(field)
+ if err != nil {
+ return nil, err
+ }
+ e, err = variable(e)
if err != nil {
return nil, err
}
- decls = append(decls, decl)
}
- var err error
- e, err = Declarations(decls...)(e)
+ return Types(dynamicpb.NewMessage(descriptor))(e)
+ }
+}
+
+// ContextProtoVars uses the fields of the input proto.Messages as top-level variables within an Activation.
+//
+// Consider using with `DeclareContextProto` to simplify variable type declarations and publishing when using
+// protocol buffers.
+func ContextProtoVars(ctx proto.Message) (interpreter.Activation, error) {
+ if ctx == nil || !ctx.ProtoReflect().IsValid() {
+ return interpreter.EmptyActivation(), nil
+ }
+ reg, err := types.NewRegistry(ctx)
+ if err != nil {
+ return nil, err
+ }
+ pbRef := ctx.ProtoReflect()
+ typeName := string(pbRef.Descriptor().FullName())
+ fields := pbRef.Descriptor().Fields()
+ vars := make(map[string]any, fields.Len())
+ for i := 0; i < fields.Len(); i++ {
+ field := fields.Get(i)
+ sft, found := reg.FindStructFieldType(typeName, field.TextName())
+ if !found {
+ return nil, fmt.Errorf("no such field: %s", field.TextName())
+ }
+ fieldVal, err := sft.GetFrom(ctx)
if err != nil {
return nil, err
}
- return Types(dynamicpb.NewMessage(descriptor))(e)
+ vars[field.TextName()] = fieldVal
}
+ return interpreter.NewActivation(vars)
}
// EnableMacroCallTracking ensures that call expressions which are replaced by macros
@@ -542,13 +602,6 @@ func DefaultUTCTimeZone(enabled bool) EnvOption {
return features(featureDefaultUTCTimeZone, enabled)
}
-// OptionalTypes enable support for optional syntax and types in CEL. The optional value type makes
-// it possible to express whether variables have been provided, whether a result has been computed,
-// and in the future whether an object field path, map key value, or list index has a value.
-func OptionalTypes() EnvOption {
- return Lib(optionalLibrary{})
-}
-
// features sets the given feature flags. See list of Feature constants above.
func features(flag int, enabled bool) EnvOption {
return func(e *Env) (*Env, error) {
@@ -565,3 +618,23 @@ func ParserRecursionLimit(limit int) EnvOption {
return e, nil
}
}
+
+// ParserExpressionSizeLimit adjusts the number of code points the expression parser is allowed to parse.
+// Defaults defined in the parser package.
+func ParserExpressionSizeLimit(limit int) EnvOption {
+ return func(e *Env) (*Env, error) {
+ e.prsrOpts = append(e.prsrOpts, parser.ExpressionSizeCodePointLimit(limit))
+ return e, nil
+ }
+}
+
+func maybeInteropProvider(provider any) (types.Provider, error) {
+ switch p := provider.(type) {
+ case types.Provider:
+ return p, nil
+ case ref.TypeProvider:
+ return &interopCELTypeProvider{TypeProvider: p}, nil
+ default:
+ return nil, fmt.Errorf("unsupported type provider: %T", provider)
+ }
+}
diff --git a/vendor/github.com/google/cel-go/cel/program.go b/vendor/github.com/google/cel-go/cel/program.go
index f4b77f77a..11c5c447e 100644
--- a/vendor/github.com/google/cel-go/cel/program.go
+++ b/vendor/github.com/google/cel-go/cel/program.go
@@ -17,14 +17,12 @@ package cel
import (
"context"
"fmt"
- "math"
"sync"
+ celast "github.com/google/cel-go/common/ast"
"github.com/google/cel-go/common/types"
"github.com/google/cel-go/common/types/ref"
"github.com/google/cel-go/interpreter"
-
- exprpb "google.golang.org/genproto/googleapis/api/expr/v1alpha1"
)
// Program is an evaluable view of an Ast.
@@ -63,6 +61,9 @@ func NoVars() interpreter.Activation {
// PartialVars returns a PartialActivation which contains variables and a set of AttributePattern
// values that indicate variables or parts of variables whose value are not yet known.
//
+// This method relies on manually configured sets of missing attribute patterns. For a method which
+// infers the missing variables from the input and the configured environment, use Env.PartialVars().
+//
// The `vars` value may either be an interpreter.Activation or any valid input to the
// interpreter.NewActivation call.
func PartialVars(vars any,
@@ -170,7 +171,7 @@ func newProgram(e *Env, ast *Ast, opts []ProgramOption) (Program, error) {
// Add the function bindings created via Function() options.
for _, fn := range e.functions {
- bindings, err := fn.bindings()
+ bindings, err := fn.Bindings()
if err != nil {
return nil, err
}
@@ -207,13 +208,44 @@ func newProgram(e *Env, ast *Ast, opts []ProgramOption) (Program, error) {
if len(p.regexOptimizations) > 0 {
decorators = append(decorators, interpreter.CompileRegexConstants(p.regexOptimizations...))
}
+ // Enable compile-time checking of syntax/cardinality for string.format calls.
+ if p.evalOpts&OptCheckStringFormat == OptCheckStringFormat {
+ var isValidType func(id int64, validTypes ...ref.Type) (bool, error)
+ if ast.IsChecked() {
+ isValidType = func(id int64, validTypes ...ref.Type) (bool, error) {
+ t := ast.typeMap[id]
+ if t.Kind() == DynKind {
+ return true, nil
+ }
+ for _, vt := range validTypes {
+ k, err := typeValueToKind(vt)
+ if err != nil {
+ return false, err
+ }
+ if t.Kind() == k {
+ return true, nil
+ }
+ }
+ return false, nil
+ }
+ } else {
+ // if the AST isn't type-checked, short-circuit validation
+ isValidType = func(id int64, validTypes ...ref.Type) (bool, error) {
+ return true, nil
+ }
+ }
+ decorators = append(decorators, interpreter.InterpolateFormattedString(isValidType))
+ }
// Enable exhaustive eval, state tracking and cost tracking last since they require a factory.
if p.evalOpts&(OptExhaustiveEval|OptTrackState|OptTrackCost) != 0 {
factory := func(state interpreter.EvalState, costTracker *interpreter.CostTracker) (Program, error) {
costTracker.Estimator = p.callCostEstimator
costTracker.Limit = p.costLimit
- decs := decorators
+ // Limit capacity to guarantee a reallocation when calling 'append(decs, ...)' below. This
+ // prevents the underlying memory from being shared between factory function calls causing
+ // undesired mutations.
+ decs := decorators[:len(decorators):len(decorators)]
var observers []interpreter.EvalObserver
if p.evalOpts&(OptExhaustiveEval|OptTrackState) != 0 {
@@ -251,10 +283,11 @@ func (p *prog) initInterpretable(ast *Ast, decs []interpreter.InterpretableDecor
}
// When the AST has been checked it contains metadata that can be used to speed up program execution.
- var checked *exprpb.CheckedExpr
- checked, err := AstToCheckedExpr(ast)
- if err != nil {
- return nil, err
+ checked := &celast.CheckedAST{
+ Expr: ast.Expr(),
+ SourceInfo: ast.SourceInfo(),
+ TypeMap: ast.typeMap,
+ ReferenceMap: ast.refMap,
}
interpretable, err := p.interpreter.NewInterpretable(checked, decs...)
if err != nil {
@@ -326,11 +359,6 @@ func (p *prog) ContextEval(ctx context.Context, input any) (ref.Val, *EvalDetail
return p.Eval(vars)
}
-// Cost implements the Coster interface method.
-func (p *prog) Cost() (min, max int64) {
- return estimateCost(p.interpretable)
-}
-
// progFactory is a helper alias for marking a program creation factory function.
type progFactory func(interpreter.EvalState, *interpreter.CostTracker) (Program, error)
@@ -403,29 +431,6 @@ func (gen *progGen) ContextEval(ctx context.Context, input any) (ref.Val, *EvalD
return v, det, nil
}
-// Cost implements the Coster interface method.
-func (gen *progGen) Cost() (min, max int64) {
- // Use an empty state value since no evaluation is performed.
- p, err := gen.factory(emptyEvalState, nil)
- if err != nil {
- return 0, math.MaxInt64
- }
- return estimateCost(p)
-}
-
-// EstimateCost returns the heuristic cost interval for the program.
-func EstimateCost(p Program) (min, max int64) {
- return estimateCost(p)
-}
-
-func estimateCost(i any) (min, max int64) {
- c, ok := i.(interpreter.Coster)
- if !ok {
- return 0, math.MaxInt64
- }
- return c.Cost()
-}
-
type ctxEvalActivation struct {
parent interpreter.Activation
interrupt <-chan struct{}
@@ -493,7 +498,7 @@ type evalActivation struct {
// The lazy binding will only be invoked once per evaluation.
//
// Values which are not represented as ref.Val types on input may be adapted to a ref.Val using
-// the ref.TypeAdapter configured in the environment.
+// the types.Adapter configured in the environment.
func (a *evalActivation) ResolveName(name string) (any, bool) {
v, found := a.vars[name]
if !found {
diff --git a/vendor/github.com/google/cel-go/cel/validator.go b/vendor/github.com/google/cel-go/cel/validator.go
new file mode 100644
index 000000000..78b311381
--- /dev/null
+++ b/vendor/github.com/google/cel-go/cel/validator.go
@@ -0,0 +1,388 @@
+// Copyright 2023 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package cel
+
+import (
+ "fmt"
+ "reflect"
+ "regexp"
+
+ "github.com/google/cel-go/common/ast"
+ "github.com/google/cel-go/common/overloads"
+
+ exprpb "google.golang.org/genproto/googleapis/api/expr/v1alpha1"
+)
+
+const (
+ homogeneousValidatorName = "cel.lib.std.validate.types.homogeneous"
+
+ // HomogeneousAggregateLiteralExemptFunctions is the ValidatorConfig key used to configure
+ // the set of function names which are exempt from homogeneous type checks. The expected type
+ // is a string list of function names.
+ //
+ // As an example, the `.format([args])` call expects the input arguments list to be
+ // comprised of a variety of types which correspond to the types expected by the format control
+ // clauses; however, all other uses of a mixed element type list, would be unexpected.
+ HomogeneousAggregateLiteralExemptFunctions = homogeneousValidatorName + ".exempt"
+)
+
+// ASTValidators configures a set of ASTValidator instances into the target environment.
+//
+// Validators are applied in the order in which the are specified and are treated as singletons.
+// The same ASTValidator with a given name will not be applied more than once.
+func ASTValidators(validators ...ASTValidator) EnvOption {
+ return func(e *Env) (*Env, error) {
+ for _, v := range validators {
+ if !e.HasValidator(v.Name()) {
+ e.validators = append(e.validators, v)
+ }
+ }
+ return e, nil
+ }
+}
+
+// ASTValidator defines a singleton interface for validating a type-checked Ast against an environment.
+//
+// Note: the Issues argument is mutable in the sense that it is intended to collect errors which will be
+// reported to the caller.
+type ASTValidator interface {
+ // Name returns the name of the validator. Names must be unique.
+ Name() string
+
+ // Validate validates a given Ast within an Environment and collects a set of potential issues.
+ //
+ // The ValidatorConfig is generated from the set of ASTValidatorConfigurer instances prior to
+ // the invocation of the Validate call. The expectation is that the validator configuration
+ // is created in sequence and immutable once provided to the Validate call.
+ //
+ // See individual validators for more information on their configuration keys and configuration
+ // properties.
+ Validate(*Env, ValidatorConfig, *ast.CheckedAST, *Issues)
+}
+
+// ValidatorConfig provides an accessor method for querying validator configuration state.
+type ValidatorConfig interface {
+ GetOrDefault(name string, value any) any
+}
+
+// MutableValidatorConfig provides mutation methods for querying and updating validator configuration
+// settings.
+type MutableValidatorConfig interface {
+ ValidatorConfig
+ Set(name string, value any) error
+}
+
+// ASTValidatorConfigurer indicates that this object, currently expected to be an ASTValidator,
+// participates in validator configuration settings.
+//
+// This interface may be split from the expectation of being an ASTValidator instance in the future.
+type ASTValidatorConfigurer interface {
+ Configure(MutableValidatorConfig) error
+}
+
+// validatorConfig implements the ValidatorConfig and MutableValidatorConfig interfaces.
+type validatorConfig struct {
+ data map[string]any
+}
+
+// newValidatorConfig initializes the validator config with default values for core CEL validators.
+func newValidatorConfig() *validatorConfig {
+ return &validatorConfig{
+ data: map[string]any{
+ HomogeneousAggregateLiteralExemptFunctions: []string{},
+ },
+ }
+}
+
+// GetOrDefault returns the configured value for the name, if present, else the input default value.
+//
+// Note, the type-agreement between the input default and configured value is not checked on read.
+func (config *validatorConfig) GetOrDefault(name string, value any) any {
+ v, found := config.data[name]
+ if !found {
+ return value
+ }
+ return v
+}
+
+// Set configures a validator option with the given name and value.
+//
+// If the value had previously been set, the new value must have the same reflection type as the old one,
+// or the call will error.
+func (config *validatorConfig) Set(name string, value any) error {
+ v, found := config.data[name]
+ if found && reflect.TypeOf(v) != reflect.TypeOf(value) {
+ return fmt.Errorf("incompatible configuration type for %s, got %T, wanted %T", name, value, v)
+ }
+ config.data[name] = value
+ return nil
+}
+
+// ExtendedValidations collects a set of common AST validations which reduce the likelihood of runtime errors.
+//
+// - Validate duration and timestamp literals
+// - Ensure regex strings are valid
+// - Disable mixed type list and map literals
+func ExtendedValidations() EnvOption {
+ return ASTValidators(
+ ValidateDurationLiterals(),
+ ValidateTimestampLiterals(),
+ ValidateRegexLiterals(),
+ ValidateHomogeneousAggregateLiterals(),
+ )
+}
+
+// ValidateDurationLiterals ensures that duration literal arguments are valid immediately after type-check.
+func ValidateDurationLiterals() ASTValidator {
+ return newFormatValidator(overloads.TypeConvertDuration, 0, evalCall)
+}
+
+// ValidateTimestampLiterals ensures that timestamp literal arguments are valid immediately after type-check.
+func ValidateTimestampLiterals() ASTValidator {
+ return newFormatValidator(overloads.TypeConvertTimestamp, 0, evalCall)
+}
+
+// ValidateRegexLiterals ensures that regex patterns are validated after type-check.
+func ValidateRegexLiterals() ASTValidator {
+ return newFormatValidator(overloads.Matches, 0, compileRegex)
+}
+
+// ValidateHomogeneousAggregateLiterals checks that all list and map literals entries have the same types, i.e.
+// no mixed list element types or mixed map key or map value types.
+//
+// Note: the string format call relies on a mixed element type list for ease of use, so this check skips all
+// literals which occur within string format calls.
+func ValidateHomogeneousAggregateLiterals() ASTValidator {
+ return homogeneousAggregateLiteralValidator{}
+}
+
+// ValidateComprehensionNestingLimit ensures that comprehension nesting does not exceed the specified limit.
+//
+// This validator can be useful for preventing arbitrarily nested comprehensions which can take high polynomial
+// time to complete.
+//
+// Note, this limit does not apply to comprehensions with an empty iteration range, as these comprehensions have
+// no actual looping cost. The cel.bind() utilizes the comprehension structure to perform local variable
+// assignments and supplies an empty iteration range, so they won't count against the nesting limit either.
+func ValidateComprehensionNestingLimit(limit int) ASTValidator {
+ return nestingLimitValidator{limit: limit}
+}
+
+type argChecker func(env *Env, call, arg ast.NavigableExpr) error
+
+func newFormatValidator(funcName string, argNum int, check argChecker) formatValidator {
+ return formatValidator{
+ funcName: funcName,
+ check: check,
+ argNum: argNum,
+ }
+}
+
+type formatValidator struct {
+ funcName string
+ argNum int
+ check argChecker
+}
+
+// Name returns the unique name of this function format validator.
+func (v formatValidator) Name() string {
+ return fmt.Sprintf("cel.lib.std.validate.functions.%s", v.funcName)
+}
+
+// Validate searches the AST for uses of a given function name with a constant argument and performs a check
+// on whether the argument is a valid literal value.
+func (v formatValidator) Validate(e *Env, _ ValidatorConfig, a *ast.CheckedAST, iss *Issues) {
+ root := ast.NavigateCheckedAST(a)
+ funcCalls := ast.MatchDescendants(root, ast.FunctionMatcher(v.funcName))
+ for _, call := range funcCalls {
+ callArgs := call.AsCall().Args()
+ if len(callArgs) <= v.argNum {
+ continue
+ }
+ litArg := callArgs[v.argNum]
+ if litArg.Kind() != ast.LiteralKind {
+ continue
+ }
+ if err := v.check(e, call, litArg); err != nil {
+ iss.ReportErrorAtID(litArg.ID(), "invalid %s argument", v.funcName)
+ }
+ }
+}
+
+func evalCall(env *Env, call, arg ast.NavigableExpr) error {
+ ast := ParsedExprToAst(&exprpb.ParsedExpr{Expr: call.ToExpr()})
+ prg, err := env.Program(ast)
+ if err != nil {
+ return err
+ }
+ _, _, err = prg.Eval(NoVars())
+ return err
+}
+
+func compileRegex(_ *Env, _, arg ast.NavigableExpr) error {
+ pattern := arg.AsLiteral().Value().(string)
+ _, err := regexp.Compile(pattern)
+ return err
+}
+
+type homogeneousAggregateLiteralValidator struct{}
+
+// Name returns the unique name of the homogeneous type validator.
+func (homogeneousAggregateLiteralValidator) Name() string {
+ return homogeneousValidatorName
+}
+
+// Configure implements the ASTValidatorConfigurer interface and currently sets the list of standard
+// and exempt functions from homogeneous aggregate literal checks.
+//
+// TODO: Move this call into the string.format() ASTValidator once ported.
+func (homogeneousAggregateLiteralValidator) Configure(c MutableValidatorConfig) error {
+ emptyList := []string{}
+ exemptFunctions := c.GetOrDefault(HomogeneousAggregateLiteralExemptFunctions, emptyList).([]string)
+ exemptFunctions = append(exemptFunctions, "format")
+ return c.Set(HomogeneousAggregateLiteralExemptFunctions, exemptFunctions)
+}
+
+// Validate validates that all lists and map literals have homogeneous types, i.e. don't contain dyn types.
+//
+// This validator makes an exception for list and map literals which occur at any level of nesting within
+// string format calls.
+func (v homogeneousAggregateLiteralValidator) Validate(_ *Env, c ValidatorConfig, a *ast.CheckedAST, iss *Issues) {
+ var exemptedFunctions []string
+ exemptedFunctions = c.GetOrDefault(HomogeneousAggregateLiteralExemptFunctions, exemptedFunctions).([]string)
+ root := ast.NavigateCheckedAST(a)
+ listExprs := ast.MatchDescendants(root, ast.KindMatcher(ast.ListKind))
+ for _, listExpr := range listExprs {
+ if inExemptFunction(listExpr, exemptedFunctions) {
+ continue
+ }
+ l := listExpr.AsList()
+ elements := l.Elements()
+ optIndices := l.OptionalIndices()
+ var elemType *Type
+ for i, e := range elements {
+ et := e.Type()
+ if isOptionalIndex(i, optIndices) {
+ et = et.Parameters()[0]
+ }
+ if elemType == nil {
+ elemType = et
+ continue
+ }
+ if !elemType.IsEquivalentType(et) {
+ v.typeMismatch(iss, e.ID(), elemType, et)
+ break
+ }
+ }
+ }
+ mapExprs := ast.MatchDescendants(root, ast.KindMatcher(ast.MapKind))
+ for _, mapExpr := range mapExprs {
+ if inExemptFunction(mapExpr, exemptedFunctions) {
+ continue
+ }
+ m := mapExpr.AsMap()
+ entries := m.Entries()
+ var keyType, valType *Type
+ for _, e := range entries {
+ key, val := e.Key(), e.Value()
+ kt, vt := key.Type(), val.Type()
+ if e.IsOptional() {
+ vt = vt.Parameters()[0]
+ }
+ if keyType == nil && valType == nil {
+ keyType, valType = kt, vt
+ continue
+ }
+ if !keyType.IsEquivalentType(kt) {
+ v.typeMismatch(iss, key.ID(), keyType, kt)
+ }
+ if !valType.IsEquivalentType(vt) {
+ v.typeMismatch(iss, val.ID(), valType, vt)
+ }
+ }
+ }
+}
+
+func inExemptFunction(e ast.NavigableExpr, exemptFunctions []string) bool {
+ if parent, found := e.Parent(); found {
+ if parent.Kind() == ast.CallKind {
+ fnName := parent.AsCall().FunctionName()
+ for _, exempt := range exemptFunctions {
+ if exempt == fnName {
+ return true
+ }
+ }
+ }
+ if parent.Kind() == ast.ListKind || parent.Kind() == ast.MapKind {
+ return inExemptFunction(parent, exemptFunctions)
+ }
+ }
+ return false
+}
+
+func isOptionalIndex(i int, optIndices []int32) bool {
+ for _, optInd := range optIndices {
+ if i == int(optInd) {
+ return true
+ }
+ }
+ return false
+}
+
+func (homogeneousAggregateLiteralValidator) typeMismatch(iss *Issues, id int64, expected, actual *Type) {
+ iss.ReportErrorAtID(id, "expected type '%s' but found '%s'", FormatCELType(expected), FormatCELType(actual))
+}
+
+type nestingLimitValidator struct {
+ limit int
+}
+
+func (v nestingLimitValidator) Name() string {
+ return "cel.lib.std.validate.comprehension_nesting_limit"
+}
+
+func (v nestingLimitValidator) Validate(e *Env, _ ValidatorConfig, a *ast.CheckedAST, iss *Issues) {
+ root := ast.NavigateCheckedAST(a)
+ comprehensions := ast.MatchDescendants(root, ast.KindMatcher(ast.ComprehensionKind))
+ if len(comprehensions) <= v.limit {
+ return
+ }
+ for _, comp := range comprehensions {
+ count := 0
+ e := comp
+ hasParent := true
+ for hasParent {
+ // When the expression is not a comprehension, continue to the next ancestor.
+ if e.Kind() != ast.ComprehensionKind {
+ e, hasParent = e.Parent()
+ continue
+ }
+ // When the comprehension has an empty range, continue to the next ancestor
+ // as this comprehension does not have any associated cost.
+ iterRange := e.AsComprehension().IterRange()
+ if iterRange.Kind() == ast.ListKind && iterRange.AsList().Size() == 0 {
+ e, hasParent = e.Parent()
+ continue
+ }
+ // Otherwise check the nesting limit.
+ count++
+ if count > v.limit {
+ iss.ReportErrorAtID(comp.ID(), "comprehension exceeds nesting limit")
+ break
+ }
+ e, hasParent = e.Parent()
+ }
+ }
+}
diff --git a/vendor/github.com/google/cel-go/checker/BUILD.bazel b/vendor/github.com/google/cel-go/checker/BUILD.bazel
index bec40b6e6..0459d3523 100644
--- a/vendor/github.com/google/cel-go/checker/BUILD.bazel
+++ b/vendor/github.com/google/cel-go/checker/BUILD.bazel
@@ -11,9 +11,11 @@ go_library(
"cost.go",
"env.go",
"errors.go",
+ "format.go",
"mapping.go",
"options.go",
"printer.go",
+ "scopes.go",
"standard.go",
"types.go",
],
@@ -22,15 +24,18 @@ go_library(
deps = [
"//checker/decls:go_default_library",
"//common:go_default_library",
+ "//common/ast:go_default_library",
"//common/containers:go_default_library",
"//common/debug:go_default_library",
+ "//common/decls:go_default_library",
"//common/operators:go_default_library",
"//common/overloads:go_default_library",
+ "//common/stdlib:go_default_library",
"//common/types:go_default_library",
"//common/types/pb:go_default_library",
"//common/types/ref:go_default_library",
"//parser:go_default_library",
- "@org_golang_google_genproto//googleapis/api/expr/v1alpha1:go_default_library",
+ "@org_golang_google_genproto_googleapis_api//expr/v1alpha1:go_default_library",
"@org_golang_google_protobuf//proto:go_default_library",
"@org_golang_google_protobuf//types/known/emptypb:go_default_library",
"@org_golang_google_protobuf//types/known/structpb:go_default_library",
@@ -44,6 +49,7 @@ go_test(
"checker_test.go",
"cost_test.go",
"env_test.go",
+ "format_test.go",
],
embed = [
":go_default_library",
@@ -54,7 +60,7 @@ go_test(
"//test:go_default_library",
"//test/proto2pb:go_default_library",
"//test/proto3pb:go_default_library",
- "@com_github_antlr_antlr4_runtime_go_antlr//:go_default_library",
+ "@com_github_antlr_antlr4_runtime_go_antlr_v4//:go_default_library",
"@org_golang_google_protobuf//proto:go_default_library",
],
)
diff --git a/vendor/github.com/google/cel-go/checker/checker.go b/vendor/github.com/google/cel-go/checker/checker.go
index dc4cb5c64..720e4fa96 100644
--- a/vendor/github.com/google/cel-go/checker/checker.go
+++ b/vendor/github.com/google/cel-go/checker/checker.go
@@ -18,15 +18,13 @@ package checker
import (
"fmt"
- "reflect"
- "github.com/google/cel-go/checker/decls"
"github.com/google/cel-go/common"
+ "github.com/google/cel-go/common/ast"
"github.com/google/cel-go/common/containers"
+ "github.com/google/cel-go/common/decls"
"github.com/google/cel-go/common/operators"
- "github.com/google/cel-go/common/types/ref"
-
- "google.golang.org/protobuf/proto"
+ "github.com/google/cel-go/common/types"
exprpb "google.golang.org/genproto/googleapis/api/expr/v1alpha1"
)
@@ -37,8 +35,8 @@ type checker struct {
mappings *mapping
freeTypeVarCounter int
sourceInfo *exprpb.SourceInfo
- types map[int64]*exprpb.Type
- references map[int64]*exprpb.Reference
+ types map[int64]*types.Type
+ references map[int64]*ast.ReferenceInfo
}
// Check performs type checking, giving a typed AST.
@@ -47,40 +45,38 @@ type checker struct {
// descriptions of protocol buffers, and a registry for errors.
// Returns a CheckedExpr proto, which might not be usable if
// there are errors in the error registry.
-func Check(parsedExpr *exprpb.ParsedExpr,
- source common.Source,
- env *Env) (*exprpb.CheckedExpr, *common.Errors) {
+func Check(parsedExpr *exprpb.ParsedExpr, source common.Source, env *Env) (*ast.CheckedAST, *common.Errors) {
+ errs := common.NewErrors(source)
c := checker{
env: env,
- errors: &typeErrors{common.NewErrors(source)},
+ errors: &typeErrors{errs: errs},
mappings: newMapping(),
freeTypeVarCounter: 0,
sourceInfo: parsedExpr.GetSourceInfo(),
- types: make(map[int64]*exprpb.Type),
- references: make(map[int64]*exprpb.Reference),
+ types: make(map[int64]*types.Type),
+ references: make(map[int64]*ast.ReferenceInfo),
}
c.check(parsedExpr.GetExpr())
// Walk over the final type map substituting any type parameters either by their bound value or
// by DYN.
- m := make(map[int64]*exprpb.Type)
- for k, v := range c.types {
- m[k] = substitute(c.mappings, v, true)
+ m := make(map[int64]*types.Type)
+ for id, t := range c.types {
+ m[id] = substitute(c.mappings, t, true)
}
- return &exprpb.CheckedExpr{
+ return &ast.CheckedAST{
Expr: parsedExpr.GetExpr(),
SourceInfo: parsedExpr.GetSourceInfo(),
TypeMap: m,
ReferenceMap: c.references,
- }, c.errors.Errors
+ }, errs
}
func (c *checker) check(e *exprpb.Expr) {
if e == nil {
return
}
-
switch e.GetExprKind().(type) {
case *exprpb.Expr_ConstExpr:
literal := e.GetConstExpr()
@@ -113,53 +109,51 @@ func (c *checker) check(e *exprpb.Expr) {
case *exprpb.Expr_ComprehensionExpr:
c.checkComprehension(e)
default:
- c.errors.ReportError(
- c.location(e), "Unrecognized ast type: %v", reflect.TypeOf(e))
+ c.errors.unexpectedASTType(e.GetId(), c.location(e), e)
}
}
func (c *checker) checkInt64Literal(e *exprpb.Expr) {
- c.setType(e, decls.Int)
+ c.setType(e, types.IntType)
}
func (c *checker) checkUint64Literal(e *exprpb.Expr) {
- c.setType(e, decls.Uint)
+ c.setType(e, types.UintType)
}
func (c *checker) checkStringLiteral(e *exprpb.Expr) {
- c.setType(e, decls.String)
+ c.setType(e, types.StringType)
}
func (c *checker) checkBytesLiteral(e *exprpb.Expr) {
- c.setType(e, decls.Bytes)
+ c.setType(e, types.BytesType)
}
func (c *checker) checkDoubleLiteral(e *exprpb.Expr) {
- c.setType(e, decls.Double)
+ c.setType(e, types.DoubleType)
}
func (c *checker) checkBoolLiteral(e *exprpb.Expr) {
- c.setType(e, decls.Bool)
+ c.setType(e, types.BoolType)
}
func (c *checker) checkNullLiteral(e *exprpb.Expr) {
- c.setType(e, decls.Null)
+ c.setType(e, types.NullType)
}
func (c *checker) checkIdent(e *exprpb.Expr) {
identExpr := e.GetIdentExpr()
// Check to see if the identifier is declared.
if ident := c.env.LookupIdent(identExpr.GetName()); ident != nil {
- c.setType(e, ident.GetIdent().GetType())
- c.setReference(e, newIdentReference(ident.GetName(), ident.GetIdent().GetValue()))
+ c.setType(e, ident.Type())
+ c.setReference(e, ast.NewIdentReference(ident.Name(), ident.Value()))
// Overwrite the identifier with its fully qualified name.
- identExpr.Name = ident.GetName()
+ identExpr.Name = ident.Name()
return
}
- c.setType(e, decls.Error)
- c.errors.undeclaredReference(
- c.location(e), c.env.container.Name(), identExpr.GetName())
+ c.setType(e, types.ErrorType)
+ c.errors.undeclaredReference(e.GetId(), c.location(e), c.env.container.Name(), identExpr.GetName())
}
func (c *checker) checkSelect(e *exprpb.Expr) {
@@ -174,9 +168,9 @@ func (c *checker) checkSelect(e *exprpb.Expr) {
// Rewrite the node to be a variable reference to the resolved fully-qualified
// variable name.
- c.setType(e, ident.GetIdent().GetType())
- c.setReference(e, newIdentReference(ident.GetName(), ident.GetIdent().GetValue()))
- identName := ident.GetName()
+ c.setType(e, ident.Type())
+ c.setReference(e, ast.NewIdentReference(ident.Name(), ident.Value()))
+ identName := ident.Name()
e.ExprKind = &exprpb.Expr_IdentExpr{
IdentExpr: &exprpb.Expr_Ident{
Name: identName,
@@ -188,7 +182,7 @@ func (c *checker) checkSelect(e *exprpb.Expr) {
resultType := c.checkSelectField(e, sel.GetOperand(), sel.GetField(), false)
if sel.TestOnly {
- resultType = decls.Bool
+ resultType = types.BoolType
}
c.setType(e, substitute(c.mappings, resultType, false))
}
@@ -200,16 +194,17 @@ func (c *checker) checkOptSelect(e *exprpb.Expr) {
field := call.GetArgs()[1]
fieldName, isString := maybeUnwrapString(field)
if !isString {
- c.errors.ReportError(c.location(field), "unsupported optional field selection: %v", field)
+ c.errors.notAnOptionalFieldSelection(field.GetId(), c.location(field), field)
return
}
// Perform type-checking using the field selection logic.
resultType := c.checkSelectField(e, operand, fieldName, true)
c.setType(e, substitute(c.mappings, resultType, false))
+ c.setReference(e, ast.NewFunctionReference("select_optional_field"))
}
-func (c *checker) checkSelectField(e, operand *exprpb.Expr, field string, optional bool) *exprpb.Type {
+func (c *checker) checkSelectField(e, operand *exprpb.Expr, field string, optional bool) *types.Type {
// Interpret as field selection, first traversing down the operand.
c.check(operand)
operandType := substitute(c.mappings, c.getType(operand), false)
@@ -218,38 +213,37 @@ func (c *checker) checkSelectField(e, operand *exprpb.Expr, field string, option
targetType, isOpt := maybeUnwrapOptional(operandType)
// Assume error type by default as most types do not support field selection.
- resultType := decls.Error
- switch kindOf(targetType) {
- case kindMap:
+ resultType := types.ErrorType
+ switch targetType.Kind() {
+ case types.MapKind:
// Maps yield their value type as the selection result type.
- mapType := targetType.GetMapType()
- resultType = mapType.GetValueType()
- case kindObject:
+ resultType = targetType.Parameters()[1]
+ case types.StructKind:
// Objects yield their field type declaration as the selection result type, but only if
// the field is defined.
messageType := targetType
- if fieldType, found := c.lookupFieldType(c.location(e), messageType.GetMessageType(), field); found {
- resultType = fieldType.Type
+ if fieldType, found := c.lookupFieldType(e.GetId(), messageType.TypeName(), field); found {
+ resultType = fieldType
}
- case kindTypeParam:
+ case types.TypeParamKind:
// Set the operand type to DYN to prevent assignment to a potentially incorrect type
// at a later point in type-checking. The isAssignable call will update the type
// substitutions for the type param under the covers.
- c.isAssignable(decls.Dyn, targetType)
+ c.isAssignable(types.DynType, targetType)
// Also, set the result type to DYN.
- resultType = decls.Dyn
+ resultType = types.DynType
default:
// Dynamic / error values are treated as DYN type. Errors are handled this way as well
// in order to allow forward progress on the check.
if !isDynOrError(targetType) {
- c.errors.typeDoesNotSupportFieldSelection(c.location(e), targetType)
+ c.errors.typeDoesNotSupportFieldSelection(e.GetId(), c.location(e), targetType)
}
- resultType = decls.Dyn
+ resultType = types.DynType
}
// If the target type was optional coming in, then the result must be optional going out.
if isOpt || optional {
- return decls.NewOptionalType(resultType)
+ return types.NewOptionalType(resultType)
}
return resultType
}
@@ -277,15 +271,14 @@ func (c *checker) checkCall(e *exprpb.Expr) {
// Check for the existence of the function.
fn := c.env.LookupFunction(fnName)
if fn == nil {
- c.errors.undeclaredReference(
- c.location(e), c.env.container.Name(), fnName)
- c.setType(e, decls.Error)
+ c.errors.undeclaredReference(e.GetId(), c.location(e), c.env.container.Name(), fnName)
+ c.setType(e, types.ErrorType)
return
}
// Overwrite the function name with its fully qualified resolved name.
- call.Function = fn.GetName()
+ call.Function = fn.Name()
// Check to see whether the overload resolves.
- c.resolveOverloadOrError(c.location(e), e, fn, nil, args)
+ c.resolveOverloadOrError(e, fn, nil, args)
return
}
@@ -303,8 +296,8 @@ func (c *checker) checkCall(e *exprpb.Expr) {
// be an inaccurate representation of the desired evaluation behavior.
// Overwrite with fully-qualified resolved function name sans receiver target.
call.Target = nil
- call.Function = fn.GetName()
- c.resolveOverloadOrError(c.location(e), e, fn, nil, args)
+ call.Function = fn.Name()
+ c.resolveOverloadOrError(e, fn, nil, args)
return
}
}
@@ -314,22 +307,21 @@ func (c *checker) checkCall(e *exprpb.Expr) {
fn := c.env.LookupFunction(fnName)
// Function found, attempt overload resolution.
if fn != nil {
- c.resolveOverloadOrError(c.location(e), e, fn, target, args)
+ c.resolveOverloadOrError(e, fn, target, args)
return
}
// Function name not declared, record error.
- c.errors.undeclaredReference(c.location(e), c.env.container.Name(), fnName)
+ c.setType(e, types.ErrorType)
+ c.errors.undeclaredReference(e.GetId(), c.location(e), c.env.container.Name(), fnName)
}
func (c *checker) resolveOverloadOrError(
- loc common.Location,
- e *exprpb.Expr,
- fn *exprpb.Decl, target *exprpb.Expr, args []*exprpb.Expr) {
+ e *exprpb.Expr, fn *decls.FunctionDecl, target *exprpb.Expr, args []*exprpb.Expr) {
// Attempt to resolve the overload.
- resolution := c.resolveOverload(loc, fn, target, args)
+ resolution := c.resolveOverload(e, fn, target, args)
// No such overload, error noted in the resolveOverload call, type recorded here.
if resolution == nil {
- c.setType(e, decls.Error)
+ c.setType(e, types.ErrorType)
return
}
// Overload found.
@@ -338,10 +330,9 @@ func (c *checker) resolveOverloadOrError(
}
func (c *checker) resolveOverload(
- loc common.Location,
- fn *exprpb.Decl, target *exprpb.Expr, args []*exprpb.Expr) *overloadResolution {
+ call *exprpb.Expr, fn *decls.FunctionDecl, target *exprpb.Expr, args []*exprpb.Expr) *overloadResolution {
- var argTypes []*exprpb.Type
+ var argTypes []*types.Type
if target != nil {
argTypes = append(argTypes, c.getType(target))
}
@@ -349,55 +340,75 @@ func (c *checker) resolveOverload(
argTypes = append(argTypes, c.getType(arg))
}
- var resultType *exprpb.Type
- var checkedRef *exprpb.Reference
- for _, overload := range fn.GetFunction().GetOverloads() {
+ var resultType *types.Type
+ var checkedRef *ast.ReferenceInfo
+ for _, overload := range fn.OverloadDecls() {
// Determine whether the overload is currently considered.
- if c.env.isOverloadDisabled(overload.GetOverloadId()) {
+ if c.env.isOverloadDisabled(overload.ID()) {
continue
}
// Ensure the call style for the overload matches.
- if (target == nil && overload.GetIsInstanceFunction()) ||
- (target != nil && !overload.GetIsInstanceFunction()) {
+ if (target == nil && overload.IsMemberFunction()) ||
+ (target != nil && !overload.IsMemberFunction()) {
// not a compatible call style.
continue
}
- overloadType := decls.NewFunctionType(overload.ResultType, overload.Params...)
- if len(overload.GetTypeParams()) > 0 {
+ // Alternative type-checking behavior when the logical operators are compacted into
+ // variadic AST representations.
+ if fn.Name() == operators.LogicalAnd || fn.Name() == operators.LogicalOr {
+ checkedRef = ast.NewFunctionReference(overload.ID())
+ for i, argType := range argTypes {
+ if !c.isAssignable(argType, types.BoolType) {
+ c.errors.typeMismatch(
+ args[i].GetId(),
+ c.locationByID(args[i].GetId()),
+ types.BoolType,
+ argType)
+ resultType = types.ErrorType
+ }
+ }
+ if isError(resultType) {
+ return nil
+ }
+ return newResolution(checkedRef, types.BoolType)
+ }
+
+ overloadType := newFunctionType(overload.ResultType(), overload.ArgTypes()...)
+ typeParams := overload.TypeParams()
+ if len(typeParams) != 0 {
// Instantiate overload's type with fresh type variables.
substitutions := newMapping()
- for _, typePar := range overload.GetTypeParams() {
- substitutions.add(decls.NewTypeParamType(typePar), c.newTypeVar())
+ for _, typePar := range typeParams {
+ substitutions.add(types.NewTypeParamType(typePar), c.newTypeVar())
}
overloadType = substitute(substitutions, overloadType, false)
}
- candidateArgTypes := overloadType.GetFunction().GetArgTypes()
+ candidateArgTypes := overloadType.Parameters()[1:]
if c.isAssignableList(argTypes, candidateArgTypes) {
if checkedRef == nil {
- checkedRef = newFunctionReference(overload.GetOverloadId())
+ checkedRef = ast.NewFunctionReference(overload.ID())
} else {
- checkedRef.OverloadId = append(checkedRef.GetOverloadId(), overload.GetOverloadId())
+ checkedRef.AddOverload(overload.ID())
}
// First matching overload, determines result type.
- fnResultType := substitute(c.mappings, overloadType.GetFunction().GetResultType(), false)
+ fnResultType := substitute(c.mappings, overloadType.Parameters()[0], false)
if resultType == nil {
resultType = fnResultType
- } else if !isDyn(resultType) && !proto.Equal(fnResultType, resultType) {
- resultType = decls.Dyn
+ } else if !isDyn(resultType) && !fnResultType.IsExactType(resultType) {
+ resultType = types.DynType
}
}
}
if resultType == nil {
- for i, arg := range argTypes {
- argTypes[i] = substitute(c.mappings, arg, true)
+ for i, argType := range argTypes {
+ argTypes[i] = substitute(c.mappings, argType, true)
}
- c.errors.noMatchingOverload(loc, fn.GetName(), argTypes, target != nil)
- resultType = decls.Error
+ c.errors.noMatchingOverload(call.GetId(), c.location(call), fn.Name(), argTypes, target != nil)
return nil
}
@@ -406,16 +417,29 @@ func (c *checker) resolveOverload(
func (c *checker) checkCreateList(e *exprpb.Expr) {
create := e.GetListExpr()
- var elemType *exprpb.Type
- for _, e := range create.GetElements() {
+ var elemsType *types.Type
+ optionalIndices := create.GetOptionalIndices()
+ optionals := make(map[int32]bool, len(optionalIndices))
+ for _, optInd := range optionalIndices {
+ optionals[optInd] = true
+ }
+ for i, e := range create.GetElements() {
c.check(e)
- elemType = c.joinTypes(c.location(e), elemType, c.getType(e))
+ elemType := c.getType(e)
+ if optionals[int32(i)] {
+ var isOptional bool
+ elemType, isOptional = maybeUnwrapOptional(elemType)
+ if !isOptional && !isDyn(elemType) {
+ c.errors.typeMismatch(e.GetId(), c.location(e), types.NewOptionalType(elemType), elemType)
+ }
+ }
+ elemsType = c.joinTypes(e, elemsType, elemType)
}
- if elemType == nil {
+ if elemsType == nil {
// If the list is empty, assign free type var to elem type.
- elemType = c.newTypeVar()
+ elemsType = c.newTypeVar()
}
- c.setType(e, decls.NewListType(elemType))
+ c.setType(e, types.NewListType(elemsType))
}
func (c *checker) checkCreateStruct(e *exprpb.Expr) {
@@ -429,12 +453,12 @@ func (c *checker) checkCreateStruct(e *exprpb.Expr) {
func (c *checker) checkCreateMap(e *exprpb.Expr) {
mapVal := e.GetStructExpr()
- var mapKeyType *exprpb.Type
- var mapValueType *exprpb.Type
+ var mapKeyType *types.Type
+ var mapValueType *types.Type
for _, ent := range mapVal.GetEntries() {
key := ent.GetMapKey()
c.check(key)
- mapKeyType = c.joinTypes(c.location(key), mapKeyType, c.getType(key))
+ mapKeyType = c.joinTypes(key, mapKeyType, c.getType(key))
val := ent.GetValue()
c.check(val)
@@ -443,50 +467,54 @@ func (c *checker) checkCreateMap(e *exprpb.Expr) {
var isOptional bool
valType, isOptional = maybeUnwrapOptional(valType)
if !isOptional && !isDyn(valType) {
- c.errors.typeMismatch(c.location(val), decls.NewOptionalType(valType), valType)
+ c.errors.typeMismatch(val.GetId(), c.location(val), types.NewOptionalType(valType), valType)
}
}
- mapValueType = c.joinTypes(c.location(val), mapValueType, valType)
+ mapValueType = c.joinTypes(val, mapValueType, valType)
}
if mapKeyType == nil {
// If the map is empty, assign free type variables to typeKey and value type.
mapKeyType = c.newTypeVar()
mapValueType = c.newTypeVar()
}
- c.setType(e, decls.NewMapType(mapKeyType, mapValueType))
+ c.setType(e, types.NewMapType(mapKeyType, mapValueType))
}
func (c *checker) checkCreateMessage(e *exprpb.Expr) {
msgVal := e.GetStructExpr()
// Determine the type of the message.
- messageType := decls.Error
- decl := c.env.LookupIdent(msgVal.GetMessageName())
- if decl == nil {
+ resultType := types.ErrorType
+ ident := c.env.LookupIdent(msgVal.GetMessageName())
+ if ident == nil {
c.errors.undeclaredReference(
- c.location(e), c.env.container.Name(), msgVal.GetMessageName())
+ e.GetId(), c.location(e), c.env.container.Name(), msgVal.GetMessageName())
+ c.setType(e, types.ErrorType)
return
}
// Ensure the type name is fully qualified in the AST.
- msgVal.MessageName = decl.GetName()
- c.setReference(e, newIdentReference(decl.GetName(), nil))
- ident := decl.GetIdent()
- identKind := kindOf(ident.GetType())
- if identKind != kindError {
- if identKind != kindType {
- c.errors.notAType(c.location(e), ident.GetType())
+ typeName := ident.Name()
+ msgVal.MessageName = typeName
+ c.setReference(e, ast.NewIdentReference(ident.Name(), nil))
+ identKind := ident.Type().Kind()
+ if identKind != types.ErrorKind {
+ if identKind != types.TypeKind {
+ c.errors.notAType(e.GetId(), c.location(e), ident.Type().DeclaredTypeName())
} else {
- messageType = ident.GetType().GetType()
- if kindOf(messageType) != kindObject {
- c.errors.notAMessageType(c.location(e), messageType)
- messageType = decls.Error
+ resultType = ident.Type().Parameters()[0]
+ // Backwards compatibility test between well-known types and message types
+ // In this context, the type is being instantiated by its protobuf name which
+ // is not ideal or recommended, but some users expect this to work.
+ if isWellKnownType(resultType) {
+ typeName = getWellKnownTypeName(resultType)
+ } else if resultType.Kind() == types.StructKind {
+ typeName = resultType.DeclaredTypeName()
+ } else {
+ c.errors.notAMessageType(e.GetId(), c.location(e), resultType.DeclaredTypeName())
+ resultType = types.ErrorType
}
}
}
- if isObjectWellKnownType(messageType) {
- c.setType(e, getObjectWellKnownType(messageType))
- } else {
- c.setType(e, messageType)
- }
+ c.setType(e, resultType)
// Check the field initializers.
for _, ent := range msgVal.GetEntries() {
@@ -494,10 +522,10 @@ func (c *checker) checkCreateMessage(e *exprpb.Expr) {
value := ent.GetValue()
c.check(value)
- fieldType := decls.Error
- ft, found := c.lookupFieldType(c.locationByID(ent.GetId()), messageType.GetMessageType(), field)
+ fieldType := types.ErrorType
+ ft, found := c.lookupFieldType(ent.GetId(), typeName, field)
if found {
- fieldType = ft.Type
+ fieldType = ft
}
valType := c.getType(value)
@@ -505,11 +533,11 @@ func (c *checker) checkCreateMessage(e *exprpb.Expr) {
var isOptional bool
valType, isOptional = maybeUnwrapOptional(valType)
if !isOptional && !isDyn(valType) {
- c.errors.typeMismatch(c.location(value), decls.NewOptionalType(valType), valType)
+ c.errors.typeMismatch(value.GetId(), c.location(value), types.NewOptionalType(valType), valType)
}
}
if !c.isAssignable(fieldType, valType) {
- c.errors.fieldTypeMismatch(c.locationByID(ent.Id), field, fieldType, valType)
+ c.errors.fieldTypeMismatch(ent.GetId(), c.locationByID(ent.GetId()), field, fieldType, valType)
}
}
}
@@ -520,36 +548,36 @@ func (c *checker) checkComprehension(e *exprpb.Expr) {
c.check(comp.GetAccuInit())
accuType := c.getType(comp.GetAccuInit())
rangeType := substitute(c.mappings, c.getType(comp.GetIterRange()), false)
- var varType *exprpb.Type
+ var varType *types.Type
- switch kindOf(rangeType) {
- case kindList:
- varType = rangeType.GetListType().GetElemType()
- case kindMap:
+ switch rangeType.Kind() {
+ case types.ListKind:
+ varType = rangeType.Parameters()[0]
+ case types.MapKind:
// Ranges over the keys.
- varType = rangeType.GetMapType().GetKeyType()
- case kindDyn, kindError, kindTypeParam:
+ varType = rangeType.Parameters()[0]
+ case types.DynKind, types.ErrorKind, types.TypeParamKind:
// Set the range type to DYN to prevent assignment to a potentially incorrect type
// at a later point in type-checking. The isAssignable call will update the type
// substitutions for the type param under the covers.
- c.isAssignable(decls.Dyn, rangeType)
+ c.isAssignable(types.DynType, rangeType)
// Set the range iteration variable to type DYN as well.
- varType = decls.Dyn
+ varType = types.DynType
default:
- c.errors.notAComprehensionRange(c.location(comp.GetIterRange()), rangeType)
- varType = decls.Error
+ c.errors.notAComprehensionRange(comp.GetIterRange().GetId(), c.location(comp.GetIterRange()), rangeType)
+ varType = types.ErrorType
}
// Create a scope for the comprehension since it has a local accumulation variable.
// This scope will contain the accumulation variable used to compute the result.
c.env = c.env.enterScope()
- c.env.Add(decls.NewVar(comp.GetAccuVar(), accuType))
+ c.env.AddIdents(decls.NewVariable(comp.GetAccuVar(), accuType))
// Create a block scope for the loop.
c.env = c.env.enterScope()
- c.env.Add(decls.NewVar(comp.GetIterVar(), varType))
+ c.env.AddIdents(decls.NewVariable(comp.GetIterVar(), varType))
// Check the variable references in the condition and step.
c.check(comp.GetLoopCondition())
- c.assertType(comp.GetLoopCondition(), decls.Bool)
+ c.assertType(comp.GetLoopCondition(), types.BoolType)
c.check(comp.GetLoopStep())
c.assertType(comp.GetLoopStep(), accuType)
// Exit the loop's block scope before checking the result.
@@ -561,9 +589,7 @@ func (c *checker) checkComprehension(e *exprpb.Expr) {
}
// Checks compatibility of joined types, and returns the most general common type.
-func (c *checker) joinTypes(loc common.Location,
- previous *exprpb.Type,
- current *exprpb.Type) *exprpb.Type {
+func (c *checker) joinTypes(e *exprpb.Expr, previous, current *types.Type) *types.Type {
if previous == nil {
return current
}
@@ -571,23 +597,23 @@ func (c *checker) joinTypes(loc common.Location,
return mostGeneral(previous, current)
}
if c.dynAggregateLiteralElementTypesEnabled() {
- return decls.Dyn
+ return types.DynType
}
- c.errors.typeMismatch(loc, previous, current)
- return decls.Error
+ c.errors.typeMismatch(e.GetId(), c.location(e), previous, current)
+ return types.ErrorType
}
func (c *checker) dynAggregateLiteralElementTypesEnabled() bool {
return c.env.aggLitElemType == dynElementType
}
-func (c *checker) newTypeVar() *exprpb.Type {
+func (c *checker) newTypeVar() *types.Type {
id := c.freeTypeVarCounter
c.freeTypeVarCounter++
- return decls.NewTypeParamType(fmt.Sprintf("_var%d", id))
+ return types.NewTypeParamType(fmt.Sprintf("_var%d", id))
}
-func (c *checker) isAssignable(t1 *exprpb.Type, t2 *exprpb.Type) bool {
+func (c *checker) isAssignable(t1, t2 *types.Type) bool {
subs := isAssignable(c.mappings, t1, t2)
if subs != nil {
c.mappings = subs
@@ -597,7 +623,7 @@ func (c *checker) isAssignable(t1 *exprpb.Type, t2 *exprpb.Type) bool {
return false
}
-func (c *checker) isAssignableList(l1 []*exprpb.Type, l2 []*exprpb.Type) bool {
+func (c *checker) isAssignableList(l1, l2 []*types.Type) bool {
subs := isAssignableList(c.mappings, l1, l2)
if subs != nil {
c.mappings = subs
@@ -607,57 +633,52 @@ func (c *checker) isAssignableList(l1 []*exprpb.Type, l2 []*exprpb.Type) bool {
return false
}
-func (c *checker) lookupFieldType(l common.Location, messageType string, fieldName string) (*ref.FieldType, bool) {
- if _, found := c.env.provider.FindType(messageType); !found {
- // This should not happen, anyway, report an error.
- c.errors.unexpectedFailedResolution(l, messageType)
- return nil, false
- }
-
- if ft, found := c.env.provider.FindFieldType(messageType, fieldName); found {
- return ft, found
+func maybeUnwrapString(e *exprpb.Expr) (string, bool) {
+ switch e.GetExprKind().(type) {
+ case *exprpb.Expr_ConstExpr:
+ literal := e.GetConstExpr()
+ switch literal.GetConstantKind().(type) {
+ case *exprpb.Constant_StringValue:
+ return literal.GetStringValue(), true
+ }
}
-
- c.errors.undefinedField(l, fieldName)
- return nil, false
+ return "", false
}
-func (c *checker) setType(e *exprpb.Expr, t *exprpb.Type) {
- if old, found := c.types[e.GetId()]; found && !proto.Equal(old, t) {
- c.errors.ReportError(c.location(e),
- "(Incompatible) Type already exists for expression: %v(%d) old:%v, new:%v", e, e.GetId(), old, t)
+func (c *checker) setType(e *exprpb.Expr, t *types.Type) {
+ if old, found := c.types[e.GetId()]; found && !old.IsExactType(t) {
+ c.errors.incompatibleType(e.GetId(), c.location(e), e, old, t)
return
}
c.types[e.GetId()] = t
}
-func (c *checker) getType(e *exprpb.Expr) *exprpb.Type {
+func (c *checker) getType(e *exprpb.Expr) *types.Type {
return c.types[e.GetId()]
}
-func (c *checker) setReference(e *exprpb.Expr, r *exprpb.Reference) {
- if old, found := c.references[e.GetId()]; found && !proto.Equal(old, r) {
- c.errors.ReportError(c.location(e),
- "Reference already exists for expression: %v(%d) old:%v, new:%v", e, e.GetId(), old, r)
+func (c *checker) setReference(e *exprpb.Expr, r *ast.ReferenceInfo) {
+ if old, found := c.references[e.GetId()]; found && !old.Equals(r) {
+ c.errors.referenceRedefinition(e.GetId(), c.location(e), e, old, r)
return
}
c.references[e.GetId()] = r
}
-func (c *checker) assertType(e *exprpb.Expr, t *exprpb.Type) {
+func (c *checker) assertType(e *exprpb.Expr, t *types.Type) {
if !c.isAssignable(t, c.getType(e)) {
- c.errors.typeMismatch(c.location(e), t, c.getType(e))
+ c.errors.typeMismatch(e.GetId(), c.location(e), t, c.getType(e))
}
}
type overloadResolution struct {
- Reference *exprpb.Reference
- Type *exprpb.Type
+ Type *types.Type
+ Reference *ast.ReferenceInfo
}
-func newResolution(checkedRef *exprpb.Reference, t *exprpb.Type) *overloadResolution {
+func newResolution(r *ast.ReferenceInfo, t *types.Type) *overloadResolution {
return &overloadResolution{
- Reference: checkedRef,
+ Reference: r,
Type: t,
}
}
@@ -684,10 +705,56 @@ func (c *checker) locationByID(id int64) common.Location {
return common.NoLocation
}
-func newIdentReference(name string, value *exprpb.Constant) *exprpb.Reference {
- return &exprpb.Reference{Name: name, Value: value}
+func (c *checker) lookupFieldType(exprID int64, structType, fieldName string) (*types.Type, bool) {
+ if _, found := c.env.provider.FindStructType(structType); !found {
+ // This should not happen, anyway, report an error.
+ c.errors.unexpectedFailedResolution(exprID, c.locationByID(exprID), structType)
+ return nil, false
+ }
+
+ if ft, found := c.env.provider.FindStructFieldType(structType, fieldName); found {
+ return ft.Type, found
+ }
+
+ c.errors.undefinedField(exprID, c.locationByID(exprID), fieldName)
+ return nil, false
+}
+
+func isWellKnownType(t *types.Type) bool {
+ switch t.Kind() {
+ case types.AnyKind, types.TimestampKind, types.DurationKind, types.DynKind, types.NullTypeKind:
+ return true
+ case types.BoolKind, types.BytesKind, types.DoubleKind, types.IntKind, types.StringKind, types.UintKind:
+ return t.IsAssignableType(types.NullType)
+ case types.ListKind:
+ return t.Parameters()[0] == types.DynType
+ case types.MapKind:
+ return t.Parameters()[0] == types.StringType && t.Parameters()[1] == types.DynType
+ }
+ return false
}
-func newFunctionReference(overloads ...string) *exprpb.Reference {
- return &exprpb.Reference{OverloadId: overloads}
+func getWellKnownTypeName(t *types.Type) string {
+ if name, found := wellKnownTypes[t.Kind()]; found {
+ return name
+ }
+ return ""
}
+
+var (
+ wellKnownTypes = map[types.Kind]string{
+ types.AnyKind: "google.protobuf.Any",
+ types.BoolKind: "google.protobuf.BoolValue",
+ types.BytesKind: "google.protobuf.BytesValue",
+ types.DoubleKind: "google.protobuf.DoubleValue",
+ types.DurationKind: "google.protobuf.Duration",
+ types.DynKind: "google.protobuf.Value",
+ types.IntKind: "google.protobuf.Int64Value",
+ types.ListKind: "google.protobuf.ListValue",
+ types.NullTypeKind: "google.protobuf.NullValue",
+ types.MapKind: "google.protobuf.Struct",
+ types.StringKind: "google.protobuf.StringValue",
+ types.TimestampKind: "google.protobuf.Timestamp",
+ types.UintKind: "google.protobuf.UInt64Value",
+ }
+)
diff --git a/vendor/github.com/google/cel-go/checker/cost.go b/vendor/github.com/google/cel-go/checker/cost.go
index 7312d1fe2..d6a799a8d 100644
--- a/vendor/github.com/google/cel-go/checker/cost.go
+++ b/vendor/github.com/google/cel-go/checker/cost.go
@@ -18,7 +18,9 @@ import (
"math"
"github.com/google/cel-go/common"
+ "github.com/google/cel-go/common/ast"
"github.com/google/cel-go/common/overloads"
+ "github.com/google/cel-go/common/types"
"github.com/google/cel-go/parser"
exprpb "google.golang.org/genproto/googleapis/api/expr/v1alpha1"
@@ -54,7 +56,7 @@ type AstNode interface {
// The first path element is a variable. All subsequent path elements are one of: field name, '@items', '@keys', '@values'.
Path() []string
// Type returns the deduced type of the AstNode.
- Type() *exprpb.Type
+ Type() *types.Type
// Expr returns the expression of the AstNode.
Expr() *exprpb.Expr
// ComputedSize returns a size estimate of the AstNode derived from information available in the CEL expression.
@@ -66,7 +68,7 @@ type AstNode interface {
type astNode struct {
path []string
- t *exprpb.Type
+ t *types.Type
expr *exprpb.Expr
derivedSize *SizeEstimate
}
@@ -75,7 +77,7 @@ func (e astNode) Path() []string {
return e.path
}
-func (e astNode) Type() *exprpb.Type {
+func (e astNode) Type() *types.Type {
return e.t
}
@@ -92,7 +94,10 @@ func (e astNode) ComputedSize() *SizeEstimate {
case *exprpb.Expr_ConstExpr:
switch ck := ek.ConstExpr.GetConstantKind().(type) {
case *exprpb.Constant_StringValue:
- v = uint64(len(ck.StringValue))
+ // converting to runes here is an O(n) operation, but
+ // this is consistent with how size is computed at runtime,
+ // and how the language definition defines string size
+ v = uint64(len([]rune(ck.StringValue)))
case *exprpb.Constant_BytesValue:
v = uint64(len(ck.BytesValue))
case *exprpb.Constant_BoolValue, *exprpb.Constant_DoubleValue, *exprpb.Constant_DurationValue,
@@ -256,8 +261,10 @@ type coster struct {
iterRanges iterRangeScopes
// computedSizes tracks the computed sizes of call results.
computedSizes map[int64]SizeEstimate
- checkedExpr *exprpb.CheckedExpr
+ checkedAST *ast.CheckedAST
estimator CostEstimator
+ // presenceTestCost will either be a zero or one based on whether has() macros count against cost computations.
+ presenceTestCost CostEstimate
}
// Use a stack of iterVar -> iterRange Expr Ids to handle shadowed variable names.
@@ -280,16 +287,39 @@ func (vs iterRangeScopes) peek(varName string) (int64, bool) {
return 0, false
}
+// CostOption configures flags which affect cost computations.
+type CostOption func(*coster) error
+
+// PresenceTestHasCost determines whether presence testing has a cost of one or zero.
+// Defaults to presence test has a cost of one.
+func PresenceTestHasCost(hasCost bool) CostOption {
+ return func(c *coster) error {
+ if hasCost {
+ c.presenceTestCost = selectAndIdentCost
+ return nil
+ }
+ c.presenceTestCost = CostEstimate{Min: 0, Max: 0}
+ return nil
+ }
+}
+
// Cost estimates the cost of the parsed and type checked CEL expression.
-func Cost(checker *exprpb.CheckedExpr, estimator CostEstimator) CostEstimate {
- c := coster{
- checkedExpr: checker,
- estimator: estimator,
- exprPath: map[int64][]string{},
- iterRanges: map[string][]int64{},
- computedSizes: map[int64]SizeEstimate{},
+func Cost(checker *ast.CheckedAST, estimator CostEstimator, opts ...CostOption) (CostEstimate, error) {
+ c := &coster{
+ checkedAST: checker,
+ estimator: estimator,
+ exprPath: map[int64][]string{},
+ iterRanges: map[string][]int64{},
+ computedSizes: map[int64]SizeEstimate{},
+ presenceTestCost: CostEstimate{Min: 1, Max: 1},
+ }
+ for _, opt := range opts {
+ err := opt(c)
+ if err != nil {
+ return CostEstimate{}, err
+ }
}
- return c.cost(checker.GetExpr())
+ return c.cost(checker.Expr), nil
}
func (c *coster) cost(e *exprpb.Expr) CostEstimate {
@@ -323,10 +353,10 @@ func (c *coster) costIdent(e *exprpb.Expr) CostEstimate {
// build and track the field path
if iterRange, ok := c.iterRanges.peek(identExpr.GetName()); ok {
- switch c.checkedExpr.TypeMap[iterRange].GetTypeKind().(type) {
- case *exprpb.Type_ListType_:
+ switch c.checkedAST.TypeMap[iterRange].Kind() {
+ case types.ListKind:
c.addPath(e, append(c.exprPath[iterRange], "@items"))
- case *exprpb.Type_MapType_:
+ case types.MapKind:
c.addPath(e, append(c.exprPath[iterRange], "@keys"))
}
} else {
@@ -340,12 +370,18 @@ func (c *coster) costSelect(e *exprpb.Expr) CostEstimate {
sel := e.GetSelectExpr()
var sum CostEstimate
if sel.GetTestOnly() {
+ // recurse, but do not add any cost
+ // this is equivalent to how evalTestOnly increments the runtime cost counter
+ // but does not add any additional cost for the qualifier, except here we do
+ // the reverse (ident adds cost)
+ sum = sum.Add(c.presenceTestCost)
+ sum = sum.Add(c.cost(sel.GetOperand()))
return sum
}
sum = sum.Add(c.cost(sel.GetOperand()))
targetType := c.getType(sel.GetOperand())
- switch kindOf(targetType) {
- case kindMap, kindObject, kindTypeParam:
+ switch targetType.Kind() {
+ case types.MapKind, types.StructKind, types.TypeParamKind:
sum = sum.Add(selectAndIdentCost)
}
@@ -369,8 +405,8 @@ func (c *coster) costCall(e *exprpb.Expr) CostEstimate {
argTypes[i] = c.newAstNode(arg)
}
- ref := c.checkedExpr.ReferenceMap[e.GetId()]
- if ref == nil || len(ref.GetOverloadId()) == 0 {
+ ref := c.checkedAST.ReferenceMap[e.GetId()]
+ if ref == nil || len(ref.OverloadIDs) == 0 {
return CostEstimate{}
}
var targetType AstNode
@@ -383,7 +419,7 @@ func (c *coster) costCall(e *exprpb.Expr) CostEstimate {
// Pick a cost estimate range that covers all the overload cost estimation ranges
fnCost := CostEstimate{Min: uint64(math.MaxUint64), Max: 0}
var resultSize *SizeEstimate
- for _, overload := range ref.GetOverloadId() {
+ for _, overload := range ref.OverloadIDs {
overloadCost := c.functionCost(call.GetFunction(), overload, &targetType, argTypes, argCosts)
fnCost = fnCost.Union(overloadCost.CostEstimate)
if overloadCost.ResultSize != nil {
@@ -503,7 +539,10 @@ func (c *coster) functionCost(function, overloadID string, target *AstNode, args
}
switch overloadID {
// O(n) functions
- case overloads.StartsWithString, overloads.EndsWithString, overloads.StringToBytes, overloads.BytesToString:
+ case overloads.StartsWithString, overloads.EndsWithString, overloads.StringToBytes, overloads.BytesToString, overloads.ExtQuoteString, overloads.ExtFormatString:
+ if overloadID == overloads.ExtFormatString {
+ return CallEstimate{CostEstimate: c.sizeEstimate(*target).MultiplyByCostFactor(common.StringTraversalCostFactor).Add(argCostSum())}
+ }
if len(args) == 1 {
return CallEstimate{CostEstimate: c.sizeEstimate(args[0]).MultiplyByCostFactor(common.StringTraversalCostFactor).Add(argCostSum())}
}
@@ -584,8 +623,8 @@ func (c *coster) functionCost(function, overloadID string, target *AstNode, args
return CallEstimate{CostEstimate: CostEstimate{Min: 1, Max: 1}.Add(argCostSum())}
}
-func (c *coster) getType(e *exprpb.Expr) *exprpb.Type {
- return c.checkedExpr.TypeMap[e.GetId()]
+func (c *coster) getType(e *exprpb.Expr) *types.Type {
+ return c.checkedAST.TypeMap[e.GetId()]
}
func (c *coster) getPath(e *exprpb.Expr) []string {
@@ -606,22 +645,20 @@ func (c *coster) newAstNode(e *exprpb.Expr) *astNode {
if size, ok := c.computedSizes[e.GetId()]; ok {
derivedSize = &size
}
- return &astNode{path: path, t: c.getType(e), expr: e, derivedSize: derivedSize}
+ return &astNode{
+ path: path,
+ t: c.getType(e),
+ expr: e,
+ derivedSize: derivedSize}
}
// isScalar returns true if the given type is known to be of a constant size at
// compile time. isScalar will return false for strings (they are variable-width)
// in addition to protobuf.Any and protobuf.Value (their size is not knowable at compile time).
-func isScalar(t *exprpb.Type) bool {
- switch kindOf(t) {
- case kindPrimitive:
- if t.GetPrimitive() != exprpb.Type_STRING && t.GetPrimitive() != exprpb.Type_BYTES {
- return true
- }
- case kindWellKnown:
- if t.GetWellKnown() == exprpb.Type_DURATION || t.GetWellKnown() == exprpb.Type_TIMESTAMP {
- return true
- }
+func isScalar(t *types.Type) bool {
+ switch t.Kind() {
+ case types.BoolKind, types.DoubleKind, types.DurationKind, types.IntKind, types.TimestampKind, types.UintKind:
+ return true
}
return false
}
diff --git a/vendor/github.com/google/cel-go/checker/decls/BUILD.bazel b/vendor/github.com/google/cel-go/checker/decls/BUILD.bazel
index 5a24f1da8..a6b0be292 100644
--- a/vendor/github.com/google/cel-go/checker/decls/BUILD.bazel
+++ b/vendor/github.com/google/cel-go/checker/decls/BUILD.bazel
@@ -9,11 +9,10 @@ go_library(
name = "go_default_library",
srcs = [
"decls.go",
- "scopes.go",
],
importpath = "github.com/google/cel-go/checker/decls",
deps = [
- "@org_golang_google_genproto//googleapis/api/expr/v1alpha1:go_default_library",
+ "@org_golang_google_genproto_googleapis_api//expr/v1alpha1:go_default_library",
"@org_golang_google_protobuf//types/known/emptypb:go_default_library",
"@org_golang_google_protobuf//types/known/structpb:go_default_library",
],
diff --git a/vendor/github.com/google/cel-go/checker/env.go b/vendor/github.com/google/cel-go/checker/env.go
index c7eeb04ee..70682b17c 100644
--- a/vendor/github.com/google/cel-go/checker/env.go
+++ b/vendor/github.com/google/cel-go/checker/env.go
@@ -18,17 +18,11 @@ import (
"fmt"
"strings"
- "google.golang.org/protobuf/proto"
-
- "github.com/google/cel-go/checker/decls"
"github.com/google/cel-go/common/containers"
+ "github.com/google/cel-go/common/decls"
"github.com/google/cel-go/common/overloads"
"github.com/google/cel-go/common/types"
- "github.com/google/cel-go/common/types/pb"
- "github.com/google/cel-go/common/types/ref"
"github.com/google/cel-go/parser"
-
- exprpb "google.golang.org/genproto/googleapis/api/expr/v1alpha1"
)
type aggregateLiteralElementType int
@@ -76,15 +70,15 @@ var (
// which can be used to assist with type-checking.
type Env struct {
container *containers.Container
- provider ref.TypeProvider
- declarations *decls.Scopes
+ provider types.Provider
+ declarations *Scopes
aggLitElemType aggregateLiteralElementType
filteredOverloadIDs map[string]struct{}
}
// NewEnv returns a new *Env with the given parameters.
-func NewEnv(container *containers.Container, provider ref.TypeProvider, opts ...Option) (*Env, error) {
- declarations := decls.NewScopes()
+func NewEnv(container *containers.Container, provider types.Provider, opts ...Option) (*Env, error) {
+ declarations := newScopes()
declarations.Push()
envOptions := &options{}
@@ -113,24 +107,31 @@ func NewEnv(container *containers.Container, provider ref.TypeProvider, opts ...
}, nil
}
-// Add adds new Decl protos to the Env.
-// Returns an error for identifier redeclarations.
-func (e *Env) Add(decls ...*exprpb.Decl) error {
+// AddIdents configures the checker with a list of variable declarations.
+//
+// If there are overlapping declarations, the method will error.
+func (e *Env) AddIdents(declarations ...*decls.VariableDecl) error {
errMsgs := make([]errorMsg, 0)
- for _, decl := range decls {
- switch decl.DeclKind.(type) {
- case *exprpb.Decl_Ident:
- errMsgs = append(errMsgs, e.addIdent(sanitizeIdent(decl)))
- case *exprpb.Decl_Function:
- errMsgs = append(errMsgs, e.setFunction(sanitizeFunction(decl))...)
- }
+ for _, d := range declarations {
+ errMsgs = append(errMsgs, e.addIdent(d))
+ }
+ return formatError(errMsgs)
+}
+
+// AddFunctions configures the checker with a list of function declarations.
+//
+// If there are overlapping declarations, the method will error.
+func (e *Env) AddFunctions(declarations ...*decls.FunctionDecl) error {
+ errMsgs := make([]errorMsg, 0)
+ for _, d := range declarations {
+ errMsgs = append(errMsgs, e.setFunction(d)...)
}
return formatError(errMsgs)
}
// LookupIdent returns a Decl proto for typeName as an identifier in the Env.
// Returns nil if no such identifier is found in the Env.
-func (e *Env) LookupIdent(name string) *exprpb.Decl {
+func (e *Env) LookupIdent(name string) *decls.VariableDecl {
for _, candidate := range e.container.ResolveCandidateNames(name) {
if ident := e.declarations.FindIdent(candidate); ident != nil {
return ident
@@ -139,8 +140,8 @@ func (e *Env) LookupIdent(name string) *exprpb.Decl {
// Next try to import the name as a reference to a message type. If found,
// the declaration is added to the outest (global) scope of the
// environment, so next time we can access it faster.
- if t, found := e.provider.FindType(candidate); found {
- decl := decls.NewVar(candidate, t)
+ if t, found := e.provider.FindStructType(candidate); found {
+ decl := decls.NewVariable(candidate, t)
e.declarations.AddIdent(decl)
return decl
}
@@ -148,11 +149,7 @@ func (e *Env) LookupIdent(name string) *exprpb.Decl {
// Next try to import this as an enum value by splitting the name in a type prefix and
// the enum inside.
if enumValue := e.provider.EnumValue(candidate); enumValue.Type() != types.ErrType {
- decl := decls.NewIdent(candidate,
- decls.Int,
- &exprpb.Constant{
- ConstantKind: &exprpb.Constant_Int64Value{
- Int64Value: int64(enumValue.(types.Int))}})
+ decl := decls.NewConstant(candidate, types.IntType, enumValue)
e.declarations.AddIdent(decl)
return decl
}
@@ -162,7 +159,7 @@ func (e *Env) LookupIdent(name string) *exprpb.Decl {
// LookupFunction returns a Decl proto for typeName as a function in env.
// Returns nil if no such function is found in env.
-func (e *Env) LookupFunction(name string) *exprpb.Decl {
+func (e *Env) LookupFunction(name string) *decls.FunctionDecl {
for _, candidate := range e.container.ResolveCandidateNames(name) {
if fn := e.declarations.FindFunction(candidate); fn != nil {
return fn
@@ -171,88 +168,46 @@ func (e *Env) LookupFunction(name string) *exprpb.Decl {
return nil
}
-// addOverload adds overload to function declaration f.
-// Returns one or more errorMsg values if the overload overlaps with an existing overload or macro.
-func (e *Env) addOverload(f *exprpb.Decl, overload *exprpb.Decl_FunctionDecl_Overload) []errorMsg {
- errMsgs := make([]errorMsg, 0)
- function := f.GetFunction()
- emptyMappings := newMapping()
- overloadFunction := decls.NewFunctionType(overload.GetResultType(),
- overload.GetParams()...)
- overloadErased := substitute(emptyMappings, overloadFunction, true)
- for _, existing := range function.GetOverloads() {
- existingFunction := decls.NewFunctionType(existing.GetResultType(), existing.GetParams()...)
- existingErased := substitute(emptyMappings, existingFunction, true)
- overlap := isAssignable(emptyMappings, overloadErased, existingErased) != nil ||
- isAssignable(emptyMappings, existingErased, overloadErased) != nil
- if overlap &&
- overload.GetIsInstanceFunction() == existing.GetIsInstanceFunction() {
- errMsgs = append(errMsgs,
- overlappingOverloadError(f.Name,
- overload.GetOverloadId(), overloadFunction,
- existing.GetOverloadId(), existingFunction))
- }
- }
-
- for _, macro := range parser.AllMacros {
- if macro.Function() == f.Name &&
- macro.IsReceiverStyle() == overload.GetIsInstanceFunction() &&
- macro.ArgCount() == len(overload.GetParams()) {
- errMsgs = append(errMsgs, overlappingMacroError(f.Name, macro.ArgCount()))
- }
- }
- if len(errMsgs) > 0 {
- return errMsgs
- }
- function.Overloads = append(function.GetOverloads(), overload)
- return errMsgs
-}
-
// setFunction adds the function Decl to the Env.
// Adds a function decl if one doesn't already exist, then adds all overloads from the Decl.
// If overload overlaps with an existing overload, adds to the errors in the Env instead.
-func (e *Env) setFunction(decl *exprpb.Decl) []errorMsg {
- errorMsgs := make([]errorMsg, 0)
- overloads := decl.GetFunction().GetOverloads()
- current := e.declarations.FindFunction(decl.Name)
- if current == nil {
- //Add the function declaration without overloads and check the overloads below.
- current = decls.NewFunction(decl.Name)
- } else {
- existingOverloads := map[string]*exprpb.Decl_FunctionDecl_Overload{}
- for _, overload := range current.GetFunction().GetOverloads() {
- existingOverloads[overload.GetOverloadId()] = overload
+func (e *Env) setFunction(fn *decls.FunctionDecl) []errorMsg {
+ errMsgs := make([]errorMsg, 0)
+ current := e.declarations.FindFunction(fn.Name())
+ if current != nil {
+ var err error
+ current, err = current.Merge(fn)
+ if err != nil {
+ return append(errMsgs, errorMsg(err.Error()))
}
- newOverloads := []*exprpb.Decl_FunctionDecl_Overload{}
- for _, overload := range overloads {
- existing, found := existingOverloads[overload.GetOverloadId()]
- if !found || !proto.Equal(existing, overload) {
- newOverloads = append(newOverloads, overload)
+ } else {
+ current = fn
+ }
+ for _, overload := range current.OverloadDecls() {
+ for _, macro := range parser.AllMacros {
+ if macro.Function() == current.Name() &&
+ macro.IsReceiverStyle() == overload.IsMemberFunction() &&
+ macro.ArgCount() == len(overload.ArgTypes()) {
+ errMsgs = append(errMsgs, overlappingMacroError(current.Name(), macro.ArgCount()))
}
}
- overloads = newOverloads
- if len(newOverloads) == 0 {
- return errorMsgs
+ if len(errMsgs) > 0 {
+ return errMsgs
}
- // Copy on write since we don't know where this original definition came from.
- current = proto.Clone(current).(*exprpb.Decl)
}
e.declarations.SetFunction(current)
- for _, overload := range overloads {
- errorMsgs = append(errorMsgs, e.addOverload(current, overload)...)
- }
- return errorMsgs
+ return errMsgs
}
// addIdent adds the Decl to the declarations in the Env.
// Returns a non-empty errorMsg if the identifier is already declared in the scope.
-func (e *Env) addIdent(decl *exprpb.Decl) errorMsg {
- current := e.declarations.FindIdentInScope(decl.Name)
+func (e *Env) addIdent(decl *decls.VariableDecl) errorMsg {
+ current := e.declarations.FindIdentInScope(decl.Name())
if current != nil {
- if proto.Equal(current, decl) {
+ if current.DeclarationIsEquivalent(decl) {
return ""
}
- return overlappingIdentifierError(decl.Name)
+ return overlappingIdentifierError(decl.Name())
}
e.declarations.AddIdent(decl)
return ""
@@ -264,86 +219,9 @@ func (e *Env) isOverloadDisabled(overloadID string) bool {
return found
}
-// sanitizeFunction replaces well-known types referenced by message name with their equivalent
-// CEL built-in type instances.
-func sanitizeFunction(decl *exprpb.Decl) *exprpb.Decl {
- fn := decl.GetFunction()
- // Determine whether the declaration requires replacements from proto-based message type
- // references to well-known CEL type references.
- var needsSanitizing bool
- for _, o := range fn.GetOverloads() {
- if isObjectWellKnownType(o.GetResultType()) {
- needsSanitizing = true
- break
- }
- for _, p := range o.GetParams() {
- if isObjectWellKnownType(p) {
- needsSanitizing = true
- break
- }
- }
- }
-
- // Early return if the declaration requires no modification.
- if !needsSanitizing {
- return decl
- }
-
- // Sanitize all of the overloads if any overload requires an update to its type references.
- overloads := make([]*exprpb.Decl_FunctionDecl_Overload, len(fn.GetOverloads()))
- for i, o := range fn.GetOverloads() {
- rt := o.GetResultType()
- if isObjectWellKnownType(rt) {
- rt = getObjectWellKnownType(rt)
- }
- params := make([]*exprpb.Type, len(o.GetParams()))
- copy(params, o.GetParams())
- for j, p := range params {
- if isObjectWellKnownType(p) {
- params[j] = getObjectWellKnownType(p)
- }
- }
- // If sanitized, replace the overload definition.
- if o.IsInstanceFunction {
- overloads[i] =
- decls.NewInstanceOverload(o.GetOverloadId(), params, rt)
- } else {
- overloads[i] =
- decls.NewOverload(o.GetOverloadId(), params, rt)
- }
- }
- return decls.NewFunction(decl.GetName(), overloads...)
-}
-
-// sanitizeIdent replaces the identifier's well-known types referenced by message name with
-// references to CEL built-in type instances.
-func sanitizeIdent(decl *exprpb.Decl) *exprpb.Decl {
- id := decl.GetIdent()
- t := id.GetType()
- if !isObjectWellKnownType(t) {
- return decl
- }
- return decls.NewIdent(decl.GetName(), getObjectWellKnownType(t), id.GetValue())
-}
-
-// isObjectWellKnownType returns true if the input type is an OBJECT type with a message name
-// that corresponds the message name of a built-in CEL type.
-func isObjectWellKnownType(t *exprpb.Type) bool {
- if kindOf(t) != kindObject {
- return false
- }
- _, found := pb.CheckedWellKnowns[t.GetMessageType()]
- return found
-}
-
-// getObjectWellKnownType returns the built-in CEL type declaration for input type's message name.
-func getObjectWellKnownType(t *exprpb.Type) *exprpb.Type {
- return pb.CheckedWellKnowns[t.GetMessageType()]
-}
-
// validatedDeclarations returns a reference to the validated variable and function declaration scope stack.
// must be copied before use.
-func (e *Env) validatedDeclarations() *decls.Scopes {
+func (e *Env) validatedDeclarations() *Scopes {
return e.declarations
}
@@ -377,19 +255,6 @@ func overlappingIdentifierError(name string) errorMsg {
return errorMsg(fmt.Sprintf("overlapping identifier for name '%s'", name))
}
-func overlappingOverloadError(name string,
- overloadID1 string, f1 *exprpb.Type,
- overloadID2 string, f2 *exprpb.Type) errorMsg {
- return errorMsg(fmt.Sprintf(
- "overlapping overload for name '%s' (type '%s' with overloadId: '%s' "+
- "cannot be distinguished from '%s' with overloadId: '%s')",
- name,
- FormatCheckedType(f1),
- overloadID1,
- FormatCheckedType(f2),
- overloadID2))
-}
-
func overlappingMacroError(name string, argCount int) errorMsg {
return errorMsg(fmt.Sprintf(
"overlapping macro for name '%s' with %d args", name, argCount))
diff --git a/vendor/github.com/google/cel-go/checker/errors.go b/vendor/github.com/google/cel-go/checker/errors.go
index 0014f9abe..c2b96498d 100644
--- a/vendor/github.com/google/cel-go/checker/errors.go
+++ b/vendor/github.com/google/cel-go/checker/errors.go
@@ -15,82 +15,78 @@
package checker
import (
+ "reflect"
+
"github.com/google/cel-go/common"
+ "github.com/google/cel-go/common/ast"
+ "github.com/google/cel-go/common/types"
exprpb "google.golang.org/genproto/googleapis/api/expr/v1alpha1"
)
// typeErrors is a specialization of Errors.
type typeErrors struct {
- *common.Errors
+ errs *common.Errors
+}
+
+func (e *typeErrors) fieldTypeMismatch(id int64, l common.Location, name string, field, value *types.Type) {
+ e.errs.ReportErrorAtID(id, l, "expected type of field '%s' is '%s' but provided type is '%s'",
+ name, FormatCELType(field), FormatCELType(value))
+}
+
+func (e *typeErrors) incompatibleType(id int64, l common.Location, ex *exprpb.Expr, prev, next *types.Type) {
+ e.errs.ReportErrorAtID(id, l,
+ "incompatible type already exists for expression: %v(%d) old:%v, new:%v", ex, ex.GetId(), prev, next)
+}
+
+func (e *typeErrors) noMatchingOverload(id int64, l common.Location, name string, args []*types.Type, isInstance bool) {
+ signature := formatFunctionDeclType(nil, args, isInstance)
+ e.errs.ReportErrorAtID(id, l, "found no matching overload for '%s' applied to '%s'", name, signature)
}
-func (e *typeErrors) undeclaredReference(l common.Location, container string, name string) {
- e.ReportError(l, "undeclared reference to '%s' (in container '%s')", name, container)
+func (e *typeErrors) notAComprehensionRange(id int64, l common.Location, t *types.Type) {
+ e.errs.ReportErrorAtID(id, l, "expression of type '%s' cannot be range of a comprehension (must be list, map, or dynamic)",
+ FormatCELType(t))
}
-func (e *typeErrors) typeDoesNotSupportFieldSelection(l common.Location, t *exprpb.Type) {
- e.ReportError(l, "type '%s' does not support field selection", t)
+func (e *typeErrors) notAnOptionalFieldSelection(id int64, l common.Location, field *exprpb.Expr) {
+ e.errs.ReportErrorAtID(id, l, "unsupported optional field selection: %v", field)
}
-func (e *typeErrors) undefinedField(l common.Location, field string) {
- e.ReportError(l, "undefined field '%s'", field)
+func (e *typeErrors) notAType(id int64, l common.Location, typeName string) {
+ e.errs.ReportErrorAtID(id, l, "'%s' is not a type", typeName)
}
-func (e *typeErrors) noMatchingOverload(l common.Location, name string, args []*exprpb.Type, isInstance bool) {
- signature := formatFunction(nil, args, isInstance)
- e.ReportError(l, "found no matching overload for '%s' applied to '%s'", name, signature)
+func (e *typeErrors) notAMessageType(id int64, l common.Location, typeName string) {
+ e.errs.ReportErrorAtID(id, l, "'%s' is not a message type", typeName)
}
-func (e *typeErrors) notAType(l common.Location, t *exprpb.Type) {
- e.ReportError(l, "'%s(%v)' is not a type", FormatCheckedType(t), t)
+func (e *typeErrors) referenceRedefinition(id int64, l common.Location, ex *exprpb.Expr, prev, next *ast.ReferenceInfo) {
+ e.errs.ReportErrorAtID(id, l,
+ "reference already exists for expression: %v(%d) old:%v, new:%v", ex, ex.GetId(), prev, next)
}
-func (e *typeErrors) notAMessageType(l common.Location, t *exprpb.Type) {
- e.ReportError(l, "'%s' is not a message type", FormatCheckedType(t))
+func (e *typeErrors) typeDoesNotSupportFieldSelection(id int64, l common.Location, t *types.Type) {
+ e.errs.ReportErrorAtID(id, l, "type '%s' does not support field selection", FormatCELType(t))
}
-func (e *typeErrors) fieldTypeMismatch(l common.Location, name string, field *exprpb.Type, value *exprpb.Type) {
- e.ReportError(l, "expected type of field '%s' is '%s' but provided type is '%s'",
- name, FormatCheckedType(field), FormatCheckedType(value))
+func (e *typeErrors) typeMismatch(id int64, l common.Location, expected, actual *types.Type) {
+ e.errs.ReportErrorAtID(id, l, "expected type '%s' but found '%s'",
+ FormatCELType(expected), FormatCELType(actual))
}
-func (e *typeErrors) unexpectedFailedResolution(l common.Location, typeName string) {
- e.ReportError(l, "[internal] unexpected failed resolution of '%s'", typeName)
+func (e *typeErrors) undefinedField(id int64, l common.Location, field string) {
+ e.errs.ReportErrorAtID(id, l, "undefined field '%s'", field)
}
-func (e *typeErrors) notAComprehensionRange(l common.Location, t *exprpb.Type) {
- e.ReportError(l, "expression of type '%s' cannot be range of a comprehension (must be list, map, or dynamic)",
- FormatCheckedType(t))
+func (e *typeErrors) undeclaredReference(id int64, l common.Location, container string, name string) {
+ e.errs.ReportErrorAtID(id, l, "undeclared reference to '%s' (in container '%s')", name, container)
}
-func (e *typeErrors) typeMismatch(l common.Location, expected *exprpb.Type, actual *exprpb.Type) {
- e.ReportError(l, "expected type '%s' but found '%s'",
- FormatCheckedType(expected), FormatCheckedType(actual))
+func (e *typeErrors) unexpectedFailedResolution(id int64, l common.Location, typeName string) {
+ e.errs.ReportErrorAtID(id, l, "unexpected failed resolution of '%s'", typeName)
}
-func formatFunction(resultType *exprpb.Type, argTypes []*exprpb.Type, isInstance bool) string {
- result := ""
- if isInstance {
- target := argTypes[0]
- argTypes = argTypes[1:]
-
- result += FormatCheckedType(target)
- result += "."
- }
-
- result += "("
- for i, arg := range argTypes {
- if i > 0 {
- result += ", "
- }
- result += FormatCheckedType(arg)
- }
- result += ")"
- if resultType != nil {
- result += " -> "
- result += FormatCheckedType(resultType)
- }
-
- return result
+func (e *typeErrors) unexpectedASTType(id int64, l common.Location, ex *exprpb.Expr) {
+ e.errs.ReportErrorAtID(id, l, "unrecognized ast type: %v", reflect.TypeOf(ex))
}
diff --git a/vendor/github.com/google/cel-go/checker/format.go b/vendor/github.com/google/cel-go/checker/format.go
new file mode 100644
index 000000000..95842905e
--- /dev/null
+++ b/vendor/github.com/google/cel-go/checker/format.go
@@ -0,0 +1,216 @@
+// Copyright 2023 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package checker
+
+import (
+ "fmt"
+ "strings"
+
+ chkdecls "github.com/google/cel-go/checker/decls"
+ "github.com/google/cel-go/common/types"
+
+ exprpb "google.golang.org/genproto/googleapis/api/expr/v1alpha1"
+)
+
+const (
+ kindUnknown = iota + 1
+ kindError
+ kindFunction
+ kindDyn
+ kindPrimitive
+ kindWellKnown
+ kindWrapper
+ kindNull
+ kindAbstract
+ kindType
+ kindList
+ kindMap
+ kindObject
+ kindTypeParam
+)
+
+// FormatCheckedType converts a type message into a string representation.
+func FormatCheckedType(t *exprpb.Type) string {
+ switch kindOf(t) {
+ case kindDyn:
+ return "dyn"
+ case kindFunction:
+ return formatFunctionExprType(t.GetFunction().GetResultType(),
+ t.GetFunction().GetArgTypes(),
+ false)
+ case kindList:
+ return fmt.Sprintf("list(%s)", FormatCheckedType(t.GetListType().GetElemType()))
+ case kindObject:
+ return t.GetMessageType()
+ case kindMap:
+ return fmt.Sprintf("map(%s, %s)",
+ FormatCheckedType(t.GetMapType().GetKeyType()),
+ FormatCheckedType(t.GetMapType().GetValueType()))
+ case kindNull:
+ return "null"
+ case kindPrimitive:
+ switch t.GetPrimitive() {
+ case exprpb.Type_UINT64:
+ return "uint"
+ case exprpb.Type_INT64:
+ return "int"
+ }
+ return strings.Trim(strings.ToLower(t.GetPrimitive().String()), " ")
+ case kindType:
+ if t.GetType() == nil || t.GetType().GetTypeKind() == nil {
+ return "type"
+ }
+ return fmt.Sprintf("type(%s)", FormatCheckedType(t.GetType()))
+ case kindWellKnown:
+ switch t.GetWellKnown() {
+ case exprpb.Type_ANY:
+ return "any"
+ case exprpb.Type_DURATION:
+ return "duration"
+ case exprpb.Type_TIMESTAMP:
+ return "timestamp"
+ }
+ case kindWrapper:
+ return fmt.Sprintf("wrapper(%s)",
+ FormatCheckedType(chkdecls.NewPrimitiveType(t.GetWrapper())))
+ case kindError:
+ return "!error!"
+ case kindTypeParam:
+ return t.GetTypeParam()
+ case kindAbstract:
+ at := t.GetAbstractType()
+ params := at.GetParameterTypes()
+ paramStrs := make([]string, len(params))
+ for i, p := range params {
+ paramStrs[i] = FormatCheckedType(p)
+ }
+ return fmt.Sprintf("%s(%s)", at.GetName(), strings.Join(paramStrs, ", "))
+ }
+ return t.String()
+}
+
+type formatter func(any) string
+
+// FormatCELType formats a types.Type value to a string representation.
+//
+// The type formatting is identical to FormatCheckedType.
+func FormatCELType(t any) string {
+ dt := t.(*types.Type)
+ switch dt.Kind() {
+ case types.AnyKind:
+ return "any"
+ case types.DurationKind:
+ return "duration"
+ case types.ErrorKind:
+ return "!error!"
+ case types.NullTypeKind:
+ return "null"
+ case types.TimestampKind:
+ return "timestamp"
+ case types.TypeParamKind:
+ return dt.TypeName()
+ case types.OpaqueKind:
+ if dt.TypeName() == "function" {
+ // There is no explicit function type in the new types representation, so information like
+ // whether the function is a member function is absent.
+ return formatFunctionDeclType(dt.Parameters()[0], dt.Parameters()[1:], false)
+ }
+ case types.UnspecifiedKind:
+ return ""
+ }
+ if len(dt.Parameters()) == 0 {
+ return dt.DeclaredTypeName()
+ }
+ paramTypeNames := make([]string, 0, len(dt.Parameters()))
+ for _, p := range dt.Parameters() {
+ paramTypeNames = append(paramTypeNames, FormatCELType(p))
+ }
+ return fmt.Sprintf("%s(%s)", dt.TypeName(), strings.Join(paramTypeNames, ", "))
+}
+
+func formatExprType(t any) string {
+ if t == nil {
+ return ""
+ }
+ return FormatCheckedType(t.(*exprpb.Type))
+}
+
+func formatFunctionExprType(resultType *exprpb.Type, argTypes []*exprpb.Type, isInstance bool) string {
+ return formatFunctionInternal[*exprpb.Type](resultType, argTypes, isInstance, formatExprType)
+}
+
+func formatFunctionDeclType(resultType *types.Type, argTypes []*types.Type, isInstance bool) string {
+ return formatFunctionInternal[*types.Type](resultType, argTypes, isInstance, FormatCELType)
+}
+
+func formatFunctionInternal[T any](resultType T, argTypes []T, isInstance bool, format formatter) string {
+ result := ""
+ if isInstance {
+ target := argTypes[0]
+ argTypes = argTypes[1:]
+ result += format(target)
+ result += "."
+ }
+ result += "("
+ for i, arg := range argTypes {
+ if i > 0 {
+ result += ", "
+ }
+ result += format(arg)
+ }
+ result += ")"
+ rt := format(resultType)
+ if rt != "" {
+ result += " -> "
+ result += rt
+ }
+ return result
+}
+
+// kindOf returns the kind of the type as defined in the checked.proto.
+func kindOf(t *exprpb.Type) int {
+ if t == nil || t.TypeKind == nil {
+ return kindUnknown
+ }
+ switch t.GetTypeKind().(type) {
+ case *exprpb.Type_Error:
+ return kindError
+ case *exprpb.Type_Function:
+ return kindFunction
+ case *exprpb.Type_Dyn:
+ return kindDyn
+ case *exprpb.Type_Primitive:
+ return kindPrimitive
+ case *exprpb.Type_WellKnown:
+ return kindWellKnown
+ case *exprpb.Type_Wrapper:
+ return kindWrapper
+ case *exprpb.Type_Null:
+ return kindNull
+ case *exprpb.Type_Type:
+ return kindType
+ case *exprpb.Type_ListType_:
+ return kindList
+ case *exprpb.Type_MapType_:
+ return kindMap
+ case *exprpb.Type_MessageType:
+ return kindObject
+ case *exprpb.Type_TypeParam:
+ return kindTypeParam
+ case *exprpb.Type_AbstractType_:
+ return kindAbstract
+ }
+ return kindUnknown
+}
diff --git a/vendor/github.com/google/cel-go/checker/mapping.go b/vendor/github.com/google/cel-go/checker/mapping.go
index fbc55a28d..8163a908a 100644
--- a/vendor/github.com/google/cel-go/checker/mapping.go
+++ b/vendor/github.com/google/cel-go/checker/mapping.go
@@ -15,25 +15,25 @@
package checker
import (
- exprpb "google.golang.org/genproto/googleapis/api/expr/v1alpha1"
+ "github.com/google/cel-go/common/types"
)
type mapping struct {
- mapping map[string]*exprpb.Type
+ mapping map[string]*types.Type
}
func newMapping() *mapping {
return &mapping{
- mapping: make(map[string]*exprpb.Type),
+ mapping: make(map[string]*types.Type),
}
}
-func (m *mapping) add(from *exprpb.Type, to *exprpb.Type) {
- m.mapping[typeKey(from)] = to
+func (m *mapping) add(from, to *types.Type) {
+ m.mapping[FormatCELType(from)] = to
}
-func (m *mapping) find(from *exprpb.Type) (*exprpb.Type, bool) {
- if r, found := m.mapping[typeKey(from)]; found {
+func (m *mapping) find(from *types.Type) (*types.Type, bool) {
+ if r, found := m.mapping[FormatCELType(from)]; found {
return r, found
}
return nil, false
diff --git a/vendor/github.com/google/cel-go/checker/options.go b/vendor/github.com/google/cel-go/checker/options.go
index cded00a66..0560c3813 100644
--- a/vendor/github.com/google/cel-go/checker/options.go
+++ b/vendor/github.com/google/cel-go/checker/options.go
@@ -14,12 +14,10 @@
package checker
-import "github.com/google/cel-go/checker/decls"
-
type options struct {
crossTypeNumericComparisons bool
homogeneousAggregateLiterals bool
- validatedDeclarations *decls.Scopes
+ validatedDeclarations *Scopes
}
// Option is a functional option for configuring the type-checker
@@ -34,15 +32,6 @@ func CrossTypeNumericComparisons(enabled bool) Option {
}
}
-// HomogeneousAggregateLiterals toggles support for constructing lists and maps whose elements all
-// have the same type.
-func HomogeneousAggregateLiterals(enabled bool) Option {
- return func(opts *options) error {
- opts.homogeneousAggregateLiterals = enabled
- return nil
- }
-}
-
// ValidatedDeclarations provides a references to validated declarations which will be copied
// into new checker instances.
func ValidatedDeclarations(env *Env) Option {
diff --git a/vendor/github.com/google/cel-go/checker/printer.go b/vendor/github.com/google/cel-go/checker/printer.go
index 0cecc5210..15cba06ee 100644
--- a/vendor/github.com/google/cel-go/checker/printer.go
+++ b/vendor/github.com/google/cel-go/checker/printer.go
@@ -15,6 +15,8 @@
package checker
import (
+ "sort"
+
"github.com/google/cel-go/common/debug"
exprpb "google.golang.org/genproto/googleapis/api/expr/v1alpha1"
@@ -47,6 +49,7 @@ func (a *semanticAdorner) GetMetadata(elem any) string {
if len(ref.GetOverloadId()) == 0 {
result += "^" + ref.Name
} else {
+ sort.Strings(ref.GetOverloadId())
for i, overload := range ref.GetOverloadId() {
if i == 0 {
result += "^"
diff --git a/vendor/github.com/google/cel-go/checker/decls/scopes.go b/vendor/github.com/google/cel-go/checker/scopes.go
similarity index 81%
rename from vendor/github.com/google/cel-go/checker/decls/scopes.go
rename to vendor/github.com/google/cel-go/checker/scopes.go
index 608bca3e5..8bb73ddb6 100644
--- a/vendor/github.com/google/cel-go/checker/decls/scopes.go
+++ b/vendor/github.com/google/cel-go/checker/scopes.go
@@ -12,9 +12,11 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package decls
+package checker
-import exprpb "google.golang.org/genproto/googleapis/api/expr/v1alpha1"
+import (
+ "github.com/google/cel-go/common/decls"
+)
// Scopes represents nested Decl sets where the Scopes value contains a Groups containing all
// identifiers in scope and an optional parent representing outer scopes.
@@ -25,9 +27,9 @@ type Scopes struct {
scopes *Group
}
-// NewScopes creates a new, empty Scopes.
+// newScopes creates a new, empty Scopes.
// Some operations can't be safely performed until a Group is added with Push.
-func NewScopes() *Scopes {
+func newScopes() *Scopes {
return &Scopes{
scopes: newGroup(),
}
@@ -35,7 +37,7 @@ func NewScopes() *Scopes {
// Copy creates a copy of the current Scopes values, including a copy of its parent if non-nil.
func (s *Scopes) Copy() *Scopes {
- cpy := NewScopes()
+ cpy := newScopes()
if s == nil {
return cpy
}
@@ -66,14 +68,14 @@ func (s *Scopes) Pop() *Scopes {
// AddIdent adds the ident Decl in the current scope.
// Note: If the name collides with an existing identifier in the scope, the Decl is overwritten.
-func (s *Scopes) AddIdent(decl *exprpb.Decl) {
- s.scopes.idents[decl.Name] = decl
+func (s *Scopes) AddIdent(decl *decls.VariableDecl) {
+ s.scopes.idents[decl.Name()] = decl
}
// FindIdent finds the first ident Decl with a matching name in Scopes, or nil if one cannot be
// found.
// Note: The search is performed from innermost to outermost.
-func (s *Scopes) FindIdent(name string) *exprpb.Decl {
+func (s *Scopes) FindIdent(name string) *decls.VariableDecl {
if ident, found := s.scopes.idents[name]; found {
return ident
}
@@ -86,7 +88,7 @@ func (s *Scopes) FindIdent(name string) *exprpb.Decl {
// FindIdentInScope finds the first ident Decl with a matching name in the current Scopes value, or
// nil if one does not exist.
// Note: The search is only performed on the current scope and does not search outer scopes.
-func (s *Scopes) FindIdentInScope(name string) *exprpb.Decl {
+func (s *Scopes) FindIdentInScope(name string) *decls.VariableDecl {
if ident, found := s.scopes.idents[name]; found {
return ident
}
@@ -95,14 +97,14 @@ func (s *Scopes) FindIdentInScope(name string) *exprpb.Decl {
// SetFunction adds the function Decl to the current scope.
// Note: Any previous entry for a function in the current scope with the same name is overwritten.
-func (s *Scopes) SetFunction(fn *exprpb.Decl) {
- s.scopes.functions[fn.Name] = fn
+func (s *Scopes) SetFunction(fn *decls.FunctionDecl) {
+ s.scopes.functions[fn.Name()] = fn
}
// FindFunction finds the first function Decl with a matching name in Scopes.
// The search is performed from innermost to outermost.
// Returns nil if no such function in Scopes.
-func (s *Scopes) FindFunction(name string) *exprpb.Decl {
+func (s *Scopes) FindFunction(name string) *decls.FunctionDecl {
if fn, found := s.scopes.functions[name]; found {
return fn
}
@@ -116,16 +118,16 @@ func (s *Scopes) FindFunction(name string) *exprpb.Decl {
// Contains separate namespaces for identifier and function Decls.
// (Should be named "Scope" perhaps?)
type Group struct {
- idents map[string]*exprpb.Decl
- functions map[string]*exprpb.Decl
+ idents map[string]*decls.VariableDecl
+ functions map[string]*decls.FunctionDecl
}
// copy creates a new Group instance with a shallow copy of the variables and functions.
// If callers need to mutate the exprpb.Decl definitions for a Function, they should copy-on-write.
func (g *Group) copy() *Group {
cpy := &Group{
- idents: make(map[string]*exprpb.Decl, len(g.idents)),
- functions: make(map[string]*exprpb.Decl, len(g.functions)),
+ idents: make(map[string]*decls.VariableDecl, len(g.idents)),
+ functions: make(map[string]*decls.FunctionDecl, len(g.functions)),
}
for n, id := range g.idents {
cpy.idents[n] = id
@@ -139,7 +141,7 @@ func (g *Group) copy() *Group {
// newGroup creates a new Group with empty maps for identifiers and functions.
func newGroup() *Group {
return &Group{
- idents: make(map[string]*exprpb.Decl),
- functions: make(map[string]*exprpb.Decl),
+ idents: make(map[string]*decls.VariableDecl),
+ functions: make(map[string]*decls.FunctionDecl),
}
}
diff --git a/vendor/github.com/google/cel-go/checker/standard.go b/vendor/github.com/google/cel-go/checker/standard.go
index e64337ba4..11b35b80e 100644
--- a/vendor/github.com/google/cel-go/checker/standard.go
+++ b/vendor/github.com/google/cel-go/checker/standard.go
@@ -15,480 +15,21 @@
package checker
import (
- "github.com/google/cel-go/checker/decls"
- "github.com/google/cel-go/common/operators"
- "github.com/google/cel-go/common/overloads"
+ "github.com/google/cel-go/common/stdlib"
exprpb "google.golang.org/genproto/googleapis/api/expr/v1alpha1"
)
-var (
- standardDeclarations []*exprpb.Decl
-)
-
-func init() {
- // Some shortcuts we use when building declarations.
- paramA := decls.NewTypeParamType("A")
- typeParamAList := []string{"A"}
- listOfA := decls.NewListType(paramA)
- paramB := decls.NewTypeParamType("B")
- typeParamABList := []string{"A", "B"}
- mapOfAB := decls.NewMapType(paramA, paramB)
-
- var idents []*exprpb.Decl
- for _, t := range []*exprpb.Type{
- decls.Int, decls.Uint, decls.Bool,
- decls.Double, decls.Bytes, decls.String} {
- idents = append(idents,
- decls.NewVar(FormatCheckedType(t), decls.NewTypeType(t)))
- }
- idents = append(idents,
- decls.NewVar("list", decls.NewTypeType(listOfA)),
- decls.NewVar("map", decls.NewTypeType(mapOfAB)),
- decls.NewVar("null_type", decls.NewTypeType(decls.Null)),
- decls.NewVar("type", decls.NewTypeType(decls.NewTypeType(nil))))
-
- standardDeclarations = append(standardDeclarations, idents...)
- standardDeclarations = append(standardDeclarations, []*exprpb.Decl{
- // Booleans
- decls.NewFunction(operators.Conditional,
- decls.NewParameterizedOverload(overloads.Conditional,
- []*exprpb.Type{decls.Bool, paramA, paramA}, paramA,
- typeParamAList)),
-
- decls.NewFunction(operators.LogicalAnd,
- decls.NewOverload(overloads.LogicalAnd,
- []*exprpb.Type{decls.Bool, decls.Bool}, decls.Bool)),
-
- decls.NewFunction(operators.LogicalOr,
- decls.NewOverload(overloads.LogicalOr,
- []*exprpb.Type{decls.Bool, decls.Bool}, decls.Bool)),
-
- decls.NewFunction(operators.LogicalNot,
- decls.NewOverload(overloads.LogicalNot,
- []*exprpb.Type{decls.Bool}, decls.Bool)),
-
- decls.NewFunction(operators.NotStrictlyFalse,
- decls.NewOverload(overloads.NotStrictlyFalse,
- []*exprpb.Type{decls.Bool}, decls.Bool)),
-
- decls.NewFunction(operators.Equals,
- decls.NewParameterizedOverload(overloads.Equals,
- []*exprpb.Type{paramA, paramA}, decls.Bool,
- typeParamAList)),
-
- decls.NewFunction(operators.NotEquals,
- decls.NewParameterizedOverload(overloads.NotEquals,
- []*exprpb.Type{paramA, paramA}, decls.Bool,
- typeParamAList)),
-
- // Algebra.
-
- decls.NewFunction(operators.Subtract,
- decls.NewOverload(overloads.SubtractInt64,
- []*exprpb.Type{decls.Int, decls.Int}, decls.Int),
- decls.NewOverload(overloads.SubtractUint64,
- []*exprpb.Type{decls.Uint, decls.Uint}, decls.Uint),
- decls.NewOverload(overloads.SubtractDouble,
- []*exprpb.Type{decls.Double, decls.Double}, decls.Double),
- decls.NewOverload(overloads.SubtractTimestampTimestamp,
- []*exprpb.Type{decls.Timestamp, decls.Timestamp}, decls.Duration),
- decls.NewOverload(overloads.SubtractTimestampDuration,
- []*exprpb.Type{decls.Timestamp, decls.Duration}, decls.Timestamp),
- decls.NewOverload(overloads.SubtractDurationDuration,
- []*exprpb.Type{decls.Duration, decls.Duration}, decls.Duration)),
-
- decls.NewFunction(operators.Multiply,
- decls.NewOverload(overloads.MultiplyInt64,
- []*exprpb.Type{decls.Int, decls.Int}, decls.Int),
- decls.NewOverload(overloads.MultiplyUint64,
- []*exprpb.Type{decls.Uint, decls.Uint}, decls.Uint),
- decls.NewOverload(overloads.MultiplyDouble,
- []*exprpb.Type{decls.Double, decls.Double}, decls.Double)),
-
- decls.NewFunction(operators.Divide,
- decls.NewOverload(overloads.DivideInt64,
- []*exprpb.Type{decls.Int, decls.Int}, decls.Int),
- decls.NewOverload(overloads.DivideUint64,
- []*exprpb.Type{decls.Uint, decls.Uint}, decls.Uint),
- decls.NewOverload(overloads.DivideDouble,
- []*exprpb.Type{decls.Double, decls.Double}, decls.Double)),
-
- decls.NewFunction(operators.Modulo,
- decls.NewOverload(overloads.ModuloInt64,
- []*exprpb.Type{decls.Int, decls.Int}, decls.Int),
- decls.NewOverload(overloads.ModuloUint64,
- []*exprpb.Type{decls.Uint, decls.Uint}, decls.Uint)),
-
- decls.NewFunction(operators.Add,
- decls.NewOverload(overloads.AddInt64,
- []*exprpb.Type{decls.Int, decls.Int}, decls.Int),
- decls.NewOverload(overloads.AddUint64,
- []*exprpb.Type{decls.Uint, decls.Uint}, decls.Uint),
- decls.NewOverload(overloads.AddDouble,
- []*exprpb.Type{decls.Double, decls.Double}, decls.Double),
- decls.NewOverload(overloads.AddString,
- []*exprpb.Type{decls.String, decls.String}, decls.String),
- decls.NewOverload(overloads.AddBytes,
- []*exprpb.Type{decls.Bytes, decls.Bytes}, decls.Bytes),
- decls.NewParameterizedOverload(overloads.AddList,
- []*exprpb.Type{listOfA, listOfA}, listOfA,
- typeParamAList),
- decls.NewOverload(overloads.AddTimestampDuration,
- []*exprpb.Type{decls.Timestamp, decls.Duration}, decls.Timestamp),
- decls.NewOverload(overloads.AddDurationTimestamp,
- []*exprpb.Type{decls.Duration, decls.Timestamp}, decls.Timestamp),
- decls.NewOverload(overloads.AddDurationDuration,
- []*exprpb.Type{decls.Duration, decls.Duration}, decls.Duration)),
-
- decls.NewFunction(operators.Negate,
- decls.NewOverload(overloads.NegateInt64,
- []*exprpb.Type{decls.Int}, decls.Int),
- decls.NewOverload(overloads.NegateDouble,
- []*exprpb.Type{decls.Double}, decls.Double)),
-
- // Index.
-
- decls.NewFunction(operators.Index,
- decls.NewParameterizedOverload(overloads.IndexList,
- []*exprpb.Type{listOfA, decls.Int}, paramA,
- typeParamAList),
- decls.NewParameterizedOverload(overloads.IndexMap,
- []*exprpb.Type{mapOfAB, paramA}, paramB,
- typeParamABList)),
-
- // Collections.
-
- decls.NewFunction(overloads.Size,
- decls.NewInstanceOverload(overloads.SizeStringInst,
- []*exprpb.Type{decls.String}, decls.Int),
- decls.NewInstanceOverload(overloads.SizeBytesInst,
- []*exprpb.Type{decls.Bytes}, decls.Int),
- decls.NewParameterizedInstanceOverload(overloads.SizeListInst,
- []*exprpb.Type{listOfA}, decls.Int, typeParamAList),
- decls.NewParameterizedInstanceOverload(overloads.SizeMapInst,
- []*exprpb.Type{mapOfAB}, decls.Int, typeParamABList),
- decls.NewOverload(overloads.SizeString,
- []*exprpb.Type{decls.String}, decls.Int),
- decls.NewOverload(overloads.SizeBytes,
- []*exprpb.Type{decls.Bytes}, decls.Int),
- decls.NewParameterizedOverload(overloads.SizeList,
- []*exprpb.Type{listOfA}, decls.Int, typeParamAList),
- decls.NewParameterizedOverload(overloads.SizeMap,
- []*exprpb.Type{mapOfAB}, decls.Int, typeParamABList)),
-
- decls.NewFunction(operators.In,
- decls.NewParameterizedOverload(overloads.InList,
- []*exprpb.Type{paramA, listOfA}, decls.Bool,
- typeParamAList),
- decls.NewParameterizedOverload(overloads.InMap,
- []*exprpb.Type{paramA, mapOfAB}, decls.Bool,
- typeParamABList)),
-
- // Deprecated 'in()' function.
-
- decls.NewFunction(overloads.DeprecatedIn,
- decls.NewParameterizedOverload(overloads.InList,
- []*exprpb.Type{paramA, listOfA}, decls.Bool,
- typeParamAList),
- decls.NewParameterizedOverload(overloads.InMap,
- []*exprpb.Type{paramA, mapOfAB}, decls.Bool,
- typeParamABList)),
-
- // Conversions to type.
-
- decls.NewFunction(overloads.TypeConvertType,
- decls.NewParameterizedOverload(overloads.TypeConvertType,
- []*exprpb.Type{paramA}, decls.NewTypeType(paramA), typeParamAList)),
-
- // Conversions to int.
-
- decls.NewFunction(overloads.TypeConvertInt,
- decls.NewOverload(overloads.IntToInt, []*exprpb.Type{decls.Int}, decls.Int),
- decls.NewOverload(overloads.UintToInt, []*exprpb.Type{decls.Uint}, decls.Int),
- decls.NewOverload(overloads.DoubleToInt, []*exprpb.Type{decls.Double}, decls.Int),
- decls.NewOverload(overloads.StringToInt, []*exprpb.Type{decls.String}, decls.Int),
- decls.NewOverload(overloads.TimestampToInt, []*exprpb.Type{decls.Timestamp}, decls.Int),
- decls.NewOverload(overloads.DurationToInt, []*exprpb.Type{decls.Duration}, decls.Int)),
-
- // Conversions to uint.
-
- decls.NewFunction(overloads.TypeConvertUint,
- decls.NewOverload(overloads.UintToUint, []*exprpb.Type{decls.Uint}, decls.Uint),
- decls.NewOverload(overloads.IntToUint, []*exprpb.Type{decls.Int}, decls.Uint),
- decls.NewOverload(overloads.DoubleToUint, []*exprpb.Type{decls.Double}, decls.Uint),
- decls.NewOverload(overloads.StringToUint, []*exprpb.Type{decls.String}, decls.Uint)),
-
- // Conversions to double.
-
- decls.NewFunction(overloads.TypeConvertDouble,
- decls.NewOverload(overloads.DoubleToDouble, []*exprpb.Type{decls.Double}, decls.Double),
- decls.NewOverload(overloads.IntToDouble, []*exprpb.Type{decls.Int}, decls.Double),
- decls.NewOverload(overloads.UintToDouble, []*exprpb.Type{decls.Uint}, decls.Double),
- decls.NewOverload(overloads.StringToDouble, []*exprpb.Type{decls.String}, decls.Double)),
-
- // Conversions to bool.
-
- decls.NewFunction(overloads.TypeConvertBool,
- decls.NewOverload(overloads.BoolToBool, []*exprpb.Type{decls.Bool}, decls.Bool),
- decls.NewOverload(overloads.StringToBool, []*exprpb.Type{decls.String}, decls.Bool)),
-
- // Conversions to string.
-
- decls.NewFunction(overloads.TypeConvertString,
- decls.NewOverload(overloads.StringToString, []*exprpb.Type{decls.String}, decls.String),
- decls.NewOverload(overloads.BoolToString, []*exprpb.Type{decls.Bool}, decls.String),
- decls.NewOverload(overloads.IntToString, []*exprpb.Type{decls.Int}, decls.String),
- decls.NewOverload(overloads.UintToString, []*exprpb.Type{decls.Uint}, decls.String),
- decls.NewOverload(overloads.DoubleToString, []*exprpb.Type{decls.Double}, decls.String),
- decls.NewOverload(overloads.BytesToString, []*exprpb.Type{decls.Bytes}, decls.String),
- decls.NewOverload(overloads.TimestampToString, []*exprpb.Type{decls.Timestamp}, decls.String),
- decls.NewOverload(overloads.DurationToString, []*exprpb.Type{decls.Duration}, decls.String)),
-
- // Conversions to bytes.
-
- decls.NewFunction(overloads.TypeConvertBytes,
- decls.NewOverload(overloads.BytesToBytes, []*exprpb.Type{decls.Bytes}, decls.Bytes),
- decls.NewOverload(overloads.StringToBytes, []*exprpb.Type{decls.String}, decls.Bytes)),
-
- // Conversions to timestamps.
-
- decls.NewFunction(overloads.TypeConvertTimestamp,
- decls.NewOverload(overloads.TimestampToTimestamp,
- []*exprpb.Type{decls.Timestamp}, decls.Timestamp),
- decls.NewOverload(overloads.StringToTimestamp,
- []*exprpb.Type{decls.String}, decls.Timestamp),
- decls.NewOverload(overloads.IntToTimestamp,
- []*exprpb.Type{decls.Int}, decls.Timestamp)),
-
- // Conversions to durations.
-
- decls.NewFunction(overloads.TypeConvertDuration,
- decls.NewOverload(overloads.DurationToDuration,
- []*exprpb.Type{decls.Duration}, decls.Duration),
- decls.NewOverload(overloads.StringToDuration,
- []*exprpb.Type{decls.String}, decls.Duration),
- decls.NewOverload(overloads.IntToDuration,
- []*exprpb.Type{decls.Int}, decls.Duration)),
-
- // Conversions to Dyn.
-
- decls.NewFunction(overloads.TypeConvertDyn,
- decls.NewParameterizedOverload(overloads.ToDyn,
- []*exprpb.Type{paramA}, decls.Dyn,
- typeParamAList)),
-
- // String functions.
-
- decls.NewFunction(overloads.Contains,
- decls.NewInstanceOverload(overloads.ContainsString,
- []*exprpb.Type{decls.String, decls.String}, decls.Bool)),
- decls.NewFunction(overloads.EndsWith,
- decls.NewInstanceOverload(overloads.EndsWithString,
- []*exprpb.Type{decls.String, decls.String}, decls.Bool)),
- decls.NewFunction(overloads.Matches,
- decls.NewOverload(overloads.Matches,
- []*exprpb.Type{decls.String, decls.String}, decls.Bool),
- decls.NewInstanceOverload(overloads.MatchesString,
- []*exprpb.Type{decls.String, decls.String}, decls.Bool)),
- decls.NewFunction(overloads.StartsWith,
- decls.NewInstanceOverload(overloads.StartsWithString,
- []*exprpb.Type{decls.String, decls.String}, decls.Bool)),
-
- // Date/time functions.
-
- decls.NewFunction(overloads.TimeGetFullYear,
- decls.NewInstanceOverload(overloads.TimestampToYear,
- []*exprpb.Type{decls.Timestamp}, decls.Int),
- decls.NewInstanceOverload(overloads.TimestampToYearWithTz,
- []*exprpb.Type{decls.Timestamp, decls.String}, decls.Int)),
-
- decls.NewFunction(overloads.TimeGetMonth,
- decls.NewInstanceOverload(overloads.TimestampToMonth,
- []*exprpb.Type{decls.Timestamp}, decls.Int),
- decls.NewInstanceOverload(overloads.TimestampToMonthWithTz,
- []*exprpb.Type{decls.Timestamp, decls.String}, decls.Int)),
-
- decls.NewFunction(overloads.TimeGetDayOfYear,
- decls.NewInstanceOverload(overloads.TimestampToDayOfYear,
- []*exprpb.Type{decls.Timestamp}, decls.Int),
- decls.NewInstanceOverload(overloads.TimestampToDayOfYearWithTz,
- []*exprpb.Type{decls.Timestamp, decls.String}, decls.Int)),
-
- decls.NewFunction(overloads.TimeGetDayOfMonth,
- decls.NewInstanceOverload(overloads.TimestampToDayOfMonthZeroBased,
- []*exprpb.Type{decls.Timestamp}, decls.Int),
- decls.NewInstanceOverload(overloads.TimestampToDayOfMonthZeroBasedWithTz,
- []*exprpb.Type{decls.Timestamp, decls.String}, decls.Int)),
-
- decls.NewFunction(overloads.TimeGetDate,
- decls.NewInstanceOverload(overloads.TimestampToDayOfMonthOneBased,
- []*exprpb.Type{decls.Timestamp}, decls.Int),
- decls.NewInstanceOverload(overloads.TimestampToDayOfMonthOneBasedWithTz,
- []*exprpb.Type{decls.Timestamp, decls.String}, decls.Int)),
-
- decls.NewFunction(overloads.TimeGetDayOfWeek,
- decls.NewInstanceOverload(overloads.TimestampToDayOfWeek,
- []*exprpb.Type{decls.Timestamp}, decls.Int),
- decls.NewInstanceOverload(overloads.TimestampToDayOfWeekWithTz,
- []*exprpb.Type{decls.Timestamp, decls.String}, decls.Int)),
-
- decls.NewFunction(overloads.TimeGetHours,
- decls.NewInstanceOverload(overloads.TimestampToHours,
- []*exprpb.Type{decls.Timestamp}, decls.Int),
- decls.NewInstanceOverload(overloads.TimestampToHoursWithTz,
- []*exprpb.Type{decls.Timestamp, decls.String}, decls.Int),
- decls.NewInstanceOverload(overloads.DurationToHours,
- []*exprpb.Type{decls.Duration}, decls.Int)),
-
- decls.NewFunction(overloads.TimeGetMinutes,
- decls.NewInstanceOverload(overloads.TimestampToMinutes,
- []*exprpb.Type{decls.Timestamp}, decls.Int),
- decls.NewInstanceOverload(overloads.TimestampToMinutesWithTz,
- []*exprpb.Type{decls.Timestamp, decls.String}, decls.Int),
- decls.NewInstanceOverload(overloads.DurationToMinutes,
- []*exprpb.Type{decls.Duration}, decls.Int)),
-
- decls.NewFunction(overloads.TimeGetSeconds,
- decls.NewInstanceOverload(overloads.TimestampToSeconds,
- []*exprpb.Type{decls.Timestamp}, decls.Int),
- decls.NewInstanceOverload(overloads.TimestampToSecondsWithTz,
- []*exprpb.Type{decls.Timestamp, decls.String}, decls.Int),
- decls.NewInstanceOverload(overloads.DurationToSeconds,
- []*exprpb.Type{decls.Duration}, decls.Int)),
-
- decls.NewFunction(overloads.TimeGetMilliseconds,
- decls.NewInstanceOverload(overloads.TimestampToMilliseconds,
- []*exprpb.Type{decls.Timestamp}, decls.Int),
- decls.NewInstanceOverload(overloads.TimestampToMillisecondsWithTz,
- []*exprpb.Type{decls.Timestamp, decls.String}, decls.Int),
- decls.NewInstanceOverload(overloads.DurationToMilliseconds,
- []*exprpb.Type{decls.Duration}, decls.Int)),
-
- // Relations.
- decls.NewFunction(operators.Less,
- decls.NewOverload(overloads.LessBool,
- []*exprpb.Type{decls.Bool, decls.Bool}, decls.Bool),
- decls.NewOverload(overloads.LessInt64,
- []*exprpb.Type{decls.Int, decls.Int}, decls.Bool),
- decls.NewOverload(overloads.LessInt64Double,
- []*exprpb.Type{decls.Int, decls.Double}, decls.Bool),
- decls.NewOverload(overloads.LessInt64Uint64,
- []*exprpb.Type{decls.Int, decls.Uint}, decls.Bool),
- decls.NewOverload(overloads.LessUint64,
- []*exprpb.Type{decls.Uint, decls.Uint}, decls.Bool),
- decls.NewOverload(overloads.LessUint64Double,
- []*exprpb.Type{decls.Uint, decls.Double}, decls.Bool),
- decls.NewOverload(overloads.LessUint64Int64,
- []*exprpb.Type{decls.Uint, decls.Int}, decls.Bool),
- decls.NewOverload(overloads.LessDouble,
- []*exprpb.Type{decls.Double, decls.Double}, decls.Bool),
- decls.NewOverload(overloads.LessDoubleInt64,
- []*exprpb.Type{decls.Double, decls.Int}, decls.Bool),
- decls.NewOverload(overloads.LessDoubleUint64,
- []*exprpb.Type{decls.Double, decls.Uint}, decls.Bool),
- decls.NewOverload(overloads.LessString,
- []*exprpb.Type{decls.String, decls.String}, decls.Bool),
- decls.NewOverload(overloads.LessBytes,
- []*exprpb.Type{decls.Bytes, decls.Bytes}, decls.Bool),
- decls.NewOverload(overloads.LessTimestamp,
- []*exprpb.Type{decls.Timestamp, decls.Timestamp}, decls.Bool),
- decls.NewOverload(overloads.LessDuration,
- []*exprpb.Type{decls.Duration, decls.Duration}, decls.Bool)),
-
- decls.NewFunction(operators.LessEquals,
- decls.NewOverload(overloads.LessEqualsBool,
- []*exprpb.Type{decls.Bool, decls.Bool}, decls.Bool),
- decls.NewOverload(overloads.LessEqualsInt64,
- []*exprpb.Type{decls.Int, decls.Int}, decls.Bool),
- decls.NewOverload(overloads.LessEqualsInt64Double,
- []*exprpb.Type{decls.Int, decls.Double}, decls.Bool),
- decls.NewOverload(overloads.LessEqualsInt64Uint64,
- []*exprpb.Type{decls.Int, decls.Uint}, decls.Bool),
- decls.NewOverload(overloads.LessEqualsUint64,
- []*exprpb.Type{decls.Uint, decls.Uint}, decls.Bool),
- decls.NewOverload(overloads.LessEqualsUint64Double,
- []*exprpb.Type{decls.Uint, decls.Double}, decls.Bool),
- decls.NewOverload(overloads.LessEqualsUint64Int64,
- []*exprpb.Type{decls.Uint, decls.Int}, decls.Bool),
- decls.NewOverload(overloads.LessEqualsDouble,
- []*exprpb.Type{decls.Double, decls.Double}, decls.Bool),
- decls.NewOverload(overloads.LessEqualsDoubleInt64,
- []*exprpb.Type{decls.Double, decls.Int}, decls.Bool),
- decls.NewOverload(overloads.LessEqualsDoubleUint64,
- []*exprpb.Type{decls.Double, decls.Uint}, decls.Bool),
- decls.NewOverload(overloads.LessEqualsString,
- []*exprpb.Type{decls.String, decls.String}, decls.Bool),
- decls.NewOverload(overloads.LessEqualsBytes,
- []*exprpb.Type{decls.Bytes, decls.Bytes}, decls.Bool),
- decls.NewOverload(overloads.LessEqualsTimestamp,
- []*exprpb.Type{decls.Timestamp, decls.Timestamp}, decls.Bool),
- decls.NewOverload(overloads.LessEqualsDuration,
- []*exprpb.Type{decls.Duration, decls.Duration}, decls.Bool)),
-
- decls.NewFunction(operators.Greater,
- decls.NewOverload(overloads.GreaterBool,
- []*exprpb.Type{decls.Bool, decls.Bool}, decls.Bool),
- decls.NewOverload(overloads.GreaterInt64,
- []*exprpb.Type{decls.Int, decls.Int}, decls.Bool),
- decls.NewOverload(overloads.GreaterInt64Double,
- []*exprpb.Type{decls.Int, decls.Double}, decls.Bool),
- decls.NewOverload(overloads.GreaterInt64Uint64,
- []*exprpb.Type{decls.Int, decls.Uint}, decls.Bool),
- decls.NewOverload(overloads.GreaterUint64,
- []*exprpb.Type{decls.Uint, decls.Uint}, decls.Bool),
- decls.NewOverload(overloads.GreaterUint64Double,
- []*exprpb.Type{decls.Uint, decls.Double}, decls.Bool),
- decls.NewOverload(overloads.GreaterUint64Int64,
- []*exprpb.Type{decls.Uint, decls.Int}, decls.Bool),
- decls.NewOverload(overloads.GreaterDouble,
- []*exprpb.Type{decls.Double, decls.Double}, decls.Bool),
- decls.NewOverload(overloads.GreaterDoubleInt64,
- []*exprpb.Type{decls.Double, decls.Int}, decls.Bool),
- decls.NewOverload(overloads.GreaterDoubleUint64,
- []*exprpb.Type{decls.Double, decls.Uint}, decls.Bool),
- decls.NewOverload(overloads.GreaterString,
- []*exprpb.Type{decls.String, decls.String}, decls.Bool),
- decls.NewOverload(overloads.GreaterBytes,
- []*exprpb.Type{decls.Bytes, decls.Bytes}, decls.Bool),
- decls.NewOverload(overloads.GreaterTimestamp,
- []*exprpb.Type{decls.Timestamp, decls.Timestamp}, decls.Bool),
- decls.NewOverload(overloads.GreaterDuration,
- []*exprpb.Type{decls.Duration, decls.Duration}, decls.Bool)),
-
- decls.NewFunction(operators.GreaterEquals,
- decls.NewOverload(overloads.GreaterEqualsBool,
- []*exprpb.Type{decls.Bool, decls.Bool}, decls.Bool),
- decls.NewOverload(overloads.GreaterEqualsInt64,
- []*exprpb.Type{decls.Int, decls.Int}, decls.Bool),
- decls.NewOverload(overloads.GreaterEqualsInt64Double,
- []*exprpb.Type{decls.Int, decls.Double}, decls.Bool),
- decls.NewOverload(overloads.GreaterEqualsInt64Uint64,
- []*exprpb.Type{decls.Int, decls.Uint}, decls.Bool),
- decls.NewOverload(overloads.GreaterEqualsUint64,
- []*exprpb.Type{decls.Uint, decls.Uint}, decls.Bool),
- decls.NewOverload(overloads.GreaterEqualsUint64Double,
- []*exprpb.Type{decls.Uint, decls.Double}, decls.Bool),
- decls.NewOverload(overloads.GreaterEqualsUint64Int64,
- []*exprpb.Type{decls.Uint, decls.Int}, decls.Bool),
- decls.NewOverload(overloads.GreaterEqualsDouble,
- []*exprpb.Type{decls.Double, decls.Double}, decls.Bool),
- decls.NewOverload(overloads.GreaterEqualsDoubleInt64,
- []*exprpb.Type{decls.Double, decls.Int}, decls.Bool),
- decls.NewOverload(overloads.GreaterEqualsDoubleUint64,
- []*exprpb.Type{decls.Double, decls.Uint}, decls.Bool),
- decls.NewOverload(overloads.GreaterEqualsString,
- []*exprpb.Type{decls.String, decls.String}, decls.Bool),
- decls.NewOverload(overloads.GreaterEqualsBytes,
- []*exprpb.Type{decls.Bytes, decls.Bytes}, decls.Bool),
- decls.NewOverload(overloads.GreaterEqualsTimestamp,
- []*exprpb.Type{decls.Timestamp, decls.Timestamp}, decls.Bool),
- decls.NewOverload(overloads.GreaterEqualsDuration,
- []*exprpb.Type{decls.Duration, decls.Duration}, decls.Bool)),
- }...)
+// StandardFunctions returns the Decls for all functions in the evaluator.
+//
+// Deprecated: prefer stdlib.FunctionExprDecls()
+func StandardFunctions() []*exprpb.Decl {
+ return stdlib.FunctionExprDecls()
}
-// StandardDeclarations returns the Decls for all functions and constants in the evaluator.
-func StandardDeclarations() []*exprpb.Decl {
- return standardDeclarations
+// StandardTypes returns the set of type identifiers for standard library types.
+//
+// Deprecated: prefer stdlib.TypeExprDecls()
+func StandardTypes() []*exprpb.Decl {
+ return stdlib.TypeExprDecls()
}
diff --git a/vendor/github.com/google/cel-go/checker/types.go b/vendor/github.com/google/cel-go/checker/types.go
index f5c382725..e2373d1b7 100644
--- a/vendor/github.com/google/cel-go/checker/types.go
+++ b/vendor/github.com/google/cel-go/checker/types.go
@@ -15,154 +15,54 @@
package checker
import (
- "fmt"
- "strings"
-
- "github.com/google/cel-go/checker/decls"
-
- "google.golang.org/protobuf/proto"
-
- exprpb "google.golang.org/genproto/googleapis/api/expr/v1alpha1"
+ "github.com/google/cel-go/common/types"
)
-const (
- kindUnknown = iota + 1
- kindError
- kindFunction
- kindDyn
- kindPrimitive
- kindWellKnown
- kindWrapper
- kindNull
- kindAbstract
- kindType
- kindList
- kindMap
- kindObject
- kindTypeParam
-)
-
-// FormatCheckedType converts a type message into a string representation.
-func FormatCheckedType(t *exprpb.Type) string {
- switch kindOf(t) {
- case kindDyn:
- return "dyn"
- case kindFunction:
- return formatFunction(t.GetFunction().GetResultType(),
- t.GetFunction().GetArgTypes(),
- false)
- case kindList:
- return fmt.Sprintf("list(%s)", FormatCheckedType(t.GetListType().GetElemType()))
- case kindObject:
- return t.GetMessageType()
- case kindMap:
- return fmt.Sprintf("map(%s, %s)",
- FormatCheckedType(t.GetMapType().GetKeyType()),
- FormatCheckedType(t.GetMapType().GetValueType()))
- case kindNull:
- return "null"
- case kindPrimitive:
- switch t.GetPrimitive() {
- case exprpb.Type_UINT64:
- return "uint"
- case exprpb.Type_INT64:
- return "int"
- }
- return strings.Trim(strings.ToLower(t.GetPrimitive().String()), " ")
- case kindType:
- if t.GetType() == nil {
- return "type"
- }
- return fmt.Sprintf("type(%s)", FormatCheckedType(t.GetType()))
- case kindWellKnown:
- switch t.GetWellKnown() {
- case exprpb.Type_ANY:
- return "any"
- case exprpb.Type_DURATION:
- return "duration"
- case exprpb.Type_TIMESTAMP:
- return "timestamp"
- }
- case kindWrapper:
- return fmt.Sprintf("wrapper(%s)",
- FormatCheckedType(decls.NewPrimitiveType(t.GetWrapper())))
- case kindError:
- return "!error!"
- case kindTypeParam:
- return t.GetTypeParam()
- case kindAbstract:
- at := t.GetAbstractType()
- params := at.GetParameterTypes()
- paramStrs := make([]string, len(params))
- for i, p := range params {
- paramStrs[i] = FormatCheckedType(p)
- }
- return fmt.Sprintf("%s(%s)", at.GetName(), strings.Join(paramStrs, ", "))
- }
- return t.String()
-}
-
// isDyn returns true if the input t is either type DYN or a well-known ANY message.
-func isDyn(t *exprpb.Type) bool {
+func isDyn(t *types.Type) bool {
// Note: object type values that are well-known and map to a DYN value in practice
// are sanitized prior to being added to the environment.
- switch kindOf(t) {
- case kindDyn:
+ switch t.Kind() {
+ case types.DynKind, types.AnyKind:
return true
- case kindWellKnown:
- return t.GetWellKnown() == exprpb.Type_ANY
default:
return false
}
}
// isDynOrError returns true if the input is either an Error, DYN, or well-known ANY message.
-func isDynOrError(t *exprpb.Type) bool {
+func isDynOrError(t *types.Type) bool {
return isError(t) || isDyn(t)
}
-func isError(t *exprpb.Type) bool {
- return kindOf(t) == kindError
+func isError(t *types.Type) bool {
+ return t.Kind() == types.ErrorKind
}
-func isOptional(t *exprpb.Type) bool {
- if kindOf(t) == kindAbstract {
- at := t.GetAbstractType()
- return at.GetName() == "optional"
+func isOptional(t *types.Type) bool {
+ if t.Kind() == types.OpaqueKind {
+ return t.TypeName() == "optional"
}
return false
}
-func maybeUnwrapOptional(t *exprpb.Type) (*exprpb.Type, bool) {
+func maybeUnwrapOptional(t *types.Type) (*types.Type, bool) {
if isOptional(t) {
- at := t.GetAbstractType()
- return at.GetParameterTypes()[0], true
+ return t.Parameters()[0], true
}
return t, false
}
-func maybeUnwrapString(e *exprpb.Expr) (string, bool) {
- switch e.GetExprKind().(type) {
- case *exprpb.Expr_ConstExpr:
- literal := e.GetConstExpr()
- switch literal.GetConstantKind().(type) {
- case *exprpb.Constant_StringValue:
- return literal.GetStringValue(), true
- }
- }
- return "", false
-}
-
// isEqualOrLessSpecific checks whether one type is equal or less specific than the other one.
// A type is less specific if it matches the other type using the DYN type.
-func isEqualOrLessSpecific(t1 *exprpb.Type, t2 *exprpb.Type) bool {
- kind1, kind2 := kindOf(t1), kindOf(t2)
+func isEqualOrLessSpecific(t1, t2 *types.Type) bool {
+ kind1, kind2 := t1.Kind(), t2.Kind()
// The first type is less specific.
- if isDyn(t1) || kind1 == kindTypeParam {
+ if isDyn(t1) || kind1 == types.TypeParamKind {
return true
}
// The first type is not less specific.
- if isDyn(t2) || kind2 == kindTypeParam {
+ if isDyn(t2) || kind2 == types.TypeParamKind {
return false
}
// Types must be of the same kind to be equal.
@@ -173,38 +73,34 @@ func isEqualOrLessSpecific(t1 *exprpb.Type, t2 *exprpb.Type) bool {
// With limited exceptions for ANY and JSON values, the types must agree and be equivalent in
// order to return true.
switch kind1 {
- case kindAbstract:
- a1 := t1.GetAbstractType()
- a2 := t2.GetAbstractType()
- if a1.GetName() != a2.GetName() ||
- len(a1.GetParameterTypes()) != len(a2.GetParameterTypes()) {
+ case types.OpaqueKind:
+ if t1.TypeName() != t2.TypeName() ||
+ len(t1.Parameters()) != len(t2.Parameters()) {
return false
}
- for i, p1 := range a1.GetParameterTypes() {
- if !isEqualOrLessSpecific(p1, a2.GetParameterTypes()[i]) {
+ for i, p1 := range t1.Parameters() {
+ if !isEqualOrLessSpecific(p1, t2.Parameters()[i]) {
return false
}
}
return true
- case kindList:
- return isEqualOrLessSpecific(t1.GetListType().GetElemType(), t2.GetListType().GetElemType())
- case kindMap:
- m1 := t1.GetMapType()
- m2 := t2.GetMapType()
- return isEqualOrLessSpecific(m1.GetKeyType(), m2.GetKeyType()) &&
- isEqualOrLessSpecific(m1.GetValueType(), m2.GetValueType())
- case kindType:
+ case types.ListKind:
+ return isEqualOrLessSpecific(t1.Parameters()[0], t2.Parameters()[0])
+ case types.MapKind:
+ return isEqualOrLessSpecific(t1.Parameters()[0], t2.Parameters()[0]) &&
+ isEqualOrLessSpecific(t1.Parameters()[1], t2.Parameters()[1])
+ case types.TypeKind:
return true
default:
- return proto.Equal(t1, t2)
+ return t1.IsExactType(t2)
}
}
// / internalIsAssignable returns true if t1 is assignable to t2.
-func internalIsAssignable(m *mapping, t1 *exprpb.Type, t2 *exprpb.Type) bool {
+func internalIsAssignable(m *mapping, t1, t2 *types.Type) bool {
// Process type parameters.
- kind1, kind2 := kindOf(t1), kindOf(t2)
- if kind2 == kindTypeParam {
+ kind1, kind2 := t1.Kind(), t2.Kind()
+ if kind2 == types.TypeParamKind {
// If t2 is a valid type substitution for t1, return true.
valid, t2HasSub := isValidTypeSubstitution(m, t1, t2)
if valid {
@@ -217,7 +113,7 @@ func internalIsAssignable(m *mapping, t1 *exprpb.Type, t2 *exprpb.Type) bool {
}
// Otherwise, fall through to check whether t1 is a possible substitution for t2.
}
- if kind1 == kindTypeParam {
+ if kind1 == types.TypeParamKind {
// Return whether t1 is a valid substitution for t2. If not, do no additional checks as the
// possible type substitutions have been searched in both directions.
valid, _ := isValidTypeSubstitution(m, t2, t1)
@@ -228,40 +124,25 @@ func internalIsAssignable(m *mapping, t1 *exprpb.Type, t2 *exprpb.Type) bool {
if isDynOrError(t1) || isDynOrError(t2) {
return true
}
-
- // Test for when the types do not need to agree, but are more specific than dyn.
- switch kind1 {
- case kindNull:
+ // Preserve the nullness checks of the legacy type-checker.
+ if kind1 == types.NullTypeKind {
return internalIsAssignableNull(t2)
- case kindPrimitive:
- return internalIsAssignablePrimitive(t1.GetPrimitive(), t2)
- case kindWrapper:
- return internalIsAssignable(m, decls.NewPrimitiveType(t1.GetWrapper()), t2)
- default:
- if kind1 != kind2 {
- return false
- }
+ }
+ if kind2 == types.NullTypeKind {
+ return internalIsAssignableNull(t1)
}
- // Test for when the types must agree.
+ // Test for when the types do not need to agree, but are more specific than dyn.
switch kind1 {
- // ERROR, TYPE_PARAM, and DYN handled above.
- case kindAbstract:
- return internalIsAssignableAbstractType(m, t1.GetAbstractType(), t2.GetAbstractType())
- case kindFunction:
- return internalIsAssignableFunction(m, t1.GetFunction(), t2.GetFunction())
- case kindList:
- return internalIsAssignable(m, t1.GetListType().GetElemType(), t2.GetListType().GetElemType())
- case kindMap:
- return internalIsAssignableMap(m, t1.GetMapType(), t2.GetMapType())
- case kindObject:
- return t1.GetMessageType() == t2.GetMessageType()
- case kindType:
- // A type is a type is a type, any additional parameterization of the
- // type cannot affect method resolution or assignability.
- return true
- case kindWellKnown:
- return t1.GetWellKnown() == t2.GetWellKnown()
+ case types.BoolKind, types.BytesKind, types.DoubleKind, types.IntKind, types.StringKind, types.UintKind,
+ types.AnyKind, types.DurationKind, types.TimestampKind,
+ types.StructKind:
+ return t1.IsAssignableType(t2)
+ case types.TypeKind:
+ return kind2 == types.TypeKind
+ case types.OpaqueKind, types.ListKind, types.MapKind:
+ return t1.Kind() == t2.Kind() && t1.TypeName() == t2.TypeName() &&
+ internalIsAssignableList(m, t1.Parameters(), t2.Parameters())
default:
return false
}
@@ -271,19 +152,19 @@ func internalIsAssignable(m *mapping, t1 *exprpb.Type, t2 *exprpb.Type) bool {
// substitution for t1, and whether t2 has a type substitution in mapping m.
//
// The type t2 is a valid substitution for t1 if any of the following statements is true
-// - t2 has a type substitition (t2sub) equal to t1
+// - t2 has a type substitution (t2sub) equal to t1
// - t2 has a type substitution (t2sub) assignable to t1
// - t2 does not occur within t1.
-func isValidTypeSubstitution(m *mapping, t1, t2 *exprpb.Type) (valid, hasSub bool) {
+func isValidTypeSubstitution(m *mapping, t1, t2 *types.Type) (valid, hasSub bool) {
// Early return if the t1 and t2 are the same instance.
- kind1, kind2 := kindOf(t1), kindOf(t2)
- if kind1 == kind2 && (t1 == t2 || proto.Equal(t1, t2)) {
+ kind1, kind2 := t1.Kind(), t2.Kind()
+ if kind1 == kind2 && t1.IsExactType(t2) {
return true, true
}
if t2Sub, found := m.find(t2); found {
// Early return if t1 and t2Sub are the same instance as otherwise the mapping
// might mark a type as being a subtitution for itself.
- if kind1 == kindOf(t2Sub) && (t1 == t2Sub || proto.Equal(t1, t2Sub)) {
+ if kind1 == t2Sub.Kind() && t1.IsExactType(t2Sub) {
return true, true
}
// If the types are compatible, pick the more general type and return true
@@ -305,28 +186,10 @@ func isValidTypeSubstitution(m *mapping, t1, t2 *exprpb.Type) (valid, hasSub boo
return false, false
}
-// internalIsAssignableAbstractType returns true if the abstract type names agree and all type
-// parameters are assignable.
-func internalIsAssignableAbstractType(m *mapping, a1 *exprpb.Type_AbstractType, a2 *exprpb.Type_AbstractType) bool {
- return a1.GetName() == a2.GetName() &&
- internalIsAssignableList(m, a1.GetParameterTypes(), a2.GetParameterTypes())
-}
-
-// internalIsAssignableFunction returns true if the function return type and arg types are
-// assignable.
-func internalIsAssignableFunction(m *mapping, f1 *exprpb.Type_FunctionType, f2 *exprpb.Type_FunctionType) bool {
- f1ArgTypes := flattenFunctionTypes(f1)
- f2ArgTypes := flattenFunctionTypes(f2)
- if internalIsAssignableList(m, f1ArgTypes, f2ArgTypes) {
- return true
- }
- return false
-}
-
// internalIsAssignableList returns true if the element types at each index in the list are
// assignable from l1[i] to l2[i]. The list lengths must also agree for the lists to be
// assignable.
-func internalIsAssignableList(m *mapping, l1 []*exprpb.Type, l2 []*exprpb.Type) bool {
+func internalIsAssignableList(m *mapping, l1, l2 []*types.Type) bool {
if len(l1) != len(l2) {
return false
}
@@ -338,41 +201,22 @@ func internalIsAssignableList(m *mapping, l1 []*exprpb.Type, l2 []*exprpb.Type)
return true
}
-// internalIsAssignableMap returns true if map m1 may be assigned to map m2.
-func internalIsAssignableMap(m *mapping, m1 *exprpb.Type_MapType, m2 *exprpb.Type_MapType) bool {
- if internalIsAssignableList(m,
- []*exprpb.Type{m1.GetKeyType(), m1.GetValueType()},
- []*exprpb.Type{m2.GetKeyType(), m2.GetValueType()}) {
- return true
- }
- return false
-}
-
// internalIsAssignableNull returns true if the type is nullable.
-func internalIsAssignableNull(t *exprpb.Type) bool {
- switch kindOf(t) {
- case kindAbstract, kindObject, kindNull, kindWellKnown, kindWrapper:
- return true
- default:
- return false
- }
+func internalIsAssignableNull(t *types.Type) bool {
+ return isLegacyNullable(t) || t.IsAssignableType(types.NullType)
}
-// internalIsAssignablePrimitive returns true if the target type is the same or if it is a wrapper
-// for the primitive type.
-func internalIsAssignablePrimitive(p exprpb.Type_PrimitiveType, target *exprpb.Type) bool {
- switch kindOf(target) {
- case kindPrimitive:
- return p == target.GetPrimitive()
- case kindWrapper:
- return p == target.GetWrapper()
- default:
- return false
+// isLegacyNullable preserves the null-ness compatibility of the original type-checker implementation.
+func isLegacyNullable(t *types.Type) bool {
+ switch t.Kind() {
+ case types.OpaqueKind, types.StructKind, types.AnyKind, types.DurationKind, types.TimestampKind:
+ return true
}
+ return false
}
// isAssignable returns an updated type substitution mapping if t1 is assignable to t2.
-func isAssignable(m *mapping, t1 *exprpb.Type, t2 *exprpb.Type) *mapping {
+func isAssignable(m *mapping, t1, t2 *types.Type) *mapping {
mCopy := m.copy()
if internalIsAssignable(mCopy, t1, t2) {
return mCopy
@@ -381,7 +225,7 @@ func isAssignable(m *mapping, t1 *exprpb.Type, t2 *exprpb.Type) *mapping {
}
// isAssignableList returns an updated type substitution mapping if l1 is assignable to l2.
-func isAssignableList(m *mapping, l1 []*exprpb.Type, l2 []*exprpb.Type) *mapping {
+func isAssignableList(m *mapping, l1, l2 []*types.Type) *mapping {
mCopy := m.copy()
if internalIsAssignableList(mCopy, l1, l2) {
return mCopy
@@ -389,44 +233,8 @@ func isAssignableList(m *mapping, l1 []*exprpb.Type, l2 []*exprpb.Type) *mapping
return nil
}
-// kindOf returns the kind of the type as defined in the checked.proto.
-func kindOf(t *exprpb.Type) int {
- if t == nil || t.TypeKind == nil {
- return kindUnknown
- }
- switch t.GetTypeKind().(type) {
- case *exprpb.Type_Error:
- return kindError
- case *exprpb.Type_Function:
- return kindFunction
- case *exprpb.Type_Dyn:
- return kindDyn
- case *exprpb.Type_Primitive:
- return kindPrimitive
- case *exprpb.Type_WellKnown:
- return kindWellKnown
- case *exprpb.Type_Wrapper:
- return kindWrapper
- case *exprpb.Type_Null:
- return kindNull
- case *exprpb.Type_Type:
- return kindType
- case *exprpb.Type_ListType_:
- return kindList
- case *exprpb.Type_MapType_:
- return kindMap
- case *exprpb.Type_MessageType:
- return kindObject
- case *exprpb.Type_TypeParam:
- return kindTypeParam
- case *exprpb.Type_AbstractType_:
- return kindAbstract
- }
- return kindUnknown
-}
-
// mostGeneral returns the more general of two types which are known to unify.
-func mostGeneral(t1 *exprpb.Type, t2 *exprpb.Type) *exprpb.Type {
+func mostGeneral(t1, t2 *types.Type) *types.Type {
if isEqualOrLessSpecific(t1, t2) {
return t1
}
@@ -436,32 +244,25 @@ func mostGeneral(t1 *exprpb.Type, t2 *exprpb.Type) *exprpb.Type {
// notReferencedIn checks whether the type doesn't appear directly or transitively within the other
// type. This is a standard requirement for type unification, commonly referred to as the "occurs
// check".
-func notReferencedIn(m *mapping, t *exprpb.Type, withinType *exprpb.Type) bool {
- if proto.Equal(t, withinType) {
+func notReferencedIn(m *mapping, t, withinType *types.Type) bool {
+ if t.IsExactType(withinType) {
return false
}
- withinKind := kindOf(withinType)
+ withinKind := withinType.Kind()
switch withinKind {
- case kindTypeParam:
+ case types.TypeParamKind:
wtSub, found := m.find(withinType)
if !found {
return true
}
return notReferencedIn(m, t, wtSub)
- case kindAbstract:
- for _, pt := range withinType.GetAbstractType().GetParameterTypes() {
+ case types.OpaqueKind, types.ListKind, types.MapKind:
+ for _, pt := range withinType.Parameters() {
if !notReferencedIn(m, t, pt) {
return false
}
}
return true
- case kindList:
- return notReferencedIn(m, t, withinType.GetListType().GetElemType())
- case kindMap:
- mt := withinType.GetMapType()
- return notReferencedIn(m, t, mt.GetKeyType()) && notReferencedIn(m, t, mt.GetValueType())
- case kindWrapper:
- return notReferencedIn(m, t, decls.NewPrimitiveType(withinType.GetWrapper()))
default:
return true
}
@@ -469,39 +270,25 @@ func notReferencedIn(m *mapping, t *exprpb.Type, withinType *exprpb.Type) bool {
// substitute replaces all direct and indirect occurrences of bound type parameters. Unbound type
// parameters are replaced by DYN if typeParamToDyn is true.
-func substitute(m *mapping, t *exprpb.Type, typeParamToDyn bool) *exprpb.Type {
+func substitute(m *mapping, t *types.Type, typeParamToDyn bool) *types.Type {
if tSub, found := m.find(t); found {
return substitute(m, tSub, typeParamToDyn)
}
- kind := kindOf(t)
- if typeParamToDyn && kind == kindTypeParam {
- return decls.Dyn
+ kind := t.Kind()
+ if typeParamToDyn && kind == types.TypeParamKind {
+ return types.DynType
}
switch kind {
- case kindAbstract:
- at := t.GetAbstractType()
- params := make([]*exprpb.Type, len(at.GetParameterTypes()))
- for i, p := range at.GetParameterTypes() {
- params[i] = substitute(m, p, typeParamToDyn)
- }
- return decls.NewAbstractType(at.GetName(), params...)
- case kindFunction:
- fn := t.GetFunction()
- rt := substitute(m, fn.ResultType, typeParamToDyn)
- args := make([]*exprpb.Type, len(fn.GetArgTypes()))
- for i, a := range fn.ArgTypes {
- args[i] = substitute(m, a, typeParamToDyn)
- }
- return decls.NewFunctionType(rt, args...)
- case kindList:
- return decls.NewListType(substitute(m, t.GetListType().GetElemType(), typeParamToDyn))
- case kindMap:
- mt := t.GetMapType()
- return decls.NewMapType(substitute(m, mt.GetKeyType(), typeParamToDyn),
- substitute(m, mt.GetValueType(), typeParamToDyn))
- case kindType:
- if t.GetType() != nil {
- return decls.NewTypeType(substitute(m, t.GetType(), typeParamToDyn))
+ case types.OpaqueKind:
+ return types.NewOpaqueType(t.TypeName(), substituteParams(m, t.Parameters(), typeParamToDyn)...)
+ case types.ListKind:
+ return types.NewListType(substitute(m, t.Parameters()[0], typeParamToDyn))
+ case types.MapKind:
+ return types.NewMapType(substitute(m, t.Parameters()[0], typeParamToDyn),
+ substitute(m, t.Parameters()[1], typeParamToDyn))
+ case types.TypeKind:
+ if len(t.Parameters()) > 0 {
+ return types.NewTypeTypeWithParam(substitute(m, t.Parameters()[0], typeParamToDyn))
}
return t
default:
@@ -509,21 +296,14 @@ func substitute(m *mapping, t *exprpb.Type, typeParamToDyn bool) *exprpb.Type {
}
}
-func typeKey(t *exprpb.Type) string {
- return FormatCheckedType(t)
+func substituteParams(m *mapping, typeParams []*types.Type, typeParamToDyn bool) []*types.Type {
+ subParams := make([]*types.Type, len(typeParams))
+ for i, tp := range typeParams {
+ subParams[i] = substitute(m, tp, typeParamToDyn)
+ }
+ return subParams
}
-// flattenFunctionTypes takes a function with arg types T1, T2, ..., TN and result type TR
-// and returns a slice containing {T1, T2, ..., TN, TR}.
-func flattenFunctionTypes(f *exprpb.Type_FunctionType) []*exprpb.Type {
- argTypes := f.GetArgTypes()
- if len(argTypes) == 0 {
- return []*exprpb.Type{f.GetResultType()}
- }
- flattend := make([]*exprpb.Type, len(argTypes)+1, len(argTypes)+1)
- for i, at := range argTypes {
- flattend[i] = at
- }
- flattend[len(argTypes)] = f.GetResultType()
- return flattend
+func newFunctionType(resultType *types.Type, argTypes ...*types.Type) *types.Type {
+ return types.NewOpaqueType("function", append([]*types.Type{resultType}, argTypes...)...)
}
diff --git a/vendor/github.com/google/cel-go/common/BUILD.bazel b/vendor/github.com/google/cel-go/common/BUILD.bazel
index a0058aebe..d6165b13a 100644
--- a/vendor/github.com/google/cel-go/common/BUILD.bazel
+++ b/vendor/github.com/google/cel-go/common/BUILD.bazel
@@ -17,7 +17,7 @@ go_library(
importpath = "github.com/google/cel-go/common",
deps = [
"//common/runes:go_default_library",
- "@org_golang_google_genproto//googleapis/api/expr/v1alpha1:go_default_library",
+ "@org_golang_google_genproto_googleapis_api//expr/v1alpha1:go_default_library",
"@org_golang_x_text//width:go_default_library",
],
)
diff --git a/vendor/github.com/google/cel-go/common/ast/BUILD.bazel b/vendor/github.com/google/cel-go/common/ast/BUILD.bazel
new file mode 100644
index 000000000..7269cdff5
--- /dev/null
+++ b/vendor/github.com/google/cel-go/common/ast/BUILD.bazel
@@ -0,0 +1,52 @@
+load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
+
+package(
+ default_visibility = [
+ "//cel:__subpackages__",
+ "//checker:__subpackages__",
+ "//common:__subpackages__",
+ "//interpreter:__subpackages__",
+ ],
+ licenses = ["notice"], # Apache 2.0
+)
+
+go_library(
+ name = "go_default_library",
+ srcs = [
+ "ast.go",
+ "expr.go",
+ ],
+ importpath = "github.com/google/cel-go/common/ast",
+ deps = [
+ "//common/types:go_default_library",
+ "//common/types/ref:go_default_library",
+ "@org_golang_google_genproto_googleapis_api//expr/v1alpha1:go_default_library",
+ "@org_golang_google_protobuf//types/known/structpb:go_default_library",
+ ],
+)
+
+go_test(
+ name = "go_default_test",
+ srcs = [
+ "ast_test.go",
+ "expr_test.go",
+ ],
+ embed = [
+ ":go_default_library",
+ ],
+ deps = [
+ "//checker:go_default_library",
+ "//checker/decls:go_default_library",
+ "//common:go_default_library",
+ "//common/containers:go_default_library",
+ "//common/decls:go_default_library",
+ "//common/overloads:go_default_library",
+ "//common/stdlib:go_default_library",
+ "//common/types:go_default_library",
+ "//common/types/ref:go_default_library",
+ "//parser:go_default_library",
+ "//test/proto3pb:go_default_library",
+ "@org_golang_google_genproto_googleapis_api//expr/v1alpha1:go_default_library",
+ "@org_golang_google_protobuf//proto:go_default_library",
+ ],
+)
\ No newline at end of file
diff --git a/vendor/github.com/google/cel-go/common/ast/ast.go b/vendor/github.com/google/cel-go/common/ast/ast.go
new file mode 100644
index 000000000..b3c150793
--- /dev/null
+++ b/vendor/github.com/google/cel-go/common/ast/ast.go
@@ -0,0 +1,226 @@
+// Copyright 2023 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package ast declares data structures useful for parsed and checked abstract syntax trees
+package ast
+
+import (
+ "fmt"
+
+ "github.com/google/cel-go/common/types"
+ "github.com/google/cel-go/common/types/ref"
+
+ structpb "google.golang.org/protobuf/types/known/structpb"
+
+ exprpb "google.golang.org/genproto/googleapis/api/expr/v1alpha1"
+)
+
+// CheckedAST contains a protobuf expression and source info along with CEL-native type and reference information.
+type CheckedAST struct {
+ Expr *exprpb.Expr
+ SourceInfo *exprpb.SourceInfo
+ TypeMap map[int64]*types.Type
+ ReferenceMap map[int64]*ReferenceInfo
+}
+
+// CheckedASTToCheckedExpr converts a CheckedAST to a CheckedExpr protobouf.
+func CheckedASTToCheckedExpr(ast *CheckedAST) (*exprpb.CheckedExpr, error) {
+ refMap := make(map[int64]*exprpb.Reference, len(ast.ReferenceMap))
+ for id, ref := range ast.ReferenceMap {
+ r, err := ReferenceInfoToReferenceExpr(ref)
+ if err != nil {
+ return nil, err
+ }
+ refMap[id] = r
+ }
+ typeMap := make(map[int64]*exprpb.Type, len(ast.TypeMap))
+ for id, typ := range ast.TypeMap {
+ t, err := types.TypeToExprType(typ)
+ if err != nil {
+ return nil, err
+ }
+ typeMap[id] = t
+ }
+ return &exprpb.CheckedExpr{
+ Expr: ast.Expr,
+ SourceInfo: ast.SourceInfo,
+ ReferenceMap: refMap,
+ TypeMap: typeMap,
+ }, nil
+}
+
+// CheckedExprToCheckedAST converts a CheckedExpr protobuf to a CheckedAST instance.
+func CheckedExprToCheckedAST(checked *exprpb.CheckedExpr) (*CheckedAST, error) {
+ refMap := make(map[int64]*ReferenceInfo, len(checked.GetReferenceMap()))
+ for id, ref := range checked.GetReferenceMap() {
+ r, err := ReferenceExprToReferenceInfo(ref)
+ if err != nil {
+ return nil, err
+ }
+ refMap[id] = r
+ }
+ typeMap := make(map[int64]*types.Type, len(checked.GetTypeMap()))
+ for id, typ := range checked.GetTypeMap() {
+ t, err := types.ExprTypeToType(typ)
+ if err != nil {
+ return nil, err
+ }
+ typeMap[id] = t
+ }
+ return &CheckedAST{
+ Expr: checked.GetExpr(),
+ SourceInfo: checked.GetSourceInfo(),
+ ReferenceMap: refMap,
+ TypeMap: typeMap,
+ }, nil
+}
+
+// ReferenceInfo contains a CEL native representation of an identifier reference which may refer to
+// either a qualified identifier name, a set of overload ids, or a constant value from an enum.
+type ReferenceInfo struct {
+ Name string
+ OverloadIDs []string
+ Value ref.Val
+}
+
+// NewIdentReference creates a ReferenceInfo instance for an identifier with an optional constant value.
+func NewIdentReference(name string, value ref.Val) *ReferenceInfo {
+ return &ReferenceInfo{Name: name, Value: value}
+}
+
+// NewFunctionReference creates a ReferenceInfo instance for a set of function overloads.
+func NewFunctionReference(overloads ...string) *ReferenceInfo {
+ info := &ReferenceInfo{}
+ for _, id := range overloads {
+ info.AddOverload(id)
+ }
+ return info
+}
+
+// AddOverload appends a function overload ID to the ReferenceInfo.
+func (r *ReferenceInfo) AddOverload(overloadID string) {
+ for _, id := range r.OverloadIDs {
+ if id == overloadID {
+ return
+ }
+ }
+ r.OverloadIDs = append(r.OverloadIDs, overloadID)
+}
+
+// Equals returns whether two references are identical to each other.
+func (r *ReferenceInfo) Equals(other *ReferenceInfo) bool {
+ if r.Name != other.Name {
+ return false
+ }
+ if len(r.OverloadIDs) != len(other.OverloadIDs) {
+ return false
+ }
+ if len(r.OverloadIDs) != 0 {
+ overloadMap := make(map[string]struct{}, len(r.OverloadIDs))
+ for _, id := range r.OverloadIDs {
+ overloadMap[id] = struct{}{}
+ }
+ for _, id := range other.OverloadIDs {
+ _, found := overloadMap[id]
+ if !found {
+ return false
+ }
+ }
+ }
+ if r.Value == nil && other.Value == nil {
+ return true
+ }
+ if r.Value == nil && other.Value != nil ||
+ r.Value != nil && other.Value == nil ||
+ r.Value.Equal(other.Value) != types.True {
+ return false
+ }
+ return true
+}
+
+// ReferenceInfoToReferenceExpr converts a ReferenceInfo instance to a protobuf Reference suitable for serialization.
+func ReferenceInfoToReferenceExpr(info *ReferenceInfo) (*exprpb.Reference, error) {
+ c, err := ValToConstant(info.Value)
+ if err != nil {
+ return nil, err
+ }
+ return &exprpb.Reference{
+ Name: info.Name,
+ OverloadId: info.OverloadIDs,
+ Value: c,
+ }, nil
+}
+
+// ReferenceExprToReferenceInfo converts a protobuf Reference into a CEL-native ReferenceInfo instance.
+func ReferenceExprToReferenceInfo(ref *exprpb.Reference) (*ReferenceInfo, error) {
+ v, err := ConstantToVal(ref.GetValue())
+ if err != nil {
+ return nil, err
+ }
+ return &ReferenceInfo{
+ Name: ref.GetName(),
+ OverloadIDs: ref.GetOverloadId(),
+ Value: v,
+ }, nil
+}
+
+// ValToConstant converts a CEL-native ref.Val to a protobuf Constant.
+//
+// Only simple scalar types are supported by this method.
+func ValToConstant(v ref.Val) (*exprpb.Constant, error) {
+ if v == nil {
+ return nil, nil
+ }
+ switch v.Type() {
+ case types.BoolType:
+ return &exprpb.Constant{ConstantKind: &exprpb.Constant_BoolValue{BoolValue: v.Value().(bool)}}, nil
+ case types.BytesType:
+ return &exprpb.Constant{ConstantKind: &exprpb.Constant_BytesValue{BytesValue: v.Value().([]byte)}}, nil
+ case types.DoubleType:
+ return &exprpb.Constant{ConstantKind: &exprpb.Constant_DoubleValue{DoubleValue: v.Value().(float64)}}, nil
+ case types.IntType:
+ return &exprpb.Constant{ConstantKind: &exprpb.Constant_Int64Value{Int64Value: v.Value().(int64)}}, nil
+ case types.NullType:
+ return &exprpb.Constant{ConstantKind: &exprpb.Constant_NullValue{NullValue: structpb.NullValue_NULL_VALUE}}, nil
+ case types.StringType:
+ return &exprpb.Constant{ConstantKind: &exprpb.Constant_StringValue{StringValue: v.Value().(string)}}, nil
+ case types.UintType:
+ return &exprpb.Constant{ConstantKind: &exprpb.Constant_Uint64Value{Uint64Value: v.Value().(uint64)}}, nil
+ }
+ return nil, fmt.Errorf("unsupported constant kind: %v", v.Type())
+}
+
+// ConstantToVal converts a protobuf Constant to a CEL-native ref.Val.
+func ConstantToVal(c *exprpb.Constant) (ref.Val, error) {
+ if c == nil {
+ return nil, nil
+ }
+ switch c.GetConstantKind().(type) {
+ case *exprpb.Constant_BoolValue:
+ return types.Bool(c.GetBoolValue()), nil
+ case *exprpb.Constant_BytesValue:
+ return types.Bytes(c.GetBytesValue()), nil
+ case *exprpb.Constant_DoubleValue:
+ return types.Double(c.GetDoubleValue()), nil
+ case *exprpb.Constant_Int64Value:
+ return types.Int(c.GetInt64Value()), nil
+ case *exprpb.Constant_NullValue:
+ return types.NullValue, nil
+ case *exprpb.Constant_StringValue:
+ return types.String(c.GetStringValue()), nil
+ case *exprpb.Constant_Uint64Value:
+ return types.Uint(c.GetUint64Value()), nil
+ }
+ return nil, fmt.Errorf("unsupported constant kind: %v", c.GetConstantKind())
+}
diff --git a/vendor/github.com/google/cel-go/common/ast/expr.go b/vendor/github.com/google/cel-go/common/ast/expr.go
new file mode 100644
index 000000000..b63884a60
--- /dev/null
+++ b/vendor/github.com/google/cel-go/common/ast/expr.go
@@ -0,0 +1,709 @@
+// Copyright 2023 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package ast
+
+import (
+ "github.com/google/cel-go/common/types"
+ "github.com/google/cel-go/common/types/ref"
+
+ exprpb "google.golang.org/genproto/googleapis/api/expr/v1alpha1"
+)
+
+// ExprKind represents the expression node kind.
+type ExprKind int
+
+const (
+ // UnspecifiedKind represents an unset expression with no specified properties.
+ UnspecifiedKind ExprKind = iota
+
+ // LiteralKind represents a primitive scalar literal.
+ LiteralKind
+
+ // IdentKind represents a simple variable, constant, or type identifier.
+ IdentKind
+
+ // SelectKind represents a field selection expression.
+ SelectKind
+
+ // CallKind represents a function call.
+ CallKind
+
+ // ListKind represents a list literal expression.
+ ListKind
+
+ // MapKind represents a map literal expression.
+ MapKind
+
+ // StructKind represents a struct literal expression.
+ StructKind
+
+ // ComprehensionKind represents a comprehension expression generated by a macro.
+ ComprehensionKind
+)
+
+// NavigateCheckedAST converts a CheckedAST to a NavigableExpr
+func NavigateCheckedAST(ast *CheckedAST) NavigableExpr {
+ return newNavigableExpr(nil, ast.Expr, ast.TypeMap)
+}
+
+// ExprMatcher takes a NavigableExpr in and indicates whether the value is a match.
+//
+// This function type should be use with the `Match` and `MatchList` calls.
+type ExprMatcher func(NavigableExpr) bool
+
+// ConstantValueMatcher returns an ExprMatcher which will return true if the input NavigableExpr
+// is comprised of all constant values, such as a simple literal or even list and map literal.
+func ConstantValueMatcher() ExprMatcher {
+ return matchIsConstantValue
+}
+
+// KindMatcher returns an ExprMatcher which will return true if the input NavigableExpr.Kind() matches
+// the specified `kind`.
+func KindMatcher(kind ExprKind) ExprMatcher {
+ return func(e NavigableExpr) bool {
+ return e.Kind() == kind
+ }
+}
+
+// FunctionMatcher returns an ExprMatcher which will match NavigableExpr nodes of CallKind type whose
+// function name is equal to `funcName`.
+func FunctionMatcher(funcName string) ExprMatcher {
+ return func(e NavigableExpr) bool {
+ if e.Kind() != CallKind {
+ return false
+ }
+ return e.AsCall().FunctionName() == funcName
+ }
+}
+
+// AllMatcher returns true for all descendants of a NavigableExpr, effectively flattening them into a list.
+//
+// Such a result would work well with subsequent MatchList calls.
+func AllMatcher() ExprMatcher {
+ return func(NavigableExpr) bool {
+ return true
+ }
+}
+
+// MatchDescendants takes a NavigableExpr and ExprMatcher and produces a list of NavigableExpr values of the
+// descendants which match.
+func MatchDescendants(expr NavigableExpr, matcher ExprMatcher) []NavigableExpr {
+ return matchListInternal([]NavigableExpr{expr}, matcher, true)
+}
+
+// MatchSubset applies an ExprMatcher to a list of NavigableExpr values and their descendants, producing a
+// subset of NavigableExpr values which match.
+func MatchSubset(exprs []NavigableExpr, matcher ExprMatcher) []NavigableExpr {
+ visit := make([]NavigableExpr, len(exprs))
+ copy(visit, exprs)
+ return matchListInternal(visit, matcher, false)
+}
+
+func matchListInternal(visit []NavigableExpr, matcher ExprMatcher, visitDescendants bool) []NavigableExpr {
+ var matched []NavigableExpr
+ for len(visit) != 0 {
+ e := visit[0]
+ if matcher(e) {
+ matched = append(matched, e)
+ }
+ if visitDescendants {
+ visit = append(visit[1:], e.Children()...)
+ } else {
+ visit = visit[1:]
+ }
+ }
+ return matched
+}
+
+func matchIsConstantValue(e NavigableExpr) bool {
+ if e.Kind() == LiteralKind {
+ return true
+ }
+ if e.Kind() == StructKind || e.Kind() == MapKind || e.Kind() == ListKind {
+ for _, child := range e.Children() {
+ if !matchIsConstantValue(child) {
+ return false
+ }
+ }
+ return true
+ }
+ return false
+}
+
+// NavigableExpr represents the base navigable expression value.
+//
+// Depending on the `Kind()` value, the NavigableExpr may be converted to a concrete expression types
+// as indicated by the `As` methods.
+//
+// NavigableExpr values and their concrete expression types should be nil-safe. Conversion of an expr
+// to the wrong kind should produce a nil value.
+type NavigableExpr interface {
+ // ID of the expression as it appears in the AST
+ ID() int64
+
+ // Kind of the expression node. See ExprKind for the valid enum values.
+ Kind() ExprKind
+
+ // Type of the expression node.
+ Type() *types.Type
+
+ // Parent returns the parent expression node, if one exists.
+ Parent() (NavigableExpr, bool)
+
+ // Children returns a list of child expression nodes.
+ Children() []NavigableExpr
+
+ // ToExpr adapts this NavigableExpr to a protobuf representation.
+ ToExpr() *exprpb.Expr
+
+ // AsCall adapts the expr into a NavigableCallExpr
+ //
+ // The Kind() must be equal to a CallKind for the conversion to be well-defined.
+ AsCall() NavigableCallExpr
+
+ // AsComprehension adapts the expr into a NavigableComprehensionExpr.
+ //
+ // The Kind() must be equal to a ComprehensionKind for the conversion to be well-defined.
+ AsComprehension() NavigableComprehensionExpr
+
+ // AsIdent adapts the expr into an identifier string.
+ //
+ // The Kind() must be equal to an IdentKind for the conversion to be well-defined.
+ AsIdent() string
+
+ // AsLiteral adapts the expr into a constant ref.Val.
+ //
+ // The Kind() must be equal to a LiteralKind for the conversion to be well-defined.
+ AsLiteral() ref.Val
+
+ // AsList adapts the expr into a NavigableListExpr.
+ //
+ // The Kind() must be equal to a ListKind for the conversion to be well-defined.
+ AsList() NavigableListExpr
+
+ // AsMap adapts the expr into a NavigableMapExpr.
+ //
+ // The Kind() must be equal to a MapKind for the conversion to be well-defined.
+ AsMap() NavigableMapExpr
+
+ // AsSelect adapts the expr into a NavigableSelectExpr.
+ //
+ // The Kind() must be equal to a SelectKind for the conversion to be well-defined.
+ AsSelect() NavigableSelectExpr
+
+ // AsStruct adapts the expr into a NavigableStructExpr.
+ //
+ // The Kind() must be equal to a StructKind for the conversion to be well-defined.
+ AsStruct() NavigableStructExpr
+
+ // marker interface method
+ isNavigable()
+}
+
+// NavigableCallExpr defines an interface for inspecting a function call and its arugments.
+type NavigableCallExpr interface {
+ // FunctionName returns the name of the function.
+ FunctionName() string
+
+ // Target returns the target of the expression if one is present.
+ Target() NavigableExpr
+
+ // Args returns the list of call arguments, excluding the target.
+ Args() []NavigableExpr
+
+ // ReturnType returns the result type of the call.
+ ReturnType() *types.Type
+
+ // marker interface method
+ isNavigable()
+}
+
+// NavigableListExpr defines an interface for inspecting a list literal expression.
+type NavigableListExpr interface {
+ // Elements returns the list elements as navigable expressions.
+ Elements() []NavigableExpr
+
+ // OptionalIndicies returns the list of optional indices in the list literal.
+ OptionalIndices() []int32
+
+ // Size returns the number of elements in the list.
+ Size() int
+
+ // marker interface method
+ isNavigable()
+}
+
+// NavigableSelectExpr defines an interface for inspecting a select expression.
+type NavigableSelectExpr interface {
+ // Operand returns the selection operand expression.
+ Operand() NavigableExpr
+
+ // FieldName returns the field name being selected from the operand.
+ FieldName() string
+
+ // IsTestOnly indicates whether the select expression is a presence test generated by a macro.
+ IsTestOnly() bool
+
+ // marker interface method
+ isNavigable()
+}
+
+// NavigableMapExpr defines an interface for inspecting a map expression.
+type NavigableMapExpr interface {
+ // Entries returns the map key value pairs as NavigableEntry values.
+ Entries() []NavigableEntry
+
+ // Size returns the number of entries in the map.
+ Size() int
+
+ // marker interface method
+ isNavigable()
+}
+
+// NavigableEntry defines an interface for inspecting a map entry.
+type NavigableEntry interface {
+ // Key returns the map entry key expression.
+ Key() NavigableExpr
+
+ // Value returns the map entry value expression.
+ Value() NavigableExpr
+
+ // IsOptional returns whether the entry is optional.
+ IsOptional() bool
+
+ // marker interface method
+ isNavigable()
+}
+
+// NavigableStructExpr defines an interfaces for inspecting a struct and its field initializers.
+type NavigableStructExpr interface {
+ // TypeName returns the struct type name.
+ TypeName() string
+
+ // Fields returns the set of field initializers in the struct expression as NavigableField values.
+ Fields() []NavigableField
+
+ // marker interface method
+ isNavigable()
+}
+
+// NavigableField defines an interface for inspecting a struct field initialization.
+type NavigableField interface {
+ // FieldName returns the name of the field.
+ FieldName() string
+
+ // Value returns the field initialization expression.
+ Value() NavigableExpr
+
+ // IsOptional returns whether the field is optional.
+ IsOptional() bool
+
+ // marker interface method
+ isNavigable()
+}
+
+// NavigableComprehensionExpr defines an interface for inspecting a comprehension expression.
+type NavigableComprehensionExpr interface {
+ // IterRange returns the iteration range expression.
+ IterRange() NavigableExpr
+
+ // IterVar returns the iteration variable name.
+ IterVar() string
+
+ // AccuVar returns the accumulation variable name.
+ AccuVar() string
+
+ // AccuInit returns the accumulation variable initialization expression.
+ AccuInit() NavigableExpr
+
+ // LoopCondition returns the loop condition expression.
+ LoopCondition() NavigableExpr
+
+ // LoopStep returns the loop step expression.
+ LoopStep() NavigableExpr
+
+ // Result returns the comprehension result expression.
+ Result() NavigableExpr
+
+ // marker interface method
+ isNavigable()
+}
+
+func newNavigableExpr(parent NavigableExpr, expr *exprpb.Expr, typeMap map[int64]*types.Type) NavigableExpr {
+ kind, factory := kindOf(expr)
+ nav := &navigableExprImpl{
+ parent: parent,
+ kind: kind,
+ expr: expr,
+ typeMap: typeMap,
+ createChildren: factory,
+ }
+ return nav
+}
+
+type navigableExprImpl struct {
+ parent NavigableExpr
+ kind ExprKind
+ expr *exprpb.Expr
+ typeMap map[int64]*types.Type
+ createChildren childFactory
+}
+
+func (nav *navigableExprImpl) ID() int64 {
+ return nav.ToExpr().GetId()
+}
+
+func (nav *navigableExprImpl) Kind() ExprKind {
+ return nav.kind
+}
+
+func (nav *navigableExprImpl) Type() *types.Type {
+ if t, found := nav.typeMap[nav.ID()]; found {
+ return t
+ }
+ return types.DynType
+}
+
+func (nav *navigableExprImpl) Parent() (NavigableExpr, bool) {
+ if nav.parent != nil {
+ return nav.parent, true
+ }
+ return nil, false
+}
+
+func (nav *navigableExprImpl) Children() []NavigableExpr {
+ return nav.createChildren(nav)
+}
+
+func (nav *navigableExprImpl) ToExpr() *exprpb.Expr {
+ return nav.expr
+}
+
+func (nav *navigableExprImpl) AsCall() NavigableCallExpr {
+ return navigableCallImpl{navigableExprImpl: nav}
+}
+
+func (nav *navigableExprImpl) AsComprehension() NavigableComprehensionExpr {
+ return navigableComprehensionImpl{navigableExprImpl: nav}
+}
+
+func (nav *navigableExprImpl) AsIdent() string {
+ return nav.ToExpr().GetIdentExpr().GetName()
+}
+
+func (nav *navigableExprImpl) AsLiteral() ref.Val {
+ if nav.Kind() != LiteralKind {
+ return nil
+ }
+ val, err := ConstantToVal(nav.ToExpr().GetConstExpr())
+ if err != nil {
+ panic(err)
+ }
+ return val
+}
+
+func (nav *navigableExprImpl) AsList() NavigableListExpr {
+ return navigableListImpl{navigableExprImpl: nav}
+}
+
+func (nav *navigableExprImpl) AsMap() NavigableMapExpr {
+ return navigableMapImpl{navigableExprImpl: nav}
+}
+
+func (nav *navigableExprImpl) AsSelect() NavigableSelectExpr {
+ return navigableSelectImpl{navigableExprImpl: nav}
+}
+
+func (nav *navigableExprImpl) AsStruct() NavigableStructExpr {
+ return navigableStructImpl{navigableExprImpl: nav}
+}
+
+func (nav *navigableExprImpl) createChild(e *exprpb.Expr) NavigableExpr {
+ return newNavigableExpr(nav, e, nav.typeMap)
+}
+
+func (nav *navigableExprImpl) isNavigable() {}
+
+type navigableCallImpl struct {
+ *navigableExprImpl
+}
+
+func (call navigableCallImpl) FunctionName() string {
+ return call.ToExpr().GetCallExpr().GetFunction()
+}
+
+func (call navigableCallImpl) Target() NavigableExpr {
+ t := call.ToExpr().GetCallExpr().GetTarget()
+ if t != nil {
+ return call.createChild(t)
+ }
+ return nil
+}
+
+func (call navigableCallImpl) Args() []NavigableExpr {
+ args := call.ToExpr().GetCallExpr().GetArgs()
+ navArgs := make([]NavigableExpr, len(args))
+ for i, a := range args {
+ navArgs[i] = call.createChild(a)
+ }
+ return navArgs
+}
+
+func (call navigableCallImpl) ReturnType() *types.Type {
+ return call.Type()
+}
+
+type navigableComprehensionImpl struct {
+ *navigableExprImpl
+}
+
+func (comp navigableComprehensionImpl) IterRange() NavigableExpr {
+ return comp.createChild(comp.ToExpr().GetComprehensionExpr().GetIterRange())
+}
+
+func (comp navigableComprehensionImpl) IterVar() string {
+ return comp.ToExpr().GetComprehensionExpr().GetIterVar()
+}
+
+func (comp navigableComprehensionImpl) AccuVar() string {
+ return comp.ToExpr().GetComprehensionExpr().GetAccuVar()
+}
+
+func (comp navigableComprehensionImpl) AccuInit() NavigableExpr {
+ return comp.createChild(comp.ToExpr().GetComprehensionExpr().GetAccuInit())
+}
+
+func (comp navigableComprehensionImpl) LoopCondition() NavigableExpr {
+ return comp.createChild(comp.ToExpr().GetComprehensionExpr().GetLoopCondition())
+}
+
+func (comp navigableComprehensionImpl) LoopStep() NavigableExpr {
+ return comp.createChild(comp.ToExpr().GetComprehensionExpr().GetLoopStep())
+}
+
+func (comp navigableComprehensionImpl) Result() NavigableExpr {
+ return comp.createChild(comp.ToExpr().GetComprehensionExpr().GetResult())
+}
+
+type navigableListImpl struct {
+ *navigableExprImpl
+}
+
+func (l navigableListImpl) Elements() []NavigableExpr {
+ return l.Children()
+}
+
+func (l navigableListImpl) OptionalIndices() []int32 {
+ return l.ToExpr().GetListExpr().GetOptionalIndices()
+}
+
+func (l navigableListImpl) Size() int {
+ return len(l.ToExpr().GetListExpr().GetElements())
+}
+
+type navigableMapImpl struct {
+ *navigableExprImpl
+}
+
+func (m navigableMapImpl) Entries() []NavigableEntry {
+ mapExpr := m.ToExpr().GetStructExpr()
+ entries := make([]NavigableEntry, len(mapExpr.GetEntries()))
+ for i, e := range mapExpr.GetEntries() {
+ entries[i] = navigableEntryImpl{
+ key: m.createChild(e.GetMapKey()),
+ val: m.createChild(e.GetValue()),
+ isOpt: e.GetOptionalEntry(),
+ }
+ }
+ return entries
+}
+
+func (m navigableMapImpl) Size() int {
+ return len(m.ToExpr().GetStructExpr().GetEntries())
+}
+
+type navigableEntryImpl struct {
+ key NavigableExpr
+ val NavigableExpr
+ isOpt bool
+}
+
+func (e navigableEntryImpl) Key() NavigableExpr {
+ return e.key
+}
+
+func (e navigableEntryImpl) Value() NavigableExpr {
+ return e.val
+}
+
+func (e navigableEntryImpl) IsOptional() bool {
+ return e.isOpt
+}
+
+func (e navigableEntryImpl) isNavigable() {}
+
+type navigableSelectImpl struct {
+ *navigableExprImpl
+}
+
+func (sel navigableSelectImpl) FieldName() string {
+ return sel.ToExpr().GetSelectExpr().GetField()
+}
+
+func (sel navigableSelectImpl) IsTestOnly() bool {
+ return sel.ToExpr().GetSelectExpr().GetTestOnly()
+}
+
+func (sel navigableSelectImpl) Operand() NavigableExpr {
+ return sel.createChild(sel.ToExpr().GetSelectExpr().GetOperand())
+}
+
+type navigableStructImpl struct {
+ *navigableExprImpl
+}
+
+func (s navigableStructImpl) TypeName() string {
+ return s.ToExpr().GetStructExpr().GetMessageName()
+}
+
+func (s navigableStructImpl) Fields() []NavigableField {
+ fieldInits := s.ToExpr().GetStructExpr().GetEntries()
+ fields := make([]NavigableField, len(fieldInits))
+ for i, f := range fieldInits {
+ fields[i] = navigableFieldImpl{
+ name: f.GetFieldKey(),
+ val: s.createChild(f.GetValue()),
+ isOpt: f.GetOptionalEntry(),
+ }
+ }
+ return fields
+}
+
+type navigableFieldImpl struct {
+ name string
+ val NavigableExpr
+ isOpt bool
+}
+
+func (f navigableFieldImpl) FieldName() string {
+ return f.name
+}
+
+func (f navigableFieldImpl) Value() NavigableExpr {
+ return f.val
+}
+
+func (f navigableFieldImpl) IsOptional() bool {
+ return f.isOpt
+}
+
+func (f navigableFieldImpl) isNavigable() {}
+
+func kindOf(expr *exprpb.Expr) (ExprKind, childFactory) {
+ switch expr.GetExprKind().(type) {
+ case *exprpb.Expr_ConstExpr:
+ return LiteralKind, noopFactory
+ case *exprpb.Expr_IdentExpr:
+ return IdentKind, noopFactory
+ case *exprpb.Expr_SelectExpr:
+ return SelectKind, selectFactory
+ case *exprpb.Expr_CallExpr:
+ return CallKind, callArgFactory
+ case *exprpb.Expr_ListExpr:
+ return ListKind, listElemFactory
+ case *exprpb.Expr_StructExpr:
+ if expr.GetStructExpr().GetMessageName() != "" {
+ return StructKind, structEntryFactory
+ }
+ return MapKind, mapEntryFactory
+ case *exprpb.Expr_ComprehensionExpr:
+ return ComprehensionKind, comprehensionFactory
+ default:
+ return UnspecifiedKind, noopFactory
+ }
+}
+
+type childFactory func(*navigableExprImpl) []NavigableExpr
+
+func noopFactory(*navigableExprImpl) []NavigableExpr {
+ return nil
+}
+
+func selectFactory(nav *navigableExprImpl) []NavigableExpr {
+ return []NavigableExpr{
+ nav.createChild(nav.ToExpr().GetSelectExpr().GetOperand()),
+ }
+}
+
+func callArgFactory(nav *navigableExprImpl) []NavigableExpr {
+ call := nav.ToExpr().GetCallExpr()
+ argCount := len(call.GetArgs())
+ if call.GetTarget() != nil {
+ argCount++
+ }
+ navExprs := make([]NavigableExpr, argCount)
+ i := 0
+ if call.GetTarget() != nil {
+ navExprs[i] = nav.createChild(call.GetTarget())
+ i++
+ }
+ for _, arg := range call.GetArgs() {
+ navExprs[i] = nav.createChild(arg)
+ i++
+ }
+ return navExprs
+}
+
+func listElemFactory(nav *navigableExprImpl) []NavigableExpr {
+ l := nav.ToExpr().GetListExpr()
+ navExprs := make([]NavigableExpr, len(l.GetElements()))
+ for i, e := range l.GetElements() {
+ navExprs[i] = nav.createChild(e)
+ }
+ return navExprs
+}
+
+func structEntryFactory(nav *navigableExprImpl) []NavigableExpr {
+ s := nav.ToExpr().GetStructExpr()
+ entries := make([]NavigableExpr, len(s.GetEntries()))
+ for i, e := range s.GetEntries() {
+
+ entries[i] = nav.createChild(e.GetValue())
+ }
+ return entries
+}
+
+func mapEntryFactory(nav *navigableExprImpl) []NavigableExpr {
+ s := nav.ToExpr().GetStructExpr()
+ entries := make([]NavigableExpr, len(s.GetEntries())*2)
+ j := 0
+ for _, e := range s.GetEntries() {
+ entries[j] = nav.createChild(e.GetMapKey())
+ entries[j+1] = nav.createChild(e.GetValue())
+ j += 2
+ }
+ return entries
+}
+
+func comprehensionFactory(nav *navigableExprImpl) []NavigableExpr {
+ compre := nav.ToExpr().GetComprehensionExpr()
+ return []NavigableExpr{
+ nav.createChild(compre.GetIterRange()),
+ nav.createChild(compre.GetAccuInit()),
+ nav.createChild(compre.GetLoopCondition()),
+ nav.createChild(compre.GetLoopStep()),
+ nav.createChild(compre.GetResult()),
+ }
+}
diff --git a/vendor/github.com/google/cel-go/common/containers/BUILD.bazel b/vendor/github.com/google/cel-go/common/containers/BUILD.bazel
index 18142d94e..3f3f07887 100644
--- a/vendor/github.com/google/cel-go/common/containers/BUILD.bazel
+++ b/vendor/github.com/google/cel-go/common/containers/BUILD.bazel
@@ -12,7 +12,7 @@ go_library(
],
importpath = "github.com/google/cel-go/common/containers",
deps = [
- "@org_golang_google_genproto//googleapis/api/expr/v1alpha1:go_default_library",
+ "@org_golang_google_genproto_googleapis_api//expr/v1alpha1:go_default_library",
],
)
@@ -26,6 +26,6 @@ go_test(
":go_default_library",
],
deps = [
- "@org_golang_google_genproto//googleapis/api/expr/v1alpha1:go_default_library",
+ "@org_golang_google_genproto_googleapis_api//expr/v1alpha1:go_default_library",
],
)
diff --git a/vendor/github.com/google/cel-go/common/debug/BUILD.bazel b/vendor/github.com/google/cel-go/common/debug/BUILD.bazel
index cf5c5d246..1f029839c 100644
--- a/vendor/github.com/google/cel-go/common/debug/BUILD.bazel
+++ b/vendor/github.com/google/cel-go/common/debug/BUILD.bazel
@@ -13,6 +13,6 @@ go_library(
importpath = "github.com/google/cel-go/common/debug",
deps = [
"//common:go_default_library",
- "@org_golang_google_genproto//googleapis/api/expr/v1alpha1:go_default_library",
+ "@org_golang_google_genproto_googleapis_api//expr/v1alpha1:go_default_library",
],
)
diff --git a/vendor/github.com/google/cel-go/common/decls/BUILD.bazel b/vendor/github.com/google/cel-go/common/decls/BUILD.bazel
new file mode 100644
index 000000000..17791dce6
--- /dev/null
+++ b/vendor/github.com/google/cel-go/common/decls/BUILD.bazel
@@ -0,0 +1,39 @@
+load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
+
+package(
+ default_visibility = ["//visibility:public"],
+ licenses = ["notice"], # Apache 2.0
+)
+
+go_library(
+ name = "go_default_library",
+ srcs = [
+ "decls.go",
+ ],
+ importpath = "github.com/google/cel-go/common/decls",
+ deps = [
+ "//checker/decls:go_default_library",
+ "//common/functions:go_default_library",
+ "//common/types:go_default_library",
+ "//common/types/ref:go_default_library",
+ "//common/types/traits:go_default_library",
+ "@org_golang_google_genproto_googleapis_api//expr/v1alpha1:go_default_library",
+ ],
+)
+
+go_test(
+ name = "go_default_test",
+ srcs = [
+ "decls_test.go",
+ ],
+ embed = [":go_default_library"],
+ deps = [
+ "//checker/decls:go_default_library",
+ "//common/overloads:go_default_library",
+ "//common/types:go_default_library",
+ "//common/types/ref:go_default_library",
+ "//common/types/traits:go_default_library",
+ "@org_golang_google_genproto_googleapis_api//expr/v1alpha1:go_default_library",
+ "@org_golang_google_protobuf//proto:go_default_library",
+ ],
+)
diff --git a/vendor/github.com/google/cel-go/common/decls/decls.go b/vendor/github.com/google/cel-go/common/decls/decls.go
new file mode 100644
index 000000000..0284f8dbc
--- /dev/null
+++ b/vendor/github.com/google/cel-go/common/decls/decls.go
@@ -0,0 +1,843 @@
+// Copyright 2023 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package decls contains function and variable declaration structs and helper methods.
+package decls
+
+import (
+ "fmt"
+ "strings"
+
+ chkdecls "github.com/google/cel-go/checker/decls"
+ "github.com/google/cel-go/common/functions"
+ "github.com/google/cel-go/common/types"
+ "github.com/google/cel-go/common/types/ref"
+
+ exprpb "google.golang.org/genproto/googleapis/api/expr/v1alpha1"
+)
+
+// NewFunction creates a new function declaration with a set of function options to configure overloads
+// and function definitions (implementations).
+//
+// Functions are checked for name collisions and singleton redefinition.
+func NewFunction(name string, opts ...FunctionOpt) (*FunctionDecl, error) {
+ fn := &FunctionDecl{
+ name: name,
+ overloads: map[string]*OverloadDecl{},
+ overloadOrdinals: []string{},
+ }
+ var err error
+ for _, opt := range opts {
+ fn, err = opt(fn)
+ if err != nil {
+ return nil, err
+ }
+ }
+ if len(fn.overloads) == 0 {
+ return nil, fmt.Errorf("function %s must have at least one overload", name)
+ }
+ return fn, nil
+}
+
+// FunctionDecl defines a function name, overload set, and optionally a singleton definition for all
+// overload instances.
+type FunctionDecl struct {
+ name string
+
+ // overloads associated with the function name.
+ overloads map[string]*OverloadDecl
+
+ // singleton implementation of the function for all overloads.
+ //
+ // If this option is set, an error will occur if any overloads specify a per-overload implementation
+ // or if another function with the same name attempts to redefine the singleton.
+ singleton *functions.Overload
+
+ // disableTypeGuards is a performance optimization to disable detailed runtime type checks which could
+ // add overhead on common operations. Setting this option true leaves error checks and argument checks
+ // intact.
+ disableTypeGuards bool
+
+ // state indicates that the binding should be provided as a declaration, as a runtime binding, or both.
+ state declarationState
+
+ // overloadOrdinals indicates the order in which the overload was declared.
+ overloadOrdinals []string
+}
+
+type declarationState int
+
+const (
+ declarationStateUnset declarationState = iota
+ declarationDisabled
+ declarationEnabled
+)
+
+// Name returns the function name in human-readable terms, e.g. 'contains' of 'math.least'
+func (f *FunctionDecl) Name() string {
+ if f == nil {
+ return ""
+ }
+ return f.name
+}
+
+// IsDeclarationDisabled indicates that the function implementation should be added to the dispatcher, but the
+// declaration should not be exposed for use in expressions.
+func (f *FunctionDecl) IsDeclarationDisabled() bool {
+ return f.state == declarationDisabled
+}
+
+// Merge combines an existing function declaration with another.
+//
+// If a function is extended, by say adding new overloads to an existing function, then it is merged with the
+// prior definition of the function at which point its overloads must not collide with pre-existing overloads
+// and its bindings (singleton, or per-overload) must not conflict with previous definitions either.
+func (f *FunctionDecl) Merge(other *FunctionDecl) (*FunctionDecl, error) {
+ if f == other {
+ return f, nil
+ }
+ if f.Name() != other.Name() {
+ return nil, fmt.Errorf("cannot merge unrelated functions. %s and %s", f.Name(), other.Name())
+ }
+ merged := &FunctionDecl{
+ name: f.Name(),
+ overloads: make(map[string]*OverloadDecl, len(f.overloads)),
+ singleton: f.singleton,
+ overloadOrdinals: make([]string, len(f.overloads)),
+ // if one function is expecting type-guards and the other is not, then they
+ // must not be disabled.
+ disableTypeGuards: f.disableTypeGuards && other.disableTypeGuards,
+ // default to the current functions declaration state.
+ state: f.state,
+ }
+ // If the other state indicates that the declaration should be explicitly enabled or
+ // disabled, then update the merged state with the most recent value.
+ if other.state != declarationStateUnset {
+ merged.state = other.state
+ }
+ // baseline copy of the overloads and their ordinals
+ copy(merged.overloadOrdinals, f.overloadOrdinals)
+ for oID, o := range f.overloads {
+ merged.overloads[oID] = o
+ }
+ // overloads and their ordinals are added from the left
+ for _, oID := range other.overloadOrdinals {
+ o := other.overloads[oID]
+ err := merged.AddOverload(o)
+ if err != nil {
+ return nil, fmt.Errorf("function declaration merge failed: %v", err)
+ }
+ }
+ if other.singleton != nil {
+ if merged.singleton != nil && merged.singleton != other.singleton {
+ return nil, fmt.Errorf("function already has a singleton binding: %s", f.Name())
+ }
+ merged.singleton = other.singleton
+ }
+ return merged, nil
+}
+
+// AddOverload ensures that the new overload does not collide with an existing overload signature;
+// however, if the function signatures are identical, the implementation may be rewritten as its
+// difficult to compare functions by object identity.
+func (f *FunctionDecl) AddOverload(overload *OverloadDecl) error {
+ if f == nil {
+ return fmt.Errorf("nil function cannot add overload: %s", overload.ID())
+ }
+ for oID, o := range f.overloads {
+ if oID != overload.ID() && o.SignatureOverlaps(overload) {
+ return fmt.Errorf("overload signature collision in function %s: %s collides with %s", f.Name(), oID, overload.ID())
+ }
+ if oID == overload.ID() {
+ if o.SignatureEquals(overload) && o.IsNonStrict() == overload.IsNonStrict() {
+ // Allow redefinition of an overload implementation so long as the signatures match.
+ f.overloads[oID] = overload
+ return nil
+ }
+ return fmt.Errorf("overload redefinition in function. %s: %s has multiple definitions", f.Name(), oID)
+ }
+ }
+ f.overloadOrdinals = append(f.overloadOrdinals, overload.ID())
+ f.overloads[overload.ID()] = overload
+ return nil
+}
+
+// OverloadDecls returns the overload declarations in the order in which they were declared.
+func (f *FunctionDecl) OverloadDecls() []*OverloadDecl {
+ if f == nil {
+ return []*OverloadDecl{}
+ }
+ overloads := make([]*OverloadDecl, 0, len(f.overloads))
+ for _, oID := range f.overloadOrdinals {
+ overloads = append(overloads, f.overloads[oID])
+ }
+ return overloads
+}
+
+// Bindings produces a set of function bindings, if any are defined.
+func (f *FunctionDecl) Bindings() ([]*functions.Overload, error) {
+ if f == nil {
+ return []*functions.Overload{}, nil
+ }
+ overloads := []*functions.Overload{}
+ nonStrict := false
+ for _, oID := range f.overloadOrdinals {
+ o := f.overloads[oID]
+ if o.hasBinding() {
+ overload := &functions.Overload{
+ Operator: o.ID(),
+ Unary: o.guardedUnaryOp(f.Name(), f.disableTypeGuards),
+ Binary: o.guardedBinaryOp(f.Name(), f.disableTypeGuards),
+ Function: o.guardedFunctionOp(f.Name(), f.disableTypeGuards),
+ OperandTrait: o.OperandTrait(),
+ NonStrict: o.IsNonStrict(),
+ }
+ overloads = append(overloads, overload)
+ nonStrict = nonStrict || o.IsNonStrict()
+ }
+ }
+ if f.singleton != nil {
+ if len(overloads) != 0 {
+ return nil, fmt.Errorf("singleton function incompatible with specialized overloads: %s", f.Name())
+ }
+ overloads = []*functions.Overload{
+ {
+ Operator: f.Name(),
+ Unary: f.singleton.Unary,
+ Binary: f.singleton.Binary,
+ Function: f.singleton.Function,
+ OperandTrait: f.singleton.OperandTrait,
+ },
+ }
+ // fall-through to return single overload case.
+ }
+ if len(overloads) == 0 {
+ return overloads, nil
+ }
+ // Single overload. Replicate an entry for it using the function name as well.
+ if len(overloads) == 1 {
+ if overloads[0].Operator == f.Name() {
+ return overloads, nil
+ }
+ return append(overloads, &functions.Overload{
+ Operator: f.Name(),
+ Unary: overloads[0].Unary,
+ Binary: overloads[0].Binary,
+ Function: overloads[0].Function,
+ NonStrict: overloads[0].NonStrict,
+ OperandTrait: overloads[0].OperandTrait,
+ }), nil
+ }
+ // All of the defined overloads are wrapped into a top-level function which
+ // performs dynamic dispatch to the proper overload based on the argument types.
+ bindings := append([]*functions.Overload{}, overloads...)
+ funcDispatch := func(args ...ref.Val) ref.Val {
+ for _, o := range f.overloads {
+ // During dynamic dispatch over multiple functions, signature agreement checks
+ // are preserved in order to assist with the function resolution step.
+ switch len(args) {
+ case 1:
+ if o.unaryOp != nil && o.matchesRuntimeSignature( /* disableTypeGuards=*/ false, args...) {
+ return o.unaryOp(args[0])
+ }
+ case 2:
+ if o.binaryOp != nil && o.matchesRuntimeSignature( /* disableTypeGuards=*/ false, args...) {
+ return o.binaryOp(args[0], args[1])
+ }
+ }
+ if o.functionOp != nil && o.matchesRuntimeSignature( /* disableTypeGuards=*/ false, args...) {
+ return o.functionOp(args...)
+ }
+ // eventually this will fall through to the noSuchOverload below.
+ }
+ return MaybeNoSuchOverload(f.Name(), args...)
+ }
+ function := &functions.Overload{
+ Operator: f.Name(),
+ Function: funcDispatch,
+ NonStrict: nonStrict,
+ }
+ return append(bindings, function), nil
+}
+
+// MaybeNoSuchOverload determines whether to propagate an error if one is provided as an argument, or
+// to return an unknown set, or to produce a new error for a missing function signature.
+func MaybeNoSuchOverload(funcName string, args ...ref.Val) ref.Val {
+ argTypes := make([]string, len(args))
+ var unk *types.Unknown = nil
+ for i, arg := range args {
+ if types.IsError(arg) {
+ return arg
+ }
+ if types.IsUnknown(arg) {
+ unk = types.MergeUnknowns(arg.(*types.Unknown), unk)
+ }
+ argTypes[i] = arg.Type().TypeName()
+ }
+ if unk != nil {
+ return unk
+ }
+ signature := strings.Join(argTypes, ", ")
+ return types.NewErr("no such overload: %s(%s)", funcName, signature)
+}
+
+// FunctionOpt defines a functional option for mutating a function declaration.
+type FunctionOpt func(*FunctionDecl) (*FunctionDecl, error)
+
+// DisableTypeGuards disables automatically generated function invocation guards on direct overload calls.
+// Type guards remain on during dynamic dispatch for parsed-only expressions.
+func DisableTypeGuards(value bool) FunctionOpt {
+ return func(fn *FunctionDecl) (*FunctionDecl, error) {
+ fn.disableTypeGuards = value
+ return fn, nil
+ }
+}
+
+// DisableDeclaration indicates that the function declaration should be disabled, but the runtime function
+// binding should be provided. Marking a function as runtime-only is a safe way to manage deprecations
+// of function declarations while still preserving the runtime behavior for previously compiled expressions.
+func DisableDeclaration(value bool) FunctionOpt {
+ return func(fn *FunctionDecl) (*FunctionDecl, error) {
+ if value {
+ fn.state = declarationDisabled
+ } else {
+ fn.state = declarationEnabled
+ }
+ return fn, nil
+ }
+}
+
+// SingletonUnaryBinding creates a singleton function definition to be used for all function overloads.
+//
+// Note, this approach works well if operand is expected to have a specific trait which it implements,
+// e.g. traits.ContainerType. Otherwise, prefer per-overload function bindings.
+func SingletonUnaryBinding(fn functions.UnaryOp, traits ...int) FunctionOpt {
+ trait := 0
+ for _, t := range traits {
+ trait = trait | t
+ }
+ return func(f *FunctionDecl) (*FunctionDecl, error) {
+ if f.singleton != nil {
+ return nil, fmt.Errorf("function already has a singleton binding: %s", f.Name())
+ }
+ f.singleton = &functions.Overload{
+ Operator: f.Name(),
+ Unary: fn,
+ OperandTrait: trait,
+ }
+ return f, nil
+ }
+}
+
+// SingletonBinaryBinding creates a singleton function definition to be used with all function overloads.
+//
+// Note, this approach works well if operand is expected to have a specific trait which it implements,
+// e.g. traits.ContainerType. Otherwise, prefer per-overload function bindings.
+func SingletonBinaryBinding(fn functions.BinaryOp, traits ...int) FunctionOpt {
+ trait := 0
+ for _, t := range traits {
+ trait = trait | t
+ }
+ return func(f *FunctionDecl) (*FunctionDecl, error) {
+ if f.singleton != nil {
+ return nil, fmt.Errorf("function already has a singleton binding: %s", f.Name())
+ }
+ f.singleton = &functions.Overload{
+ Operator: f.Name(),
+ Binary: fn,
+ OperandTrait: trait,
+ }
+ return f, nil
+ }
+}
+
+// SingletonFunctionBinding creates a singleton function definition to be used with all function overloads.
+//
+// Note, this approach works well if operand is expected to have a specific trait which it implements,
+// e.g. traits.ContainerType. Otherwise, prefer per-overload function bindings.
+func SingletonFunctionBinding(fn functions.FunctionOp, traits ...int) FunctionOpt {
+ trait := 0
+ for _, t := range traits {
+ trait = trait | t
+ }
+ return func(f *FunctionDecl) (*FunctionDecl, error) {
+ if f.singleton != nil {
+ return nil, fmt.Errorf("function already has a singleton binding: %s", f.Name())
+ }
+ f.singleton = &functions.Overload{
+ Operator: f.Name(),
+ Function: fn,
+ OperandTrait: trait,
+ }
+ return f, nil
+ }
+}
+
+// Overload defines a new global overload with an overload id, argument types, and result type. Through the
+// use of OverloadOpt options, the overload may also be configured with a binding, an operand trait, and to
+// be non-strict.
+//
+// Note: function bindings should be commonly configured with Overload instances whereas operand traits and
+// strict-ness should be rare occurrences.
+func Overload(overloadID string,
+ args []*types.Type, resultType *types.Type,
+ opts ...OverloadOpt) FunctionOpt {
+ return newOverload(overloadID, false, args, resultType, opts...)
+}
+
+// MemberOverload defines a new receiver-style overload (or member function) with an overload id, argument types,
+// and result type. Through the use of OverloadOpt options, the overload may also be configured with a binding,
+// an operand trait, and to be non-strict.
+//
+// Note: function bindings should be commonly configured with Overload instances whereas operand traits and
+// strict-ness should be rare occurrences.
+func MemberOverload(overloadID string,
+ args []*types.Type, resultType *types.Type,
+ opts ...OverloadOpt) FunctionOpt {
+ return newOverload(overloadID, true, args, resultType, opts...)
+}
+
+func newOverload(overloadID string,
+ memberFunction bool, args []*types.Type, resultType *types.Type,
+ opts ...OverloadOpt) FunctionOpt {
+ return func(f *FunctionDecl) (*FunctionDecl, error) {
+ overload, err := newOverloadInternal(overloadID, memberFunction, args, resultType, opts...)
+ if err != nil {
+ return nil, err
+ }
+ err = f.AddOverload(overload)
+ if err != nil {
+ return nil, err
+ }
+ return f, nil
+ }
+}
+
+func newOverloadInternal(overloadID string,
+ memberFunction bool, args []*types.Type, resultType *types.Type,
+ opts ...OverloadOpt) (*OverloadDecl, error) {
+ overload := &OverloadDecl{
+ id: overloadID,
+ argTypes: args,
+ resultType: resultType,
+ isMemberFunction: memberFunction,
+ }
+ var err error
+ for _, opt := range opts {
+ overload, err = opt(overload)
+ if err != nil {
+ return nil, err
+ }
+ }
+ return overload, nil
+}
+
+// OverloadDecl contains the definition of a single overload id with a specific signature, and an optional
+// implementation.
+type OverloadDecl struct {
+ id string
+ argTypes []*types.Type
+ resultType *types.Type
+ isMemberFunction bool
+ // nonStrict indicates that the function will accept error and unknown arguments as inputs.
+ nonStrict bool
+ // operandTrait indicates whether the member argument should have a specific type-trait.
+ //
+ // This is useful for creating overloads which operate on a type-interface rather than a concrete type.
+ operandTrait int
+
+ // Function implementation options. Optional, but encouraged.
+ // unaryOp is a function binding that takes a single argument.
+ unaryOp functions.UnaryOp
+ // binaryOp is a function binding that takes two arguments.
+ binaryOp functions.BinaryOp
+ // functionOp is a catch-all for zero-arity and three-plus arity functions.
+ functionOp functions.FunctionOp
+}
+
+// ID mirrors the overload signature and provides a unique id which may be referenced within the type-checker
+// and interpreter to optimize performance.
+//
+// The ID format is usually one of two styles:
+// global: __
+// member: ___
+func (o *OverloadDecl) ID() string {
+ if o == nil {
+ return ""
+ }
+ return o.id
+}
+
+// ArgTypes contains the set of argument types expected by the overload.
+//
+// For member functions ArgTypes[0] represents the member operand type.
+func (o *OverloadDecl) ArgTypes() []*types.Type {
+ if o == nil {
+ return emptyArgs
+ }
+ return o.argTypes
+}
+
+// IsMemberFunction indicates whether the overload is a member function
+func (o *OverloadDecl) IsMemberFunction() bool {
+ if o == nil {
+ return false
+ }
+ return o.isMemberFunction
+}
+
+// IsNonStrict returns whether the overload accepts errors and unknown values as arguments.
+func (o *OverloadDecl) IsNonStrict() bool {
+ if o == nil {
+ return false
+ }
+ return o.nonStrict
+}
+
+// OperandTrait returns the trait mask of the first operand to the overload call, e.g.
+// `traits.Indexer`
+func (o *OverloadDecl) OperandTrait() int {
+ if o == nil {
+ return 0
+ }
+ return o.operandTrait
+}
+
+// ResultType indicates the output type from calling the function.
+func (o *OverloadDecl) ResultType() *types.Type {
+ if o == nil {
+ // *types.Type is nil-safe
+ return nil
+ }
+ return o.resultType
+}
+
+// TypeParams returns the type parameter names associated with the overload.
+func (o *OverloadDecl) TypeParams() []string {
+ typeParams := map[string]struct{}{}
+ collectParamNames(typeParams, o.ResultType())
+ for _, arg := range o.ArgTypes() {
+ collectParamNames(typeParams, arg)
+ }
+ params := make([]string, 0, len(typeParams))
+ for param := range typeParams {
+ params = append(params, param)
+ }
+ return params
+}
+
+// SignatureEquals determines whether the incoming overload declaration signature is equal to the current signature.
+//
+// Result type, operand trait, and strict-ness are not considered as part of signature equality.
+func (o *OverloadDecl) SignatureEquals(other *OverloadDecl) bool {
+ if o == other {
+ return true
+ }
+ if o.ID() != other.ID() || o.IsMemberFunction() != other.IsMemberFunction() || len(o.ArgTypes()) != len(other.ArgTypes()) {
+ return false
+ }
+ for i, at := range o.ArgTypes() {
+ oat := other.ArgTypes()[i]
+ if !at.IsEquivalentType(oat) {
+ return false
+ }
+ }
+ return o.ResultType().IsEquivalentType(other.ResultType())
+}
+
+// SignatureOverlaps indicates whether two functions have non-equal, but overloapping function signatures.
+//
+// For example, list(dyn) collides with list(string) since the 'dyn' type can contain a 'string' type.
+func (o *OverloadDecl) SignatureOverlaps(other *OverloadDecl) bool {
+ if o.IsMemberFunction() != other.IsMemberFunction() || len(o.ArgTypes()) != len(other.ArgTypes()) {
+ return false
+ }
+ argsOverlap := true
+ for i, argType := range o.ArgTypes() {
+ otherArgType := other.ArgTypes()[i]
+ argsOverlap = argsOverlap &&
+ (argType.IsAssignableType(otherArgType) ||
+ otherArgType.IsAssignableType(argType))
+ }
+ return argsOverlap
+}
+
+// hasBinding indicates whether the overload already has a definition.
+func (o *OverloadDecl) hasBinding() bool {
+ return o != nil && (o.unaryOp != nil || o.binaryOp != nil || o.functionOp != nil)
+}
+
+// guardedUnaryOp creates an invocation guard around the provided unary operator, if one is defined.
+func (o *OverloadDecl) guardedUnaryOp(funcName string, disableTypeGuards bool) functions.UnaryOp {
+ if o.unaryOp == nil {
+ return nil
+ }
+ return func(arg ref.Val) ref.Val {
+ if !o.matchesRuntimeUnarySignature(disableTypeGuards, arg) {
+ return MaybeNoSuchOverload(funcName, arg)
+ }
+ return o.unaryOp(arg)
+ }
+}
+
+// guardedBinaryOp creates an invocation guard around the provided binary operator, if one is defined.
+func (o *OverloadDecl) guardedBinaryOp(funcName string, disableTypeGuards bool) functions.BinaryOp {
+ if o.binaryOp == nil {
+ return nil
+ }
+ return func(arg1, arg2 ref.Val) ref.Val {
+ if !o.matchesRuntimeBinarySignature(disableTypeGuards, arg1, arg2) {
+ return MaybeNoSuchOverload(funcName, arg1, arg2)
+ }
+ return o.binaryOp(arg1, arg2)
+ }
+}
+
+// guardedFunctionOp creates an invocation guard around the provided variadic function binding, if one is provided.
+func (o *OverloadDecl) guardedFunctionOp(funcName string, disableTypeGuards bool) functions.FunctionOp {
+ if o.functionOp == nil {
+ return nil
+ }
+ return func(args ...ref.Val) ref.Val {
+ if !o.matchesRuntimeSignature(disableTypeGuards, args...) {
+ return MaybeNoSuchOverload(funcName, args...)
+ }
+ return o.functionOp(args...)
+ }
+}
+
+// matchesRuntimeUnarySignature indicates whether the argument type is runtime assiganble to the overload's expected argument.
+func (o *OverloadDecl) matchesRuntimeUnarySignature(disableTypeGuards bool, arg ref.Val) bool {
+ return matchRuntimeArgType(o.IsNonStrict(), disableTypeGuards, o.ArgTypes()[0], arg) &&
+ matchOperandTrait(o.OperandTrait(), arg)
+}
+
+// matchesRuntimeBinarySignature indicates whether the argument types are runtime assiganble to the overload's expected arguments.
+func (o *OverloadDecl) matchesRuntimeBinarySignature(disableTypeGuards bool, arg1, arg2 ref.Val) bool {
+ return matchRuntimeArgType(o.IsNonStrict(), disableTypeGuards, o.ArgTypes()[0], arg1) &&
+ matchRuntimeArgType(o.IsNonStrict(), disableTypeGuards, o.ArgTypes()[1], arg2) &&
+ matchOperandTrait(o.OperandTrait(), arg1)
+}
+
+// matchesRuntimeSignature indicates whether the argument types are runtime assiganble to the overload's expected arguments.
+func (o *OverloadDecl) matchesRuntimeSignature(disableTypeGuards bool, args ...ref.Val) bool {
+ if len(args) != len(o.ArgTypes()) {
+ return false
+ }
+ if len(args) == 0 {
+ return true
+ }
+ for i, arg := range args {
+ if !matchRuntimeArgType(o.IsNonStrict(), disableTypeGuards, o.ArgTypes()[i], arg) {
+ return false
+ }
+ }
+ return matchOperandTrait(o.OperandTrait(), args[0])
+}
+
+func matchRuntimeArgType(nonStrict, disableTypeGuards bool, argType *types.Type, arg ref.Val) bool {
+ if nonStrict && (disableTypeGuards || types.IsUnknownOrError(arg)) {
+ return true
+ }
+ if types.IsUnknownOrError(arg) {
+ return false
+ }
+ return disableTypeGuards || argType.IsAssignableRuntimeType(arg)
+}
+
+func matchOperandTrait(trait int, arg ref.Val) bool {
+ return trait == 0 || arg.Type().HasTrait(trait) || types.IsUnknownOrError(arg)
+}
+
+// OverloadOpt is a functional option for configuring a function overload.
+type OverloadOpt func(*OverloadDecl) (*OverloadDecl, error)
+
+// UnaryBinding provides the implementation of a unary overload. The provided function is protected by a runtime
+// type-guard which ensures runtime type agreement between the overload signature and runtime argument types.
+func UnaryBinding(binding functions.UnaryOp) OverloadOpt {
+ return func(o *OverloadDecl) (*OverloadDecl, error) {
+ if o.hasBinding() {
+ return nil, fmt.Errorf("overload already has a binding: %s", o.ID())
+ }
+ if len(o.ArgTypes()) != 1 {
+ return nil, fmt.Errorf("unary function bound to non-unary overload: %s", o.ID())
+ }
+ o.unaryOp = binding
+ return o, nil
+ }
+}
+
+// BinaryBinding provides the implementation of a binary overload. The provided function is protected by a runtime
+// type-guard which ensures runtime type agreement between the overload signature and runtime argument types.
+func BinaryBinding(binding functions.BinaryOp) OverloadOpt {
+ return func(o *OverloadDecl) (*OverloadDecl, error) {
+ if o.hasBinding() {
+ return nil, fmt.Errorf("overload already has a binding: %s", o.ID())
+ }
+ if len(o.ArgTypes()) != 2 {
+ return nil, fmt.Errorf("binary function bound to non-binary overload: %s", o.ID())
+ }
+ o.binaryOp = binding
+ return o, nil
+ }
+}
+
+// FunctionBinding provides the implementation of a variadic overload. The provided function is protected by a runtime
+// type-guard which ensures runtime type agreement between the overload signature and runtime argument types.
+func FunctionBinding(binding functions.FunctionOp) OverloadOpt {
+ return func(o *OverloadDecl) (*OverloadDecl, error) {
+ if o.hasBinding() {
+ return nil, fmt.Errorf("overload already has a binding: %s", o.ID())
+ }
+ o.functionOp = binding
+ return o, nil
+ }
+}
+
+// OverloadIsNonStrict enables the function to be called with error and unknown argument values.
+//
+// Note: do not use this option unless absoluately necessary as it should be an uncommon feature.
+func OverloadIsNonStrict() OverloadOpt {
+ return func(o *OverloadDecl) (*OverloadDecl, error) {
+ o.nonStrict = true
+ return o, nil
+ }
+}
+
+// OverloadOperandTrait configures a set of traits which the first argument to the overload must implement in order to be
+// successfully invoked.
+func OverloadOperandTrait(trait int) OverloadOpt {
+ return func(o *OverloadDecl) (*OverloadDecl, error) {
+ o.operandTrait = trait
+ return o, nil
+ }
+}
+
+// NewConstant creates a new constant declaration.
+func NewConstant(name string, t *types.Type, v ref.Val) *VariableDecl {
+ return &VariableDecl{name: name, varType: t, value: v}
+}
+
+// NewVariable creates a new variable declaration.
+func NewVariable(name string, t *types.Type) *VariableDecl {
+ return &VariableDecl{name: name, varType: t}
+}
+
+// VariableDecl defines a variable declaration which may optionally have a constant value.
+type VariableDecl struct {
+ name string
+ varType *types.Type
+ value ref.Val
+}
+
+// Name returns the fully-qualified variable name
+func (v *VariableDecl) Name() string {
+ if v == nil {
+ return ""
+ }
+ return v.name
+}
+
+// Type returns the types.Type value associated with the variable.
+func (v *VariableDecl) Type() *types.Type {
+ if v == nil {
+ // types.Type is nil-safe
+ return nil
+ }
+ return v.varType
+}
+
+// Value returns the constant value associated with the declaration.
+func (v *VariableDecl) Value() ref.Val {
+ if v == nil {
+ return nil
+ }
+ return v.value
+}
+
+// DeclarationIsEquivalent returns true if one variable declaration has the same name and same type as the input.
+func (v *VariableDecl) DeclarationIsEquivalent(other *VariableDecl) bool {
+ if v == other {
+ return true
+ }
+ return v.Name() == other.Name() && v.Type().IsEquivalentType(other.Type())
+}
+
+// VariableDeclToExprDecl converts a go-native variable declaration into a protobuf-type variable declaration.
+func VariableDeclToExprDecl(v *VariableDecl) (*exprpb.Decl, error) {
+ varType, err := types.TypeToExprType(v.Type())
+ if err != nil {
+ return nil, err
+ }
+ return chkdecls.NewVar(v.Name(), varType), nil
+}
+
+// TypeVariable creates a new type identifier for use within a types.Provider
+func TypeVariable(t *types.Type) *VariableDecl {
+ return NewVariable(t.TypeName(), types.NewTypeTypeWithParam(t))
+}
+
+// FunctionDeclToExprDecl converts a go-native function declaration into a protobuf-typed function declaration.
+func FunctionDeclToExprDecl(f *FunctionDecl) (*exprpb.Decl, error) {
+ overloads := make([]*exprpb.Decl_FunctionDecl_Overload, len(f.overloads))
+ for i, oID := range f.overloadOrdinals {
+ o := f.overloads[oID]
+ paramNames := map[string]struct{}{}
+ argTypes := make([]*exprpb.Type, len(o.ArgTypes()))
+ for j, a := range o.ArgTypes() {
+ collectParamNames(paramNames, a)
+ at, err := types.TypeToExprType(a)
+ if err != nil {
+ return nil, err
+ }
+ argTypes[j] = at
+ }
+ collectParamNames(paramNames, o.ResultType())
+ resultType, err := types.TypeToExprType(o.ResultType())
+ if err != nil {
+ return nil, err
+ }
+ if len(paramNames) == 0 {
+ if o.IsMemberFunction() {
+ overloads[i] = chkdecls.NewInstanceOverload(oID, argTypes, resultType)
+ } else {
+ overloads[i] = chkdecls.NewOverload(oID, argTypes, resultType)
+ }
+ } else {
+ params := []string{}
+ for pn := range paramNames {
+ params = append(params, pn)
+ }
+ if o.IsMemberFunction() {
+ overloads[i] = chkdecls.NewParameterizedInstanceOverload(oID, argTypes, resultType, params)
+ } else {
+ overloads[i] = chkdecls.NewParameterizedOverload(oID, argTypes, resultType, params)
+ }
+ }
+ }
+ return chkdecls.NewFunction(f.Name(), overloads...), nil
+}
+
+func collectParamNames(paramNames map[string]struct{}, arg *types.Type) {
+ if arg.Kind() == types.TypeParamKind {
+ paramNames[arg.TypeName()] = struct{}{}
+ }
+ for _, param := range arg.Parameters() {
+ collectParamNames(paramNames, param)
+ }
+}
+
+var (
+ emptyArgs = []*types.Type{}
+)
diff --git a/vendor/github.com/google/cel-go/common/error.go b/vendor/github.com/google/cel-go/common/error.go
index f91f7f8d1..774dcb5b4 100644
--- a/vendor/github.com/google/cel-go/common/error.go
+++ b/vendor/github.com/google/cel-go/common/error.go
@@ -22,10 +22,16 @@ import (
"golang.org/x/text/width"
)
-// Error type which references a location within source and a message.
+// NewError creates an error associated with an expression id with the given message at the given location.
+func NewError(id int64, message string, location Location) *Error {
+ return &Error{Message: message, Location: location, ExprID: id}
+}
+
+// Error type which references an expression id, a location within source, and a message.
type Error struct {
Location Location
Message string
+ ExprID int64
}
const (
diff --git a/vendor/github.com/google/cel-go/common/errors.go b/vendor/github.com/google/cel-go/common/errors.go
index 1565085ab..63919714e 100644
--- a/vendor/github.com/google/cel-go/common/errors.go
+++ b/vendor/github.com/google/cel-go/common/errors.go
@@ -22,7 +22,7 @@ import (
// Errors type which contains a list of errors observed during parsing.
type Errors struct {
- errors []Error
+ errors []*Error
source Source
numErrors int
maxErrorsToReport int
@@ -31,7 +31,7 @@ type Errors struct {
// NewErrors creates a new instance of the Errors type.
func NewErrors(source Source) *Errors {
return &Errors{
- errors: []Error{},
+ errors: []*Error{},
source: source,
maxErrorsToReport: 100,
}
@@ -39,11 +39,17 @@ func NewErrors(source Source) *Errors {
// ReportError records an error at a source location.
func (e *Errors) ReportError(l Location, format string, args ...any) {
+ e.ReportErrorAtID(0, l, format, args...)
+}
+
+// ReportErrorAtID records an error at a source location and expression id.
+func (e *Errors) ReportErrorAtID(id int64, l Location, format string, args ...any) {
e.numErrors++
if e.numErrors > e.maxErrorsToReport {
return
}
- err := Error{
+ err := &Error{
+ ExprID: id,
Location: l,
Message: fmt.Sprintf(format, args...),
}
@@ -51,12 +57,12 @@ func (e *Errors) ReportError(l Location, format string, args ...any) {
}
// GetErrors returns the list of observed errors.
-func (e *Errors) GetErrors() []Error {
+func (e *Errors) GetErrors() []*Error {
return e.errors[:]
}
// Append creates a new Errors object with the current and input errors.
-func (e *Errors) Append(errs []Error) *Errors {
+func (e *Errors) Append(errs []*Error) *Errors {
return &Errors{
errors: append(e.errors, errs...),
source: e.source,
diff --git a/vendor/github.com/google/cel-go/common/functions/BUILD.bazel b/vendor/github.com/google/cel-go/common/functions/BUILD.bazel
new file mode 100644
index 000000000..3cc27d60c
--- /dev/null
+++ b/vendor/github.com/google/cel-go/common/functions/BUILD.bazel
@@ -0,0 +1,17 @@
+load("@io_bazel_rules_go//go:def.bzl", "go_library")
+
+package(
+ default_visibility = ["//visibility:public"],
+ licenses = ["notice"], # Apache 2.0
+)
+
+go_library(
+ name = "go_default_library",
+ srcs = [
+ "functions.go",
+ ],
+ importpath = "github.com/google/cel-go/common/functions",
+ deps = [
+ "//common/types/ref:go_default_library",
+ ],
+)
diff --git a/vendor/github.com/google/cel-go/common/functions/functions.go b/vendor/github.com/google/cel-go/common/functions/functions.go
new file mode 100644
index 000000000..67f4a5944
--- /dev/null
+++ b/vendor/github.com/google/cel-go/common/functions/functions.go
@@ -0,0 +1,61 @@
+// Copyright 2023 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package functions defines the standard builtin functions supported by the interpreter
+package functions
+
+import "github.com/google/cel-go/common/types/ref"
+
+// Overload defines a named overload of a function, indicating an operand trait
+// which must be present on the first argument to the overload as well as one
+// of either a unary, binary, or function implementation.
+//
+// The majority of operators within the expression language are unary or binary
+// and the specializations simplify the call contract for implementers of
+// types with operator overloads. Any added complexity is assumed to be handled
+// by the generic FunctionOp.
+type Overload struct {
+ // Operator name as written in an expression or defined within
+ // operators.go.
+ Operator string
+
+ // Operand trait used to dispatch the call. The zero-value indicates a
+ // global function overload or that one of the Unary / Binary / Function
+ // definitions should be used to execute the call.
+ OperandTrait int
+
+ // Unary defines the overload with a UnaryOp implementation. May be nil.
+ Unary UnaryOp
+
+ // Binary defines the overload with a BinaryOp implementation. May be nil.
+ Binary BinaryOp
+
+ // Function defines the overload with a FunctionOp implementation. May be
+ // nil.
+ Function FunctionOp
+
+ // NonStrict specifies whether the Overload will tolerate arguments that
+ // are types.Err or types.Unknown.
+ NonStrict bool
+}
+
+// UnaryOp is a function that takes a single value and produces an output.
+type UnaryOp func(value ref.Val) ref.Val
+
+// BinaryOp is a function that takes two values and produces an output.
+type BinaryOp func(lhs ref.Val, rhs ref.Val) ref.Val
+
+// FunctionOp is a function with accepts zero or more arguments and produces
+// a value or error as a result.
+type FunctionOp func(values ...ref.Val) ref.Val
diff --git a/vendor/github.com/google/cel-go/common/overloads/overloads.go b/vendor/github.com/google/cel-go/common/overloads/overloads.go
index 9ebaf6fab..9d50f4367 100644
--- a/vendor/github.com/google/cel-go/common/overloads/overloads.go
+++ b/vendor/github.com/google/cel-go/common/overloads/overloads.go
@@ -148,6 +148,11 @@ const (
StartsWith = "startsWith"
)
+// Extension function overloads with complex behaviors that need to be referenced in runtime and static analysis cost computations.
+const (
+ ExtQuoteString = "strings_quote"
+)
+
// String function overload names.
const (
ContainsString = "contains_string"
@@ -156,6 +161,11 @@ const (
StartsWithString = "starts_with_string"
)
+// Extension function overloads with complex behaviors that need to be referenced in runtime and static analysis cost computations.
+const (
+ ExtFormatString = "string_format"
+)
+
// Time-based functions.
const (
TimeGetFullYear = "getFullYear"
diff --git a/vendor/github.com/google/cel-go/common/source.go b/vendor/github.com/google/cel-go/common/source.go
index 52377d930..acf22bdf1 100644
--- a/vendor/github.com/google/cel-go/common/source.go
+++ b/vendor/github.com/google/cel-go/common/source.go
@@ -64,7 +64,6 @@ type sourceImpl struct {
runes.Buffer
description string
lineOffsets []int32
- idOffsets map[int64]int32
}
var _ runes.Buffer = &sourceImpl{}
@@ -92,7 +91,6 @@ func NewStringSource(contents string, description string) Source {
Buffer: runes.NewBuffer(contents),
description: description,
lineOffsets: offsets,
- idOffsets: map[int64]int32{},
}
}
@@ -102,7 +100,6 @@ func NewInfoSource(info *exprpb.SourceInfo) Source {
Buffer: runes.NewBuffer(""),
description: info.GetLocation(),
lineOffsets: info.GetLineOffsets(),
- idOffsets: info.GetPositions(),
}
}
diff --git a/vendor/github.com/google/cel-go/common/stdlib/BUILD.bazel b/vendor/github.com/google/cel-go/common/stdlib/BUILD.bazel
new file mode 100644
index 000000000..c130a93f6
--- /dev/null
+++ b/vendor/github.com/google/cel-go/common/stdlib/BUILD.bazel
@@ -0,0 +1,25 @@
+load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
+
+package(
+ default_visibility = ["//visibility:public"],
+ licenses = ["notice"], # Apache 2.0
+)
+
+go_library(
+ name = "go_default_library",
+ srcs = [
+ "standard.go",
+ ],
+ importpath = "github.com/google/cel-go/common/stdlib",
+ deps = [
+ "//checker/decls:go_default_library",
+ "//common/decls:go_default_library",
+ "//common/functions:go_default_library",
+ "//common/operators:go_default_library",
+ "//common/overloads:go_default_library",
+ "//common/types:go_default_library",
+ "//common/types/ref:go_default_library",
+ "//common/types/traits:go_default_library",
+ "@org_golang_google_genproto_googleapis_api//expr/v1alpha1:go_default_library",
+ ],
+)
\ No newline at end of file
diff --git a/vendor/github.com/google/cel-go/common/stdlib/standard.go b/vendor/github.com/google/cel-go/common/stdlib/standard.go
new file mode 100644
index 000000000..d02cb64bf
--- /dev/null
+++ b/vendor/github.com/google/cel-go/common/stdlib/standard.go
@@ -0,0 +1,661 @@
+// Copyright 2018 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package stdlib contains all of the standard library function declarations and definitions for CEL.
+package stdlib
+
+import (
+ "github.com/google/cel-go/common/decls"
+ "github.com/google/cel-go/common/functions"
+ "github.com/google/cel-go/common/operators"
+ "github.com/google/cel-go/common/overloads"
+ "github.com/google/cel-go/common/types"
+ "github.com/google/cel-go/common/types/ref"
+ "github.com/google/cel-go/common/types/traits"
+
+ exprpb "google.golang.org/genproto/googleapis/api/expr/v1alpha1"
+)
+
+var (
+ stdFunctions []*decls.FunctionDecl
+ stdFnDecls []*exprpb.Decl
+ stdTypes []*decls.VariableDecl
+ stdTypeDecls []*exprpb.Decl
+)
+
+func init() {
+ paramA := types.NewTypeParamType("A")
+ paramB := types.NewTypeParamType("B")
+ listOfA := types.NewListType(paramA)
+ mapOfAB := types.NewMapType(paramA, paramB)
+
+ stdTypes = []*decls.VariableDecl{
+ decls.TypeVariable(types.BoolType),
+ decls.TypeVariable(types.BytesType),
+ decls.TypeVariable(types.DoubleType),
+ decls.TypeVariable(types.DurationType),
+ decls.TypeVariable(types.IntType),
+ decls.TypeVariable(listOfA),
+ decls.TypeVariable(mapOfAB),
+ decls.TypeVariable(types.NullType),
+ decls.TypeVariable(types.StringType),
+ decls.TypeVariable(types.TimestampType),
+ decls.TypeVariable(types.TypeType),
+ decls.TypeVariable(types.UintType),
+ }
+
+ stdTypeDecls = make([]*exprpb.Decl, 0, len(stdTypes))
+ for _, stdType := range stdTypes {
+ typeVar, err := decls.VariableDeclToExprDecl(stdType)
+ if err != nil {
+ panic(err)
+ }
+ stdTypeDecls = append(stdTypeDecls, typeVar)
+ }
+
+ stdFunctions = []*decls.FunctionDecl{
+ // Logical operators. Special-cased within the interpreter.
+ // Note, the singleton binding prevents extensions from overriding the operator behavior.
+ function(operators.Conditional,
+ decls.Overload(overloads.Conditional, argTypes(types.BoolType, paramA, paramA), paramA,
+ decls.OverloadIsNonStrict()),
+ decls.SingletonFunctionBinding(noFunctionOverrides)),
+ function(operators.LogicalAnd,
+ decls.Overload(overloads.LogicalAnd, argTypes(types.BoolType, types.BoolType), types.BoolType,
+ decls.OverloadIsNonStrict()),
+ decls.SingletonBinaryBinding(noBinaryOverrides)),
+ function(operators.LogicalOr,
+ decls.Overload(overloads.LogicalOr, argTypes(types.BoolType, types.BoolType), types.BoolType,
+ decls.OverloadIsNonStrict()),
+ decls.SingletonBinaryBinding(noBinaryOverrides)),
+ function(operators.LogicalNot,
+ decls.Overload(overloads.LogicalNot, argTypes(types.BoolType), types.BoolType),
+ decls.SingletonUnaryBinding(func(val ref.Val) ref.Val {
+ b, ok := val.(types.Bool)
+ if !ok {
+ return types.MaybeNoSuchOverloadErr(val)
+ }
+ return b.Negate()
+ })),
+
+ // Comprehension short-circuiting related function
+ function(operators.NotStrictlyFalse,
+ decls.Overload(overloads.NotStrictlyFalse, argTypes(types.BoolType), types.BoolType,
+ decls.OverloadIsNonStrict(),
+ decls.UnaryBinding(notStrictlyFalse))),
+ // Deprecated: __not_strictly_false__
+ function(operators.OldNotStrictlyFalse,
+ decls.DisableDeclaration(true), // safe deprecation
+ decls.Overload(operators.OldNotStrictlyFalse, argTypes(types.BoolType), types.BoolType,
+ decls.OverloadIsNonStrict(),
+ decls.UnaryBinding(notStrictlyFalse))),
+
+ // Equality / inequality. Special-cased in the interpreter
+ function(operators.Equals,
+ decls.Overload(overloads.Equals, argTypes(paramA, paramA), types.BoolType),
+ decls.SingletonBinaryBinding(noBinaryOverrides)),
+ function(operators.NotEquals,
+ decls.Overload(overloads.NotEquals, argTypes(paramA, paramA), types.BoolType),
+ decls.SingletonBinaryBinding(noBinaryOverrides)),
+
+ // Mathematical operators
+ function(operators.Add,
+ decls.Overload(overloads.AddBytes,
+ argTypes(types.BytesType, types.BytesType), types.BytesType),
+ decls.Overload(overloads.AddDouble,
+ argTypes(types.DoubleType, types.DoubleType), types.DoubleType),
+ decls.Overload(overloads.AddDurationDuration,
+ argTypes(types.DurationType, types.DurationType), types.DurationType),
+ decls.Overload(overloads.AddDurationTimestamp,
+ argTypes(types.DurationType, types.TimestampType), types.TimestampType),
+ decls.Overload(overloads.AddTimestampDuration,
+ argTypes(types.TimestampType, types.DurationType), types.TimestampType),
+ decls.Overload(overloads.AddInt64,
+ argTypes(types.IntType, types.IntType), types.IntType),
+ decls.Overload(overloads.AddList,
+ argTypes(listOfA, listOfA), listOfA),
+ decls.Overload(overloads.AddString,
+ argTypes(types.StringType, types.StringType), types.StringType),
+ decls.Overload(overloads.AddUint64,
+ argTypes(types.UintType, types.UintType), types.UintType),
+ decls.SingletonBinaryBinding(func(lhs, rhs ref.Val) ref.Val {
+ return lhs.(traits.Adder).Add(rhs)
+ }, traits.AdderType)),
+ function(operators.Divide,
+ decls.Overload(overloads.DivideDouble,
+ argTypes(types.DoubleType, types.DoubleType), types.DoubleType),
+ decls.Overload(overloads.DivideInt64,
+ argTypes(types.IntType, types.IntType), types.IntType),
+ decls.Overload(overloads.DivideUint64,
+ argTypes(types.UintType, types.UintType), types.UintType),
+ decls.SingletonBinaryBinding(func(lhs, rhs ref.Val) ref.Val {
+ return lhs.(traits.Divider).Divide(rhs)
+ }, traits.DividerType)),
+ function(operators.Modulo,
+ decls.Overload(overloads.ModuloInt64,
+ argTypes(types.IntType, types.IntType), types.IntType),
+ decls.Overload(overloads.ModuloUint64,
+ argTypes(types.UintType, types.UintType), types.UintType),
+ decls.SingletonBinaryBinding(func(lhs, rhs ref.Val) ref.Val {
+ return lhs.(traits.Modder).Modulo(rhs)
+ }, traits.ModderType)),
+ function(operators.Multiply,
+ decls.Overload(overloads.MultiplyDouble,
+ argTypes(types.DoubleType, types.DoubleType), types.DoubleType),
+ decls.Overload(overloads.MultiplyInt64,
+ argTypes(types.IntType, types.IntType), types.IntType),
+ decls.Overload(overloads.MultiplyUint64,
+ argTypes(types.UintType, types.UintType), types.UintType),
+ decls.SingletonBinaryBinding(func(lhs, rhs ref.Val) ref.Val {
+ return lhs.(traits.Multiplier).Multiply(rhs)
+ }, traits.MultiplierType)),
+ function(operators.Negate,
+ decls.Overload(overloads.NegateDouble, argTypes(types.DoubleType), types.DoubleType),
+ decls.Overload(overloads.NegateInt64, argTypes(types.IntType), types.IntType),
+ decls.SingletonUnaryBinding(func(val ref.Val) ref.Val {
+ if types.IsBool(val) {
+ return types.MaybeNoSuchOverloadErr(val)
+ }
+ return val.(traits.Negater).Negate()
+ }, traits.NegatorType)),
+ function(operators.Subtract,
+ decls.Overload(overloads.SubtractDouble,
+ argTypes(types.DoubleType, types.DoubleType), types.DoubleType),
+ decls.Overload(overloads.SubtractDurationDuration,
+ argTypes(types.DurationType, types.DurationType), types.DurationType),
+ decls.Overload(overloads.SubtractInt64,
+ argTypes(types.IntType, types.IntType), types.IntType),
+ decls.Overload(overloads.SubtractTimestampDuration,
+ argTypes(types.TimestampType, types.DurationType), types.TimestampType),
+ decls.Overload(overloads.SubtractTimestampTimestamp,
+ argTypes(types.TimestampType, types.TimestampType), types.DurationType),
+ decls.Overload(overloads.SubtractUint64,
+ argTypes(types.UintType, types.UintType), types.UintType),
+ decls.SingletonBinaryBinding(func(lhs, rhs ref.Val) ref.Val {
+ return lhs.(traits.Subtractor).Subtract(rhs)
+ }, traits.SubtractorType)),
+
+ // Relations operators
+
+ function(operators.Less,
+ decls.Overload(overloads.LessBool,
+ argTypes(types.BoolType, types.BoolType), types.BoolType),
+ decls.Overload(overloads.LessInt64,
+ argTypes(types.IntType, types.IntType), types.BoolType),
+ decls.Overload(overloads.LessInt64Double,
+ argTypes(types.IntType, types.DoubleType), types.BoolType),
+ decls.Overload(overloads.LessInt64Uint64,
+ argTypes(types.IntType, types.UintType), types.BoolType),
+ decls.Overload(overloads.LessUint64,
+ argTypes(types.UintType, types.UintType), types.BoolType),
+ decls.Overload(overloads.LessUint64Double,
+ argTypes(types.UintType, types.DoubleType), types.BoolType),
+ decls.Overload(overloads.LessUint64Int64,
+ argTypes(types.UintType, types.IntType), types.BoolType),
+ decls.Overload(overloads.LessDouble,
+ argTypes(types.DoubleType, types.DoubleType), types.BoolType),
+ decls.Overload(overloads.LessDoubleInt64,
+ argTypes(types.DoubleType, types.IntType), types.BoolType),
+ decls.Overload(overloads.LessDoubleUint64,
+ argTypes(types.DoubleType, types.UintType), types.BoolType),
+ decls.Overload(overloads.LessString,
+ argTypes(types.StringType, types.StringType), types.BoolType),
+ decls.Overload(overloads.LessBytes,
+ argTypes(types.BytesType, types.BytesType), types.BoolType),
+ decls.Overload(overloads.LessTimestamp,
+ argTypes(types.TimestampType, types.TimestampType), types.BoolType),
+ decls.Overload(overloads.LessDuration,
+ argTypes(types.DurationType, types.DurationType), types.BoolType),
+ decls.SingletonBinaryBinding(func(lhs, rhs ref.Val) ref.Val {
+ cmp := lhs.(traits.Comparer).Compare(rhs)
+ if cmp == types.IntNegOne {
+ return types.True
+ }
+ if cmp == types.IntOne || cmp == types.IntZero {
+ return types.False
+ }
+ return cmp
+ }, traits.ComparerType)),
+
+ function(operators.LessEquals,
+ decls.Overload(overloads.LessEqualsBool,
+ argTypes(types.BoolType, types.BoolType), types.BoolType),
+ decls.Overload(overloads.LessEqualsInt64,
+ argTypes(types.IntType, types.IntType), types.BoolType),
+ decls.Overload(overloads.LessEqualsInt64Double,
+ argTypes(types.IntType, types.DoubleType), types.BoolType),
+ decls.Overload(overloads.LessEqualsInt64Uint64,
+ argTypes(types.IntType, types.UintType), types.BoolType),
+ decls.Overload(overloads.LessEqualsUint64,
+ argTypes(types.UintType, types.UintType), types.BoolType),
+ decls.Overload(overloads.LessEqualsUint64Double,
+ argTypes(types.UintType, types.DoubleType), types.BoolType),
+ decls.Overload(overloads.LessEqualsUint64Int64,
+ argTypes(types.UintType, types.IntType), types.BoolType),
+ decls.Overload(overloads.LessEqualsDouble,
+ argTypes(types.DoubleType, types.DoubleType), types.BoolType),
+ decls.Overload(overloads.LessEqualsDoubleInt64,
+ argTypes(types.DoubleType, types.IntType), types.BoolType),
+ decls.Overload(overloads.LessEqualsDoubleUint64,
+ argTypes(types.DoubleType, types.UintType), types.BoolType),
+ decls.Overload(overloads.LessEqualsString,
+ argTypes(types.StringType, types.StringType), types.BoolType),
+ decls.Overload(overloads.LessEqualsBytes,
+ argTypes(types.BytesType, types.BytesType), types.BoolType),
+ decls.Overload(overloads.LessEqualsTimestamp,
+ argTypes(types.TimestampType, types.TimestampType), types.BoolType),
+ decls.Overload(overloads.LessEqualsDuration,
+ argTypes(types.DurationType, types.DurationType), types.BoolType),
+ decls.SingletonBinaryBinding(func(lhs, rhs ref.Val) ref.Val {
+ cmp := lhs.(traits.Comparer).Compare(rhs)
+ if cmp == types.IntNegOne || cmp == types.IntZero {
+ return types.True
+ }
+ if cmp == types.IntOne {
+ return types.False
+ }
+ return cmp
+ }, traits.ComparerType)),
+
+ function(operators.Greater,
+ decls.Overload(overloads.GreaterBool,
+ argTypes(types.BoolType, types.BoolType), types.BoolType),
+ decls.Overload(overloads.GreaterInt64,
+ argTypes(types.IntType, types.IntType), types.BoolType),
+ decls.Overload(overloads.GreaterInt64Double,
+ argTypes(types.IntType, types.DoubleType), types.BoolType),
+ decls.Overload(overloads.GreaterInt64Uint64,
+ argTypes(types.IntType, types.UintType), types.BoolType),
+ decls.Overload(overloads.GreaterUint64,
+ argTypes(types.UintType, types.UintType), types.BoolType),
+ decls.Overload(overloads.GreaterUint64Double,
+ argTypes(types.UintType, types.DoubleType), types.BoolType),
+ decls.Overload(overloads.GreaterUint64Int64,
+ argTypes(types.UintType, types.IntType), types.BoolType),
+ decls.Overload(overloads.GreaterDouble,
+ argTypes(types.DoubleType, types.DoubleType), types.BoolType),
+ decls.Overload(overloads.GreaterDoubleInt64,
+ argTypes(types.DoubleType, types.IntType), types.BoolType),
+ decls.Overload(overloads.GreaterDoubleUint64,
+ argTypes(types.DoubleType, types.UintType), types.BoolType),
+ decls.Overload(overloads.GreaterString,
+ argTypes(types.StringType, types.StringType), types.BoolType),
+ decls.Overload(overloads.GreaterBytes,
+ argTypes(types.BytesType, types.BytesType), types.BoolType),
+ decls.Overload(overloads.GreaterTimestamp,
+ argTypes(types.TimestampType, types.TimestampType), types.BoolType),
+ decls.Overload(overloads.GreaterDuration,
+ argTypes(types.DurationType, types.DurationType), types.BoolType),
+ decls.SingletonBinaryBinding(func(lhs, rhs ref.Val) ref.Val {
+ cmp := lhs.(traits.Comparer).Compare(rhs)
+ if cmp == types.IntOne {
+ return types.True
+ }
+ if cmp == types.IntNegOne || cmp == types.IntZero {
+ return types.False
+ }
+ return cmp
+ }, traits.ComparerType)),
+
+ function(operators.GreaterEquals,
+ decls.Overload(overloads.GreaterEqualsBool,
+ argTypes(types.BoolType, types.BoolType), types.BoolType),
+ decls.Overload(overloads.GreaterEqualsInt64,
+ argTypes(types.IntType, types.IntType), types.BoolType),
+ decls.Overload(overloads.GreaterEqualsInt64Double,
+ argTypes(types.IntType, types.DoubleType), types.BoolType),
+ decls.Overload(overloads.GreaterEqualsInt64Uint64,
+ argTypes(types.IntType, types.UintType), types.BoolType),
+ decls.Overload(overloads.GreaterEqualsUint64,
+ argTypes(types.UintType, types.UintType), types.BoolType),
+ decls.Overload(overloads.GreaterEqualsUint64Double,
+ argTypes(types.UintType, types.DoubleType), types.BoolType),
+ decls.Overload(overloads.GreaterEqualsUint64Int64,
+ argTypes(types.UintType, types.IntType), types.BoolType),
+ decls.Overload(overloads.GreaterEqualsDouble,
+ argTypes(types.DoubleType, types.DoubleType), types.BoolType),
+ decls.Overload(overloads.GreaterEqualsDoubleInt64,
+ argTypes(types.DoubleType, types.IntType), types.BoolType),
+ decls.Overload(overloads.GreaterEqualsDoubleUint64,
+ argTypes(types.DoubleType, types.UintType), types.BoolType),
+ decls.Overload(overloads.GreaterEqualsString,
+ argTypes(types.StringType, types.StringType), types.BoolType),
+ decls.Overload(overloads.GreaterEqualsBytes,
+ argTypes(types.BytesType, types.BytesType), types.BoolType),
+ decls.Overload(overloads.GreaterEqualsTimestamp,
+ argTypes(types.TimestampType, types.TimestampType), types.BoolType),
+ decls.Overload(overloads.GreaterEqualsDuration,
+ argTypes(types.DurationType, types.DurationType), types.BoolType),
+ decls.SingletonBinaryBinding(func(lhs, rhs ref.Val) ref.Val {
+ cmp := lhs.(traits.Comparer).Compare(rhs)
+ if cmp == types.IntOne || cmp == types.IntZero {
+ return types.True
+ }
+ if cmp == types.IntNegOne {
+ return types.False
+ }
+ return cmp
+ }, traits.ComparerType)),
+
+ // Indexing
+ function(operators.Index,
+ decls.Overload(overloads.IndexList, argTypes(listOfA, types.IntType), paramA),
+ decls.Overload(overloads.IndexMap, argTypes(mapOfAB, paramA), paramB),
+ decls.SingletonBinaryBinding(func(lhs, rhs ref.Val) ref.Val {
+ return lhs.(traits.Indexer).Get(rhs)
+ }, traits.IndexerType)),
+
+ // Collections operators
+ function(operators.In,
+ decls.Overload(overloads.InList, argTypes(paramA, listOfA), types.BoolType),
+ decls.Overload(overloads.InMap, argTypes(paramA, mapOfAB), types.BoolType),
+ decls.SingletonBinaryBinding(inAggregate)),
+ function(operators.OldIn,
+ decls.DisableDeclaration(true), // safe deprecation
+ decls.Overload(overloads.InList, argTypes(paramA, listOfA), types.BoolType),
+ decls.Overload(overloads.InMap, argTypes(paramA, mapOfAB), types.BoolType),
+ decls.SingletonBinaryBinding(inAggregate)),
+ function(overloads.DeprecatedIn,
+ decls.DisableDeclaration(true), // safe deprecation
+ decls.Overload(overloads.InList, argTypes(paramA, listOfA), types.BoolType),
+ decls.Overload(overloads.InMap, argTypes(paramA, mapOfAB), types.BoolType),
+ decls.SingletonBinaryBinding(inAggregate)),
+ function(overloads.Size,
+ decls.Overload(overloads.SizeBytes, argTypes(types.BytesType), types.IntType),
+ decls.MemberOverload(overloads.SizeBytesInst, argTypes(types.BytesType), types.IntType),
+ decls.Overload(overloads.SizeList, argTypes(listOfA), types.IntType),
+ decls.MemberOverload(overloads.SizeListInst, argTypes(listOfA), types.IntType),
+ decls.Overload(overloads.SizeMap, argTypes(mapOfAB), types.IntType),
+ decls.MemberOverload(overloads.SizeMapInst, argTypes(mapOfAB), types.IntType),
+ decls.Overload(overloads.SizeString, argTypes(types.StringType), types.IntType),
+ decls.MemberOverload(overloads.SizeStringInst, argTypes(types.StringType), types.IntType),
+ decls.SingletonUnaryBinding(func(val ref.Val) ref.Val {
+ return val.(traits.Sizer).Size()
+ }, traits.SizerType)),
+
+ // Type conversions
+ function(overloads.TypeConvertType,
+ decls.Overload(overloads.TypeConvertType, argTypes(paramA), types.NewTypeTypeWithParam(paramA)),
+ decls.SingletonUnaryBinding(convertToType(types.TypeType))),
+
+ // Bool conversions
+ function(overloads.TypeConvertBool,
+ decls.Overload(overloads.BoolToBool, argTypes(types.BoolType), types.BoolType,
+ decls.UnaryBinding(identity)),
+ decls.Overload(overloads.StringToBool, argTypes(types.StringType), types.BoolType,
+ decls.UnaryBinding(convertToType(types.BoolType)))),
+
+ // Bytes conversions
+ function(overloads.TypeConvertBytes,
+ decls.Overload(overloads.BytesToBytes, argTypes(types.BytesType), types.BytesType,
+ decls.UnaryBinding(identity)),
+ decls.Overload(overloads.StringToBytes, argTypes(types.StringType), types.BytesType,
+ decls.UnaryBinding(convertToType(types.BytesType)))),
+
+ // Double conversions
+ function(overloads.TypeConvertDouble,
+ decls.Overload(overloads.DoubleToDouble, argTypes(types.DoubleType), types.DoubleType,
+ decls.UnaryBinding(identity)),
+ decls.Overload(overloads.IntToDouble, argTypes(types.IntType), types.DoubleType,
+ decls.UnaryBinding(convertToType(types.DoubleType))),
+ decls.Overload(overloads.StringToDouble, argTypes(types.StringType), types.DoubleType,
+ decls.UnaryBinding(convertToType(types.DoubleType))),
+ decls.Overload(overloads.UintToDouble, argTypes(types.UintType), types.DoubleType,
+ decls.UnaryBinding(convertToType(types.DoubleType)))),
+
+ // Duration conversions
+ function(overloads.TypeConvertDuration,
+ decls.Overload(overloads.DurationToDuration, argTypes(types.DurationType), types.DurationType,
+ decls.UnaryBinding(identity)),
+ decls.Overload(overloads.IntToDuration, argTypes(types.IntType), types.DurationType,
+ decls.UnaryBinding(convertToType(types.DurationType))),
+ decls.Overload(overloads.StringToDuration, argTypes(types.StringType), types.DurationType,
+ decls.UnaryBinding(convertToType(types.DurationType)))),
+
+ // Dyn conversions
+ function(overloads.TypeConvertDyn,
+ decls.Overload(overloads.ToDyn, argTypes(paramA), types.DynType),
+ decls.SingletonUnaryBinding(identity)),
+
+ // Int conversions
+ function(overloads.TypeConvertInt,
+ decls.Overload(overloads.IntToInt, argTypes(types.IntType), types.IntType,
+ decls.UnaryBinding(identity)),
+ decls.Overload(overloads.DoubleToInt, argTypes(types.DoubleType), types.IntType,
+ decls.UnaryBinding(convertToType(types.IntType))),
+ decls.Overload(overloads.DurationToInt, argTypes(types.DurationType), types.IntType,
+ decls.UnaryBinding(convertToType(types.IntType))),
+ decls.Overload(overloads.StringToInt, argTypes(types.StringType), types.IntType,
+ decls.UnaryBinding(convertToType(types.IntType))),
+ decls.Overload(overloads.TimestampToInt, argTypes(types.TimestampType), types.IntType,
+ decls.UnaryBinding(convertToType(types.IntType))),
+ decls.Overload(overloads.UintToInt, argTypes(types.UintType), types.IntType,
+ decls.UnaryBinding(convertToType(types.IntType))),
+ ),
+
+ // String conversions
+ function(overloads.TypeConvertString,
+ decls.Overload(overloads.StringToString, argTypes(types.StringType), types.StringType,
+ decls.UnaryBinding(identity)),
+ decls.Overload(overloads.BoolToString, argTypes(types.BoolType), types.StringType,
+ decls.UnaryBinding(convertToType(types.StringType))),
+ decls.Overload(overloads.BytesToString, argTypes(types.BytesType), types.StringType,
+ decls.UnaryBinding(convertToType(types.StringType))),
+ decls.Overload(overloads.DoubleToString, argTypes(types.DoubleType), types.StringType,
+ decls.UnaryBinding(convertToType(types.StringType))),
+ decls.Overload(overloads.DurationToString, argTypes(types.DurationType), types.StringType,
+ decls.UnaryBinding(convertToType(types.StringType))),
+ decls.Overload(overloads.IntToString, argTypes(types.IntType), types.StringType,
+ decls.UnaryBinding(convertToType(types.StringType))),
+ decls.Overload(overloads.TimestampToString, argTypes(types.TimestampType), types.StringType,
+ decls.UnaryBinding(convertToType(types.StringType))),
+ decls.Overload(overloads.UintToString, argTypes(types.UintType), types.StringType,
+ decls.UnaryBinding(convertToType(types.StringType)))),
+
+ // Timestamp conversions
+ function(overloads.TypeConvertTimestamp,
+ decls.Overload(overloads.TimestampToTimestamp, argTypes(types.TimestampType), types.TimestampType,
+ decls.UnaryBinding(identity)),
+ decls.Overload(overloads.IntToTimestamp, argTypes(types.IntType), types.TimestampType,
+ decls.UnaryBinding(convertToType(types.TimestampType))),
+ decls.Overload(overloads.StringToTimestamp, argTypes(types.StringType), types.TimestampType,
+ decls.UnaryBinding(convertToType(types.TimestampType)))),
+
+ // Uint conversions
+ function(overloads.TypeConvertUint,
+ decls.Overload(overloads.UintToUint, argTypes(types.UintType), types.UintType,
+ decls.UnaryBinding(identity)),
+ decls.Overload(overloads.DoubleToUint, argTypes(types.DoubleType), types.UintType,
+ decls.UnaryBinding(convertToType(types.UintType))),
+ decls.Overload(overloads.IntToUint, argTypes(types.IntType), types.UintType,
+ decls.UnaryBinding(convertToType(types.UintType))),
+ decls.Overload(overloads.StringToUint, argTypes(types.StringType), types.UintType,
+ decls.UnaryBinding(convertToType(types.UintType)))),
+
+ // String functions
+ function(overloads.Contains,
+ decls.MemberOverload(overloads.ContainsString,
+ argTypes(types.StringType, types.StringType), types.BoolType,
+ decls.BinaryBinding(types.StringContains)),
+ decls.DisableTypeGuards(true)),
+ function(overloads.EndsWith,
+ decls.MemberOverload(overloads.EndsWithString,
+ argTypes(types.StringType, types.StringType), types.BoolType,
+ decls.BinaryBinding(types.StringEndsWith)),
+ decls.DisableTypeGuards(true)),
+ function(overloads.StartsWith,
+ decls.MemberOverload(overloads.StartsWithString,
+ argTypes(types.StringType, types.StringType), types.BoolType,
+ decls.BinaryBinding(types.StringStartsWith)),
+ decls.DisableTypeGuards(true)),
+ function(overloads.Matches,
+ decls.Overload(overloads.Matches, argTypes(types.StringType, types.StringType), types.BoolType),
+ decls.MemberOverload(overloads.MatchesString,
+ argTypes(types.StringType, types.StringType), types.BoolType),
+ decls.SingletonBinaryBinding(func(str, pat ref.Val) ref.Val {
+ return str.(traits.Matcher).Match(pat)
+ }, traits.MatcherType)),
+
+ // Timestamp / duration functions
+ function(overloads.TimeGetFullYear,
+ decls.MemberOverload(overloads.TimestampToYear,
+ argTypes(types.TimestampType), types.IntType),
+ decls.MemberOverload(overloads.TimestampToYearWithTz,
+ argTypes(types.TimestampType, types.StringType), types.IntType)),
+
+ function(overloads.TimeGetMonth,
+ decls.MemberOverload(overloads.TimestampToMonth,
+ argTypes(types.TimestampType), types.IntType),
+ decls.MemberOverload(overloads.TimestampToMonthWithTz,
+ argTypes(types.TimestampType, types.StringType), types.IntType)),
+
+ function(overloads.TimeGetDayOfYear,
+ decls.MemberOverload(overloads.TimestampToDayOfYear,
+ argTypes(types.TimestampType), types.IntType),
+ decls.MemberOverload(overloads.TimestampToDayOfYearWithTz,
+ argTypes(types.TimestampType, types.StringType), types.IntType)),
+
+ function(overloads.TimeGetDayOfMonth,
+ decls.MemberOverload(overloads.TimestampToDayOfMonthZeroBased,
+ argTypes(types.TimestampType), types.IntType),
+ decls.MemberOverload(overloads.TimestampToDayOfMonthZeroBasedWithTz,
+ argTypes(types.TimestampType, types.StringType), types.IntType)),
+
+ function(overloads.TimeGetDate,
+ decls.MemberOverload(overloads.TimestampToDayOfMonthOneBased,
+ argTypes(types.TimestampType), types.IntType),
+ decls.MemberOverload(overloads.TimestampToDayOfMonthOneBasedWithTz,
+ argTypes(types.TimestampType, types.StringType), types.IntType)),
+
+ function(overloads.TimeGetDayOfWeek,
+ decls.MemberOverload(overloads.TimestampToDayOfWeek,
+ argTypes(types.TimestampType), types.IntType),
+ decls.MemberOverload(overloads.TimestampToDayOfWeekWithTz,
+ argTypes(types.TimestampType, types.StringType), types.IntType)),
+
+ function(overloads.TimeGetHours,
+ decls.MemberOverload(overloads.TimestampToHours,
+ argTypes(types.TimestampType), types.IntType),
+ decls.MemberOverload(overloads.TimestampToHoursWithTz,
+ argTypes(types.TimestampType, types.StringType), types.IntType),
+ decls.MemberOverload(overloads.DurationToHours,
+ argTypes(types.DurationType), types.IntType)),
+
+ function(overloads.TimeGetMinutes,
+ decls.MemberOverload(overloads.TimestampToMinutes,
+ argTypes(types.TimestampType), types.IntType),
+ decls.MemberOverload(overloads.TimestampToMinutesWithTz,
+ argTypes(types.TimestampType, types.StringType), types.IntType),
+ decls.MemberOverload(overloads.DurationToMinutes,
+ argTypes(types.DurationType), types.IntType)),
+
+ function(overloads.TimeGetSeconds,
+ decls.MemberOverload(overloads.TimestampToSeconds,
+ argTypes(types.TimestampType), types.IntType),
+ decls.MemberOverload(overloads.TimestampToSecondsWithTz,
+ argTypes(types.TimestampType, types.StringType), types.IntType),
+ decls.MemberOverload(overloads.DurationToSeconds,
+ argTypes(types.DurationType), types.IntType)),
+
+ function(overloads.TimeGetMilliseconds,
+ decls.MemberOverload(overloads.TimestampToMilliseconds,
+ argTypes(types.TimestampType), types.IntType),
+ decls.MemberOverload(overloads.TimestampToMillisecondsWithTz,
+ argTypes(types.TimestampType, types.StringType), types.IntType),
+ decls.MemberOverload(overloads.DurationToMilliseconds,
+ argTypes(types.DurationType), types.IntType)),
+ }
+
+ stdFnDecls = make([]*exprpb.Decl, 0, len(stdFunctions))
+ for _, fn := range stdFunctions {
+ if fn.IsDeclarationDisabled() {
+ continue
+ }
+ ed, err := decls.FunctionDeclToExprDecl(fn)
+ if err != nil {
+ panic(err)
+ }
+ stdFnDecls = append(stdFnDecls, ed)
+ }
+}
+
+// Functions returns the set of standard library function declarations and definitions for CEL.
+func Functions() []*decls.FunctionDecl {
+ return stdFunctions
+}
+
+// FunctionExprDecls returns the legacy style protobuf-typed declarations for all functions and overloads
+// in the CEL standard environment.
+//
+// Deprecated: use Functions
+func FunctionExprDecls() []*exprpb.Decl {
+ return stdFnDecls
+}
+
+// Types returns the set of standard library types for CEL.
+func Types() []*decls.VariableDecl {
+ return stdTypes
+}
+
+// TypeExprDecls returns the legacy style protobuf-typed declarations for all types in the CEL
+// standard environment.
+//
+// Deprecated: use Types
+func TypeExprDecls() []*exprpb.Decl {
+ return stdTypeDecls
+}
+
+func notStrictlyFalse(value ref.Val) ref.Val {
+ if types.IsBool(value) {
+ return value
+ }
+ return types.True
+}
+
+func inAggregate(lhs ref.Val, rhs ref.Val) ref.Val {
+ if rhs.Type().HasTrait(traits.ContainerType) {
+ return rhs.(traits.Container).Contains(lhs)
+ }
+ return types.ValOrErr(rhs, "no such overload")
+}
+
+func function(name string, opts ...decls.FunctionOpt) *decls.FunctionDecl {
+ fn, err := decls.NewFunction(name, opts...)
+ if err != nil {
+ panic(err)
+ }
+ return fn
+}
+
+func argTypes(args ...*types.Type) []*types.Type {
+ return args
+}
+
+func noBinaryOverrides(rhs, lhs ref.Val) ref.Val {
+ return types.NoSuchOverloadErr()
+}
+
+func noFunctionOverrides(args ...ref.Val) ref.Val {
+ return types.NoSuchOverloadErr()
+}
+
+func identity(val ref.Val) ref.Val {
+ return val
+}
+
+func convertToType(t ref.Type) functions.UnaryOp {
+ return func(val ref.Val) ref.Val {
+ return val.ConvertToType(t)
+ }
+}
diff --git a/vendor/github.com/google/cel-go/common/types/BUILD.bazel b/vendor/github.com/google/cel-go/common/types/BUILD.bazel
index f56700de5..b5e44ffbf 100644
--- a/vendor/github.com/google/cel-go/common/types/BUILD.bazel
+++ b/vendor/github.com/google/cel-go/common/types/BUILD.bazel
@@ -27,20 +27,20 @@ go_library(
"provider.go",
"string.go",
"timestamp.go",
- "type.go",
+ "types.go",
"uint.go",
"unknown.go",
"util.go",
],
importpath = "github.com/google/cel-go/common/types",
deps = [
+ "//checker/decls:go_default_library",
"//common/overloads:go_default_library",
"//common/types/pb:go_default_library",
"//common/types/ref:go_default_library",
"//common/types/traits:go_default_library",
"@com_github_stoewer_go_strcase//:go_default_library",
- "@org_golang_google_genproto//googleapis/api/expr/v1alpha1:go_default_library",
- "@org_golang_google_genproto//googleapis/rpc/status:go_default_library",
+ "@org_golang_google_genproto_googleapis_api//expr/v1alpha1:go_default_library",
"@org_golang_google_protobuf//encoding/protojson:go_default_library",
"@org_golang_google_protobuf//proto:go_default_library",
"@org_golang_google_protobuf//reflect/protoreflect:go_default_library",
@@ -71,8 +71,9 @@ go_test(
"provider_test.go",
"string_test.go",
"timestamp_test.go",
- "type_test.go",
+ "types_test.go",
"uint_test.go",
+ "unknown_test.go",
"util_test.go",
],
embed = [":go_default_library"],
@@ -80,7 +81,7 @@ go_test(
"//common/types/ref:go_default_library",
"//test:go_default_library",
"//test/proto3pb:test_all_types_go_proto",
- "@org_golang_google_genproto//googleapis/api/expr/v1alpha1:go_default_library",
+ "@org_golang_google_genproto_googleapis_api//expr/v1alpha1:go_default_library",
"@org_golang_google_protobuf//encoding/protojson:go_default_library",
"@org_golang_google_protobuf//types/known/anypb:go_default_library",
"@org_golang_google_protobuf//types/known/durationpb:go_default_library",
diff --git a/vendor/github.com/google/cel-go/common/types/bool.go b/vendor/github.com/google/cel-go/common/types/bool.go
index a634ecc28..565734f3f 100644
--- a/vendor/github.com/google/cel-go/common/types/bool.go
+++ b/vendor/github.com/google/cel-go/common/types/bool.go
@@ -20,7 +20,6 @@ import (
"strconv"
"github.com/google/cel-go/common/types/ref"
- "github.com/google/cel-go/common/types/traits"
anypb "google.golang.org/protobuf/types/known/anypb"
structpb "google.golang.org/protobuf/types/known/structpb"
@@ -31,11 +30,6 @@ import (
type Bool bool
var (
- // BoolType singleton.
- BoolType = NewTypeValue("bool",
- traits.ComparerType,
- traits.NegatorType)
-
// boolWrapperType golang reflected type for protobuf bool wrapper type.
boolWrapperType = reflect.TypeOf(&wrapperspb.BoolValue{})
)
diff --git a/vendor/github.com/google/cel-go/common/types/bytes.go b/vendor/github.com/google/cel-go/common/types/bytes.go
index bef190759..5838755f8 100644
--- a/vendor/github.com/google/cel-go/common/types/bytes.go
+++ b/vendor/github.com/google/cel-go/common/types/bytes.go
@@ -22,7 +22,6 @@ import (
"unicode/utf8"
"github.com/google/cel-go/common/types/ref"
- "github.com/google/cel-go/common/types/traits"
anypb "google.golang.org/protobuf/types/known/anypb"
structpb "google.golang.org/protobuf/types/known/structpb"
@@ -34,12 +33,6 @@ import (
type Bytes []byte
var (
- // BytesType singleton.
- BytesType = NewTypeValue("bytes",
- traits.AdderType,
- traits.ComparerType,
- traits.SizerType)
-
// byteWrapperType golang reflected type for protobuf bytes wrapper type.
byteWrapperType = reflect.TypeOf(&wrapperspb.BytesValue{})
)
diff --git a/vendor/github.com/google/cel-go/common/types/double.go b/vendor/github.com/google/cel-go/common/types/double.go
index 4647cf04f..027e78978 100644
--- a/vendor/github.com/google/cel-go/common/types/double.go
+++ b/vendor/github.com/google/cel-go/common/types/double.go
@@ -20,7 +20,6 @@ import (
"reflect"
"github.com/google/cel-go/common/types/ref"
- "github.com/google/cel-go/common/types/traits"
anypb "google.golang.org/protobuf/types/known/anypb"
structpb "google.golang.org/protobuf/types/known/structpb"
@@ -32,15 +31,6 @@ import (
type Double float64
var (
- // DoubleType singleton.
- DoubleType = NewTypeValue("double",
- traits.AdderType,
- traits.ComparerType,
- traits.DividerType,
- traits.MultiplierType,
- traits.NegatorType,
- traits.SubtractorType)
-
// doubleWrapperType reflected type for protobuf double wrapper type.
doubleWrapperType = reflect.TypeOf(&wrapperspb.DoubleValue{})
@@ -134,13 +124,13 @@ func (d Double) ConvertToType(typeVal ref.Type) ref.Val {
case IntType:
i, err := doubleToInt64Checked(float64(d))
if err != nil {
- return wrapErr(err)
+ return WrapErr(err)
}
return Int(i)
case UintType:
i, err := doubleToUint64Checked(float64(d))
if err != nil {
- return wrapErr(err)
+ return WrapErr(err)
}
return Uint(i)
case DoubleType:
diff --git a/vendor/github.com/google/cel-go/common/types/duration.go b/vendor/github.com/google/cel-go/common/types/duration.go
index f6a4f5a01..596e56d6b 100644
--- a/vendor/github.com/google/cel-go/common/types/duration.go
+++ b/vendor/github.com/google/cel-go/common/types/duration.go
@@ -22,7 +22,6 @@ import (
"github.com/google/cel-go/common/overloads"
"github.com/google/cel-go/common/types/ref"
- "github.com/google/cel-go/common/types/traits"
anypb "google.golang.org/protobuf/types/known/anypb"
dpb "google.golang.org/protobuf/types/known/durationpb"
@@ -41,13 +40,14 @@ func durationOf(d time.Duration) Duration {
}
var (
- // DurationType singleton.
- DurationType = NewTypeValue("google.protobuf.Duration",
- traits.AdderType,
- traits.ComparerType,
- traits.NegatorType,
- traits.ReceiverType,
- traits.SubtractorType)
+ durationValueType = reflect.TypeOf(&dpb.Duration{})
+
+ durationZeroArgOverloads = map[string]func(ref.Val) ref.Val{
+ overloads.TimeGetHours: DurationGetHours,
+ overloads.TimeGetMinutes: DurationGetMinutes,
+ overloads.TimeGetSeconds: DurationGetSeconds,
+ overloads.TimeGetMilliseconds: DurationGetMilliseconds,
+ }
)
// Add implements traits.Adder.Add.
@@ -57,14 +57,14 @@ func (d Duration) Add(other ref.Val) ref.Val {
dur2 := other.(Duration)
val, err := addDurationChecked(d.Duration, dur2.Duration)
if err != nil {
- return wrapErr(err)
+ return WrapErr(err)
}
return durationOf(val)
case TimestampType:
ts := other.(Timestamp).Time
val, err := addTimeDurationChecked(ts, d.Duration)
if err != nil {
- return wrapErr(err)
+ return WrapErr(err)
}
return timestampOf(val)
}
@@ -147,7 +147,7 @@ func (d Duration) IsZeroValue() bool {
func (d Duration) Negate() ref.Val {
val, err := negateDurationChecked(d.Duration)
if err != nil {
- return wrapErr(err)
+ return WrapErr(err)
}
return durationOf(val)
}
@@ -156,7 +156,7 @@ func (d Duration) Negate() ref.Val {
func (d Duration) Receive(function string, overload string, args []ref.Val) ref.Val {
if len(args) == 0 {
if f, found := durationZeroArgOverloads[function]; found {
- return f(d.Duration)
+ return f(d)
}
}
return NoSuchOverloadErr()
@@ -170,7 +170,7 @@ func (d Duration) Subtract(subtrahend ref.Val) ref.Val {
}
val, err := subtractDurationChecked(d.Duration, subtraDur.Duration)
if err != nil {
- return wrapErr(err)
+ return WrapErr(err)
}
return durationOf(val)
}
@@ -185,20 +185,38 @@ func (d Duration) Value() any {
return d.Duration
}
-var (
- durationValueType = reflect.TypeOf(&dpb.Duration{})
+// DurationGetHours returns the duration in hours.
+func DurationGetHours(val ref.Val) ref.Val {
+ dur, ok := val.(Duration)
+ if !ok {
+ return MaybeNoSuchOverloadErr(val)
+ }
+ return Int(dur.Hours())
+}
- durationZeroArgOverloads = map[string]func(time.Duration) ref.Val{
- overloads.TimeGetHours: func(dur time.Duration) ref.Val {
- return Int(dur.Hours())
- },
- overloads.TimeGetMinutes: func(dur time.Duration) ref.Val {
- return Int(dur.Minutes())
- },
- overloads.TimeGetSeconds: func(dur time.Duration) ref.Val {
- return Int(dur.Seconds())
- },
- overloads.TimeGetMilliseconds: func(dur time.Duration) ref.Val {
- return Int(dur.Milliseconds())
- }}
-)
+// DurationGetMinutes returns duration in minutes.
+func DurationGetMinutes(val ref.Val) ref.Val {
+ dur, ok := val.(Duration)
+ if !ok {
+ return MaybeNoSuchOverloadErr(val)
+ }
+ return Int(dur.Minutes())
+}
+
+// DurationGetSeconds returns duration in seconds.
+func DurationGetSeconds(val ref.Val) ref.Val {
+ dur, ok := val.(Duration)
+ if !ok {
+ return MaybeNoSuchOverloadErr(val)
+ }
+ return Int(dur.Seconds())
+}
+
+// DurationGetMilliseconds returns duration in milliseconds.
+func DurationGetMilliseconds(val ref.Val) ref.Val {
+ dur, ok := val.(Duration)
+ if !ok {
+ return MaybeNoSuchOverloadErr(val)
+ }
+ return Int(dur.Milliseconds())
+}
diff --git a/vendor/github.com/google/cel-go/common/types/err.go b/vendor/github.com/google/cel-go/common/types/err.go
index d9f9b6013..aa8f94b4f 100644
--- a/vendor/github.com/google/cel-go/common/types/err.go
+++ b/vendor/github.com/google/cel-go/common/types/err.go
@@ -22,6 +22,12 @@ import (
"github.com/google/cel-go/common/types/ref"
)
+// Error interface which allows types types.Err values to be treated as error values.
+type Error interface {
+ error
+ ref.Val
+}
+
// Err type which extends the built-in go error and implements ref.Val.
type Err struct {
error
@@ -29,7 +35,7 @@ type Err struct {
var (
// ErrType singleton.
- ErrType = NewTypeValue("error")
+ ErrType = NewOpaqueType("error")
// errDivideByZero is an error indicating a division by zero of an integer value.
errDivideByZero = errors.New("division by zero")
@@ -81,8 +87,8 @@ func ValOrErr(val ref.Val, format string, args ...any) ref.Val {
return val
}
-// wrapErr wraps an existing Go error value into a CEL Err value.
-func wrapErr(err error) ref.Val {
+// WrapErr wraps an existing Go error value into a CEL Err value.
+func WrapErr(err error) ref.Val {
return &Err{error: err}
}
@@ -123,6 +129,11 @@ func (e *Err) Is(target error) bool {
return e.error.Error() == target.Error()
}
+// Unwrap implements errors.Unwrap.
+func (e *Err) Unwrap() error {
+ return e.error
+}
+
// IsError returns whether the input element ref.Type or ref.Val is equal to
// the ErrType singleton.
func IsError(val ref.Val) bool {
diff --git a/vendor/github.com/google/cel-go/common/types/int.go b/vendor/github.com/google/cel-go/common/types/int.go
index 5f13956e7..940772aed 100644
--- a/vendor/github.com/google/cel-go/common/types/int.go
+++ b/vendor/github.com/google/cel-go/common/types/int.go
@@ -22,7 +22,6 @@ import (
"time"
"github.com/google/cel-go/common/types/ref"
- "github.com/google/cel-go/common/types/traits"
anypb "google.golang.org/protobuf/types/known/anypb"
structpb "google.golang.org/protobuf/types/known/structpb"
@@ -41,16 +40,6 @@ const (
)
var (
- // IntType singleton.
- IntType = NewTypeValue("int",
- traits.AdderType,
- traits.ComparerType,
- traits.DividerType,
- traits.ModderType,
- traits.MultiplierType,
- traits.NegatorType,
- traits.SubtractorType)
-
// int32WrapperType reflected type for protobuf int32 wrapper type.
int32WrapperType = reflect.TypeOf(&wrapperspb.Int32Value{})
@@ -66,7 +55,7 @@ func (i Int) Add(other ref.Val) ref.Val {
}
val, err := addInt64Checked(int64(i), int64(otherInt))
if err != nil {
- return wrapErr(err)
+ return WrapErr(err)
}
return Int(val)
}
@@ -176,7 +165,7 @@ func (i Int) ConvertToType(typeVal ref.Type) ref.Val {
case UintType:
u, err := int64ToUint64Checked(int64(i))
if err != nil {
- return wrapErr(err)
+ return WrapErr(err)
}
return Uint(u)
case DoubleType:
@@ -204,7 +193,7 @@ func (i Int) Divide(other ref.Val) ref.Val {
}
val, err := divideInt64Checked(int64(i), int64(otherInt))
if err != nil {
- return wrapErr(err)
+ return WrapErr(err)
}
return Int(val)
}
@@ -239,7 +228,7 @@ func (i Int) Modulo(other ref.Val) ref.Val {
}
val, err := moduloInt64Checked(int64(i), int64(otherInt))
if err != nil {
- return wrapErr(err)
+ return WrapErr(err)
}
return Int(val)
}
@@ -252,7 +241,7 @@ func (i Int) Multiply(other ref.Val) ref.Val {
}
val, err := multiplyInt64Checked(int64(i), int64(otherInt))
if err != nil {
- return wrapErr(err)
+ return WrapErr(err)
}
return Int(val)
}
@@ -261,7 +250,7 @@ func (i Int) Multiply(other ref.Val) ref.Val {
func (i Int) Negate() ref.Val {
val, err := negateInt64Checked(int64(i))
if err != nil {
- return wrapErr(err)
+ return WrapErr(err)
}
return Int(val)
}
@@ -274,7 +263,7 @@ func (i Int) Subtract(subtrahend ref.Val) ref.Val {
}
val, err := subtractInt64Checked(int64(i), int64(subtraInt))
if err != nil {
- return wrapErr(err)
+ return WrapErr(err)
}
return Int(val)
}
diff --git a/vendor/github.com/google/cel-go/common/types/iterator.go b/vendor/github.com/google/cel-go/common/types/iterator.go
index 9f224ad4f..98e9147b6 100644
--- a/vendor/github.com/google/cel-go/common/types/iterator.go
+++ b/vendor/github.com/google/cel-go/common/types/iterator.go
@@ -24,7 +24,7 @@ import (
var (
// IteratorType singleton.
- IteratorType = NewTypeValue("iterator", traits.IteratorType)
+ IteratorType = NewObjectType("iterator", traits.IteratorType)
)
// baseIterator is the basis for list, map, and object iterators.
diff --git a/vendor/github.com/google/cel-go/common/types/list.go b/vendor/github.com/google/cel-go/common/types/list.go
index de5f2099b..d4932b4a9 100644
--- a/vendor/github.com/google/cel-go/common/types/list.go
+++ b/vendor/github.com/google/cel-go/common/types/list.go
@@ -29,25 +29,15 @@ import (
structpb "google.golang.org/protobuf/types/known/structpb"
)
-var (
- // ListType singleton.
- ListType = NewTypeValue("list",
- traits.AdderType,
- traits.ContainerType,
- traits.IndexerType,
- traits.IterableType,
- traits.SizerType)
-)
-
// NewDynamicList returns a traits.Lister with heterogenous elements.
// value should be an array of "native" types, i.e. any type that
// NativeToValue() can convert to a ref.Val.
-func NewDynamicList(adapter ref.TypeAdapter, value any) traits.Lister {
+func NewDynamicList(adapter Adapter, value any) traits.Lister {
refValue := reflect.ValueOf(value)
return &baseList{
- TypeAdapter: adapter,
- value: value,
- size: refValue.Len(),
+ Adapter: adapter,
+ value: value,
+ size: refValue.Len(),
get: func(i int) any {
return refValue.Index(i).Interface()
},
@@ -55,56 +45,56 @@ func NewDynamicList(adapter ref.TypeAdapter, value any) traits.Lister {
}
// NewStringList returns a traits.Lister containing only strings.
-func NewStringList(adapter ref.TypeAdapter, elems []string) traits.Lister {
+func NewStringList(adapter Adapter, elems []string) traits.Lister {
return &baseList{
- TypeAdapter: adapter,
- value: elems,
- size: len(elems),
- get: func(i int) any { return elems[i] },
+ Adapter: adapter,
+ value: elems,
+ size: len(elems),
+ get: func(i int) any { return elems[i] },
}
}
// NewRefValList returns a traits.Lister with ref.Val elements.
//
// This type specialization is used with list literals within CEL expressions.
-func NewRefValList(adapter ref.TypeAdapter, elems []ref.Val) traits.Lister {
+func NewRefValList(adapter Adapter, elems []ref.Val) traits.Lister {
return &baseList{
- TypeAdapter: adapter,
- value: elems,
- size: len(elems),
- get: func(i int) any { return elems[i] },
+ Adapter: adapter,
+ value: elems,
+ size: len(elems),
+ get: func(i int) any { return elems[i] },
}
}
// NewProtoList returns a traits.Lister based on a pb.List instance.
-func NewProtoList(adapter ref.TypeAdapter, list protoreflect.List) traits.Lister {
+func NewProtoList(adapter Adapter, list protoreflect.List) traits.Lister {
return &baseList{
- TypeAdapter: adapter,
- value: list,
- size: list.Len(),
- get: func(i int) any { return list.Get(i).Interface() },
+ Adapter: adapter,
+ value: list,
+ size: list.Len(),
+ get: func(i int) any { return list.Get(i).Interface() },
}
}
// NewJSONList returns a traits.Lister based on structpb.ListValue instance.
-func NewJSONList(adapter ref.TypeAdapter, l *structpb.ListValue) traits.Lister {
+func NewJSONList(adapter Adapter, l *structpb.ListValue) traits.Lister {
vals := l.GetValues()
return &baseList{
- TypeAdapter: adapter,
- value: l,
- size: len(vals),
- get: func(i int) any { return vals[i] },
+ Adapter: adapter,
+ value: l,
+ size: len(vals),
+ get: func(i int) any { return vals[i] },
}
}
// NewMutableList creates a new mutable list whose internal state can be modified.
-func NewMutableList(adapter ref.TypeAdapter) traits.MutableLister {
+func NewMutableList(adapter Adapter) traits.MutableLister {
var mutableValues []ref.Val
l := &mutableList{
baseList: &baseList{
- TypeAdapter: adapter,
- value: mutableValues,
- size: 0,
+ Adapter: adapter,
+ value: mutableValues,
+ size: 0,
},
mutableValues: mutableValues,
}
@@ -116,9 +106,9 @@ func NewMutableList(adapter ref.TypeAdapter) traits.MutableLister {
// baseList points to a list containing elements of any type.
// The `value` is an array of native values, and refValue is its reflection object.
-// The `ref.TypeAdapter` enables native type to CEL type conversions.
+// The `Adapter` enables native type to CEL type conversions.
type baseList struct {
- ref.TypeAdapter
+ Adapter
value any
// size indicates the number of elements within the list.
@@ -143,9 +133,9 @@ func (l *baseList) Add(other ref.Val) ref.Val {
return l
}
return &concatList{
- TypeAdapter: l.TypeAdapter,
- prevList: l,
- nextList: otherList}
+ Adapter: l.Adapter,
+ prevList: l,
+ nextList: otherList}
}
// Contains implements the traits.Container interface method.
@@ -322,13 +312,13 @@ func (l *mutableList) Add(other ref.Val) ref.Val {
func (l *mutableList) ToImmutableList() traits.Lister {
// The reference to internal state is guaranteed to be safe as this call is only performed
// when mutations have been completed.
- return NewRefValList(l.TypeAdapter, l.mutableValues)
+ return NewRefValList(l.Adapter, l.mutableValues)
}
// concatList combines two list implementations together into a view.
-// The `ref.TypeAdapter` enables native type to CEL type conversions.
+// The `Adapter` enables native type to CEL type conversions.
type concatList struct {
- ref.TypeAdapter
+ Adapter
value any
prevList traits.Lister
nextList traits.Lister
@@ -347,9 +337,9 @@ func (l *concatList) Add(other ref.Val) ref.Val {
return l
}
return &concatList{
- TypeAdapter: l.TypeAdapter,
- prevList: l,
- nextList: otherList}
+ Adapter: l.Adapter,
+ prevList: l,
+ nextList: otherList}
}
// Contains implements the traits.Container interface method.
@@ -376,7 +366,7 @@ func (l *concatList) Contains(elem ref.Val) ref.Val {
// ConvertToNative implements the ref.Val interface method.
func (l *concatList) ConvertToNative(typeDesc reflect.Type) (any, error) {
- combined := NewDynamicList(l.TypeAdapter, l.Value().([]any))
+ combined := NewDynamicList(l.Adapter, l.Value().([]any))
return combined.ConvertToNative(typeDesc)
}
diff --git a/vendor/github.com/google/cel-go/common/types/map.go b/vendor/github.com/google/cel-go/common/types/map.go
index 213be4ac9..739b7aab0 100644
--- a/vendor/github.com/google/cel-go/common/types/map.go
+++ b/vendor/github.com/google/cel-go/common/types/map.go
@@ -32,10 +32,10 @@ import (
)
// NewDynamicMap returns a traits.Mapper value with dynamic key, value pairs.
-func NewDynamicMap(adapter ref.TypeAdapter, value any) traits.Mapper {
+func NewDynamicMap(adapter Adapter, value any) traits.Mapper {
refValue := reflect.ValueOf(value)
return &baseMap{
- TypeAdapter: adapter,
+ Adapter: adapter,
mapAccessor: newReflectMapAccessor(adapter, refValue),
value: value,
size: refValue.Len(),
@@ -46,10 +46,10 @@ func NewDynamicMap(adapter ref.TypeAdapter, value any) traits.Mapper {
// encoded in protocol buffer form.
//
// The `adapter` argument provides type adaptation capabilities from proto to CEL.
-func NewJSONStruct(adapter ref.TypeAdapter, value *structpb.Struct) traits.Mapper {
+func NewJSONStruct(adapter Adapter, value *structpb.Struct) traits.Mapper {
fields := value.GetFields()
return &baseMap{
- TypeAdapter: adapter,
+ Adapter: adapter,
mapAccessor: newJSONStructAccessor(adapter, fields),
value: value,
size: len(fields),
@@ -57,9 +57,9 @@ func NewJSONStruct(adapter ref.TypeAdapter, value *structpb.Struct) traits.Mappe
}
// NewRefValMap returns a specialized traits.Mapper with CEL valued keys and values.
-func NewRefValMap(adapter ref.TypeAdapter, value map[ref.Val]ref.Val) traits.Mapper {
+func NewRefValMap(adapter Adapter, value map[ref.Val]ref.Val) traits.Mapper {
return &baseMap{
- TypeAdapter: adapter,
+ Adapter: adapter,
mapAccessor: newRefValMapAccessor(value),
value: value,
size: len(value),
@@ -67,9 +67,9 @@ func NewRefValMap(adapter ref.TypeAdapter, value map[ref.Val]ref.Val) traits.Map
}
// NewStringInterfaceMap returns a specialized traits.Mapper with string keys and interface values.
-func NewStringInterfaceMap(adapter ref.TypeAdapter, value map[string]any) traits.Mapper {
+func NewStringInterfaceMap(adapter Adapter, value map[string]any) traits.Mapper {
return &baseMap{
- TypeAdapter: adapter,
+ Adapter: adapter,
mapAccessor: newStringIfaceMapAccessor(adapter, value),
value: value,
size: len(value),
@@ -77,9 +77,9 @@ func NewStringInterfaceMap(adapter ref.TypeAdapter, value map[string]any) traits
}
// NewStringStringMap returns a specialized traits.Mapper with string keys and values.
-func NewStringStringMap(adapter ref.TypeAdapter, value map[string]string) traits.Mapper {
+func NewStringStringMap(adapter Adapter, value map[string]string) traits.Mapper {
return &baseMap{
- TypeAdapter: adapter,
+ Adapter: adapter,
mapAccessor: newStringMapAccessor(value),
value: value,
size: len(value),
@@ -87,22 +87,13 @@ func NewStringStringMap(adapter ref.TypeAdapter, value map[string]string) traits
}
// NewProtoMap returns a specialized traits.Mapper for handling protobuf map values.
-func NewProtoMap(adapter ref.TypeAdapter, value *pb.Map) traits.Mapper {
+func NewProtoMap(adapter Adapter, value *pb.Map) traits.Mapper {
return &protoMap{
- TypeAdapter: adapter,
- value: value,
+ Adapter: adapter,
+ value: value,
}
}
-var (
- // MapType singleton.
- MapType = NewTypeValue("map",
- traits.ContainerType,
- traits.IndexerType,
- traits.IterableType,
- traits.SizerType)
-)
-
// mapAccessor is a private interface for finding values within a map and iterating over the keys.
// This interface implements portions of the API surface area required by the traits.Mapper
// interface.
@@ -121,7 +112,7 @@ type mapAccessor interface {
// Since CEL is side-effect free, the base map represents an immutable object.
type baseMap struct {
// TypeAdapter used to convert keys and values accessed within the map.
- ref.TypeAdapter
+ Adapter
// mapAccessor interface implementation used to find and iterate over map keys.
mapAccessor
@@ -316,15 +307,15 @@ func (m *baseMap) Value() any {
return m.value
}
-func newJSONStructAccessor(adapter ref.TypeAdapter, st map[string]*structpb.Value) mapAccessor {
+func newJSONStructAccessor(adapter Adapter, st map[string]*structpb.Value) mapAccessor {
return &jsonStructAccessor{
- TypeAdapter: adapter,
- st: st,
+ Adapter: adapter,
+ st: st,
}
}
type jsonStructAccessor struct {
- ref.TypeAdapter
+ Adapter
st map[string]*structpb.Value
}
@@ -359,17 +350,17 @@ func (a *jsonStructAccessor) Iterator() traits.Iterator {
}
}
-func newReflectMapAccessor(adapter ref.TypeAdapter, value reflect.Value) mapAccessor {
+func newReflectMapAccessor(adapter Adapter, value reflect.Value) mapAccessor {
keyType := value.Type().Key()
return &reflectMapAccessor{
- TypeAdapter: adapter,
- refValue: value,
- keyType: keyType,
+ Adapter: adapter,
+ refValue: value,
+ keyType: keyType,
}
}
type reflectMapAccessor struct {
- ref.TypeAdapter
+ Adapter
refValue reflect.Value
keyType reflect.Type
}
@@ -427,9 +418,9 @@ func (m *reflectMapAccessor) findInternal(key ref.Val) (ref.Val, bool) {
// Iterator creates a Golang reflection based traits.Iterator.
func (m *reflectMapAccessor) Iterator() traits.Iterator {
return &mapIterator{
- TypeAdapter: m.TypeAdapter,
- mapKeys: m.refValue.MapRange(),
- len: m.refValue.Len(),
+ Adapter: m.Adapter,
+ mapKeys: m.refValue.MapRange(),
+ len: m.refValue.Len(),
}
}
@@ -480,9 +471,9 @@ func (a *refValMapAccessor) Find(key ref.Val) (ref.Val, bool) {
// Iterator produces a new traits.Iterator which iterates over the map keys via Golang reflection.
func (a *refValMapAccessor) Iterator() traits.Iterator {
return &mapIterator{
- TypeAdapter: DefaultTypeAdapter,
- mapKeys: reflect.ValueOf(a.mapVal).MapRange(),
- len: len(a.mapVal),
+ Adapter: DefaultTypeAdapter,
+ mapKeys: reflect.ValueOf(a.mapVal).MapRange(),
+ len: len(a.mapVal),
}
}
@@ -524,15 +515,15 @@ func (a *stringMapAccessor) Iterator() traits.Iterator {
}
}
-func newStringIfaceMapAccessor(adapter ref.TypeAdapter, mapVal map[string]any) mapAccessor {
+func newStringIfaceMapAccessor(adapter Adapter, mapVal map[string]any) mapAccessor {
return &stringIfaceMapAccessor{
- TypeAdapter: adapter,
- mapVal: mapVal,
+ Adapter: adapter,
+ mapVal: mapVal,
}
}
type stringIfaceMapAccessor struct {
- ref.TypeAdapter
+ Adapter
mapVal map[string]any
}
@@ -569,7 +560,7 @@ func (a *stringIfaceMapAccessor) Iterator() traits.Iterator {
// protoMap is a specialized, separate implementation of the traits.Mapper interfaces tailored to
// accessing protoreflect.Map values.
type protoMap struct {
- ref.TypeAdapter
+ Adapter
value *pb.Map
}
@@ -772,9 +763,9 @@ func (m *protoMap) Iterator() traits.Iterator {
return true
})
return &protoMapIterator{
- TypeAdapter: m.TypeAdapter,
- mapKeys: mapKeys,
- len: m.value.Len(),
+ Adapter: m.Adapter,
+ mapKeys: mapKeys,
+ len: m.value.Len(),
}
}
@@ -795,7 +786,7 @@ func (m *protoMap) Value() any {
type mapIterator struct {
*baseIterator
- ref.TypeAdapter
+ Adapter
mapKeys *reflect.MapIter
cursor int
len int
@@ -818,7 +809,7 @@ func (it *mapIterator) Next() ref.Val {
type protoMapIterator struct {
*baseIterator
- ref.TypeAdapter
+ Adapter
mapKeys []protoreflect.MapKey
cursor int
len int
diff --git a/vendor/github.com/google/cel-go/common/types/null.go b/vendor/github.com/google/cel-go/common/types/null.go
index 38927a112..926ca3dc9 100644
--- a/vendor/github.com/google/cel-go/common/types/null.go
+++ b/vendor/github.com/google/cel-go/common/types/null.go
@@ -30,8 +30,6 @@ import (
type Null structpb.NullValue
var (
- // NullType singleton.
- NullType = NewTypeValue("null_type")
// NullValue singleton.
NullValue = Null(structpb.NullValue_NULL_VALUE)
diff --git a/vendor/github.com/google/cel-go/common/types/object.go b/vendor/github.com/google/cel-go/common/types/object.go
index 9955e2dce..8ba0af9fb 100644
--- a/vendor/github.com/google/cel-go/common/types/object.go
+++ b/vendor/github.com/google/cel-go/common/types/object.go
@@ -29,10 +29,10 @@ import (
)
type protoObj struct {
- ref.TypeAdapter
+ Adapter
value proto.Message
typeDesc *pb.TypeDescription
- typeValue *TypeValue
+ typeValue ref.Val
}
// NewObject returns an object based on a proto.Message value which handles
@@ -42,15 +42,15 @@ type protoObj struct {
// Note: the type value is pulled from the list of registered types within the
// type provider. If the proto type is not registered within the type provider,
// then this will result in an error within the type adapter / provider.
-func NewObject(adapter ref.TypeAdapter,
+func NewObject(adapter Adapter,
typeDesc *pb.TypeDescription,
- typeValue *TypeValue,
+ typeValue ref.Val,
value proto.Message) ref.Val {
return &protoObj{
- TypeAdapter: adapter,
- value: value,
- typeDesc: typeDesc,
- typeValue: typeValue}
+ Adapter: adapter,
+ value: value,
+ typeDesc: typeDesc,
+ typeValue: typeValue}
}
func (o *protoObj) ConvertToNative(typeDesc reflect.Type) (any, error) {
@@ -157,7 +157,7 @@ func (o *protoObj) Get(index ref.Val) ref.Val {
}
func (o *protoObj) Type() ref.Type {
- return o.typeValue
+ return o.typeValue.(ref.Type)
}
func (o *protoObj) Value() any {
diff --git a/vendor/github.com/google/cel-go/common/types/optional.go b/vendor/github.com/google/cel-go/common/types/optional.go
index 54cb35b1a..a9f30aed0 100644
--- a/vendor/github.com/google/cel-go/common/types/optional.go
+++ b/vendor/github.com/google/cel-go/common/types/optional.go
@@ -24,7 +24,7 @@ import (
var (
// OptionalType indicates the runtime type of an optional value.
- OptionalType = NewTypeValue("optional")
+ OptionalType = NewOpaqueType("optional")
// OptionalNone is a sentinel value which is used to indicate an empty optional value.
OptionalNone = &Optional{}
diff --git a/vendor/github.com/google/cel-go/common/types/pb/BUILD.bazel b/vendor/github.com/google/cel-go/common/types/pb/BUILD.bazel
index f23ac9c0e..e2b9d37b5 100644
--- a/vendor/github.com/google/cel-go/common/types/pb/BUILD.bazel
+++ b/vendor/github.com/google/cel-go/common/types/pb/BUILD.bazel
@@ -17,7 +17,7 @@ go_library(
],
importpath = "github.com/google/cel-go/common/types/pb",
deps = [
- "@org_golang_google_genproto//googleapis/api/expr/v1alpha1:go_default_library",
+ "@org_golang_google_genproto_googleapis_api//expr/v1alpha1:go_default_library",
"@org_golang_google_protobuf//encoding/protowire:go_default_library",
"@org_golang_google_protobuf//proto:go_default_library",
"@org_golang_google_protobuf//reflect/protoreflect:go_default_library",
diff --git a/vendor/github.com/google/cel-go/common/types/pb/type.go b/vendor/github.com/google/cel-go/common/types/pb/type.go
index df9532156..6cc95c276 100644
--- a/vendor/github.com/google/cel-go/common/types/pb/type.go
+++ b/vendor/github.com/google/cel-go/common/types/pb/type.go
@@ -285,7 +285,7 @@ func (fd *FieldDescription) GetFrom(target any) (any, error) {
// IsEnum returns true if the field type refers to an enum value.
func (fd *FieldDescription) IsEnum() bool {
- return fd.desc.Kind() == protoreflect.EnumKind
+ return fd.ProtoKind() == protoreflect.EnumKind
}
// IsMap returns true if the field is of map type.
@@ -295,7 +295,7 @@ func (fd *FieldDescription) IsMap() bool {
// IsMessage returns true if the field is of message type.
func (fd *FieldDescription) IsMessage() bool {
- kind := fd.desc.Kind()
+ kind := fd.ProtoKind()
return kind == protoreflect.MessageKind || kind == protoreflect.GroupKind
}
@@ -326,6 +326,11 @@ func (fd *FieldDescription) Name() string {
return string(fd.desc.Name())
}
+// ProtoKind returns the protobuf reflected kind of the field.
+func (fd *FieldDescription) ProtoKind() protoreflect.Kind {
+ return fd.desc.Kind()
+}
+
// ReflectType returns the Golang reflect.Type for this field.
func (fd *FieldDescription) ReflectType() reflect.Type {
return fd.reflectType
@@ -345,17 +350,17 @@ func (fd *FieldDescription) Zero() proto.Message {
}
func (fd *FieldDescription) typeDefToType() *exprpb.Type {
- if fd.desc.Kind() == protoreflect.MessageKind || fd.desc.Kind() == protoreflect.GroupKind {
+ if fd.IsMessage() {
msgType := string(fd.desc.Message().FullName())
if wk, found := CheckedWellKnowns[msgType]; found {
return wk
}
return checkedMessageType(msgType)
}
- if fd.desc.Kind() == protoreflect.EnumKind {
+ if fd.IsEnum() {
return checkedInt
}
- return CheckedPrimitives[fd.desc.Kind()]
+ return CheckedPrimitives[fd.ProtoKind()]
}
// Map wraps the protoreflect.Map object with a key and value FieldDescription for use in
@@ -463,13 +468,13 @@ func unwrapDynamic(desc description, refMsg protoreflect.Message) (any, bool, er
unwrappedAny := &anypb.Any{}
err := Merge(unwrappedAny, msg)
if err != nil {
- return nil, false, err
+ return nil, false, fmt.Errorf("unwrap dynamic field failed: %v", err)
}
dynMsg, err := unwrappedAny.UnmarshalNew()
if err != nil {
// Allow the error to move further up the stack as it should result in an type
// conversion error if the caller does not recover it somehow.
- return nil, false, err
+ return nil, false, fmt.Errorf("unmarshal dynamic any failed: %v", err)
}
// Attempt to unwrap the dynamic type, otherwise return the dynamic message.
unwrapped, nested, err := unwrapDynamic(desc, dynMsg.ProtoReflect())
@@ -560,8 +565,10 @@ func zeroValueOf(msg proto.Message) proto.Message {
}
var (
+ jsonValueTypeURL = "types.googleapis.com/google.protobuf.Value"
+
zeroValueMap = map[string]proto.Message{
- "google.protobuf.Any": &anypb.Any{},
+ "google.protobuf.Any": &anypb.Any{TypeUrl: jsonValueTypeURL},
"google.protobuf.Duration": &dpb.Duration{},
"google.protobuf.ListValue": &structpb.ListValue{},
"google.protobuf.Struct": &structpb.Struct{},
diff --git a/vendor/github.com/google/cel-go/common/types/provider.go b/vendor/github.com/google/cel-go/common/types/provider.go
index e66951f5b..e80b4622e 100644
--- a/vendor/github.com/google/cel-go/common/types/provider.go
+++ b/vendor/github.com/google/cel-go/common/types/provider.go
@@ -33,17 +33,64 @@ import (
tpb "google.golang.org/protobuf/types/known/timestamppb"
)
-type protoTypeRegistry struct {
- revTypeMap map[string]ref.Type
+// Adapter converts native Go values of varying type and complexity to equivalent CEL values.
+type Adapter = ref.TypeAdapter
+
+// Provider specifies functions for creating new object instances and for resolving
+// enum values by name.
+type Provider interface {
+ // EnumValue returns the numeric value of the given enum value name.
+ EnumValue(enumName string) ref.Val
+
+ // FindIdent takes a qualified identifier name and returns a ref.Val if one exists.
+ FindIdent(identName string) (ref.Val, bool)
+
+ // FindStructType returns the Type give a qualified type name.
+ //
+ // For historical reasons, only struct types are expected to be returned through this
+ // method, and the type values are expected to be wrapped in a TypeType instance using
+ // TypeTypeWithParam().
+ //
+ // Returns false if not found.
+ FindStructType(structType string) (*Type, bool)
+
+ // FieldStructFieldType returns the field type for a checked type value. Returns
+ // false if the field could not be found.
+ FindStructFieldType(structType, fieldName string) (*FieldType, bool)
+
+ // NewValue creates a new type value from a qualified name and map of field
+ // name to value.
+ //
+ // Note, for each value, the Val.ConvertToNative function will be invoked
+ // to convert the Val to the field's native type. If an error occurs during
+ // conversion, the NewValue will be a types.Err.
+ NewValue(structType string, fields map[string]ref.Val) ref.Val
+}
+
+// FieldType represents a field's type value and whether that field supports presence detection.
+type FieldType struct {
+ // Type of the field as a CEL native type value.
+ Type *Type
+
+ // IsSet indicates whether the field is set on an input object.
+ IsSet ref.FieldTester
+
+ // GetFrom retrieves the field value on the input object, if set.
+ GetFrom ref.FieldGetter
+}
+
+// Registry provides type information for a set of registered types.
+type Registry struct {
+ revTypeMap map[string]*Type
pbdb *pb.Db
}
// NewRegistry accepts a list of proto message instances and returns a type
// provider which can create new instances of the provided message or any
// message that proto depends upon in its FileDescriptor.
-func NewRegistry(types ...proto.Message) (ref.TypeRegistry, error) {
- p := &protoTypeRegistry{
- revTypeMap: make(map[string]ref.Type),
+func NewRegistry(types ...proto.Message) (*Registry, error) {
+ p := &Registry{
+ revTypeMap: make(map[string]*Type),
pbdb: pb.NewDb(),
}
err := p.RegisterType(
@@ -79,18 +126,17 @@ func NewRegistry(types ...proto.Message) (ref.TypeRegistry, error) {
}
// NewEmptyRegistry returns a registry which is completely unconfigured.
-func NewEmptyRegistry() ref.TypeRegistry {
- return &protoTypeRegistry{
- revTypeMap: make(map[string]ref.Type),
+func NewEmptyRegistry() *Registry {
+ return &Registry{
+ revTypeMap: make(map[string]*Type),
pbdb: pb.NewDb(),
}
}
-// Copy implements the ref.TypeRegistry interface method which copies the current state of the
-// registry into its own memory space.
-func (p *protoTypeRegistry) Copy() ref.TypeRegistry {
- copy := &protoTypeRegistry{
- revTypeMap: make(map[string]ref.Type),
+// Copy copies the current state of the registry into its own memory space.
+func (p *Registry) Copy() *Registry {
+ copy := &Registry{
+ revTypeMap: make(map[string]*Type),
pbdb: p.pbdb.Copy(),
}
for k, v := range p.revTypeMap {
@@ -99,7 +145,8 @@ func (p *protoTypeRegistry) Copy() ref.TypeRegistry {
return copy
}
-func (p *protoTypeRegistry) EnumValue(enumName string) ref.Val {
+// EnumValue returns the numeric value of the given enum value name.
+func (p *Registry) EnumValue(enumName string) ref.Val {
enumVal, found := p.pbdb.DescribeEnum(enumName)
if !found {
return NewErr("unknown enum name '%s'", enumName)
@@ -107,9 +154,12 @@ func (p *protoTypeRegistry) EnumValue(enumName string) ref.Val {
return Int(enumVal.Value())
}
-func (p *protoTypeRegistry) FindFieldType(messageType string,
- fieldName string) (*ref.FieldType, bool) {
- msgType, found := p.pbdb.DescribeType(messageType)
+// FieldFieldType returns the field type for a checked type value. Returns false if
+// the field could not be found.
+//
+// Deprecated: use FindStructFieldType
+func (p *Registry) FindFieldType(structType, fieldName string) (*ref.FieldType, bool) {
+ msgType, found := p.pbdb.DescribeType(structType)
if !found {
return nil, false
}
@@ -118,15 +168,32 @@ func (p *protoTypeRegistry) FindFieldType(messageType string,
return nil, false
}
return &ref.FieldType{
- Type: field.CheckedType(),
- IsSet: field.IsSet,
- GetFrom: field.GetFrom},
- true
+ Type: field.CheckedType(),
+ IsSet: field.IsSet,
+ GetFrom: field.GetFrom}, true
+}
+
+// FieldStructFieldType returns the field type for a checked type value. Returns
+// false if the field could not be found.
+func (p *Registry) FindStructFieldType(structType, fieldName string) (*FieldType, bool) {
+ msgType, found := p.pbdb.DescribeType(structType)
+ if !found {
+ return nil, false
+ }
+ field, found := msgType.FieldByName(fieldName)
+ if !found {
+ return nil, false
+ }
+ return &FieldType{
+ Type: fieldDescToCELType(field),
+ IsSet: field.IsSet,
+ GetFrom: field.GetFrom}, true
}
-func (p *protoTypeRegistry) FindIdent(identName string) (ref.Val, bool) {
+// FindIdent takes a qualified identifier name and returns a ref.Val if one exists.
+func (p *Registry) FindIdent(identName string) (ref.Val, bool) {
if t, found := p.revTypeMap[identName]; found {
- return t.(ref.Val), true
+ return t, true
}
if enumVal, found := p.pbdb.DescribeEnum(identName); found {
return Int(enumVal.Value()), true
@@ -134,24 +201,50 @@ func (p *protoTypeRegistry) FindIdent(identName string) (ref.Val, bool) {
return nil, false
}
-func (p *protoTypeRegistry) FindType(typeName string) (*exprpb.Type, bool) {
- if _, found := p.pbdb.DescribeType(typeName); !found {
+// FindType looks up the Type given a qualified typeName. Returns false if not found.
+//
+// Deprecated: use FindStructType
+func (p *Registry) FindType(structType string) (*exprpb.Type, bool) {
+ if _, found := p.pbdb.DescribeType(structType); !found {
return nil, false
}
- if typeName != "" && typeName[0] == '.' {
- typeName = typeName[1:]
+ if structType != "" && structType[0] == '.' {
+ structType = structType[1:]
}
return &exprpb.Type{
TypeKind: &exprpb.Type_Type{
Type: &exprpb.Type{
TypeKind: &exprpb.Type_MessageType{
- MessageType: typeName}}}}, true
+ MessageType: structType}}}}, true
+}
+
+// FindStructType returns the Type give a qualified type name.
+//
+// For historical reasons, only struct types are expected to be returned through this
+// method, and the type values are expected to be wrapped in a TypeType instance using
+// TypeTypeWithParam().
+//
+// Returns false if not found.
+func (p *Registry) FindStructType(structType string) (*Type, bool) {
+ if _, found := p.pbdb.DescribeType(structType); !found {
+ return nil, false
+ }
+ if structType != "" && structType[0] == '.' {
+ structType = structType[1:]
+ }
+ return NewTypeTypeWithParam(NewObjectType(structType)), true
}
-func (p *protoTypeRegistry) NewValue(typeName string, fields map[string]ref.Val) ref.Val {
- td, found := p.pbdb.DescribeType(typeName)
+// NewValue creates a new type value from a qualified name and map of field
+// name to value.
+//
+// Note, for each value, the Val.ConvertToNative function will be invoked
+// to convert the Val to the field's native type. If an error occurs during
+// conversion, the NewValue will be a types.Err.
+func (p *Registry) NewValue(structType string, fields map[string]ref.Val) ref.Val {
+ td, found := p.pbdb.DescribeType(structType)
if !found {
- return NewErr("unknown type '%s'", typeName)
+ return NewErr("unknown type '%s'", structType)
}
msg := td.New()
fieldMap := td.FieldMap()
@@ -168,7 +261,8 @@ func (p *protoTypeRegistry) NewValue(typeName string, fields map[string]ref.Val)
return p.NativeToValue(msg.Interface())
}
-func (p *protoTypeRegistry) RegisterDescriptor(fileDesc protoreflect.FileDescriptor) error {
+// RegisterDescriptor registers the contents of a protocol buffer `FileDescriptor`.
+func (p *Registry) RegisterDescriptor(fileDesc protoreflect.FileDescriptor) error {
fd, err := p.pbdb.RegisterDescriptor(fileDesc)
if err != nil {
return err
@@ -176,7 +270,8 @@ func (p *protoTypeRegistry) RegisterDescriptor(fileDesc protoreflect.FileDescrip
return p.registerAllTypes(fd)
}
-func (p *protoTypeRegistry) RegisterMessage(message proto.Message) error {
+// RegisterMessage registers a protocol buffer message and its dependencies.
+func (p *Registry) RegisterMessage(message proto.Message) error {
fd, err := p.pbdb.RegisterMessage(message)
if err != nil {
return err
@@ -184,11 +279,32 @@ func (p *protoTypeRegistry) RegisterMessage(message proto.Message) error {
return p.registerAllTypes(fd)
}
-func (p *protoTypeRegistry) RegisterType(types ...ref.Type) error {
+// RegisterType registers a type value with the provider which ensures the provider is aware of how to
+// map the type to an identifier.
+//
+// If the `ref.Type` value is a `*types.Type` it will be registered directly by its runtime type name.
+// If the `ref.Type` value is not a `*types.Type` instance, a `*types.Type` instance which reflects the
+// traits present on the input and the runtime type name. By default this foreign type will be treated
+// as a types.StructKind. To avoid potential issues where the `ref.Type` values does not match the
+// generated `*types.Type` instance, consider always using the `*types.Type` to represent type extensions
+// to CEL, even when they're not based on protobuf types.
+func (p *Registry) RegisterType(types ...ref.Type) error {
for _, t := range types {
- p.revTypeMap[t.TypeName()] = t
+ celType := maybeForeignType(t)
+ existing, found := p.revTypeMap[t.TypeName()]
+ if !found {
+ p.revTypeMap[t.TypeName()] = celType
+ continue
+ }
+ if !existing.IsEquivalentType(celType) {
+ return fmt.Errorf("type registration conflict. found: %v, input: %v", existing, celType)
+ }
+ if existing.traitMask != celType.traitMask {
+ return fmt.Errorf(
+ "type registered with conflicting traits: %v with traits %v, input: %v",
+ existing.TypeName(), existing.traitMask, celType.traitMask)
+ }
}
- // TODO: generate an error when the type name is registered more than once.
return nil
}
@@ -196,7 +312,7 @@ func (p *protoTypeRegistry) RegisterType(types ...ref.Type) error {
// providing support for custom proto-based types.
//
// This method should be the inverse of ref.Val.ConvertToNative.
-func (p *protoTypeRegistry) NativeToValue(value any) ref.Val {
+func (p *Registry) NativeToValue(value any) ref.Val {
if val, found := nativeToValue(p, value); found {
return val
}
@@ -218,7 +334,7 @@ func (p *protoTypeRegistry) NativeToValue(value any) ref.Val {
if !found {
return NewErr("unknown type: '%s'", typeName)
}
- return NewObject(p, td, typeVal.(*TypeValue), v)
+ return NewObject(p, td, typeVal, v)
case *pb.Map:
return NewProtoMap(p, v)
case protoreflect.List:
@@ -231,8 +347,13 @@ func (p *protoTypeRegistry) NativeToValue(value any) ref.Val {
return UnsupportedRefValConversionErr(value)
}
-func (p *protoTypeRegistry) registerAllTypes(fd *pb.FileDescription) error {
+func (p *Registry) registerAllTypes(fd *pb.FileDescription) error {
for _, typeName := range fd.GetTypeNames() {
+ // skip well-known type names since they're automatically sanitized
+ // during NewObjectType() calls.
+ if _, found := checkedWellKnowns[typeName]; found {
+ continue
+ }
err := p.RegisterType(NewObjectTypeValue(typeName))
if err != nil {
return err
@@ -241,6 +362,28 @@ func (p *protoTypeRegistry) registerAllTypes(fd *pb.FileDescription) error {
return nil
}
+func fieldDescToCELType(field *pb.FieldDescription) *Type {
+ if field.IsMap() {
+ return NewMapType(
+ singularFieldDescToCELType(field.KeyType),
+ singularFieldDescToCELType(field.ValueType))
+ }
+ if field.IsList() {
+ return NewListType(singularFieldDescToCELType(field))
+ }
+ return singularFieldDescToCELType(field)
+}
+
+func singularFieldDescToCELType(field *pb.FieldDescription) *Type {
+ if field.IsMessage() {
+ return NewObjectType(string(field.Descriptor().Message().FullName()))
+ }
+ if field.IsEnum() {
+ return IntType
+ }
+ return ProtoCELPrimitives[field.ProtoKind()]
+}
+
// defaultTypeAdapter converts go native types to CEL values.
type defaultTypeAdapter struct{}
@@ -259,7 +402,7 @@ func (a *defaultTypeAdapter) NativeToValue(value any) ref.Val {
// nativeToValue returns the converted (ref.Val, true) of a conversion is found,
// otherwise (nil, false)
-func nativeToValue(a ref.TypeAdapter, value any) (ref.Val, bool) {
+func nativeToValue(a Adapter, value any) (ref.Val, bool) {
switch v := value.(type) {
case nil:
return NullValue, true
@@ -547,3 +690,24 @@ func fieldTypeConversionError(field *pb.FieldDescription, err error) error {
msgName := field.Descriptor().ContainingMessage().FullName()
return fmt.Errorf("field type conversion error for %v.%v value type: %v", msgName, field.Name(), err)
}
+
+var (
+ // ProtoCELPrimitives provides a map from the protoreflect Kind to the equivalent CEL type.
+ ProtoCELPrimitives = map[protoreflect.Kind]*Type{
+ protoreflect.BoolKind: BoolType,
+ protoreflect.BytesKind: BytesType,
+ protoreflect.DoubleKind: DoubleType,
+ protoreflect.FloatKind: DoubleType,
+ protoreflect.Int32Kind: IntType,
+ protoreflect.Int64Kind: IntType,
+ protoreflect.Sint32Kind: IntType,
+ protoreflect.Sint64Kind: IntType,
+ protoreflect.Uint32Kind: UintType,
+ protoreflect.Uint64Kind: UintType,
+ protoreflect.Fixed32Kind: UintType,
+ protoreflect.Fixed64Kind: UintType,
+ protoreflect.Sfixed32Kind: IntType,
+ protoreflect.Sfixed64Kind: IntType,
+ protoreflect.StringKind: StringType,
+ }
+)
diff --git a/vendor/github.com/google/cel-go/common/types/ref/BUILD.bazel b/vendor/github.com/google/cel-go/common/types/ref/BUILD.bazel
index 1d0f46899..79330c332 100644
--- a/vendor/github.com/google/cel-go/common/types/ref/BUILD.bazel
+++ b/vendor/github.com/google/cel-go/common/types/ref/BUILD.bazel
@@ -13,7 +13,7 @@ go_library(
],
importpath = "github.com/google/cel-go/common/types/ref",
deps = [
- "@org_golang_google_genproto//googleapis/api/expr/v1alpha1:go_default_library",
+ "@org_golang_google_genproto_googleapis_api//expr/v1alpha1:go_default_library",
"@org_golang_google_protobuf//proto:go_default_library",
"@org_golang_google_protobuf//reflect/protoreflect:go_default_library",
],
diff --git a/vendor/github.com/google/cel-go/common/types/ref/provider.go b/vendor/github.com/google/cel-go/common/types/ref/provider.go
index 7eabbb9ca..b9820023d 100644
--- a/vendor/github.com/google/cel-go/common/types/ref/provider.go
+++ b/vendor/github.com/google/cel-go/common/types/ref/provider.go
@@ -23,34 +23,34 @@ import (
// TypeProvider specifies functions for creating new object instances and for
// resolving enum values by name.
+//
+// Deprecated: use types.Provider
type TypeProvider interface {
// EnumValue returns the numeric value of the given enum value name.
EnumValue(enumName string) Val
- // FindIdent takes a qualified identifier name and returns a Value if one
- // exists.
+ // FindIdent takes a qualified identifier name and returns a Value if one exists.
FindIdent(identName string) (Val, bool)
- // FindType looks up the Type given a qualified typeName. Returns false
- // if not found.
- //
- // Used during type-checking only.
+ // FindType looks up the Type given a qualified typeName. Returns false if not found.
FindType(typeName string) (*exprpb.Type, bool)
- // FieldFieldType returns the field type for a checked type value. Returns
- // false if the field could not be found.
- FindFieldType(messageType string, fieldName string) (*FieldType, bool)
+ // FieldFieldType returns the field type for a checked type value. Returns false if
+ // the field could not be found.
+ FindFieldType(messageType, fieldName string) (*FieldType, bool)
- // NewValue creates a new type value from a qualified name and map of field
- // name to value.
+ // NewValue creates a new type value from a qualified name and map of field name
+ // to value.
//
- // Note, for each value, the Val.ConvertToNative function will be invoked
- // to convert the Val to the field's native type. If an error occurs during
- // conversion, the NewValue will be a types.Err.
+ // Note, for each value, the Val.ConvertToNative function will be invoked to convert
+ // the Val to the field's native type. If an error occurs during conversion, the
+ // NewValue will be a types.Err.
NewValue(typeName string, fields map[string]Val) Val
}
// TypeAdapter converts native Go values of varying type and complexity to equivalent CEL values.
+//
+// Deprecated: use types.Adapter
type TypeAdapter interface {
// NativeToValue converts the input `value` to a CEL `ref.Val`.
NativeToValue(value any) Val
@@ -60,6 +60,8 @@ type TypeAdapter interface {
// implementations support type-customization, so these features are optional. However, a
// `TypeRegistry` should be a `TypeProvider` and a `TypeAdapter` to ensure that types
// which are registered can be converted to CEL representations.
+//
+// Deprecated: use types.Registry
type TypeRegistry interface {
TypeAdapter
TypeProvider
@@ -76,15 +78,14 @@ type TypeRegistry interface {
// If a type is provided more than once with an alternative definition, the
// call will result in an error.
RegisterType(types ...Type) error
-
- // Copy the TypeRegistry and return a new registry whose mutable state is isolated.
- Copy() TypeRegistry
}
// FieldType represents a field's type value and whether that field supports
// presence detection.
+//
+// Deprecated: use types.FieldType
type FieldType struct {
- // Type of the field.
+ // Type of the field as a protobuf type value.
Type *exprpb.Type
// IsSet indicates whether the field is set on an input object.
diff --git a/vendor/github.com/google/cel-go/common/types/ref/reference.go b/vendor/github.com/google/cel-go/common/types/ref/reference.go
index 5921ffd81..e0d58145c 100644
--- a/vendor/github.com/google/cel-go/common/types/ref/reference.go
+++ b/vendor/github.com/google/cel-go/common/types/ref/reference.go
@@ -37,9 +37,18 @@ type Type interface {
type Val interface {
// ConvertToNative converts the Value to a native Go struct according to the
// reflected type description, or error if the conversion is not feasible.
+ //
+ // The ConvertToNative method is intended to be used to support conversion between CEL types
+ // and native types during object creation expressions or by clients who need to adapt the,
+ // returned CEL value into an equivalent Go value instance.
+ //
+ // When implementing or using ConvertToNative, the following guidelines apply:
+ // - Use ConvertToNative when marshalling CEL evaluation results to native types.
+ // - Do not use ConvertToNative within CEL extension functions.
+ // - Document whether your implementation supports non-CEL field types, such as Go or Protobuf.
ConvertToNative(typeDesc reflect.Type) (any, error)
- // ConvertToType supports type conversions between value types supported by the expression language.
+ // ConvertToType supports type conversions between CEL value types supported by the expression language.
ConvertToType(typeValue Type) Val
// Equal returns true if the `other` value has the same type and content as the implementing struct.
diff --git a/vendor/github.com/google/cel-go/common/types/string.go b/vendor/github.com/google/cel-go/common/types/string.go
index a65cc14e4..028e6824d 100644
--- a/vendor/github.com/google/cel-go/common/types/string.go
+++ b/vendor/github.com/google/cel-go/common/types/string.go
@@ -24,7 +24,6 @@ import (
"github.com/google/cel-go/common/overloads"
"github.com/google/cel-go/common/types/ref"
- "github.com/google/cel-go/common/types/traits"
anypb "google.golang.org/protobuf/types/known/anypb"
structpb "google.golang.org/protobuf/types/known/structpb"
@@ -36,18 +35,10 @@ import (
type String string
var (
- // StringType singleton.
- StringType = NewTypeValue("string",
- traits.AdderType,
- traits.ComparerType,
- traits.MatcherType,
- traits.ReceiverType,
- traits.SizerType)
-
- stringOneArgOverloads = map[string]func(String, ref.Val) ref.Val{
- overloads.Contains: stringContains,
- overloads.EndsWith: stringEndsWith,
- overloads.StartsWith: stringStartsWith,
+ stringOneArgOverloads = map[string]func(ref.Val, ref.Val) ref.Val{
+ overloads.Contains: StringContains,
+ overloads.EndsWith: StringEndsWith,
+ overloads.StartsWith: StringStartsWith,
}
stringWrapperType = reflect.TypeOf(&wrapperspb.StringValue{})
@@ -198,26 +189,41 @@ func (s String) Value() any {
return string(s)
}
-func stringContains(s String, sub ref.Val) ref.Val {
+// StringContains returns whether the string contains a substring.
+func StringContains(s, sub ref.Val) ref.Val {
+ str, ok := s.(String)
+ if !ok {
+ return MaybeNoSuchOverloadErr(s)
+ }
subStr, ok := sub.(String)
if !ok {
return MaybeNoSuchOverloadErr(sub)
}
- return Bool(strings.Contains(string(s), string(subStr)))
+ return Bool(strings.Contains(string(str), string(subStr)))
}
-func stringEndsWith(s String, suf ref.Val) ref.Val {
+// StringEndsWith returns whether the target string contains the input suffix.
+func StringEndsWith(s, suf ref.Val) ref.Val {
+ str, ok := s.(String)
+ if !ok {
+ return MaybeNoSuchOverloadErr(s)
+ }
sufStr, ok := suf.(String)
if !ok {
return MaybeNoSuchOverloadErr(suf)
}
- return Bool(strings.HasSuffix(string(s), string(sufStr)))
+ return Bool(strings.HasSuffix(string(str), string(sufStr)))
}
-func stringStartsWith(s String, pre ref.Val) ref.Val {
+// StringStartsWith returns whether the target string contains the input prefix.
+func StringStartsWith(s, pre ref.Val) ref.Val {
+ str, ok := s.(String)
+ if !ok {
+ return MaybeNoSuchOverloadErr(s)
+ }
preStr, ok := pre.(String)
if !ok {
return MaybeNoSuchOverloadErr(pre)
}
- return Bool(strings.HasPrefix(string(s), string(preStr)))
+ return Bool(strings.HasPrefix(string(str), string(preStr)))
}
diff --git a/vendor/github.com/google/cel-go/common/types/timestamp.go b/vendor/github.com/google/cel-go/common/types/timestamp.go
index 2947cecf5..33acdea8e 100644
--- a/vendor/github.com/google/cel-go/common/types/timestamp.go
+++ b/vendor/github.com/google/cel-go/common/types/timestamp.go
@@ -23,7 +23,6 @@ import (
"github.com/google/cel-go/common/overloads"
"github.com/google/cel-go/common/types/ref"
- "github.com/google/cel-go/common/types/traits"
anypb "google.golang.org/protobuf/types/known/anypb"
structpb "google.golang.org/protobuf/types/known/structpb"
@@ -53,15 +52,6 @@ const (
maxUnixTime int64 = 253402300799
)
-var (
- // TimestampType singleton.
- TimestampType = NewTypeValue("google.protobuf.Timestamp",
- traits.AdderType,
- traits.ComparerType,
- traits.ReceiverType,
- traits.SubtractorType)
-)
-
// Add implements traits.Adder.Add.
func (t Timestamp) Add(other ref.Val) ref.Val {
switch other.Type() {
@@ -165,14 +155,14 @@ func (t Timestamp) Subtract(subtrahend ref.Val) ref.Val {
dur := subtrahend.(Duration)
val, err := subtractTimeDurationChecked(t.Time, dur.Duration)
if err != nil {
- return wrapErr(err)
+ return WrapErr(err)
}
return timestampOf(val)
case TimestampType:
t2 := subtrahend.(Timestamp).Time
val, err := subtractTimeChecked(t.Time, t2)
if err != nil {
- return wrapErr(err)
+ return WrapErr(err)
}
return durationOf(val)
}
@@ -293,7 +283,7 @@ func timeZone(tz ref.Val, visitor timestampVisitor) timestampVisitor {
if ind == -1 {
loc, err := time.LoadLocation(val)
if err != nil {
- return wrapErr(err)
+ return WrapErr(err)
}
return visitor(t.In(loc))
}
@@ -302,11 +292,11 @@ func timeZone(tz ref.Val, visitor timestampVisitor) timestampVisitor {
// in the format ^(+|-)(0[0-9]|1[0-4]):[0-5][0-9]$. The numerical input is parsed in terms of hours and minutes.
hr, err := strconv.Atoi(string(val[0:ind]))
if err != nil {
- return wrapErr(err)
+ return WrapErr(err)
}
min, err := strconv.Atoi(string(val[ind+1:]))
if err != nil {
- return wrapErr(err)
+ return WrapErr(err)
}
var offset int
if string(val[0]) == "-" {
diff --git a/vendor/github.com/google/cel-go/common/types/type.go b/vendor/github.com/google/cel-go/common/types/type.go
deleted file mode 100644
index 164a46050..000000000
--- a/vendor/github.com/google/cel-go/common/types/type.go
+++ /dev/null
@@ -1,102 +0,0 @@
-// Copyright 2018 Google LLC
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package types
-
-import (
- "fmt"
- "reflect"
-
- "github.com/google/cel-go/common/types/ref"
- "github.com/google/cel-go/common/types/traits"
-)
-
-var (
- // TypeType is the type of a TypeValue.
- TypeType = NewTypeValue("type")
-)
-
-// TypeValue is an instance of a Value that describes a value's type.
-type TypeValue struct {
- name string
- traitMask int
-}
-
-// NewTypeValue returns *TypeValue which is both a ref.Type and ref.Val.
-func NewTypeValue(name string, traits ...int) *TypeValue {
- traitMask := 0
- for _, trait := range traits {
- traitMask |= trait
- }
- return &TypeValue{
- name: name,
- traitMask: traitMask}
-}
-
-// NewObjectTypeValue returns a *TypeValue based on the input name, which is
-// annotated with the traits relevant to all objects.
-func NewObjectTypeValue(name string) *TypeValue {
- return NewTypeValue(name,
- traits.FieldTesterType,
- traits.IndexerType)
-}
-
-// ConvertToNative implements ref.Val.ConvertToNative.
-func (t *TypeValue) ConvertToNative(typeDesc reflect.Type) (any, error) {
- // TODO: replace the internal type representation with a proto-value.
- return nil, fmt.Errorf("type conversion not supported for 'type'")
-}
-
-// ConvertToType implements ref.Val.ConvertToType.
-func (t *TypeValue) ConvertToType(typeVal ref.Type) ref.Val {
- switch typeVal {
- case TypeType:
- return TypeType
- case StringType:
- return String(t.TypeName())
- }
- return NewErr("type conversion error from '%s' to '%s'", TypeType, typeVal)
-}
-
-// Equal implements ref.Val.Equal.
-func (t *TypeValue) Equal(other ref.Val) ref.Val {
- otherType, ok := other.(ref.Type)
- return Bool(ok && t.TypeName() == otherType.TypeName())
-}
-
-// HasTrait indicates whether the type supports the given trait.
-// Trait codes are defined in the traits package, e.g. see traits.AdderType.
-func (t *TypeValue) HasTrait(trait int) bool {
- return trait&t.traitMask == trait
-}
-
-// String implements fmt.Stringer.
-func (t *TypeValue) String() string {
- return t.name
-}
-
-// Type implements ref.Val.Type.
-func (t *TypeValue) Type() ref.Type {
- return TypeType
-}
-
-// TypeName gives the type's name as a string.
-func (t *TypeValue) TypeName() string {
- return t.name
-}
-
-// Value implements ref.Val.Value.
-func (t *TypeValue) Value() any {
- return t.name
-}
diff --git a/vendor/github.com/google/cel-go/common/types/types.go b/vendor/github.com/google/cel-go/common/types/types.go
new file mode 100644
index 000000000..76624eefd
--- /dev/null
+++ b/vendor/github.com/google/cel-go/common/types/types.go
@@ -0,0 +1,806 @@
+// Copyright 2023 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package types
+
+import (
+ "fmt"
+ "reflect"
+ "strings"
+
+ chkdecls "github.com/google/cel-go/checker/decls"
+ "github.com/google/cel-go/common/types/ref"
+ "github.com/google/cel-go/common/types/traits"
+
+ exprpb "google.golang.org/genproto/googleapis/api/expr/v1alpha1"
+)
+
+// Kind indicates a CEL type's kind which is used to differentiate quickly between simple
+// and complex types.
+type Kind uint
+
+const (
+ // UnspecifiedKind is returned when the type is nil or its kind is not specified.
+ UnspecifiedKind Kind = iota
+
+ // DynKind represents a dynamic type. This kind only exists at type-check time.
+ DynKind
+
+ // AnyKind represents a google.protobuf.Any type. This kind only exists at type-check time.
+ // Prefer DynKind to AnyKind as AnyKind has a specific meaning which is based on protobuf
+ // well-known types.
+ AnyKind
+
+ // BoolKind represents a boolean type.
+ BoolKind
+
+ // BytesKind represents a bytes type.
+ BytesKind
+
+ // DoubleKind represents a double type.
+ DoubleKind
+
+ // DurationKind represents a CEL duration type.
+ DurationKind
+
+ // ErrorKind represents a CEL error type.
+ ErrorKind
+
+ // IntKind represents an integer type.
+ IntKind
+
+ // ListKind represents a list type.
+ ListKind
+
+ // MapKind represents a map type.
+ MapKind
+
+ // NullTypeKind represents a null type.
+ NullTypeKind
+
+ // OpaqueKind represents an abstract type which has no accessible fields.
+ OpaqueKind
+
+ // StringKind represents a string type.
+ StringKind
+
+ // StructKind represents a structured object with typed fields.
+ StructKind
+
+ // TimestampKind represents a a CEL time type.
+ TimestampKind
+
+ // TypeKind represents the CEL type.
+ TypeKind
+
+ // TypeParamKind represents a parameterized type whose type name will be resolved at type-check time, if possible.
+ TypeParamKind
+
+ // UintKind represents a uint type.
+ UintKind
+
+ // UnknownKind represents an unknown value type.
+ UnknownKind
+)
+
+var (
+ // AnyType represents the google.protobuf.Any type.
+ AnyType = &Type{
+ kind: AnyKind,
+ runtimeTypeName: "google.protobuf.Any",
+ traitMask: traits.FieldTesterType |
+ traits.IndexerType,
+ }
+ // BoolType represents the bool type.
+ BoolType = &Type{
+ kind: BoolKind,
+ runtimeTypeName: "bool",
+ traitMask: traits.ComparerType |
+ traits.NegatorType,
+ }
+ // BytesType represents the bytes type.
+ BytesType = &Type{
+ kind: BytesKind,
+ runtimeTypeName: "bytes",
+ traitMask: traits.AdderType |
+ traits.ComparerType |
+ traits.SizerType,
+ }
+ // DoubleType represents the double type.
+ DoubleType = &Type{
+ kind: DoubleKind,
+ runtimeTypeName: "double",
+ traitMask: traits.AdderType |
+ traits.ComparerType |
+ traits.DividerType |
+ traits.MultiplierType |
+ traits.NegatorType |
+ traits.SubtractorType,
+ }
+ // DurationType represents the CEL duration type.
+ DurationType = &Type{
+ kind: DurationKind,
+ runtimeTypeName: "google.protobuf.Duration",
+ traitMask: traits.AdderType |
+ traits.ComparerType |
+ traits.NegatorType |
+ traits.ReceiverType |
+ traits.SubtractorType,
+ }
+ // DynType represents a dynamic CEL type whose type will be determined at runtime from context.
+ DynType = &Type{
+ kind: DynKind,
+ runtimeTypeName: "dyn",
+ }
+ // ErrorType represents a CEL error value.
+ ErrorType = &Type{
+ kind: ErrorKind,
+ runtimeTypeName: "error",
+ }
+ // IntType represents the int type.
+ IntType = &Type{
+ kind: IntKind,
+ runtimeTypeName: "int",
+ traitMask: traits.AdderType |
+ traits.ComparerType |
+ traits.DividerType |
+ traits.ModderType |
+ traits.MultiplierType |
+ traits.NegatorType |
+ traits.SubtractorType,
+ }
+ // ListType represents the runtime list type.
+ ListType = NewListType(nil)
+ // MapType represents the runtime map type.
+ MapType = NewMapType(nil, nil)
+ // NullType represents the type of a null value.
+ NullType = &Type{
+ kind: NullTypeKind,
+ runtimeTypeName: "null_type",
+ }
+ // StringType represents the string type.
+ StringType = &Type{
+ kind: StringKind,
+ runtimeTypeName: "string",
+ traitMask: traits.AdderType |
+ traits.ComparerType |
+ traits.MatcherType |
+ traits.ReceiverType |
+ traits.SizerType,
+ }
+ // TimestampType represents the time type.
+ TimestampType = &Type{
+ kind: TimestampKind,
+ runtimeTypeName: "google.protobuf.Timestamp",
+ traitMask: traits.AdderType |
+ traits.ComparerType |
+ traits.ReceiverType |
+ traits.SubtractorType,
+ }
+ // TypeType represents a CEL type
+ TypeType = &Type{
+ kind: TypeKind,
+ runtimeTypeName: "type",
+ }
+ // UintType represents a uint type.
+ UintType = &Type{
+ kind: UintKind,
+ runtimeTypeName: "uint",
+ traitMask: traits.AdderType |
+ traits.ComparerType |
+ traits.DividerType |
+ traits.ModderType |
+ traits.MultiplierType |
+ traits.SubtractorType,
+ }
+ // UnknownType represents an unknown value type.
+ UnknownType = &Type{
+ kind: UnknownKind,
+ runtimeTypeName: "unknown",
+ }
+)
+
+var _ ref.Type = &Type{}
+var _ ref.Val = &Type{}
+
+// Type holds a reference to a runtime type with an optional type-checked set of type parameters.
+type Type struct {
+ // kind indicates general category of the type.
+ kind Kind
+
+ // parameters holds the optional type-checked set of type Parameters that are used during static analysis.
+ parameters []*Type
+
+ // runtimeTypeName indicates the runtime type name of the type.
+ runtimeTypeName string
+
+ // isAssignableType function determines whether one type is assignable to this type.
+ // A nil value for the isAssignableType function falls back to equality of kind, runtimeType, and parameters.
+ isAssignableType func(other *Type) bool
+
+ // isAssignableRuntimeType function determines whether the runtime type (with erasure) is assignable to this type.
+ // A nil value for the isAssignableRuntimeType function falls back to the equality of the type or type name.
+ isAssignableRuntimeType func(other ref.Val) bool
+
+ // traitMask is a mask of flags which indicate the capabilities of the type.
+ traitMask int
+}
+
+// ConvertToNative implements ref.Val.ConvertToNative.
+func (t *Type) ConvertToNative(typeDesc reflect.Type) (any, error) {
+ return nil, fmt.Errorf("type conversion not supported for 'type'")
+}
+
+// ConvertToType implements ref.Val.ConvertToType.
+func (t *Type) ConvertToType(typeVal ref.Type) ref.Val {
+ switch typeVal {
+ case TypeType:
+ return TypeType
+ case StringType:
+ return String(t.TypeName())
+ }
+ return NewErr("type conversion error from '%s' to '%s'", TypeType, typeVal)
+}
+
+// Equal indicates whether two types have the same runtime type name.
+//
+// The name Equal is a bit of a misnomer, but for historical reasons, this is the
+// runtime behavior. For a more accurate definition see IsType().
+func (t *Type) Equal(other ref.Val) ref.Val {
+ otherType, ok := other.(ref.Type)
+ return Bool(ok && t.TypeName() == otherType.TypeName())
+}
+
+// HasTrait implements the ref.Type interface method.
+func (t *Type) HasTrait(trait int) bool {
+ return trait&t.traitMask == trait
+}
+
+// IsExactType indicates whether the two types are exactly the same. This check also verifies type parameter type names.
+func (t *Type) IsExactType(other *Type) bool {
+ return t.isTypeInternal(other, true)
+}
+
+// IsEquivalentType indicates whether two types are equivalent. This check ignores type parameter type names.
+func (t *Type) IsEquivalentType(other *Type) bool {
+ return t.isTypeInternal(other, false)
+}
+
+// Kind indicates general category of the type.
+func (t *Type) Kind() Kind {
+ if t == nil {
+ return UnspecifiedKind
+ }
+ return t.kind
+}
+
+// isTypeInternal checks whether the two types are equivalent or exactly the same based on the checkTypeParamName flag.
+func (t *Type) isTypeInternal(other *Type, checkTypeParamName bool) bool {
+ if t == nil {
+ return false
+ }
+ if t == other {
+ return true
+ }
+ if t.Kind() != other.Kind() || len(t.Parameters()) != len(other.Parameters()) {
+ return false
+ }
+ if (checkTypeParamName || t.Kind() != TypeParamKind) && t.TypeName() != other.TypeName() {
+ return false
+ }
+ for i, p := range t.Parameters() {
+ if !p.isTypeInternal(other.Parameters()[i], checkTypeParamName) {
+ return false
+ }
+ }
+ return true
+}
+
+// IsAssignableType determines whether the current type is type-check assignable from the input fromType.
+func (t *Type) IsAssignableType(fromType *Type) bool {
+ if t == nil {
+ return false
+ }
+ if t.isAssignableType != nil {
+ return t.isAssignableType(fromType)
+ }
+ return t.defaultIsAssignableType(fromType)
+}
+
+// IsAssignableRuntimeType determines whether the current type is runtime assignable from the input runtimeType.
+//
+// At runtime, parameterized types are erased and so a function which type-checks to support a map(string, string)
+// will have a runtime assignable type of a map.
+func (t *Type) IsAssignableRuntimeType(val ref.Val) bool {
+ if t == nil {
+ return false
+ }
+ if t.isAssignableRuntimeType != nil {
+ return t.isAssignableRuntimeType(val)
+ }
+ return t.defaultIsAssignableRuntimeType(val)
+}
+
+// Parameters returns the list of type parameters if set.
+//
+// For ListKind, Parameters()[0] represents the list element type
+// For MapKind, Parameters()[0] represents the map key type, and Parameters()[1] represents the map
+// value type.
+func (t *Type) Parameters() []*Type {
+ if t == nil {
+ return emptyParams
+ }
+ return t.parameters
+}
+
+// DeclaredTypeName indicates the fully qualified and parameterized type-check type name.
+func (t *Type) DeclaredTypeName() string {
+ // if the type itself is neither null, nor dyn, but is assignable to null, then it's a wrapper type.
+ if t.Kind() != NullTypeKind && !t.isDyn() && t.IsAssignableType(NullType) {
+ return fmt.Sprintf("wrapper(%s)", t.TypeName())
+ }
+ return t.TypeName()
+}
+
+// Type implements the ref.Val interface method.
+func (t *Type) Type() ref.Type {
+ return TypeType
+}
+
+// Value implements the ref.Val interface method.
+func (t *Type) Value() any {
+ return t.TypeName()
+}
+
+// TypeName returns the type-erased fully qualified runtime type name.
+//
+// TypeName implements the ref.Type interface method.
+func (t *Type) TypeName() string {
+ if t == nil {
+ return ""
+ }
+ return t.runtimeTypeName
+}
+
+// String returns a human-readable definition of the type name.
+func (t *Type) String() string {
+ if len(t.Parameters()) == 0 {
+ return t.DeclaredTypeName()
+ }
+ params := make([]string, len(t.Parameters()))
+ for i, p := range t.Parameters() {
+ params[i] = p.String()
+ }
+ return fmt.Sprintf("%s(%s)", t.DeclaredTypeName(), strings.Join(params, ", "))
+}
+
+// isDyn indicates whether the type is dynamic in any way.
+func (t *Type) isDyn() bool {
+ k := t.Kind()
+ return k == DynKind || k == AnyKind || k == TypeParamKind
+}
+
+// defaultIsAssignableType provides the standard definition of what it means for one type to be assignable to another
+// where any of the following may return a true result:
+// - The from types are the same instance
+// - The target type is dynamic
+// - The fromType has the same kind and type name as the target type, and all parameters of the target type
+//
+// are IsAssignableType() from the parameters of the fromType.
+func (t *Type) defaultIsAssignableType(fromType *Type) bool {
+ if t == fromType || t.isDyn() {
+ return true
+ }
+ if t.Kind() != fromType.Kind() ||
+ t.TypeName() != fromType.TypeName() ||
+ len(t.Parameters()) != len(fromType.Parameters()) {
+ return false
+ }
+ for i, tp := range t.Parameters() {
+ fp := fromType.Parameters()[i]
+ if !tp.IsAssignableType(fp) {
+ return false
+ }
+ }
+ return true
+}
+
+// defaultIsAssignableRuntimeType inspects the type and in the case of list and map elements, the key and element types
+// to determine whether a ref.Val is assignable to the declared type for a function signature.
+func (t *Type) defaultIsAssignableRuntimeType(val ref.Val) bool {
+ valType := val.Type()
+ // If the current type and value type don't agree, then return
+ if !(t.isDyn() || t.TypeName() == valType.TypeName()) {
+ return false
+ }
+ switch t.Kind() {
+ case ListKind:
+ elemType := t.Parameters()[0]
+ l := val.(traits.Lister)
+ if l.Size() == IntZero {
+ return true
+ }
+ it := l.Iterator()
+ elemVal := it.Next()
+ return elemType.IsAssignableRuntimeType(elemVal)
+ case MapKind:
+ keyType := t.Parameters()[0]
+ elemType := t.Parameters()[1]
+ m := val.(traits.Mapper)
+ if m.Size() == IntZero {
+ return true
+ }
+ it := m.Iterator()
+ keyVal := it.Next()
+ elemVal := m.Get(keyVal)
+ return keyType.IsAssignableRuntimeType(keyVal) && elemType.IsAssignableRuntimeType(elemVal)
+ }
+ return true
+}
+
+// NewListType creates an instances of a list type value with the provided element type.
+func NewListType(elemType *Type) *Type {
+ return &Type{
+ kind: ListKind,
+ parameters: []*Type{elemType},
+ runtimeTypeName: "list",
+ traitMask: traits.AdderType |
+ traits.ContainerType |
+ traits.IndexerType |
+ traits.IterableType |
+ traits.SizerType,
+ }
+}
+
+// NewMapType creates an instance of a map type value with the provided key and value types.
+func NewMapType(keyType, valueType *Type) *Type {
+ return &Type{
+ kind: MapKind,
+ parameters: []*Type{keyType, valueType},
+ runtimeTypeName: "map",
+ traitMask: traits.ContainerType |
+ traits.IndexerType |
+ traits.IterableType |
+ traits.SizerType,
+ }
+}
+
+// NewNullableType creates an instance of a nullable type with the provided wrapped type.
+//
+// Note: only primitive types are supported as wrapped types.
+func NewNullableType(wrapped *Type) *Type {
+ return &Type{
+ kind: wrapped.Kind(),
+ parameters: wrapped.Parameters(),
+ runtimeTypeName: wrapped.TypeName(),
+ traitMask: wrapped.traitMask,
+ isAssignableType: func(other *Type) bool {
+ return NullType.IsAssignableType(other) || wrapped.IsAssignableType(other)
+ },
+ isAssignableRuntimeType: func(other ref.Val) bool {
+ return NullType.IsAssignableRuntimeType(other) || wrapped.IsAssignableRuntimeType(other)
+ },
+ }
+}
+
+// NewOptionalType creates an abstract parameterized type instance corresponding to CEL's notion of optional.
+func NewOptionalType(param *Type) *Type {
+ return NewOpaqueType("optional", param)
+}
+
+// NewOpaqueType creates an abstract parameterized type with a given name.
+func NewOpaqueType(name string, params ...*Type) *Type {
+ return &Type{
+ kind: OpaqueKind,
+ parameters: params,
+ runtimeTypeName: name,
+ }
+}
+
+// NewObjectType creates a type reference to an externally defined type, e.g. a protobuf message type.
+//
+// An object type is assumed to support field presence testing and field indexing. Additionally, the
+// type may also indicate additional traits through the use of the optional traits vararg argument.
+func NewObjectType(typeName string, traits ...int) *Type {
+ // Function sanitizes object types on the fly
+ if wkt, found := checkedWellKnowns[typeName]; found {
+ return wkt
+ }
+ traitMask := 0
+ for _, trait := range traits {
+ traitMask |= trait
+ }
+ return &Type{
+ kind: StructKind,
+ parameters: emptyParams,
+ runtimeTypeName: typeName,
+ traitMask: structTypeTraitMask | traitMask,
+ }
+}
+
+// NewObjectTypeValue creates a type reference to an externally defined type.
+//
+// Deprecated: use cel.ObjectType(typeName)
+func NewObjectTypeValue(typeName string) *Type {
+ return NewObjectType(typeName)
+}
+
+// NewTypeValue creates an opaque type which has a set of optional type traits as defined in
+// the common/types/traits package.
+//
+// Deprecated: use cel.ObjectType(typeName, traits)
+func NewTypeValue(typeName string, traits ...int) *Type {
+ traitMask := 0
+ for _, trait := range traits {
+ traitMask |= trait
+ }
+ return &Type{
+ kind: StructKind,
+ parameters: emptyParams,
+ runtimeTypeName: typeName,
+ traitMask: traitMask,
+ }
+}
+
+// NewTypeParamType creates a parameterized type instance.
+func NewTypeParamType(paramName string) *Type {
+ return &Type{
+ kind: TypeParamKind,
+ runtimeTypeName: paramName,
+ }
+}
+
+// NewTypeTypeWithParam creates a type with a type parameter.
+// Used for type-checking purposes, but equivalent to TypeType otherwise.
+func NewTypeTypeWithParam(param *Type) *Type {
+ return &Type{
+ kind: TypeKind,
+ runtimeTypeName: "type",
+ parameters: []*Type{param},
+ }
+}
+
+// TypeToExprType converts a CEL-native type representation to a protobuf CEL Type representation.
+func TypeToExprType(t *Type) (*exprpb.Type, error) {
+ switch t.Kind() {
+ case AnyKind:
+ return chkdecls.Any, nil
+ case BoolKind:
+ return maybeWrapper(t, chkdecls.Bool), nil
+ case BytesKind:
+ return maybeWrapper(t, chkdecls.Bytes), nil
+ case DoubleKind:
+ return maybeWrapper(t, chkdecls.Double), nil
+ case DurationKind:
+ return chkdecls.Duration, nil
+ case DynKind:
+ return chkdecls.Dyn, nil
+ case ErrorKind:
+ return chkdecls.Error, nil
+ case IntKind:
+ return maybeWrapper(t, chkdecls.Int), nil
+ case ListKind:
+ if len(t.Parameters()) != 1 {
+ return nil, fmt.Errorf("invalid list, got %d parameters, wanted one", len(t.Parameters()))
+ }
+ et, err := TypeToExprType(t.Parameters()[0])
+ if err != nil {
+ return nil, err
+ }
+ return chkdecls.NewListType(et), nil
+ case MapKind:
+ if len(t.Parameters()) != 2 {
+ return nil, fmt.Errorf("invalid map, got %d parameters, wanted two", len(t.Parameters()))
+ }
+ kt, err := TypeToExprType(t.Parameters()[0])
+ if err != nil {
+ return nil, err
+ }
+ vt, err := TypeToExprType(t.Parameters()[1])
+ if err != nil {
+ return nil, err
+ }
+ return chkdecls.NewMapType(kt, vt), nil
+ case NullTypeKind:
+ return chkdecls.Null, nil
+ case OpaqueKind:
+ params := make([]*exprpb.Type, len(t.Parameters()))
+ for i, p := range t.Parameters() {
+ pt, err := TypeToExprType(p)
+ if err != nil {
+ return nil, err
+ }
+ params[i] = pt
+ }
+ return chkdecls.NewAbstractType(t.TypeName(), params...), nil
+ case StringKind:
+ return maybeWrapper(t, chkdecls.String), nil
+ case StructKind:
+ return chkdecls.NewObjectType(t.TypeName()), nil
+ case TimestampKind:
+ return chkdecls.Timestamp, nil
+ case TypeParamKind:
+ return chkdecls.NewTypeParamType(t.TypeName()), nil
+ case TypeKind:
+ if len(t.Parameters()) == 1 {
+ p, err := TypeToExprType(t.Parameters()[0])
+ if err != nil {
+ return nil, err
+ }
+ return chkdecls.NewTypeType(p), nil
+ }
+ return chkdecls.NewTypeType(nil), nil
+ case UintKind:
+ return maybeWrapper(t, chkdecls.Uint), nil
+ }
+ return nil, fmt.Errorf("missing type conversion to proto: %v", t)
+}
+
+// ExprTypeToType converts a protobuf CEL type representation to a CEL-native type representation.
+func ExprTypeToType(t *exprpb.Type) (*Type, error) {
+ switch t.GetTypeKind().(type) {
+ case *exprpb.Type_Dyn:
+ return DynType, nil
+ case *exprpb.Type_AbstractType_:
+ paramTypes := make([]*Type, len(t.GetAbstractType().GetParameterTypes()))
+ for i, p := range t.GetAbstractType().GetParameterTypes() {
+ pt, err := ExprTypeToType(p)
+ if err != nil {
+ return nil, err
+ }
+ paramTypes[i] = pt
+ }
+ return NewOpaqueType(t.GetAbstractType().GetName(), paramTypes...), nil
+ case *exprpb.Type_ListType_:
+ et, err := ExprTypeToType(t.GetListType().GetElemType())
+ if err != nil {
+ return nil, err
+ }
+ return NewListType(et), nil
+ case *exprpb.Type_MapType_:
+ kt, err := ExprTypeToType(t.GetMapType().GetKeyType())
+ if err != nil {
+ return nil, err
+ }
+ vt, err := ExprTypeToType(t.GetMapType().GetValueType())
+ if err != nil {
+ return nil, err
+ }
+ return NewMapType(kt, vt), nil
+ case *exprpb.Type_MessageType:
+ return NewObjectType(t.GetMessageType()), nil
+ case *exprpb.Type_Null:
+ return NullType, nil
+ case *exprpb.Type_Primitive:
+ switch t.GetPrimitive() {
+ case exprpb.Type_BOOL:
+ return BoolType, nil
+ case exprpb.Type_BYTES:
+ return BytesType, nil
+ case exprpb.Type_DOUBLE:
+ return DoubleType, nil
+ case exprpb.Type_INT64:
+ return IntType, nil
+ case exprpb.Type_STRING:
+ return StringType, nil
+ case exprpb.Type_UINT64:
+ return UintType, nil
+ default:
+ return nil, fmt.Errorf("unsupported primitive type: %v", t)
+ }
+ case *exprpb.Type_TypeParam:
+ return NewTypeParamType(t.GetTypeParam()), nil
+ case *exprpb.Type_Type:
+ if t.GetType().GetTypeKind() != nil {
+ p, err := ExprTypeToType(t.GetType())
+ if err != nil {
+ return nil, err
+ }
+ return NewTypeTypeWithParam(p), nil
+ }
+ return TypeType, nil
+ case *exprpb.Type_WellKnown:
+ switch t.GetWellKnown() {
+ case exprpb.Type_ANY:
+ return AnyType, nil
+ case exprpb.Type_DURATION:
+ return DurationType, nil
+ case exprpb.Type_TIMESTAMP:
+ return TimestampType, nil
+ default:
+ return nil, fmt.Errorf("unsupported well-known type: %v", t)
+ }
+ case *exprpb.Type_Wrapper:
+ t, err := ExprTypeToType(&exprpb.Type{TypeKind: &exprpb.Type_Primitive{Primitive: t.GetWrapper()}})
+ if err != nil {
+ return nil, err
+ }
+ return NewNullableType(t), nil
+ case *exprpb.Type_Error:
+ return ErrorType, nil
+ default:
+ return nil, fmt.Errorf("unsupported type: %v", t)
+ }
+}
+
+func maybeWrapper(t *Type, pbType *exprpb.Type) *exprpb.Type {
+ if t.IsAssignableType(NullType) {
+ return chkdecls.NewWrapperType(pbType)
+ }
+ return pbType
+}
+
+func maybeForeignType(t ref.Type) *Type {
+ if celType, ok := t.(*Type); ok {
+ return celType
+ }
+ // Inspect the incoming type to determine its traits. The assumption will be that the incoming
+ // type does not have any field values; however, if the trait mask indicates that field testing
+ // and indexing are supported, the foreign type is marked as a struct.
+ traitMask := 0
+ for _, trait := range allTraits {
+ if t.HasTrait(trait) {
+ traitMask |= trait
+ }
+ }
+ // Treat the value like a struct. If it has no fields, this is harmless to denote the type
+ // as such since it basically becomes an opaque type by convention.
+ return NewObjectType(t.TypeName(), traitMask)
+}
+
+var (
+ checkedWellKnowns = map[string]*Type{
+ // Wrapper types.
+ "google.protobuf.BoolValue": NewNullableType(BoolType),
+ "google.protobuf.BytesValue": NewNullableType(BytesType),
+ "google.protobuf.DoubleValue": NewNullableType(DoubleType),
+ "google.protobuf.FloatValue": NewNullableType(DoubleType),
+ "google.protobuf.Int64Value": NewNullableType(IntType),
+ "google.protobuf.Int32Value": NewNullableType(IntType),
+ "google.protobuf.UInt64Value": NewNullableType(UintType),
+ "google.protobuf.UInt32Value": NewNullableType(UintType),
+ "google.protobuf.StringValue": NewNullableType(StringType),
+ // Well-known types.
+ "google.protobuf.Any": AnyType,
+ "google.protobuf.Duration": DurationType,
+ "google.protobuf.Timestamp": TimestampType,
+ // Json types.
+ "google.protobuf.ListValue": NewListType(DynType),
+ "google.protobuf.NullValue": NullType,
+ "google.protobuf.Struct": NewMapType(StringType, DynType),
+ "google.protobuf.Value": DynType,
+ }
+
+ emptyParams = []*Type{}
+
+ allTraits = []int{
+ traits.AdderType,
+ traits.ComparerType,
+ traits.ContainerType,
+ traits.DividerType,
+ traits.FieldTesterType,
+ traits.IndexerType,
+ traits.IterableType,
+ traits.IteratorType,
+ traits.MatcherType,
+ traits.ModderType,
+ traits.MultiplierType,
+ traits.NegatorType,
+ traits.ReceiverType,
+ traits.SizerType,
+ traits.SubtractorType,
+ }
+
+ structTypeTraitMask = traits.FieldTesterType | traits.IndexerType
+)
diff --git a/vendor/github.com/google/cel-go/common/types/uint.go b/vendor/github.com/google/cel-go/common/types/uint.go
index 988e6f1ac..3257f9ade 100644
--- a/vendor/github.com/google/cel-go/common/types/uint.go
+++ b/vendor/github.com/google/cel-go/common/types/uint.go
@@ -21,7 +21,6 @@ import (
"strconv"
"github.com/google/cel-go/common/types/ref"
- "github.com/google/cel-go/common/types/traits"
anypb "google.golang.org/protobuf/types/known/anypb"
structpb "google.golang.org/protobuf/types/known/structpb"
@@ -32,15 +31,6 @@ import (
type Uint uint64
var (
- // UintType singleton.
- UintType = NewTypeValue("uint",
- traits.AdderType,
- traits.ComparerType,
- traits.DividerType,
- traits.ModderType,
- traits.MultiplierType,
- traits.SubtractorType)
-
uint32WrapperType = reflect.TypeOf(&wrapperspb.UInt32Value{})
uint64WrapperType = reflect.TypeOf(&wrapperspb.UInt64Value{})
@@ -59,7 +49,7 @@ func (i Uint) Add(other ref.Val) ref.Val {
}
val, err := addUint64Checked(uint64(i), uint64(otherUint))
if err != nil {
- return wrapErr(err)
+ return WrapErr(err)
}
return Uint(val)
}
@@ -149,7 +139,7 @@ func (i Uint) ConvertToType(typeVal ref.Type) ref.Val {
case IntType:
v, err := uint64ToInt64Checked(uint64(i))
if err != nil {
- return wrapErr(err)
+ return WrapErr(err)
}
return Int(v)
case UintType:
@@ -172,7 +162,7 @@ func (i Uint) Divide(other ref.Val) ref.Val {
}
div, err := divideUint64Checked(uint64(i), uint64(otherUint))
if err != nil {
- return wrapErr(err)
+ return WrapErr(err)
}
return Uint(div)
}
@@ -207,7 +197,7 @@ func (i Uint) Modulo(other ref.Val) ref.Val {
}
mod, err := moduloUint64Checked(uint64(i), uint64(otherUint))
if err != nil {
- return wrapErr(err)
+ return WrapErr(err)
}
return Uint(mod)
}
@@ -220,7 +210,7 @@ func (i Uint) Multiply(other ref.Val) ref.Val {
}
val, err := multiplyUint64Checked(uint64(i), uint64(otherUint))
if err != nil {
- return wrapErr(err)
+ return WrapErr(err)
}
return Uint(val)
}
@@ -233,7 +223,7 @@ func (i Uint) Subtract(subtrahend ref.Val) ref.Val {
}
val, err := subtractUint64Checked(uint64(i), uint64(subtraUint))
if err != nil {
- return wrapErr(err)
+ return WrapErr(err)
}
return Uint(val)
}
diff --git a/vendor/github.com/google/cel-go/common/types/unknown.go b/vendor/github.com/google/cel-go/common/types/unknown.go
index bc411c15b..9dd2b2579 100644
--- a/vendor/github.com/google/cel-go/common/types/unknown.go
+++ b/vendor/github.com/google/cel-go/common/types/unknown.go
@@ -15,52 +15,312 @@
package types
import (
+ "fmt"
+ "math"
"reflect"
+ "sort"
+ "strings"
+ "unicode"
"github.com/google/cel-go/common/types/ref"
)
-// Unknown type implementation which collects expression ids which caused the
-// current value to become unknown.
-type Unknown []int64
-
var (
- // UnknownType singleton.
- UnknownType = NewTypeValue("unknown")
+ unspecifiedAttribute = &AttributeTrail{qualifierPath: []any{}}
)
+// NewAttributeTrail creates a new simple attribute from a variable name.
+func NewAttributeTrail(variable string) *AttributeTrail {
+ if variable == "" {
+ return unspecifiedAttribute
+ }
+ return &AttributeTrail{variable: variable}
+}
+
+// AttributeTrail specifies a variable with an optional qualifier path. An attribute value is expected to
+// correspond to an AbsoluteAttribute, meaning a field selection which starts with a top-level variable.
+//
+// The qualifer path elements adhere to the AttributeQualifier type constraint.
+type AttributeTrail struct {
+ variable string
+ qualifierPath []any
+}
+
+// Equal returns whether two attribute values have the same variable name and qualifier paths.
+func (a *AttributeTrail) Equal(other *AttributeTrail) bool {
+ if a.Variable() != other.Variable() || len(a.QualifierPath()) != len(other.QualifierPath()) {
+ return false
+ }
+ for i, q := range a.QualifierPath() {
+ qual := other.QualifierPath()[i]
+ if !qualifiersEqual(q, qual) {
+ return false
+ }
+ }
+ return true
+}
+
+func qualifiersEqual(a, b any) bool {
+ if a == b {
+ return true
+ }
+ switch numA := a.(type) {
+ case int64:
+ numB, ok := b.(uint64)
+ if !ok {
+ return false
+ }
+ return intUintEqual(numA, numB)
+ case uint64:
+ numB, ok := b.(int64)
+ if !ok {
+ return false
+ }
+ return intUintEqual(numB, numA)
+ default:
+ return false
+ }
+}
+
+func intUintEqual(i int64, u uint64) bool {
+ if i < 0 || u > math.MaxInt64 {
+ return false
+ }
+ return i == int64(u)
+}
+
+// Variable returns the variable name associated with the attribute.
+func (a *AttributeTrail) Variable() string {
+ return a.variable
+}
+
+// QualifierPath returns the optional set of qualifying fields or indices applied to the variable.
+func (a *AttributeTrail) QualifierPath() []any {
+ return a.qualifierPath
+}
+
+// String returns the string representation of the Attribute.
+func (a *AttributeTrail) String() string {
+ if a.variable == "" {
+ return ""
+ }
+ var str strings.Builder
+ str.WriteString(a.variable)
+ for _, q := range a.qualifierPath {
+ switch q := q.(type) {
+ case bool, int64:
+ str.WriteString(fmt.Sprintf("[%v]", q))
+ case uint64:
+ str.WriteString(fmt.Sprintf("[%vu]", q))
+ case string:
+ if isIdentifierCharacter(q) {
+ str.WriteString(fmt.Sprintf(".%v", q))
+ } else {
+ str.WriteString(fmt.Sprintf("[%q]", q))
+ }
+ }
+ }
+ return str.String()
+}
+
+func isIdentifierCharacter(str string) bool {
+ for _, c := range str {
+ if unicode.IsLetter(c) || unicode.IsDigit(c) || string(c) == "_" {
+ continue
+ }
+ return false
+ }
+ return true
+}
+
+// AttributeQualifier constrains the possible types which may be used to qualify an attribute.
+type AttributeQualifier interface {
+ bool | int64 | uint64 | string
+}
+
+// QualifyAttribute qualifies an attribute using a valid AttributeQualifier type.
+func QualifyAttribute[T AttributeQualifier](attr *AttributeTrail, qualifier T) *AttributeTrail {
+ attr.qualifierPath = append(attr.qualifierPath, qualifier)
+ return attr
+}
+
+// Unknown type which collects expression ids which caused the current value to become unknown.
+type Unknown struct {
+ attributeTrails map[int64][]*AttributeTrail
+}
+
+// NewUnknown creates a new unknown at a given expression id for an attribute.
+//
+// If the attribute is nil, the attribute value will be the `unspecifiedAttribute`.
+func NewUnknown(id int64, attr *AttributeTrail) *Unknown {
+ if attr == nil {
+ attr = unspecifiedAttribute
+ }
+ return &Unknown{
+ attributeTrails: map[int64][]*AttributeTrail{id: {attr}},
+ }
+}
+
+// IDs returns the set of unknown expression ids contained by this value.
+//
+// Numeric identifiers are guaranteed to be in sorted order.
+func (u *Unknown) IDs() []int64 {
+ ids := make(int64Slice, len(u.attributeTrails))
+ i := 0
+ for id := range u.attributeTrails {
+ ids[i] = id
+ i++
+ }
+ ids.Sort()
+ return ids
+}
+
+// GetAttributeTrails returns the attribute trails, if present, missing for a given expression id.
+func (u *Unknown) GetAttributeTrails(id int64) ([]*AttributeTrail, bool) {
+ trails, found := u.attributeTrails[id]
+ return trails, found
+}
+
+// Contains returns true if the input unknown is a subset of the current unknown.
+func (u *Unknown) Contains(other *Unknown) bool {
+ for id, otherTrails := range other.attributeTrails {
+ trails, found := u.attributeTrails[id]
+ if !found || len(otherTrails) != len(trails) {
+ return false
+ }
+ for _, ot := range otherTrails {
+ found := false
+ for _, t := range trails {
+ if t.Equal(ot) {
+ found = true
+ break
+ }
+ }
+ if !found {
+ return false
+ }
+ }
+ }
+ return true
+}
+
// ConvertToNative implements ref.Val.ConvertToNative.
-func (u Unknown) ConvertToNative(typeDesc reflect.Type) (any, error) {
+func (u *Unknown) ConvertToNative(typeDesc reflect.Type) (any, error) {
return u.Value(), nil
}
// ConvertToType is an identity function since unknown values cannot be modified.
-func (u Unknown) ConvertToType(typeVal ref.Type) ref.Val {
+func (u *Unknown) ConvertToType(typeVal ref.Type) ref.Val {
return u
}
// Equal is an identity function since unknown values cannot be modified.
-func (u Unknown) Equal(other ref.Val) ref.Val {
+func (u *Unknown) Equal(other ref.Val) ref.Val {
return u
}
+// String implements the Stringer interface
+func (u *Unknown) String() string {
+ var str strings.Builder
+ for id, attrs := range u.attributeTrails {
+ if str.Len() != 0 {
+ str.WriteString(", ")
+ }
+ if len(attrs) == 1 {
+ str.WriteString(fmt.Sprintf("%v (%d)", attrs[0], id))
+ } else {
+ str.WriteString(fmt.Sprintf("%v (%d)", attrs, id))
+ }
+ }
+ return str.String()
+}
+
// Type implements ref.Val.Type.
-func (u Unknown) Type() ref.Type {
+func (u *Unknown) Type() ref.Type {
return UnknownType
}
// Value implements ref.Val.Value.
-func (u Unknown) Value() any {
- return []int64(u)
+func (u *Unknown) Value() any {
+ return u
}
-// IsUnknown returns whether the element ref.Type or ref.Val is equal to the
-// UnknownType singleton.
+// IsUnknown returns whether the element ref.Val is in instance of *types.Unknown
func IsUnknown(val ref.Val) bool {
switch val.(type) {
- case Unknown:
+ case *Unknown:
return true
default:
return false
}
}
+
+// MaybeMergeUnknowns determines whether an input value and another, possibly nil, unknown will produce
+// an unknown result.
+//
+// If the input `val` is another Unknown, then the result will be the merge of the `val` and the input
+// `unk`. If the `val` is not unknown, then the result will depend on whether the input `unk` is nil.
+// If both values are non-nil and unknown, then the return value will be a merge of both unknowns.
+func MaybeMergeUnknowns(val ref.Val, unk *Unknown) (*Unknown, bool) {
+ src, isUnk := val.(*Unknown)
+ if !isUnk {
+ if unk != nil {
+ return unk, true
+ }
+ return unk, false
+ }
+ return MergeUnknowns(src, unk), true
+}
+
+// MergeUnknowns combines two unknown values into a new unknown value.
+func MergeUnknowns(unk1, unk2 *Unknown) *Unknown {
+ if unk1 == nil {
+ return unk2
+ }
+ if unk2 == nil {
+ return unk1
+ }
+ out := &Unknown{
+ attributeTrails: make(map[int64][]*AttributeTrail, len(unk1.attributeTrails)+len(unk2.attributeTrails)),
+ }
+ for id, ats := range unk1.attributeTrails {
+ out.attributeTrails[id] = ats
+ }
+ for id, ats := range unk2.attributeTrails {
+ existing, found := out.attributeTrails[id]
+ if !found {
+ out.attributeTrails[id] = ats
+ continue
+ }
+
+ for _, at := range ats {
+ found := false
+ for _, et := range existing {
+ if at.Equal(et) {
+ found = true
+ break
+ }
+ }
+ if !found {
+ existing = append(existing, at)
+ }
+ }
+ out.attributeTrails[id] = existing
+ }
+ return out
+}
+
+// int64Slice is an implementation of the sort.Interface
+type int64Slice []int64
+
+// Len returns the number of elements in the slice.
+func (x int64Slice) Len() int { return len(x) }
+
+// Less indicates whether the value at index i is less than the value at index j.
+func (x int64Slice) Less(i, j int) bool { return x[i] < x[j] }
+
+// Swap swaps the values at indices i and j in place.
+func (x int64Slice) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
+
+// Sort is a convenience method: x.Sort() calls Sort(x).
+func (x int64Slice) Sort() { sort.Sort(x) }
diff --git a/vendor/github.com/google/cel-go/common/types/util.go b/vendor/github.com/google/cel-go/common/types/util.go
index a8e9afa9e..71662eee3 100644
--- a/vendor/github.com/google/cel-go/common/types/util.go
+++ b/vendor/github.com/google/cel-go/common/types/util.go
@@ -21,7 +21,7 @@ import (
// IsUnknownOrError returns whether the input element ref.Val is an ErrType or UnknownType.
func IsUnknownOrError(val ref.Val) bool {
switch val.(type) {
- case Unknown, *Err:
+ case *Unknown, *Err:
return true
}
return false
diff --git a/vendor/github.com/google/cel-go/ext/BUILD.bazel b/vendor/github.com/google/cel-go/ext/BUILD.bazel
new file mode 100644
index 000000000..ebdf7d01e
--- /dev/null
+++ b/vendor/github.com/google/cel-go/ext/BUILD.bazel
@@ -0,0 +1,68 @@
+load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
+
+package(
+ licenses = ["notice"], # Apache 2.0
+)
+
+go_library(
+ name = "go_default_library",
+ srcs = [
+ "encoders.go",
+ "guards.go",
+ "lists.go",
+ "math.go",
+ "native.go",
+ "protos.go",
+ "sets.go",
+ "strings.go",
+ ],
+ importpath = "github.com/google/cel-go/ext",
+ visibility = ["//visibility:public"],
+ deps = [
+ "//cel:go_default_library",
+ "//checker/decls:go_default_library",
+ "//common/overloads:go_default_library",
+ "//common/types:go_default_library",
+ "//common/types/pb:go_default_library",
+ "//common/types/ref:go_default_library",
+ "//common/types/traits:go_default_library",
+ "//interpreter:go_default_library",
+ "@org_golang_google_genproto_googleapis_api//expr/v1alpha1:go_default_library",
+ "@org_golang_google_protobuf//proto:go_default_library",
+ "@org_golang_google_protobuf//reflect/protoreflect:go_default_library",
+ "@org_golang_google_protobuf//types/known/structpb",
+ "@org_golang_x_text//language:go_default_library",
+ "@org_golang_x_text//message:go_default_library",
+ ],
+)
+
+go_test(
+ name = "go_default_test",
+ size = "small",
+ srcs = [
+ "encoders_test.go",
+ "lists_test.go",
+ "math_test.go",
+ "native_test.go",
+ "protos_test.go",
+ "sets_test.go",
+ "strings_test.go",
+ ],
+ embed = [
+ ":go_default_library",
+ ],
+ deps = [
+ "//cel:go_default_library",
+ "//checker:go_default_library",
+ "//common/types:go_default_library",
+ "//common/types/ref:go_default_library",
+ "//common/types/traits:go_default_library",
+ "//test:go_default_library",
+ "//test/proto2pb:go_default_library",
+ "//test/proto3pb:go_default_library",
+ "@org_golang_google_genproto_googleapis_api//expr/v1alpha1:go_default_library",
+ "@org_golang_google_protobuf//proto:go_default_library",
+ "@org_golang_google_protobuf//types/known/wrapperspb:go_default_library",
+ "@org_golang_google_protobuf//encoding/protojson:go_default_library",
+ ],
+)
diff --git a/vendor/github.com/google/cel-go/ext/README.md b/vendor/github.com/google/cel-go/ext/README.md
new file mode 100644
index 000000000..6f621ac4a
--- /dev/null
+++ b/vendor/github.com/google/cel-go/ext/README.md
@@ -0,0 +1,416 @@
+# Extensions
+
+CEL extensions are a related set of constants, functions, macros, or other
+features which may not be covered by the core CEL spec.
+
+## Bindings
+
+Returns a cel.EnvOption to configure support for local variable bindings
+in expressions.
+
+# Cel.Bind
+
+Binds a simple identifier to an initialization expression which may be used
+in a subsequenct result expression. Bindings may also be nested within each
+other.
+
+ cel.bind(, , )
+
+Examples:
+
+ cel.bind(a, 'hello',
+ cel.bind(b, 'world', a + b + b + a)) // "helloworldworldhello"
+
+ // Avoid a list allocation within the exists comprehension.
+ cel.bind(valid_values, [a, b, c],
+ [d, e, f].exists(elem, elem in valid_values))
+
+Local bindings are not guaranteed to be evaluated before use.
+
+## Encoders
+
+Encoding utilies for marshalling data into standardized representations.
+
+### Base64.Decode
+
+Decodes base64-encoded string to bytes.
+
+This function will return an error if the string input is not
+base64-encoded.
+
+ base64.decode() ->
+
+Examples:
+
+ base64.decode('aGVsbG8=') // return b'hello'
+ base64.decode('aGVsbG8') // error
+
+### Base64.Encode
+
+Encodes bytes to a base64-encoded string.
+
+ base64.encode() ->
+
+Example:
+
+ base64.encode(b'hello') // return 'aGVsbG8='
+
+## Math
+
+Math helper macros and functions.
+
+Note, all macros use the 'math' namespace; however, at the time of macro
+expansion the namespace looks just like any other identifier. If you are
+currently using a variable named 'math', the macro will likely work just as
+intended; however, there is some chance for collision.
+
+### Math.Greatest
+
+Returns the greatest valued number present in the arguments to the macro.
+
+Greatest is a variable argument count macro which must take at least one
+argument. Simple numeric and list literals are supported as valid argument
+types; however, other literals will be flagged as errors during macro
+expansion. If the argument expression does not resolve to a numeric or
+list(numeric) type during type-checking, or during runtime then an error
+will be produced. If a list argument is empty, this too will produce an
+error.
+
+ math.greatest(, ...) ->
+
+Examples:
+
+ math.greatest(1) // 1
+ math.greatest(1u, 2u) // 2u
+ math.greatest(-42.0, -21.5, -100.0) // -21.5
+ math.greatest([-42.0, -21.5, -100.0]) // -21.5
+ math.greatest(numbers) // numbers must be list(numeric)
+
+ math.greatest() // parse error
+ math.greatest('string') // parse error
+ math.greatest(a, b) // check-time error if a or b is non-numeric
+ math.greatest(dyn('string')) // runtime error
+
+### Math.Least
+
+Returns the least valued number present in the arguments to the macro.
+
+Least is a variable argument count macro which must take at least one
+argument. Simple numeric and list literals are supported as valid argument
+types; however, other literals will be flagged as errors during macro
+expansion. If the argument expression does not resolve to a numeric or
+list(numeric) type during type-checking, or during runtime then an error
+will be produced. If a list argument is empty, this too will produce an error.
+
+ math.least(, ...) ->
+
+Examples:
+
+ math.least(1) // 1
+ math.least(1u, 2u) // 1u
+ math.least(-42.0, -21.5, -100.0) // -100.0
+ math.least([-42.0, -21.5, -100.0]) // -100.0
+ math.least(numbers) // numbers must be list(numeric)
+
+ math.least() // parse error
+ math.least('string') // parse error
+ math.least(a, b) // check-time error if a or b is non-numeric
+ math.least(dyn('string')) // runtime error
+
+## Protos
+
+Protos configure extended macros and functions for proto manipulation.
+
+Note, all macros use the 'proto' namespace; however, at the time of macro
+expansion the namespace looks just like any other identifier. If you are
+currently using a variable named 'proto', the macro will likely work just as
+you intend; however, there is some chance for collision.
+
+### Protos.GetExt
+
+Macro which generates a select expression that retrieves an extension field
+from the input proto2 syntax message. If the field is not set, the default
+value forthe extension field is returned according to safe-traversal semantics.
+
+ proto.getExt(, ) ->
+
+Example:
+
+ proto.getExt(msg, google.expr.proto2.test.int32_ext) // returns int value
+
+### Protos.HasExt
+
+Macro which generates a test-only select expression that determines whether
+an extension field is set on a proto2 syntax message.
+
+ proto.hasExt(, ) ->
+
+Example:
+
+ proto.hasExt(msg, google.expr.proto2.test.int32_ext) // returns true || false
+
+## Lists
+
+Extended functions for list manipulation. As a general note, all indices are
+zero-based.
+
+### Slice
+
+
+Returns a new sub-list using the indexes provided.
+
+ .slice(, ) ->
+
+Examples:
+
+ [1,2,3,4].slice(1, 3) // return [2, 3]
+ [1,2,3,4].slice(2, 4) // return [3 ,4]
+
+## Sets
+
+Sets provides set relationship tests.
+
+There is no set type within CEL, and while one may be introduced in the
+future, there are cases where a `list` type is known to behave like a set.
+For such cases, this library provides some basic functionality for
+determining set containment, equivalence, and intersection.
+
+### Sets.Contains
+
+Returns whether the first list argument contains all elements in the second
+list argument. The list may contain elements of any type and standard CEL
+equality is used to determine whether a value exists in both lists. If the
+second list is empty, the result will always return true.
+
+ sets.contains(list(T), list(T)) -> bool
+
+Examples:
+
+ sets.contains([], []) // true
+ sets.contains([], [1]) // false
+ sets.contains([1, 2, 3, 4], [2, 3]) // true
+ sets.contains([1, 2.0, 3u], [1.0, 2u, 3]) // true
+
+### Sets.Equivalent
+
+Returns whether the first and second list are set equivalent. Lists are set
+equivalent if for every item in the first list, there is an element in the
+second which is equal. The lists may not be of the same size as they do not
+guarantee the elements within them are unique, so size does not factor into
+the computation.
+
+ sets.equivalent(list(T), list(T)) -> bool
+
+Examples:
+
+ sets.equivalent([], []) // true
+ sets.equivalent([1], [1, 1]) // true
+ sets.equivalent([1], [1u, 1.0]) // true
+ sets.equivalent([1, 2, 3], [3u, 2.0, 1]) // true
+
+### Sets.Intersects
+
+Returns whether the first list has at least one element whose value is equal
+to an element in the second list. If either list is empty, the result will
+be false.
+
+ sets.intersects(list(T), list(T)) -> bool
+
+Examples:
+
+ sets.intersects([1], []) // false
+ sets.intersects([1], [1, 2]) // true
+ sets.intersects([[1], [2, 3]], [[1, 2], [2, 3.0]]) // true
+
+## Strings
+
+Extended functions for string manipulation. As a general note, all indices are
+zero-based.
+
+### CharAt
+
+Returns the character at the given position. If the position is negative, or
+greater than the length of the string, the function will produce an error:
+
+ .charAt() ->
+
+Examples:
+
+ 'hello'.charAt(4) // return 'o'
+ 'hello'.charAt(5) // return ''
+ 'hello'.charAt(-1) // error
+
+### IndexOf
+
+Returns the integer index of the first occurrence of the search string. If the
+search string is not found the function returns -1.
+
+The function also accepts an optional position from which to begin the
+substring search. If the substring is the empty string, the index where the
+search starts is returned (zero or custom).
+
+ .indexOf() ->
+ .indexOf(, ) ->
+
+Examples:
+
+ 'hello mellow'.indexOf('') // returns 0
+ 'hello mellow'.indexOf('ello') // returns 1
+ 'hello mellow'.indexOf('jello') // returns -1
+ 'hello mellow'.indexOf('', 2) // returns 2
+ 'hello mellow'.indexOf('ello', 2) // returns 7
+ 'hello mellow'.indexOf('ello', 20) // error
+
+### Join
+
+Returns a new string where the elements of string list are concatenated.
+
+The function also accepts an optional separator which is placed between
+elements in the resulting string.
+
+ >.join() ->
+ >.join() ->
+
+Examples:
+
+ ['hello', 'mellow'].join() // returns 'hellomellow'
+ ['hello', 'mellow'].join(' ') // returns 'hello mellow'
+ [].join() // returns ''
+ [].join('/') // returns ''
+
+### LastIndexOf
+
+Returns the integer index of the last occurrence of the search string. If the
+search string is not found the function returns -1.
+
+The function also accepts an optional position which represents the last index
+to be considered as the beginning of the substring match. If the substring is
+the empty string, the index where the search starts is returned (string length
+or custom).
+
+ .lastIndexOf() ->
+ .lastIndexOf(, ) ->
+
+Examples:
+
+ 'hello mellow'.lastIndexOf('') // returns 12
+ 'hello mellow'.lastIndexOf('ello') // returns 7
+ 'hello mellow'.lastIndexOf('jello') // returns -1
+ 'hello mellow'.lastIndexOf('ello', 6) // returns 1
+ 'hello mellow'.lastIndexOf('ello', -1) // error
+
+### LowerAscii
+
+Returns a new string where all ASCII characters are lower-cased.
+
+This function does not perform Unicode case-mapping for characters outside the
+ASCII range.
+
+ .lowerAscii() ->
+
+Examples:
+
+ 'TacoCat'.lowerAscii() // returns 'tacocat'
+ 'TacoCÆt Xii'.lowerAscii() // returns 'tacocÆt xii'
+
+### Quote
+
+**Introduced in version 1**
+
+Takes the given string and makes it safe to print (without any formatting due to escape sequences).
+If any invalid UTF-8 characters are encountered, they are replaced with \uFFFD.
+
+ strings.quote()
+
+Examples:
+
+ strings.quote('single-quote with "double quote"') // returns '"single-quote with \"double quote\""'
+ strings.quote("two escape sequences \a\n") // returns '"two escape sequences \\a\\n"'
+
+### Replace
+
+Returns a new string based on the target, which replaces the occurrences of a
+search string with a replacement string if present. The function accepts an
+optional limit on the number of substring replacements to be made.
+
+When the replacement limit is 0, the result is the original string. When the
+limit is a negative number, the function behaves the same as replace all.
+
+ .replace(, ) ->
+ .replace(, , ) ->
+
+Examples:
+
+ 'hello hello'.replace('he', 'we') // returns 'wello wello'
+ 'hello hello'.replace('he', 'we', -1) // returns 'wello wello'
+ 'hello hello'.replace('he', 'we', 1) // returns 'wello hello'
+ 'hello hello'.replace('he', 'we', 0) // returns 'hello hello'
+
+### Split
+
+Returns a list of strings split from the input by the given separator. The
+function accepts an optional argument specifying a limit on the number of
+substrings produced by the split.
+
+When the split limit is 0, the result is an empty list. When the limit is 1,
+the result is the target string to split. When the limit is a negative
+number, the function behaves the same as split all.
+
+ .split() -> >
+ .split(, ) -> >
+
+Examples:
+
+ 'hello hello hello'.split(' ') // returns ['hello', 'hello', 'hello']
+ 'hello hello hello'.split(' ', 0) // returns []
+ 'hello hello hello'.split(' ', 1) // returns ['hello hello hello']
+ 'hello hello hello'.split(' ', 2) // returns ['hello', 'hello hello']
+ 'hello hello hello'.split(' ', -1) // returns ['hello', 'hello', 'hello']
+
+### Substring
+
+Returns the substring given a numeric range corresponding to character
+positions. Optionally may omit the trailing range for a substring from a given
+character position until the end of a string.
+
+Character offsets are 0-based with an inclusive start range and exclusive end
+range. It is an error to specify an end range that is lower than the start
+range, or for either the start or end index to be negative or exceed the string
+length.
+
+ .substring() ->
+ .substring(, ) ->
+
+Examples:
+
+ 'tacocat'.substring(4) // returns 'cat'
+ 'tacocat'.substring(0, 4) // returns 'taco'
+ 'tacocat'.substring(-1) // error
+ 'tacocat'.substring(2, 1) // error
+
+### Trim
+
+Returns a new string which removes the leading and trailing whitespace in the
+target string. The trim function uses the Unicode definition of whitespace
+which does not include the zero-width spaces. See:
+https://en.wikipedia.org/wiki/Whitespace_character#Unicode
+
+ .trim() ->
+
+Examples:
+
+ ' \ttrim\n '.trim() // returns 'trim'
+
+### UpperAscii
+
+Returns a new string where all ASCII characters are upper-cased.
+
+This function does not perform Unicode case-mapping for characters outside the
+ASCII range.
+
+ .upperAscii() ->
+
+Examples:
+
+ 'TacoCat'.upperAscii() // returns 'TACOCAT'
+ 'TacoCÆt Xii'.upperAscii() // returns 'TACOCÆT XII'
diff --git a/vendor/github.com/google/cel-go/ext/bindings.go b/vendor/github.com/google/cel-go/ext/bindings.go
new file mode 100644
index 000000000..4ac9a7f07
--- /dev/null
+++ b/vendor/github.com/google/cel-go/ext/bindings.go
@@ -0,0 +1,96 @@
+// Copyright 2023 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package ext
+
+import (
+ "github.com/google/cel-go/cel"
+
+ exprpb "google.golang.org/genproto/googleapis/api/expr/v1alpha1"
+)
+
+// Bindings returns a cel.EnvOption to configure support for local variable
+// bindings in expressions.
+//
+// # Cel.Bind
+//
+// Binds a simple identifier to an initialization expression which may be used
+// in a subsequenct result expression. Bindings may also be nested within each
+// other.
+//
+// cel.bind(, , )
+//
+// Examples:
+//
+// cel.bind(a, 'hello',
+// cel.bind(b, 'world', a + b + b + a)) // "helloworldworldhello"
+//
+// // Avoid a list allocation within the exists comprehension.
+// cel.bind(valid_values, [a, b, c],
+// [d, e, f].exists(elem, elem in valid_values))
+//
+// Local bindings are not guaranteed to be evaluated before use.
+func Bindings() cel.EnvOption {
+ return cel.Lib(celBindings{})
+}
+
+const (
+ celNamespace = "cel"
+ bindMacro = "bind"
+ unusedIterVar = "#unused"
+)
+
+type celBindings struct{}
+
+func (celBindings) LibraryName() string {
+ return "cel.lib.ext.cel.bindings"
+}
+
+func (celBindings) CompileOptions() []cel.EnvOption {
+ return []cel.EnvOption{
+ cel.Macros(
+ // cel.bind(var, , )
+ cel.NewReceiverMacro(bindMacro, 3, celBind),
+ ),
+ }
+}
+
+func (celBindings) ProgramOptions() []cel.ProgramOption {
+ return []cel.ProgramOption{}
+}
+
+func celBind(meh cel.MacroExprHelper, target *exprpb.Expr, args []*exprpb.Expr) (*exprpb.Expr, *cel.Error) {
+ if !macroTargetMatchesNamespace(celNamespace, target) {
+ return nil, nil
+ }
+ varIdent := args[0]
+ varName := ""
+ switch varIdent.GetExprKind().(type) {
+ case *exprpb.Expr_IdentExpr:
+ varName = varIdent.GetIdentExpr().GetName()
+ default:
+ return nil, meh.NewError(varIdent.GetId(), "cel.bind() variable names must be simple identifiers")
+ }
+ varInit := args[1]
+ resultExpr := args[2]
+ return meh.Fold(
+ unusedIterVar,
+ meh.NewList(),
+ varName,
+ varInit,
+ meh.LiteralBool(false),
+ meh.Ident(varName),
+ resultExpr,
+ ), nil
+}
diff --git a/vendor/github.com/google/cel-go/ext/encoders.go b/vendor/github.com/google/cel-go/ext/encoders.go
new file mode 100644
index 000000000..61ac0b777
--- /dev/null
+++ b/vendor/github.com/google/cel-go/ext/encoders.go
@@ -0,0 +1,87 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package ext
+
+import (
+ "encoding/base64"
+
+ "github.com/google/cel-go/cel"
+ "github.com/google/cel-go/common/types"
+ "github.com/google/cel-go/common/types/ref"
+)
+
+// Encoders returns a cel.EnvOption to configure extended functions for string, byte, and object
+// encodings.
+//
+// # Base64.Decode
+//
+// Decodes base64-encoded string to bytes.
+//
+// This function will return an error if the string input is not base64-encoded.
+//
+// base64.decode() ->
+//
+// Examples:
+//
+// base64.decode('aGVsbG8=') // return b'hello'
+// base64.decode('aGVsbG8') // error
+//
+// # Base64.Encode
+//
+// Encodes bytes to a base64-encoded string.
+//
+// base64.encode() ->
+//
+// Examples:
+//
+// base64.encode(b'hello') // return b'aGVsbG8='
+func Encoders() cel.EnvOption {
+ return cel.Lib(encoderLib{})
+}
+
+type encoderLib struct{}
+
+func (encoderLib) LibraryName() string {
+ return "cel.lib.ext.encoders"
+}
+
+func (encoderLib) CompileOptions() []cel.EnvOption {
+ return []cel.EnvOption{
+ cel.Function("base64.decode",
+ cel.Overload("base64_decode_string", []*cel.Type{cel.StringType}, cel.BytesType,
+ cel.UnaryBinding(func(str ref.Val) ref.Val {
+ s := str.(types.String)
+ return bytesOrError(base64DecodeString(string(s)))
+ }))),
+ cel.Function("base64.encode",
+ cel.Overload("base64_encode_bytes", []*cel.Type{cel.BytesType}, cel.StringType,
+ cel.UnaryBinding(func(bytes ref.Val) ref.Val {
+ b := bytes.(types.Bytes)
+ return stringOrError(base64EncodeBytes([]byte(b)))
+ }))),
+ }
+}
+
+func (encoderLib) ProgramOptions() []cel.ProgramOption {
+ return []cel.ProgramOption{}
+}
+
+func base64DecodeString(str string) ([]byte, error) {
+ return base64.StdEncoding.DecodeString(str)
+}
+
+func base64EncodeBytes(bytes []byte) (string, error) {
+ return base64.StdEncoding.EncodeToString(bytes), nil
+}
diff --git a/vendor/github.com/google/cel-go/ext/guards.go b/vendor/github.com/google/cel-go/ext/guards.go
new file mode 100644
index 000000000..785c8675b
--- /dev/null
+++ b/vendor/github.com/google/cel-go/ext/guards.go
@@ -0,0 +1,64 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package ext
+
+import (
+ "github.com/google/cel-go/common/types"
+ "github.com/google/cel-go/common/types/ref"
+
+ exprpb "google.golang.org/genproto/googleapis/api/expr/v1alpha1"
+)
+
+// function invocation guards for common call signatures within extension functions.
+
+func intOrError(i int64, err error) ref.Val {
+ if err != nil {
+ return types.NewErr(err.Error())
+ }
+ return types.Int(i)
+}
+
+func bytesOrError(bytes []byte, err error) ref.Val {
+ if err != nil {
+ return types.NewErr(err.Error())
+ }
+ return types.Bytes(bytes)
+}
+
+func stringOrError(str string, err error) ref.Val {
+ if err != nil {
+ return types.NewErr(err.Error())
+ }
+ return types.String(str)
+}
+
+func listStringOrError(strs []string, err error) ref.Val {
+ if err != nil {
+ return types.NewErr(err.Error())
+ }
+ return types.DefaultTypeAdapter.NativeToValue(strs)
+}
+
+func macroTargetMatchesNamespace(ns string, target *exprpb.Expr) bool {
+ switch target.GetExprKind().(type) {
+ case *exprpb.Expr_IdentExpr:
+ if target.GetIdentExpr().GetName() != ns {
+ return false
+ }
+ return true
+ default:
+ return false
+ }
+}
diff --git a/vendor/github.com/google/cel-go/ext/lists.go b/vendor/github.com/google/cel-go/ext/lists.go
new file mode 100644
index 000000000..08751d08a
--- /dev/null
+++ b/vendor/github.com/google/cel-go/ext/lists.go
@@ -0,0 +1,94 @@
+// Copyright 2023 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package ext
+
+import (
+ "fmt"
+
+ "github.com/google/cel-go/cel"
+ "github.com/google/cel-go/common/types"
+ "github.com/google/cel-go/common/types/ref"
+ "github.com/google/cel-go/common/types/traits"
+)
+
+// Lists returns a cel.EnvOption to configure extended functions for list manipulation.
+// As a general note, all indices are zero-based.
+// # Slice
+//
+// Returns a new sub-list using the indexes provided.
+//
+// .slice(, ) ->
+//
+// Examples:
+//
+// [1,2,3,4].slice(1, 3) // return [2, 3]
+// [1,2,3,4].slice(2, 4) // return [3 ,4]
+func Lists() cel.EnvOption {
+ return cel.Lib(listsLib{})
+}
+
+type listsLib struct{}
+
+// LibraryName implements the SingletonLibrary interface method.
+func (listsLib) LibraryName() string {
+ return "cel.lib.ext.lists"
+}
+
+// CompileOptions implements the Library interface method.
+func (listsLib) CompileOptions() []cel.EnvOption {
+ listType := cel.ListType(cel.TypeParamType("T"))
+ return []cel.EnvOption{
+ cel.Function("slice",
+ cel.MemberOverload("list_slice",
+ []*cel.Type{listType, cel.IntType, cel.IntType}, listType,
+ cel.FunctionBinding(func(args ...ref.Val) ref.Val {
+ list := args[0].(traits.Lister)
+ start := args[1].(types.Int)
+ end := args[2].(types.Int)
+ result, err := slice(list, start, end)
+ if err != nil {
+ return types.WrapErr(err)
+ }
+ return result
+ }),
+ ),
+ ),
+ }
+}
+
+// ProgramOptions implements the Library interface method.
+func (listsLib) ProgramOptions() []cel.ProgramOption {
+ return []cel.ProgramOption{}
+}
+
+func slice(list traits.Lister, start, end types.Int) (ref.Val, error) {
+ listLength := list.Size().(types.Int)
+ if start < 0 || end < 0 {
+ return nil, fmt.Errorf("cannot slice(%d, %d), negative indexes not supported", start, end)
+ }
+ if start > end {
+ return nil, fmt.Errorf("cannot slice(%d, %d), start index must be less than or equal to end index", start, end)
+ }
+ if listLength < end {
+ return nil, fmt.Errorf("cannot slice(%d, %d), list is length %d", start, end, listLength)
+ }
+
+ var newList []ref.Val
+ for i := types.Int(start); i < end; i++ {
+ val := list.Get(i)
+ newList = append(newList, val)
+ }
+ return types.DefaultTypeAdapter.NativeToValue(newList), nil
+}
diff --git a/vendor/github.com/google/cel-go/ext/math.go b/vendor/github.com/google/cel-go/ext/math.go
new file mode 100644
index 000000000..0b9a36103
--- /dev/null
+++ b/vendor/github.com/google/cel-go/ext/math.go
@@ -0,0 +1,373 @@
+// Copyright 2022 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package ext
+
+import (
+ "fmt"
+ "strings"
+
+ "github.com/google/cel-go/cel"
+ "github.com/google/cel-go/common/types"
+ "github.com/google/cel-go/common/types/ref"
+ "github.com/google/cel-go/common/types/traits"
+
+ exprpb "google.golang.org/genproto/googleapis/api/expr/v1alpha1"
+)
+
+// Math returns a cel.EnvOption to configure namespaced math helper macros and
+// functions.
+//
+// Note, all macros use the 'math' namespace; however, at the time of macro
+// expansion the namespace looks just like any other identifier. If you are
+// currently using a variable named 'math', the macro will likely work just as
+// intended; however, there is some chance for collision.
+//
+// # Math.Greatest
+//
+// Returns the greatest valued number present in the arguments to the macro.
+//
+// Greatest is a variable argument count macro which must take at least one
+// argument. Simple numeric and list literals are supported as valid argument
+// types; however, other literals will be flagged as errors during macro
+// expansion. If the argument expression does not resolve to a numeric or
+// list(numeric) type during type-checking, or during runtime then an error
+// will be produced. If a list argument is empty, this too will produce an
+// error.
+//
+// math.greatest(, ...) ->
+//
+// Examples:
+//
+// math.greatest(1) // 1
+// math.greatest(1u, 2u) // 2u
+// math.greatest(-42.0, -21.5, -100.0) // -21.5
+// math.greatest([-42.0, -21.5, -100.0]) // -21.5
+// math.greatest(numbers) // numbers must be list(numeric)
+//
+// math.greatest() // parse error
+// math.greatest('string') // parse error
+// math.greatest(a, b) // check-time error if a or b is non-numeric
+// math.greatest(dyn('string')) // runtime error
+//
+// # Math.Least
+//
+// Returns the least valued number present in the arguments to the macro.
+//
+// Least is a variable argument count macro which must take at least one
+// argument. Simple numeric and list literals are supported as valid argument
+// types; however, other literals will be flagged as errors during macro
+// expansion. If the argument expression does not resolve to a numeric or
+// list(numeric) type during type-checking, or during runtime then an error
+// will be produced. If a list argument is empty, this too will produce an
+// error.
+//
+// math.least(, ...) ->
+//
+// Examples:
+//
+// math.least(1) // 1
+// math.least(1u, 2u) // 1u
+// math.least(-42.0, -21.5, -100.0) // -100.0
+// math.least([-42.0, -21.5, -100.0]) // -100.0
+// math.least(numbers) // numbers must be list(numeric)
+//
+// math.least() // parse error
+// math.least('string') // parse error
+// math.least(a, b) // check-time error if a or b is non-numeric
+// math.least(dyn('string')) // runtime error
+func Math() cel.EnvOption {
+ return cel.Lib(mathLib{})
+}
+
+const (
+ mathNamespace = "math"
+ leastMacro = "least"
+ greatestMacro = "greatest"
+ minFunc = "math.@min"
+ maxFunc = "math.@max"
+)
+
+type mathLib struct{}
+
+// LibraryName implements the SingletonLibrary interface method.
+func (mathLib) LibraryName() string {
+ return "cel.lib.ext.math"
+}
+
+// CompileOptions implements the Library interface method.
+func (mathLib) CompileOptions() []cel.EnvOption {
+ return []cel.EnvOption{
+ cel.Macros(
+ // math.least(num, ...)
+ cel.NewReceiverVarArgMacro(leastMacro, mathLeast),
+ // math.greatest(num, ...)
+ cel.NewReceiverVarArgMacro(greatestMacro, mathGreatest),
+ ),
+ cel.Function(minFunc,
+ cel.Overload("math_@min_double", []*cel.Type{cel.DoubleType}, cel.DoubleType,
+ cel.UnaryBinding(identity)),
+ cel.Overload("math_@min_int", []*cel.Type{cel.IntType}, cel.IntType,
+ cel.UnaryBinding(identity)),
+ cel.Overload("math_@min_uint", []*cel.Type{cel.UintType}, cel.UintType,
+ cel.UnaryBinding(identity)),
+ cel.Overload("math_@min_double_double", []*cel.Type{cel.DoubleType, cel.DoubleType}, cel.DoubleType,
+ cel.BinaryBinding(minPair)),
+ cel.Overload("math_@min_int_int", []*cel.Type{cel.IntType, cel.IntType}, cel.IntType,
+ cel.BinaryBinding(minPair)),
+ cel.Overload("math_@min_uint_uint", []*cel.Type{cel.UintType, cel.UintType}, cel.UintType,
+ cel.BinaryBinding(minPair)),
+ cel.Overload("math_@min_int_uint", []*cel.Type{cel.IntType, cel.UintType}, cel.DynType,
+ cel.BinaryBinding(minPair)),
+ cel.Overload("math_@min_int_double", []*cel.Type{cel.IntType, cel.DoubleType}, cel.DynType,
+ cel.BinaryBinding(minPair)),
+ cel.Overload("math_@min_double_int", []*cel.Type{cel.DoubleType, cel.IntType}, cel.DynType,
+ cel.BinaryBinding(minPair)),
+ cel.Overload("math_@min_double_uint", []*cel.Type{cel.DoubleType, cel.UintType}, cel.DynType,
+ cel.BinaryBinding(minPair)),
+ cel.Overload("math_@min_uint_int", []*cel.Type{cel.UintType, cel.IntType}, cel.DynType,
+ cel.BinaryBinding(minPair)),
+ cel.Overload("math_@min_uint_double", []*cel.Type{cel.UintType, cel.DoubleType}, cel.DynType,
+ cel.BinaryBinding(minPair)),
+ cel.Overload("math_@min_list_double", []*cel.Type{cel.ListType(cel.DoubleType)}, cel.DoubleType,
+ cel.UnaryBinding(minList)),
+ cel.Overload("math_@min_list_int", []*cel.Type{cel.ListType(cel.IntType)}, cel.IntType,
+ cel.UnaryBinding(minList)),
+ cel.Overload("math_@min_list_uint", []*cel.Type{cel.ListType(cel.UintType)}, cel.UintType,
+ cel.UnaryBinding(minList)),
+ ),
+ cel.Function(maxFunc,
+ cel.Overload("math_@max_double", []*cel.Type{cel.DoubleType}, cel.DoubleType,
+ cel.UnaryBinding(identity)),
+ cel.Overload("math_@max_int", []*cel.Type{cel.IntType}, cel.IntType,
+ cel.UnaryBinding(identity)),
+ cel.Overload("math_@max_uint", []*cel.Type{cel.UintType}, cel.UintType,
+ cel.UnaryBinding(identity)),
+ cel.Overload("math_@max_double_double", []*cel.Type{cel.DoubleType, cel.DoubleType}, cel.DoubleType,
+ cel.BinaryBinding(maxPair)),
+ cel.Overload("math_@max_int_int", []*cel.Type{cel.IntType, cel.IntType}, cel.IntType,
+ cel.BinaryBinding(maxPair)),
+ cel.Overload("math_@max_uint_uint", []*cel.Type{cel.UintType, cel.UintType}, cel.UintType,
+ cel.BinaryBinding(maxPair)),
+ cel.Overload("math_@max_int_uint", []*cel.Type{cel.IntType, cel.UintType}, cel.DynType,
+ cel.BinaryBinding(maxPair)),
+ cel.Overload("math_@max_int_double", []*cel.Type{cel.IntType, cel.DoubleType}, cel.DynType,
+ cel.BinaryBinding(maxPair)),
+ cel.Overload("math_@max_double_int", []*cel.Type{cel.DoubleType, cel.IntType}, cel.DynType,
+ cel.BinaryBinding(maxPair)),
+ cel.Overload("math_@max_double_uint", []*cel.Type{cel.DoubleType, cel.UintType}, cel.DynType,
+ cel.BinaryBinding(maxPair)),
+ cel.Overload("math_@max_uint_int", []*cel.Type{cel.UintType, cel.IntType}, cel.DynType,
+ cel.BinaryBinding(maxPair)),
+ cel.Overload("math_@max_uint_double", []*cel.Type{cel.UintType, cel.DoubleType}, cel.DynType,
+ cel.BinaryBinding(maxPair)),
+ cel.Overload("math_@max_list_double", []*cel.Type{cel.ListType(cel.DoubleType)}, cel.DoubleType,
+ cel.UnaryBinding(maxList)),
+ cel.Overload("math_@max_list_int", []*cel.Type{cel.ListType(cel.IntType)}, cel.IntType,
+ cel.UnaryBinding(maxList)),
+ cel.Overload("math_@max_list_uint", []*cel.Type{cel.ListType(cel.UintType)}, cel.UintType,
+ cel.UnaryBinding(maxList)),
+ ),
+ }
+}
+
+// ProgramOptions implements the Library interface method.
+func (mathLib) ProgramOptions() []cel.ProgramOption {
+ return []cel.ProgramOption{}
+}
+
+func mathLeast(meh cel.MacroExprHelper, target *exprpb.Expr, args []*exprpb.Expr) (*exprpb.Expr, *cel.Error) {
+ if !macroTargetMatchesNamespace(mathNamespace, target) {
+ return nil, nil
+ }
+ switch len(args) {
+ case 0:
+ return nil, meh.NewError(target.GetId(), "math.least() requires at least one argument")
+ case 1:
+ if isListLiteralWithValidArgs(args[0]) || isValidArgType(args[0]) {
+ return meh.GlobalCall(minFunc, args[0]), nil
+ }
+ return nil, meh.NewError(args[0].GetId(), "math.least() invalid single argument value")
+ case 2:
+ err := checkInvalidArgs(meh, "math.least()", args)
+ if err != nil {
+ return nil, err
+ }
+ return meh.GlobalCall(minFunc, args...), nil
+ default:
+ err := checkInvalidArgs(meh, "math.least()", args)
+ if err != nil {
+ return nil, err
+ }
+ return meh.GlobalCall(minFunc, meh.NewList(args...)), nil
+ }
+}
+
+func mathGreatest(meh cel.MacroExprHelper, target *exprpb.Expr, args []*exprpb.Expr) (*exprpb.Expr, *cel.Error) {
+ if !macroTargetMatchesNamespace(mathNamespace, target) {
+ return nil, nil
+ }
+ switch len(args) {
+ case 0:
+ return nil, meh.NewError(target.GetId(), "math.greatest() requires at least one argument")
+ case 1:
+ if isListLiteralWithValidArgs(args[0]) || isValidArgType(args[0]) {
+ return meh.GlobalCall(maxFunc, args[0]), nil
+ }
+ return nil, meh.NewError(args[0].GetId(), "math.greatest() invalid single argument value")
+ case 2:
+ err := checkInvalidArgs(meh, "math.greatest()", args)
+ if err != nil {
+ return nil, err
+ }
+ return meh.GlobalCall(maxFunc, args...), nil
+ default:
+ err := checkInvalidArgs(meh, "math.greatest()", args)
+ if err != nil {
+ return nil, err
+ }
+ return meh.GlobalCall(maxFunc, meh.NewList(args...)), nil
+ }
+}
+
+func identity(val ref.Val) ref.Val {
+ return val
+}
+
+func minPair(first, second ref.Val) ref.Val {
+ cmp, ok := first.(traits.Comparer)
+ if !ok {
+ return types.MaybeNoSuchOverloadErr(first)
+ }
+ out := cmp.Compare(second)
+ if types.IsUnknownOrError(out) {
+ return maybeSuffixError(out, "math.@min")
+ }
+ if out == types.IntOne {
+ return second
+ }
+ return first
+}
+
+func minList(numList ref.Val) ref.Val {
+ l := numList.(traits.Lister)
+ size := l.Size().(types.Int)
+ if size == types.IntZero {
+ return types.NewErr("math.@min(list) argument must not be empty")
+ }
+ min := l.Get(types.IntZero)
+ for i := types.IntOne; i < size; i++ {
+ min = minPair(min, l.Get(i))
+ }
+ switch min.Type() {
+ case types.IntType, types.DoubleType, types.UintType, types.UnknownType:
+ return min
+ default:
+ return types.NewErr("no such overload: math.@min")
+ }
+}
+
+func maxPair(first, second ref.Val) ref.Val {
+ cmp, ok := first.(traits.Comparer)
+ if !ok {
+ return types.MaybeNoSuchOverloadErr(first)
+ }
+ out := cmp.Compare(second)
+ if types.IsUnknownOrError(out) {
+ return maybeSuffixError(out, "math.@max")
+ }
+ if out == types.IntNegOne {
+ return second
+ }
+ return first
+}
+
+func maxList(numList ref.Val) ref.Val {
+ l := numList.(traits.Lister)
+ size := l.Size().(types.Int)
+ if size == types.IntZero {
+ return types.NewErr("math.@max(list) argument must not be empty")
+ }
+ max := l.Get(types.IntZero)
+ for i := types.IntOne; i < size; i++ {
+ max = maxPair(max, l.Get(i))
+ }
+ switch max.Type() {
+ case types.IntType, types.DoubleType, types.UintType, types.UnknownType:
+ return max
+ default:
+ return types.NewErr("no such overload: math.@max")
+ }
+}
+
+func checkInvalidArgs(meh cel.MacroExprHelper, funcName string, args []*exprpb.Expr) *cel.Error {
+ for _, arg := range args {
+ err := checkInvalidArgLiteral(funcName, arg)
+ if err != nil {
+ return meh.NewError(arg.GetId(), err.Error())
+ }
+ }
+ return nil
+}
+
+func checkInvalidArgLiteral(funcName string, arg *exprpb.Expr) error {
+ if !isValidArgType(arg) {
+ return fmt.Errorf("%s simple literal arguments must be numeric", funcName)
+ }
+ return nil
+}
+
+func isValidArgType(arg *exprpb.Expr) bool {
+ switch arg.GetExprKind().(type) {
+ case *exprpb.Expr_ConstExpr:
+ c := arg.GetConstExpr()
+ switch c.GetConstantKind().(type) {
+ case *exprpb.Constant_DoubleValue, *exprpb.Constant_Int64Value, *exprpb.Constant_Uint64Value:
+ return true
+ default:
+ return false
+ }
+ case *exprpb.Expr_ListExpr, *exprpb.Expr_StructExpr:
+ return false
+ default:
+ return true
+ }
+}
+
+func isListLiteralWithValidArgs(arg *exprpb.Expr) bool {
+ switch arg.GetExprKind().(type) {
+ case *exprpb.Expr_ListExpr:
+ list := arg.GetListExpr()
+ if len(list.GetElements()) == 0 {
+ return false
+ }
+ for _, e := range list.GetElements() {
+ if !isValidArgType(e) {
+ return false
+ }
+ }
+ return true
+ }
+ return false
+}
+
+func maybeSuffixError(val ref.Val, suffix string) ref.Val {
+ if types.IsError(val) {
+ msg := val.(*types.Err).String()
+ if !strings.Contains(msg, suffix) {
+ return types.NewErr("%s: %s", msg, suffix)
+ }
+ }
+ return val
+}
diff --git a/vendor/github.com/google/cel-go/ext/native.go b/vendor/github.com/google/cel-go/ext/native.go
new file mode 100644
index 000000000..0b5fc38ca
--- /dev/null
+++ b/vendor/github.com/google/cel-go/ext/native.go
@@ -0,0 +1,574 @@
+// Copyright 2022 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package ext
+
+import (
+ "fmt"
+ "reflect"
+ "strings"
+ "time"
+
+ "google.golang.org/protobuf/proto"
+ "google.golang.org/protobuf/reflect/protoreflect"
+
+ "github.com/google/cel-go/cel"
+ "github.com/google/cel-go/common/types"
+ "github.com/google/cel-go/common/types/pb"
+ "github.com/google/cel-go/common/types/ref"
+ "github.com/google/cel-go/common/types/traits"
+
+ structpb "google.golang.org/protobuf/types/known/structpb"
+)
+
+var (
+ nativeObjTraitMask = traits.FieldTesterType | traits.IndexerType
+ jsonValueType = reflect.TypeOf(&structpb.Value{})
+ jsonStructType = reflect.TypeOf(&structpb.Struct{})
+)
+
+// NativeTypes creates a type provider which uses reflect.Type and reflect.Value instances
+// to produce type definitions that can be used within CEL.
+//
+// All struct types in Go are exposed to CEL via their simple package name and struct type name:
+//
+// ```go
+// package identity
+//
+// type Account struct {
+// ID int
+// }
+//
+// ```
+//
+// The type `identity.Account` would be exported to CEL using the same qualified name, e.g.
+// `identity.Account{ID: 1234}` would create a new `Account` instance with the `ID` field
+// populated.
+//
+// Only exported fields are exposed via NativeTypes, and the type-mapping between Go and CEL
+// is as follows:
+//
+// | Go type | CEL type |
+// |-------------------------------------|-----------|
+// | bool | bool |
+// | []byte | bytes |
+// | float32, float64 | double |
+// | int, int8, int16, int32, int64 | int |
+// | string | string |
+// | uint, uint8, uint16, uint32, uint64 | uint |
+// | time.Duration | duration |
+// | time.Time | timestamp |
+// | array, slice | list |
+// | map | map |
+//
+// Please note, if you intend to configure support for proto messages in addition to native
+// types, you will need to provide the protobuf types before the golang native types. The
+// same advice holds if you are using custom type adapters and type providers. The native type
+// provider composes over whichever type adapter and provider is configured in the cel.Env at
+// the time that it is invoked.
+func NativeTypes(refTypes ...any) cel.EnvOption {
+ return func(env *cel.Env) (*cel.Env, error) {
+ tp, err := newNativeTypeProvider(env.CELTypeAdapter(), env.CELTypeProvider(), refTypes...)
+ if err != nil {
+ return nil, err
+ }
+ env, err = cel.CustomTypeAdapter(tp)(env)
+ if err != nil {
+ return nil, err
+ }
+ return cel.CustomTypeProvider(tp)(env)
+ }
+}
+
+func newNativeTypeProvider(adapter types.Adapter, provider types.Provider, refTypes ...any) (*nativeTypeProvider, error) {
+ nativeTypes := make(map[string]*nativeType, len(refTypes))
+ for _, refType := range refTypes {
+ switch rt := refType.(type) {
+ case reflect.Type:
+ t, err := newNativeType(rt)
+ if err != nil {
+ return nil, err
+ }
+ nativeTypes[t.TypeName()] = t
+ case reflect.Value:
+ t, err := newNativeType(rt.Type())
+ if err != nil {
+ return nil, err
+ }
+ nativeTypes[t.TypeName()] = t
+ default:
+ return nil, fmt.Errorf("unsupported native type: %v (%T) must be reflect.Type or reflect.Value", rt, rt)
+ }
+ }
+ return &nativeTypeProvider{
+ nativeTypes: nativeTypes,
+ baseAdapter: adapter,
+ baseProvider: provider,
+ }, nil
+}
+
+type nativeTypeProvider struct {
+ nativeTypes map[string]*nativeType
+ baseAdapter types.Adapter
+ baseProvider types.Provider
+}
+
+// EnumValue proxies to the types.Provider configured at the times the NativeTypes
+// option was configured.
+func (tp *nativeTypeProvider) EnumValue(enumName string) ref.Val {
+ return tp.baseProvider.EnumValue(enumName)
+}
+
+// FindIdent looks up natives type instances by qualified identifier, and if not found
+// proxies to the composed types.Provider.
+func (tp *nativeTypeProvider) FindIdent(typeName string) (ref.Val, bool) {
+ if t, found := tp.nativeTypes[typeName]; found {
+ return t, true
+ }
+ return tp.baseProvider.FindIdent(typeName)
+}
+
+// FindStructType looks up the CEL type definition by qualified identifier, and if not found
+// proxies to the composed types.Provider.
+func (tp *nativeTypeProvider) FindStructType(typeName string) (*types.Type, bool) {
+ if _, found := tp.nativeTypes[typeName]; found {
+ return types.NewTypeTypeWithParam(types.NewObjectType(typeName)), true
+ }
+ if celType, found := tp.baseProvider.FindStructType(typeName); found {
+ return celType, true
+ }
+ return tp.baseProvider.FindStructType(typeName)
+}
+
+// FindStructFieldType looks up a native type's field definition, and if the type name is not a native
+// type then proxies to the composed types.Provider
+func (tp *nativeTypeProvider) FindStructFieldType(typeName, fieldName string) (*types.FieldType, bool) {
+ t, found := tp.nativeTypes[typeName]
+ if !found {
+ return tp.baseProvider.FindStructFieldType(typeName, fieldName)
+ }
+ refField, isDefined := t.hasField(fieldName)
+ if !found || !isDefined {
+ return nil, false
+ }
+ celType, ok := convertToCelType(refField.Type)
+ if !ok {
+ return nil, false
+ }
+ return &types.FieldType{
+ Type: celType,
+ IsSet: func(obj any) bool {
+ refVal := reflect.Indirect(reflect.ValueOf(obj))
+ refField := refVal.FieldByName(fieldName)
+ return !refField.IsZero()
+ },
+ GetFrom: func(obj any) (any, error) {
+ refVal := reflect.Indirect(reflect.ValueOf(obj))
+ refField := refVal.FieldByName(fieldName)
+ return getFieldValue(tp, refField), nil
+ },
+ }, true
+}
+
+// NewValue implements the ref.TypeProvider interface method.
+func (tp *nativeTypeProvider) NewValue(typeName string, fields map[string]ref.Val) ref.Val {
+ t, found := tp.nativeTypes[typeName]
+ if !found {
+ return tp.baseProvider.NewValue(typeName, fields)
+ }
+ refPtr := reflect.New(t.refType)
+ refVal := refPtr.Elem()
+ for fieldName, val := range fields {
+ refFieldDef, isDefined := t.hasField(fieldName)
+ if !isDefined {
+ return types.NewErr("no such field: %s", fieldName)
+ }
+ fieldVal, err := val.ConvertToNative(refFieldDef.Type)
+ if err != nil {
+ return types.NewErr(err.Error())
+ }
+ refField := refVal.FieldByIndex(refFieldDef.Index)
+ refFieldVal := reflect.ValueOf(fieldVal)
+ refField.Set(refFieldVal)
+ }
+ return tp.NativeToValue(refPtr.Interface())
+}
+
+// NewValue adapts native values to CEL values and will proxy to the composed type adapter
+// for non-native types.
+func (tp *nativeTypeProvider) NativeToValue(val any) ref.Val {
+ if val == nil {
+ return types.NullValue
+ }
+ if v, ok := val.(ref.Val); ok {
+ return v
+ }
+ rawVal := reflect.ValueOf(val)
+ refVal := rawVal
+ if refVal.Kind() == reflect.Ptr {
+ refVal = reflect.Indirect(refVal)
+ }
+ // This isn't quite right if you're also supporting proto,
+ // but maybe an acceptable limitation.
+ switch refVal.Kind() {
+ case reflect.Array, reflect.Slice:
+ switch val := val.(type) {
+ case []byte:
+ return tp.baseAdapter.NativeToValue(val)
+ default:
+ return types.NewDynamicList(tp, val)
+ }
+ case reflect.Map:
+ return types.NewDynamicMap(tp, val)
+ case reflect.Struct:
+ switch val := val.(type) {
+ case proto.Message, *pb.Map, protoreflect.List, protoreflect.Message, protoreflect.Value,
+ time.Time:
+ return tp.baseAdapter.NativeToValue(val)
+ default:
+ return newNativeObject(tp, val, rawVal)
+ }
+ default:
+ return tp.baseAdapter.NativeToValue(val)
+ }
+}
+
+func convertToCelType(refType reflect.Type) (*cel.Type, bool) {
+ switch refType.Kind() {
+ case reflect.Bool:
+ return cel.BoolType, true
+ case reflect.Float32, reflect.Float64:
+ return cel.DoubleType, true
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ if refType == durationType {
+ return cel.DurationType, true
+ }
+ return cel.IntType, true
+ case reflect.String:
+ return cel.StringType, true
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+ return cel.UintType, true
+ case reflect.Array, reflect.Slice:
+ refElem := refType.Elem()
+ if refElem == reflect.TypeOf(byte(0)) {
+ return cel.BytesType, true
+ }
+ elemType, ok := convertToCelType(refElem)
+ if !ok {
+ return nil, false
+ }
+ return cel.ListType(elemType), true
+ case reflect.Map:
+ keyType, ok := convertToCelType(refType.Key())
+ if !ok {
+ return nil, false
+ }
+ // Ensure the key type is a int, bool, uint, string
+ elemType, ok := convertToCelType(refType.Elem())
+ if !ok {
+ return nil, false
+ }
+ return cel.MapType(keyType, elemType), true
+ case reflect.Struct:
+ if refType == timestampType {
+ return cel.TimestampType, true
+ }
+ return cel.ObjectType(
+ fmt.Sprintf("%s.%s", simplePkgAlias(refType.PkgPath()), refType.Name()),
+ ), true
+ case reflect.Pointer:
+ if refType.Implements(pbMsgInterfaceType) {
+ pbMsg := reflect.New(refType.Elem()).Interface().(protoreflect.ProtoMessage)
+ return cel.ObjectType(string(pbMsg.ProtoReflect().Descriptor().FullName())), true
+ }
+ return convertToCelType(refType.Elem())
+ }
+ return nil, false
+}
+
+func newNativeObject(adapter types.Adapter, val any, refValue reflect.Value) ref.Val {
+ valType, err := newNativeType(refValue.Type())
+ if err != nil {
+ return types.NewErr(err.Error())
+ }
+ return &nativeObj{
+ Adapter: adapter,
+ val: val,
+ valType: valType,
+ refValue: refValue,
+ }
+}
+
+type nativeObj struct {
+ types.Adapter
+ val any
+ valType *nativeType
+ refValue reflect.Value
+}
+
+// ConvertToNative implements the ref.Val interface method.
+//
+// CEL does not have a notion of pointers, so whether a field is a pointer or value
+// is handled as part of this conversion step.
+func (o *nativeObj) ConvertToNative(typeDesc reflect.Type) (any, error) {
+ if o.refValue.Type() == typeDesc {
+ return o.val, nil
+ }
+ if o.refValue.Kind() == reflect.Pointer && o.refValue.Type().Elem() == typeDesc {
+ return o.refValue.Elem().Interface(), nil
+ }
+ if typeDesc.Kind() == reflect.Pointer && o.refValue.Type() == typeDesc.Elem() {
+ ptr := reflect.New(typeDesc.Elem())
+ ptr.Elem().Set(o.refValue)
+ return ptr.Interface(), nil
+ }
+ switch typeDesc {
+ case jsonValueType:
+ jsonStruct, err := o.ConvertToNative(jsonStructType)
+ if err != nil {
+ return nil, err
+ }
+ return structpb.NewStructValue(jsonStruct.(*structpb.Struct)), nil
+ case jsonStructType:
+ refVal := reflect.Indirect(o.refValue)
+ refType := refVal.Type()
+ fields := make(map[string]*structpb.Value, refVal.NumField())
+ for i := 0; i < refVal.NumField(); i++ {
+ fieldType := refType.Field(i)
+ fieldValue := refVal.Field(i)
+ if !fieldValue.IsValid() || fieldValue.IsZero() {
+ continue
+ }
+ fieldCELVal := o.NativeToValue(fieldValue.Interface())
+ fieldJSONVal, err := fieldCELVal.ConvertToNative(jsonValueType)
+ if err != nil {
+ return nil, err
+ }
+ fields[fieldType.Name] = fieldJSONVal.(*structpb.Value)
+ }
+ return &structpb.Struct{Fields: fields}, nil
+ }
+ return nil, fmt.Errorf("type conversion error from '%v' to '%v'", o.Type(), typeDesc)
+}
+
+// ConvertToType implements the ref.Val interface method.
+func (o *nativeObj) ConvertToType(typeVal ref.Type) ref.Val {
+ switch typeVal {
+ case types.TypeType:
+ return o.valType
+ default:
+ if typeVal.TypeName() == o.valType.typeName {
+ return o
+ }
+ }
+ return types.NewErr("type conversion error from '%s' to '%s'", o.Type(), typeVal)
+}
+
+// Equal implements the ref.Val interface method.
+//
+// Note, that in Golang a pointer to a value is not equal to the value it contains.
+// In CEL pointers and values to which they point are equal.
+func (o *nativeObj) Equal(other ref.Val) ref.Val {
+ otherNtv, ok := other.(*nativeObj)
+ if !ok {
+ return types.False
+ }
+ val := o.val
+ otherVal := otherNtv.val
+ refVal := o.refValue
+ otherRefVal := otherNtv.refValue
+ if refVal.Kind() != otherRefVal.Kind() {
+ if refVal.Kind() == reflect.Pointer {
+ val = refVal.Elem().Interface()
+ } else if otherRefVal.Kind() == reflect.Pointer {
+ otherVal = otherRefVal.Elem().Interface()
+ }
+ }
+ return types.Bool(reflect.DeepEqual(val, otherVal))
+}
+
+// IsZeroValue indicates whether the contained Golang value is a zero value.
+//
+// Golang largely follows proto3 semantics for zero values.
+func (o *nativeObj) IsZeroValue() bool {
+ return reflect.Indirect(o.refValue).IsZero()
+}
+
+// IsSet tests whether a field which is defined is set to a non-default value.
+func (o *nativeObj) IsSet(field ref.Val) ref.Val {
+ refField, refErr := o.getReflectedField(field)
+ if refErr != nil {
+ return refErr
+ }
+ return types.Bool(!refField.IsZero())
+}
+
+// Get returns the value fo a field name.
+func (o *nativeObj) Get(field ref.Val) ref.Val {
+ refField, refErr := o.getReflectedField(field)
+ if refErr != nil {
+ return refErr
+ }
+ return adaptFieldValue(o, refField)
+}
+
+func (o *nativeObj) getReflectedField(field ref.Val) (reflect.Value, ref.Val) {
+ fieldName, ok := field.(types.String)
+ if !ok {
+ return reflect.Value{}, types.MaybeNoSuchOverloadErr(field)
+ }
+ fieldNameStr := string(fieldName)
+ refField, isDefined := o.valType.hasField(fieldNameStr)
+ if !isDefined {
+ return reflect.Value{}, types.NewErr("no such field: %s", fieldName)
+ }
+ refVal := reflect.Indirect(o.refValue)
+ return refVal.FieldByIndex(refField.Index), nil
+}
+
+// Type implements the ref.Val interface method.
+func (o *nativeObj) Type() ref.Type {
+ return o.valType
+}
+
+// Value implements the ref.Val interface method.
+func (o *nativeObj) Value() any {
+ return o.val
+}
+
+func newNativeType(rawType reflect.Type) (*nativeType, error) {
+ refType := rawType
+ if refType.Kind() == reflect.Pointer {
+ refType = refType.Elem()
+ }
+ if !isValidObjectType(refType) {
+ return nil, fmt.Errorf("unsupported reflect.Type %v, must be reflect.Struct", rawType)
+ }
+ return &nativeType{
+ typeName: fmt.Sprintf("%s.%s", simplePkgAlias(refType.PkgPath()), refType.Name()),
+ refType: refType,
+ }, nil
+}
+
+type nativeType struct {
+ typeName string
+ refType reflect.Type
+}
+
+// ConvertToNative implements ref.Val.ConvertToNative.
+func (t *nativeType) ConvertToNative(typeDesc reflect.Type) (any, error) {
+ return nil, fmt.Errorf("type conversion error for type to '%v'", typeDesc)
+}
+
+// ConvertToType implements ref.Val.ConvertToType.
+func (t *nativeType) ConvertToType(typeVal ref.Type) ref.Val {
+ switch typeVal {
+ case types.TypeType:
+ return types.TypeType
+ }
+ return types.NewErr("type conversion error from '%s' to '%s'", types.TypeType, typeVal)
+}
+
+// Equal returns true of both type names are equal to each other.
+func (t *nativeType) Equal(other ref.Val) ref.Val {
+ otherType, ok := other.(ref.Type)
+ return types.Bool(ok && t.TypeName() == otherType.TypeName())
+}
+
+// HasTrait implements the ref.Type interface method.
+func (t *nativeType) HasTrait(trait int) bool {
+ return nativeObjTraitMask&trait == trait
+}
+
+// String implements the strings.Stringer interface method.
+func (t *nativeType) String() string {
+ return t.typeName
+}
+
+// Type implements the ref.Val interface method.
+func (t *nativeType) Type() ref.Type {
+ return types.TypeType
+}
+
+// TypeName implements the ref.Type interface method.
+func (t *nativeType) TypeName() string {
+ return t.typeName
+}
+
+// Value implements the ref.Val interface method.
+func (t *nativeType) Value() any {
+ return t.typeName
+}
+
+// hasField returns whether a field name has a corresponding Golang reflect.StructField
+func (t *nativeType) hasField(fieldName string) (reflect.StructField, bool) {
+ f, found := t.refType.FieldByName(fieldName)
+ if !found || !f.IsExported() || !isSupportedType(f.Type) {
+ return reflect.StructField{}, false
+ }
+ return f, true
+}
+
+func adaptFieldValue(adapter types.Adapter, refField reflect.Value) ref.Val {
+ return adapter.NativeToValue(getFieldValue(adapter, refField))
+}
+
+func getFieldValue(adapter types.Adapter, refField reflect.Value) any {
+ if refField.IsZero() {
+ switch refField.Kind() {
+ case reflect.Array, reflect.Slice:
+ return types.NewDynamicList(adapter, []ref.Val{})
+ case reflect.Map:
+ return types.NewDynamicMap(adapter, map[ref.Val]ref.Val{})
+ case reflect.Struct:
+ if refField.Type() == timestampType {
+ return types.Timestamp{Time: time.Unix(0, 0)}
+ }
+ return reflect.New(refField.Type()).Elem().Interface()
+ case reflect.Pointer:
+ return reflect.New(refField.Type().Elem()).Interface()
+ }
+ }
+ return refField.Interface()
+}
+
+func simplePkgAlias(pkgPath string) string {
+ paths := strings.Split(pkgPath, "/")
+ if len(paths) == 0 {
+ return ""
+ }
+ return paths[len(paths)-1]
+}
+
+func isValidObjectType(refType reflect.Type) bool {
+ return refType.Kind() == reflect.Struct
+}
+
+func isSupportedType(refType reflect.Type) bool {
+ switch refType.Kind() {
+ case reflect.Chan, reflect.Complex64, reflect.Complex128, reflect.Func, reflect.UnsafePointer, reflect.Uintptr:
+ return false
+ case reflect.Array, reflect.Slice:
+ return isSupportedType(refType.Elem())
+ case reflect.Map:
+ return isSupportedType(refType.Key()) && isSupportedType(refType.Elem())
+ }
+ return true
+}
+
+var (
+ pbMsgInterfaceType = reflect.TypeOf((*protoreflect.ProtoMessage)(nil)).Elem()
+ timestampType = reflect.TypeOf(time.Now())
+ durationType = reflect.TypeOf(time.Nanosecond)
+)
diff --git a/vendor/github.com/google/cel-go/ext/protos.go b/vendor/github.com/google/cel-go/ext/protos.go
new file mode 100644
index 000000000..a7ca27a6a
--- /dev/null
+++ b/vendor/github.com/google/cel-go/ext/protos.go
@@ -0,0 +1,141 @@
+// Copyright 2022 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package ext
+
+import (
+ "github.com/google/cel-go/cel"
+
+ exprpb "google.golang.org/genproto/googleapis/api/expr/v1alpha1"
+)
+
+// Protos returns a cel.EnvOption to configure extended macros and functions for
+// proto manipulation.
+//
+// Note, all macros use the 'proto' namespace; however, at the time of macro
+// expansion the namespace looks just like any other identifier. If you are
+// currently using a variable named 'proto', the macro will likely work just as
+// intended; however, there is some chance for collision.
+//
+// # Protos.GetExt
+//
+// Macro which generates a select expression that retrieves an extension field
+// from the input proto2 syntax message. If the field is not set, the default
+// value forthe extension field is returned according to safe-traversal semantics.
+//
+// proto.getExt(, ) ->
+//
+// Examples:
+//
+// proto.getExt(msg, google.expr.proto2.test.int32_ext) // returns int value
+//
+// # Protos.HasExt
+//
+// Macro which generates a test-only select expression that determines whether
+// an extension field is set on a proto2 syntax message.
+//
+// proto.hasExt(, ) ->
+//
+// Examples:
+//
+// proto.hasExt(msg, google.expr.proto2.test.int32_ext) // returns true || false
+func Protos() cel.EnvOption {
+ return cel.Lib(protoLib{})
+}
+
+var (
+ protoNamespace = "proto"
+ hasExtension = "hasExt"
+ getExtension = "getExt"
+)
+
+type protoLib struct{}
+
+// LibraryName implements the SingletonLibrary interface method.
+func (protoLib) LibraryName() string {
+ return "cel.lib.ext.protos"
+}
+
+// CompileOptions implements the Library interface method.
+func (protoLib) CompileOptions() []cel.EnvOption {
+ return []cel.EnvOption{
+ cel.Macros(
+ // proto.getExt(msg, select_expression)
+ cel.NewReceiverMacro(getExtension, 2, getProtoExt),
+ // proto.hasExt(msg, select_expression)
+ cel.NewReceiverMacro(hasExtension, 2, hasProtoExt),
+ ),
+ }
+}
+
+// ProgramOptions implements the Library interface method.
+func (protoLib) ProgramOptions() []cel.ProgramOption {
+ return []cel.ProgramOption{}
+}
+
+// hasProtoExt generates a test-only select expression for a fully-qualified extension name on a protobuf message.
+func hasProtoExt(meh cel.MacroExprHelper, target *exprpb.Expr, args []*exprpb.Expr) (*exprpb.Expr, *cel.Error) {
+ if !macroTargetMatchesNamespace(protoNamespace, target) {
+ return nil, nil
+ }
+ extensionField, err := getExtFieldName(meh, args[1])
+ if err != nil {
+ return nil, err
+ }
+ return meh.PresenceTest(args[0], extensionField), nil
+}
+
+// getProtoExt generates a select expression for a fully-qualified extension name on a protobuf message.
+func getProtoExt(meh cel.MacroExprHelper, target *exprpb.Expr, args []*exprpb.Expr) (*exprpb.Expr, *cel.Error) {
+ if !macroTargetMatchesNamespace(protoNamespace, target) {
+ return nil, nil
+ }
+ extFieldName, err := getExtFieldName(meh, args[1])
+ if err != nil {
+ return nil, err
+ }
+ return meh.Select(args[0], extFieldName), nil
+}
+
+func getExtFieldName(meh cel.MacroExprHelper, expr *exprpb.Expr) (string, *cel.Error) {
+ isValid := false
+ extensionField := ""
+ switch expr.GetExprKind().(type) {
+ case *exprpb.Expr_SelectExpr:
+ extensionField, isValid = validateIdentifier(expr)
+ }
+ if !isValid {
+ return "", meh.NewError(expr.GetId(), "invalid extension field")
+ }
+ return extensionField, nil
+}
+
+func validateIdentifier(expr *exprpb.Expr) (string, bool) {
+ switch expr.GetExprKind().(type) {
+ case *exprpb.Expr_IdentExpr:
+ return expr.GetIdentExpr().GetName(), true
+ case *exprpb.Expr_SelectExpr:
+ sel := expr.GetSelectExpr()
+ if sel.GetTestOnly() {
+ return "", false
+ }
+ opStr, isIdent := validateIdentifier(sel.GetOperand())
+ if !isIdent {
+ return "", false
+ }
+ return opStr + "." + sel.GetField(), true
+ default:
+ return "", false
+ }
+}
diff --git a/vendor/github.com/google/cel-go/ext/sets.go b/vendor/github.com/google/cel-go/ext/sets.go
new file mode 100644
index 000000000..4820d6199
--- /dev/null
+++ b/vendor/github.com/google/cel-go/ext/sets.go
@@ -0,0 +1,138 @@
+// Copyright 2023 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package ext
+
+import (
+ "github.com/google/cel-go/cel"
+ "github.com/google/cel-go/common/types"
+ "github.com/google/cel-go/common/types/ref"
+ "github.com/google/cel-go/common/types/traits"
+)
+
+// Sets returns a cel.EnvOption to configure namespaced set relationship
+// functions.
+//
+// There is no set type within CEL, and while one may be introduced in the
+// future, there are cases where a `list` type is known to behave like a set.
+// For such cases, this library provides some basic functionality for
+// determining set containment, equivalence, and intersection.
+//
+// # Sets.Contains
+//
+// Returns whether the first list argument contains all elements in the second
+// list argument. The list may contain elements of any type and standard CEL
+// equality is used to determine whether a value exists in both lists. If the
+// second list is empty, the result will always return true.
+//
+// sets.contains(list(T), list(T)) -> bool
+//
+// Examples:
+//
+// sets.contains([], []) // true
+// sets.contains([], [1]) // false
+// sets.contains([1, 2, 3, 4], [2, 3]) // true
+// sets.contains([1, 2.0, 3u], [1.0, 2u, 3]) // true
+//
+// # Sets.Equivalent
+//
+// Returns whether the first and second list are set equivalent. Lists are set
+// equivalent if for every item in the first list, there is an element in the
+// second which is equal. The lists may not be of the same size as they do not
+// guarantee the elements within them are unique, so size does not factor into
+// the computation.
+//
+// Examples:
+//
+// sets.equivalent([], []) // true
+// sets.equivalent([1], [1, 1]) // true
+// sets.equivalent([1], [1u, 1.0]) // true
+// sets.equivalent([1, 2, 3], [3u, 2.0, 1]) // true
+//
+// # Sets.Intersects
+//
+// Returns whether the first list has at least one element whose value is equal
+// to an element in the second list. If either list is empty, the result will
+// be false.
+//
+// Examples:
+//
+// sets.intersects([1], []) // false
+// sets.intersects([1], [1, 2]) // true
+// sets.intersects([[1], [2, 3]], [[1, 2], [2, 3.0]]) // true
+func Sets() cel.EnvOption {
+ return cel.Lib(setsLib{})
+}
+
+type setsLib struct{}
+
+// LibraryName implements the SingletonLibrary interface method.
+func (setsLib) LibraryName() string {
+ return "cel.lib.ext.sets"
+}
+
+// CompileOptions implements the Library interface method.
+func (setsLib) CompileOptions() []cel.EnvOption {
+ listType := cel.ListType(cel.TypeParamType("T"))
+ return []cel.EnvOption{
+ cel.Function("sets.contains",
+ cel.Overload("list_sets_contains_list", []*cel.Type{listType, listType}, cel.BoolType,
+ cel.BinaryBinding(setsContains))),
+ cel.Function("sets.equivalent",
+ cel.Overload("list_sets_equivalent_list", []*cel.Type{listType, listType}, cel.BoolType,
+ cel.BinaryBinding(setsEquivalent))),
+ cel.Function("sets.intersects",
+ cel.Overload("list_sets_intersects_list", []*cel.Type{listType, listType}, cel.BoolType,
+ cel.BinaryBinding(setsIntersects))),
+ }
+}
+
+// ProgramOptions implements the Library interface method.
+func (setsLib) ProgramOptions() []cel.ProgramOption {
+ return []cel.ProgramOption{}
+}
+
+func setsIntersects(listA, listB ref.Val) ref.Val {
+ lA := listA.(traits.Lister)
+ lB := listB.(traits.Lister)
+ it := lA.Iterator()
+ for it.HasNext() == types.True {
+ exists := lB.Contains(it.Next())
+ if exists == types.True {
+ return types.True
+ }
+ }
+ return types.False
+}
+
+func setsContains(list, sublist ref.Val) ref.Val {
+ l := list.(traits.Lister)
+ sub := sublist.(traits.Lister)
+ it := sub.Iterator()
+ for it.HasNext() == types.True {
+ exists := l.Contains(it.Next())
+ if exists != types.True {
+ return exists
+ }
+ }
+ return types.True
+}
+
+func setsEquivalent(listA, listB ref.Val) ref.Val {
+ aContainsB := setsContains(listA, listB)
+ if aContainsB != types.True {
+ return aContainsB
+ }
+ return setsContains(listB, listA)
+}
diff --git a/vendor/github.com/google/cel-go/ext/strings.go b/vendor/github.com/google/cel-go/ext/strings.go
new file mode 100644
index 000000000..88c119f2b
--- /dev/null
+++ b/vendor/github.com/google/cel-go/ext/strings.go
@@ -0,0 +1,1095 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package ext contains CEL extension libraries where each library defines a related set of
+// constants, functions, macros, or other configuration settings which may not be covered by
+// the core CEL spec.
+package ext
+
+import (
+ "fmt"
+ "math"
+ "reflect"
+ "sort"
+ "strings"
+ "unicode"
+ "unicode/utf8"
+
+ "golang.org/x/text/language"
+ "golang.org/x/text/message"
+
+ "github.com/google/cel-go/cel"
+ "github.com/google/cel-go/common/types"
+ "github.com/google/cel-go/common/types/ref"
+ "github.com/google/cel-go/common/types/traits"
+ "github.com/google/cel-go/interpreter"
+)
+
+const (
+ defaultLocale = "en-US"
+ defaultPrecision = 6
+)
+
+// Strings returns a cel.EnvOption to configure extended functions for string manipulation.
+// As a general note, all indices are zero-based.
+//
+// # CharAt
+//
+// Returns the character at the given position. If the position is negative, or greater than
+// the length of the string, the function will produce an error:
+//
+// .charAt() ->
+//
+// Examples:
+//
+// 'hello'.charAt(4) // return 'o'
+// 'hello'.charAt(5) // return ''
+// 'hello'.charAt(-1) // error
+//
+// # Format
+//
+// Introduced at version: 1
+//
+// Returns a new string with substitutions being performed, printf-style.
+// The valid formatting clauses are:
+//
+// `%s` - substitutes a string. This can also be used on bools, lists, maps, bytes,
+// Duration and Timestamp, in addition to all numerical types (int, uint, and double).
+// Note that the dot/period decimal separator will always be used when printing a list
+// or map that contains a double, and that null can be passed (which results in the
+// string "null") in addition to types.
+// `%d` - substitutes an integer.
+// `%f` - substitutes a double with fixed-point precision. The default precision is 6, but
+// this can be adjusted. The strings `Infinity`, `-Infinity`, and `NaN` are also valid input
+// for this clause.
+// `%e` - substitutes a double in scientific notation. The default precision is 6, but this
+// can be adjusted.
+// `%b` - substitutes an integer with its equivalent binary string. Can also be used on bools.
+// `%x` - substitutes an integer with its equivalent in hexadecimal, or if given a string or
+// bytes, will output each character's equivalent in hexadecimal.
+// `%X` - same as above, but with A-F capitalized.
+// `%o` - substitutes an integer with its equivalent in octal.
+//
+// .format() ->
+//
+// Examples:
+//
+// "this is a string: %s\nand an integer: %d".format(["str", 42]) // returns "this is a string: str\nand an integer: 42"
+// "a double substituted with %%s: %s".format([64.2]) // returns "a double substituted with %s: 64.2"
+// "string type: %s".format([type(string)]) // returns "string type: string"
+// "timestamp: %s".format([timestamp("2023-02-03T23:31:20+00:00")]) // returns "timestamp: 2023-02-03T23:31:20Z"
+// "duration: %s".format([duration("1h45m47s")]) // returns "duration: 6347s"
+// "%f".format([3.14]) // returns "3.140000"
+// "scientific notation: %e".format([2.71828]) // returns "scientific notation: 2.718280\u202f\u00d7\u202f10\u2070\u2070"
+// "5 in binary: %b".format([5]), // returns "5 in binary; 101"
+// "26 in hex: %x".format([26]), // returns "26 in hex: 1a"
+// "26 in hex (uppercase): %X".format([26]) // returns "26 in hex (uppercase): 1A"
+// "30 in octal: %o".format([30]) // returns "30 in octal: 36"
+// "a map inside a list: %s".format([[1, 2, 3, {"a": "x", "b": "y", "c": "z"}]]) // returns "a map inside a list: [1, 2, 3, {"a":"x", "b":"y", "c":"d"}]"
+// "true bool: %s - false bool: %s\nbinary bool: %b".format([true, false, true]) // returns "true bool: true - false bool: false\nbinary bool: 1"
+//
+// Passing an incorrect type (an integer to `%s`) is considered an error, as well as attempting
+// to use more formatting clauses than there are arguments (`%d %d %d` while passing two ints, for instance).
+// If compile-time checking is enabled, and the formatting string is a constant, and the argument list is a literal,
+// then letting any arguments go unused/unformatted is also considered an error.
+//
+// # IndexOf
+//
+// Returns the integer index of the first occurrence of the search string. If the search string is
+// not found the function returns -1.
+//
+// The function also accepts an optional position from which to begin the substring search. If the
+// substring is the empty string, the index where the search starts is returned (zero or custom).
+//
+// .indexOf() ->
+// .indexOf(, ) ->
+//
+// Examples:
+//
+// 'hello mellow'.indexOf('') // returns 0
+// 'hello mellow'.indexOf('ello') // returns 1
+// 'hello mellow'.indexOf('jello') // returns -1
+// 'hello mellow'.indexOf('', 2) // returns 2
+// 'hello mellow'.indexOf('ello', 2) // returns 7
+// 'hello mellow'.indexOf('ello', 20) // error
+//
+// # Join
+//
+// Returns a new string where the elements of string list are concatenated.
+//
+// The function also accepts an optional separator which is placed between elements in the resulting string.
+//
+// >.join() ->
+// >.join() ->
+//
+// Examples:
+//
+// ['hello', 'mellow'].join() // returns 'hellomellow'
+// ['hello', 'mellow'].join(' ') // returns 'hello mellow'
+// [].join() // returns ''
+// [].join('/') // returns ''
+//
+// # LastIndexOf
+//
+// Returns the integer index at the start of the last occurrence of the search string. If the
+// search string is not found the function returns -1.
+//
+// The function also accepts an optional position which represents the last index to be
+// considered as the beginning of the substring match. If the substring is the empty string,
+// the index where the search starts is returned (string length or custom).
+//
+// .lastIndexOf() ->
+// .lastIndexOf(, ) ->
+//
+// Examples:
+//
+// 'hello mellow'.lastIndexOf('') // returns 12
+// 'hello mellow'.lastIndexOf('ello') // returns 7
+// 'hello mellow'.lastIndexOf('jello') // returns -1
+// 'hello mellow'.lastIndexOf('ello', 6) // returns 1
+// 'hello mellow'.lastIndexOf('ello', -1) // error
+//
+// # LowerAscii
+//
+// Returns a new string where all ASCII characters are lower-cased.
+//
+// This function does not perform Unicode case-mapping for characters outside the ASCII range.
+//
+// .lowerAscii() ->
+//
+// Examples:
+//
+// 'TacoCat'.lowerAscii() // returns 'tacocat'
+// 'TacoCÆt Xii'.lowerAscii() // returns 'tacocÆt xii'
+//
+// # Strings.Quote
+//
+// Introduced in version: 1
+//
+// Takes the given string and makes it safe to print (without any formatting due to escape sequences).
+// If any invalid UTF-8 characters are encountered, they are replaced with \uFFFD.
+//
+// strings.quote()
+//
+// Examples:
+//
+// strings.quote('single-quote with "double quote"') // returns '"single-quote with \"double quote\""'
+// strings.quote("two escape sequences \a\n") // returns '"two escape sequences \\a\\n"'
+//
+// # Replace
+//
+// Returns a new string based on the target, which replaces the occurrences of a search string
+// with a replacement string if present. The function accepts an optional limit on the number of
+// substring replacements to be made.
+//
+// When the replacement limit is 0, the result is the original string. When the limit is a negative
+// number, the function behaves the same as replace all.
+//
+// .replace(, ) ->
+// .replace(, , ) ->
+//
+// Examples:
+//
+// 'hello hello'.replace('he', 'we') // returns 'wello wello'
+// 'hello hello'.replace('he', 'we', -1) // returns 'wello wello'
+// 'hello hello'.replace('he', 'we', 1) // returns 'wello hello'
+// 'hello hello'.replace('he', 'we', 0) // returns 'hello hello'
+//
+// # Split
+//
+// Returns a list of strings split from the input by the given separator. The function accepts
+// an optional argument specifying a limit on the number of substrings produced by the split.
+//
+// When the split limit is 0, the result is an empty list. When the limit is 1, the result is the
+// target string to split. When the limit is a negative number, the function behaves the same as
+// split all.
+//
+// .split() -> >
+// .split(, ) -> >
+//
+// Examples:
+//
+// 'hello hello hello'.split(' ') // returns ['hello', 'hello', 'hello']
+// 'hello hello hello'.split(' ', 0) // returns []
+// 'hello hello hello'.split(' ', 1) // returns ['hello hello hello']
+// 'hello hello hello'.split(' ', 2) // returns ['hello', 'hello hello']
+// 'hello hello hello'.split(' ', -1) // returns ['hello', 'hello', 'hello']
+//
+// # Substring
+//
+// Returns the substring given a numeric range corresponding to character positions. Optionally
+// may omit the trailing range for a substring from a given character position until the end of
+// a string.
+//
+// Character offsets are 0-based with an inclusive start range and exclusive end range. It is an
+// error to specify an end range that is lower than the start range, or for either the start or end
+// index to be negative or exceed the string length.
+//
+// .substring() ->
+// .substring(, ) ->
+//
+// Examples:
+//
+// 'tacocat'.substring(4) // returns 'cat'
+// 'tacocat'.substring(0, 4) // returns 'taco'
+// 'tacocat'.substring(-1) // error
+// 'tacocat'.substring(2, 1) // error
+//
+// # Trim
+//
+// Returns a new string which removes the leading and trailing whitespace in the target string.
+// The trim function uses the Unicode definition of whitespace which does not include the
+// zero-width spaces. See: https://en.wikipedia.org/wiki/Whitespace_character#Unicode
+//
+// .trim() ->
+//
+// Examples:
+//
+// ' \ttrim\n '.trim() // returns 'trim'
+//
+// # UpperAscii
+//
+// Returns a new string where all ASCII characters are upper-cased.
+//
+// This function does not perform Unicode case-mapping for characters outside the ASCII range.
+//
+// .upperAscii() ->
+//
+// Examples:
+//
+// 'TacoCat'.upperAscii() // returns 'TACOCAT'
+// 'TacoCÆt Xii'.upperAscii() // returns 'TACOCÆT XII'
+func Strings(options ...StringsOption) cel.EnvOption {
+ s := &stringLib{version: math.MaxUint32}
+ for _, o := range options {
+ s = o(s)
+ }
+ return cel.Lib(s)
+}
+
+type stringLib struct {
+ locale string
+ version uint32
+}
+
+// LibraryName implements the SingletonLibrary interface method.
+func (*stringLib) LibraryName() string {
+ return "cel.lib.ext.strings"
+}
+
+// StringsOption is a functional interface for configuring the strings library.
+type StringsOption func(*stringLib) *stringLib
+
+// StringsLocale configures the library with the given locale. The locale tag will
+// be checked for validity at the time that EnvOptions are configured. If this option
+// is not passed, string.format will behave as if en_US was passed as the locale.
+func StringsLocale(locale string) StringsOption {
+ return func(sl *stringLib) *stringLib {
+ sl.locale = locale
+ return sl
+ }
+}
+
+// StringsVersion configures the version of the string library.
+//
+// The version limits which functions are available. Only functions introduced
+// below or equal to the given version included in the library. If this option
+// is not set, all functions are available.
+//
+// See the library documentation to determine which version a function was introduced.
+// If the documentation does not state which version a function was introduced, it can
+// be assumed to be introduced at version 0, when the library was first created.
+func StringsVersion(version uint32) StringsOption {
+ return func(lib *stringLib) *stringLib {
+ lib.version = version
+ return lib
+ }
+}
+
+// CompileOptions implements the Library interface method.
+func (lib *stringLib) CompileOptions() []cel.EnvOption {
+ formatLocale := "en_US"
+ if lib.locale != "" {
+ // ensure locale is properly-formed if set
+ _, err := language.Parse(lib.locale)
+ if err != nil {
+ return []cel.EnvOption{
+ func(e *cel.Env) (*cel.Env, error) {
+ return nil, fmt.Errorf("failed to parse locale: %w", err)
+ },
+ }
+ }
+ formatLocale = lib.locale
+ }
+
+ opts := []cel.EnvOption{
+ cel.Function("charAt",
+ cel.MemberOverload("string_char_at_int", []*cel.Type{cel.StringType, cel.IntType}, cel.StringType,
+ cel.BinaryBinding(func(str, ind ref.Val) ref.Val {
+ s := str.(types.String)
+ i := ind.(types.Int)
+ return stringOrError(charAt(string(s), int64(i)))
+ }))),
+ cel.Function("indexOf",
+ cel.MemberOverload("string_index_of_string", []*cel.Type{cel.StringType, cel.StringType}, cel.IntType,
+ cel.BinaryBinding(func(str, substr ref.Val) ref.Val {
+ s := str.(types.String)
+ sub := substr.(types.String)
+ return intOrError(indexOf(string(s), string(sub)))
+ })),
+ cel.MemberOverload("string_index_of_string_int", []*cel.Type{cel.StringType, cel.StringType, cel.IntType}, cel.IntType,
+ cel.FunctionBinding(func(args ...ref.Val) ref.Val {
+ s := args[0].(types.String)
+ sub := args[1].(types.String)
+ offset := args[2].(types.Int)
+ return intOrError(indexOfOffset(string(s), string(sub), int64(offset)))
+ }))),
+ cel.Function("lastIndexOf",
+ cel.MemberOverload("string_last_index_of_string", []*cel.Type{cel.StringType, cel.StringType}, cel.IntType,
+ cel.BinaryBinding(func(str, substr ref.Val) ref.Val {
+ s := str.(types.String)
+ sub := substr.(types.String)
+ return intOrError(lastIndexOf(string(s), string(sub)))
+ })),
+ cel.MemberOverload("string_last_index_of_string_int", []*cel.Type{cel.StringType, cel.StringType, cel.IntType}, cel.IntType,
+ cel.FunctionBinding(func(args ...ref.Val) ref.Val {
+ s := args[0].(types.String)
+ sub := args[1].(types.String)
+ offset := args[2].(types.Int)
+ return intOrError(lastIndexOfOffset(string(s), string(sub), int64(offset)))
+ }))),
+ cel.Function("lowerAscii",
+ cel.MemberOverload("string_lower_ascii", []*cel.Type{cel.StringType}, cel.StringType,
+ cel.UnaryBinding(func(str ref.Val) ref.Val {
+ s := str.(types.String)
+ return stringOrError(lowerASCII(string(s)))
+ }))),
+ cel.Function("replace",
+ cel.MemberOverload(
+ "string_replace_string_string", []*cel.Type{cel.StringType, cel.StringType, cel.StringType}, cel.StringType,
+ cel.FunctionBinding(func(args ...ref.Val) ref.Val {
+ str := args[0].(types.String)
+ old := args[1].(types.String)
+ new := args[2].(types.String)
+ return stringOrError(replace(string(str), string(old), string(new)))
+ })),
+ cel.MemberOverload(
+ "string_replace_string_string_int", []*cel.Type{cel.StringType, cel.StringType, cel.StringType, cel.IntType}, cel.StringType,
+ cel.FunctionBinding(func(args ...ref.Val) ref.Val {
+ str := args[0].(types.String)
+ old := args[1].(types.String)
+ new := args[2].(types.String)
+ n := args[3].(types.Int)
+ return stringOrError(replaceN(string(str), string(old), string(new), int64(n)))
+ }))),
+ cel.Function("split",
+ cel.MemberOverload("string_split_string", []*cel.Type{cel.StringType, cel.StringType}, cel.ListType(cel.StringType),
+ cel.BinaryBinding(func(str, separator ref.Val) ref.Val {
+ s := str.(types.String)
+ sep := separator.(types.String)
+ return listStringOrError(split(string(s), string(sep)))
+ })),
+ cel.MemberOverload("string_split_string_int", []*cel.Type{cel.StringType, cel.StringType, cel.IntType}, cel.ListType(cel.StringType),
+ cel.FunctionBinding(func(args ...ref.Val) ref.Val {
+ s := args[0].(types.String)
+ sep := args[1].(types.String)
+ n := args[2].(types.Int)
+ return listStringOrError(splitN(string(s), string(sep), int64(n)))
+ }))),
+ cel.Function("substring",
+ cel.MemberOverload("string_substring_int", []*cel.Type{cel.StringType, cel.IntType}, cel.StringType,
+ cel.BinaryBinding(func(str, offset ref.Val) ref.Val {
+ s := str.(types.String)
+ off := offset.(types.Int)
+ return stringOrError(substr(string(s), int64(off)))
+ })),
+ cel.MemberOverload("string_substring_int_int", []*cel.Type{cel.StringType, cel.IntType, cel.IntType}, cel.StringType,
+ cel.FunctionBinding(func(args ...ref.Val) ref.Val {
+ s := args[0].(types.String)
+ start := args[1].(types.Int)
+ end := args[2].(types.Int)
+ return stringOrError(substrRange(string(s), int64(start), int64(end)))
+ }))),
+ cel.Function("trim",
+ cel.MemberOverload("string_trim", []*cel.Type{cel.StringType}, cel.StringType,
+ cel.UnaryBinding(func(str ref.Val) ref.Val {
+ s := str.(types.String)
+ return stringOrError(trimSpace(string(s)))
+ }))),
+ cel.Function("upperAscii",
+ cel.MemberOverload("string_upper_ascii", []*cel.Type{cel.StringType}, cel.StringType,
+ cel.UnaryBinding(func(str ref.Val) ref.Val {
+ s := str.(types.String)
+ return stringOrError(upperASCII(string(s)))
+ }))),
+ }
+ if lib.version >= 1 {
+ opts = append(opts, cel.Function("format",
+ cel.MemberOverload("string_format", []*cel.Type{cel.StringType, cel.ListType(cel.DynType)}, cel.StringType,
+ cel.FunctionBinding(func(args ...ref.Val) ref.Val {
+ s := string(args[0].(types.String))
+ formatArgs := args[1].(traits.Lister)
+ return stringOrError(interpreter.ParseFormatString(s, &stringFormatter{}, &stringArgList{formatArgs}, formatLocale))
+ }))),
+ cel.Function("strings.quote", cel.Overload("strings_quote", []*cel.Type{cel.StringType}, cel.StringType,
+ cel.UnaryBinding(func(str ref.Val) ref.Val {
+ s := str.(types.String)
+ return stringOrError(quote(string(s)))
+ }))))
+
+ }
+ if lib.version >= 2 {
+ opts = append(opts,
+ cel.Function("join",
+ cel.MemberOverload("list_join", []*cel.Type{cel.ListType(cel.StringType)}, cel.StringType,
+ cel.UnaryBinding(func(list ref.Val) ref.Val {
+ l := list.(traits.Lister)
+ return stringOrError(joinValSeparator(l, ""))
+ })),
+ cel.MemberOverload("list_join_string", []*cel.Type{cel.ListType(cel.StringType), cel.StringType}, cel.StringType,
+ cel.BinaryBinding(func(list, delim ref.Val) ref.Val {
+ l := list.(traits.Lister)
+ d := delim.(types.String)
+ return stringOrError(joinValSeparator(l, string(d)))
+ }))),
+ )
+ } else {
+ opts = append(opts,
+ cel.Function("join",
+ cel.MemberOverload("list_join", []*cel.Type{cel.ListType(cel.StringType)}, cel.StringType,
+ cel.UnaryBinding(func(list ref.Val) ref.Val {
+ l, err := list.ConvertToNative(stringListType)
+ if err != nil {
+ return types.NewErr(err.Error())
+ }
+ return stringOrError(join(l.([]string)))
+ })),
+ cel.MemberOverload("list_join_string", []*cel.Type{cel.ListType(cel.StringType), cel.StringType}, cel.StringType,
+ cel.BinaryBinding(func(list, delim ref.Val) ref.Val {
+ l, err := list.ConvertToNative(stringListType)
+ if err != nil {
+ return types.NewErr(err.Error())
+ }
+ d := delim.(types.String)
+ return stringOrError(joinSeparator(l.([]string), string(d)))
+ }))),
+ )
+ }
+ return opts
+}
+
+// ProgramOptions implements the Library interface method.
+func (*stringLib) ProgramOptions() []cel.ProgramOption {
+ return []cel.ProgramOption{}
+}
+
+func charAt(str string, ind int64) (string, error) {
+ i := int(ind)
+ runes := []rune(str)
+ if i < 0 || i > len(runes) {
+ return "", fmt.Errorf("index out of range: %d", ind)
+ }
+ if i == len(runes) {
+ return "", nil
+ }
+ return string(runes[i]), nil
+}
+
+func indexOf(str, substr string) (int64, error) {
+ return indexOfOffset(str, substr, int64(0))
+}
+
+func indexOfOffset(str, substr string, offset int64) (int64, error) {
+ if substr == "" {
+ return offset, nil
+ }
+ off := int(offset)
+ runes := []rune(str)
+ subrunes := []rune(substr)
+ if off < 0 || off >= len(runes) {
+ return -1, fmt.Errorf("index out of range: %d", off)
+ }
+ for i := off; i < len(runes)-(len(subrunes)-1); i++ {
+ found := true
+ for j := 0; j < len(subrunes); j++ {
+ if runes[i+j] != subrunes[j] {
+ found = false
+ break
+ }
+ }
+ if found {
+ return int64(i), nil
+ }
+ }
+ return -1, nil
+}
+
+func lastIndexOf(str, substr string) (int64, error) {
+ runes := []rune(str)
+ if substr == "" {
+ return int64(len(runes)), nil
+ }
+ return lastIndexOfOffset(str, substr, int64(len(runes)-1))
+}
+
+func lastIndexOfOffset(str, substr string, offset int64) (int64, error) {
+ if substr == "" {
+ return offset, nil
+ }
+ off := int(offset)
+ runes := []rune(str)
+ subrunes := []rune(substr)
+ if off < 0 || off >= len(runes) {
+ return -1, fmt.Errorf("index out of range: %d", off)
+ }
+ if off > len(runes)-len(subrunes) {
+ off = len(runes) - len(subrunes)
+ }
+ for i := off; i >= 0; i-- {
+ found := true
+ for j := 0; j < len(subrunes); j++ {
+ if runes[i+j] != subrunes[j] {
+ found = false
+ break
+ }
+ }
+ if found {
+ return int64(i), nil
+ }
+ }
+ return -1, nil
+}
+
+func lowerASCII(str string) (string, error) {
+ runes := []rune(str)
+ for i, r := range runes {
+ if r <= unicode.MaxASCII {
+ r = unicode.ToLower(r)
+ runes[i] = r
+ }
+ }
+ return string(runes), nil
+}
+
+func replace(str, old, new string) (string, error) {
+ return strings.ReplaceAll(str, old, new), nil
+}
+
+func replaceN(str, old, new string, n int64) (string, error) {
+ return strings.Replace(str, old, new, int(n)), nil
+}
+
+func split(str, sep string) ([]string, error) {
+ return strings.Split(str, sep), nil
+}
+
+func splitN(str, sep string, n int64) ([]string, error) {
+ return strings.SplitN(str, sep, int(n)), nil
+}
+
+func substr(str string, start int64) (string, error) {
+ runes := []rune(str)
+ if int(start) < 0 || int(start) > len(runes) {
+ return "", fmt.Errorf("index out of range: %d", start)
+ }
+ return string(runes[start:]), nil
+}
+
+func substrRange(str string, start, end int64) (string, error) {
+ runes := []rune(str)
+ l := len(runes)
+ if start > end {
+ return "", fmt.Errorf("invalid substring range. start: %d, end: %d", start, end)
+ }
+ if int(start) < 0 || int(start) > l {
+ return "", fmt.Errorf("index out of range: %d", start)
+ }
+ if int(end) < 0 || int(end) > l {
+ return "", fmt.Errorf("index out of range: %d", end)
+ }
+ return string(runes[int(start):int(end)]), nil
+}
+
+func trimSpace(str string) (string, error) {
+ return strings.TrimSpace(str), nil
+}
+
+func upperASCII(str string) (string, error) {
+ runes := []rune(str)
+ for i, r := range runes {
+ if r <= unicode.MaxASCII {
+ r = unicode.ToUpper(r)
+ runes[i] = r
+ }
+ }
+ return string(runes), nil
+}
+
+func joinSeparator(strs []string, separator string) (string, error) {
+ return strings.Join(strs, separator), nil
+}
+
+func join(strs []string) (string, error) {
+ return strings.Join(strs, ""), nil
+}
+
+func joinValSeparator(strs traits.Lister, separator string) (string, error) {
+ sz := strs.Size().(types.Int)
+ var sb strings.Builder
+ for i := types.Int(0); i < sz; i++ {
+ if i != 0 {
+ sb.WriteString(separator)
+ }
+ elem := strs.Get(i)
+ str, ok := elem.(types.String)
+ if !ok {
+ return "", fmt.Errorf("join: invalid input: %v", elem)
+ }
+ sb.WriteString(string(str))
+ }
+ return sb.String(), nil
+}
+
+type clauseImpl func(ref.Val, string) (string, error)
+
+func clauseForType(argType ref.Type) (clauseImpl, error) {
+ switch argType {
+ case types.IntType, types.UintType:
+ return formatDecimal, nil
+ case types.StringType, types.BytesType, types.BoolType, types.NullType, types.TypeType:
+ return FormatString, nil
+ case types.TimestampType, types.DurationType:
+ // special case to ensure timestamps/durations get printed as CEL literals
+ return func(arg ref.Val, locale string) (string, error) {
+ argStrVal := arg.ConvertToType(types.StringType)
+ argStr := argStrVal.Value().(string)
+ if arg.Type() == types.TimestampType {
+ return fmt.Sprintf("timestamp(%q)", argStr), nil
+ }
+ if arg.Type() == types.DurationType {
+ return fmt.Sprintf("duration(%q)", argStr), nil
+ }
+ return "", fmt.Errorf("cannot convert argument of type %s to timestamp/duration", arg.Type().TypeName())
+ }, nil
+ case types.ListType:
+ return formatList, nil
+ case types.MapType:
+ return formatMap, nil
+ case types.DoubleType:
+ // avoid formatFixed so we can output a period as the decimal separator in order
+ // to always be a valid CEL literal
+ return func(arg ref.Val, locale string) (string, error) {
+ argDouble, ok := arg.Value().(float64)
+ if !ok {
+ return "", fmt.Errorf("couldn't convert %s to float64", arg.Type().TypeName())
+ }
+ fmtStr := fmt.Sprintf("%%.%df", defaultPrecision)
+ return fmt.Sprintf(fmtStr, argDouble), nil
+ }, nil
+ case types.TypeType:
+ return func(arg ref.Val, locale string) (string, error) {
+ return fmt.Sprintf("type(%s)", arg.Value().(string)), nil
+ }, nil
+ default:
+ return nil, fmt.Errorf("no formatting function for %s", argType.TypeName())
+ }
+}
+
+func formatList(arg ref.Val, locale string) (string, error) {
+ argList := arg.(traits.Lister)
+ argIterator := argList.Iterator()
+ var listStrBuilder strings.Builder
+ _, err := listStrBuilder.WriteRune('[')
+ if err != nil {
+ return "", fmt.Errorf("error writing to list string: %w", err)
+ }
+ for argIterator.HasNext() == types.True {
+ member := argIterator.Next()
+ memberFormat, err := clauseForType(member.Type())
+ if err != nil {
+ return "", err
+ }
+ unquotedStr, err := memberFormat(member, locale)
+ if err != nil {
+ return "", err
+ }
+ str := quoteForCEL(member, unquotedStr)
+ _, err = listStrBuilder.WriteString(str)
+ if err != nil {
+ return "", fmt.Errorf("error writing to list string: %w", err)
+ }
+ if argIterator.HasNext() == types.True {
+ _, err = listStrBuilder.WriteString(", ")
+ if err != nil {
+ return "", fmt.Errorf("error writing to list string: %w", err)
+ }
+ }
+ }
+ _, err = listStrBuilder.WriteRune(']')
+ if err != nil {
+ return "", fmt.Errorf("error writing to list string: %w", err)
+ }
+ return listStrBuilder.String(), nil
+}
+
+func formatMap(arg ref.Val, locale string) (string, error) {
+ argMap := arg.(traits.Mapper)
+ argIterator := argMap.Iterator()
+ type mapPair struct {
+ key string
+ value string
+ }
+ argPairs := make([]mapPair, argMap.Size().Value().(int64))
+ i := 0
+ for argIterator.HasNext() == types.True {
+ key := argIterator.Next()
+ var keyFormat clauseImpl
+ switch key.Type() {
+ case types.StringType, types.BoolType:
+ keyFormat = FormatString
+ case types.IntType, types.UintType:
+ keyFormat = formatDecimal
+ default:
+ return "", fmt.Errorf("no formatting function for map key of type %s", key.Type().TypeName())
+ }
+ unquotedKeyStr, err := keyFormat(key, locale)
+ if err != nil {
+ return "", err
+ }
+ keyStr := quoteForCEL(key, unquotedKeyStr)
+ value, found := argMap.Find(key)
+ if !found {
+ return "", fmt.Errorf("could not find key: %q", key)
+ }
+ valueFormat, err := clauseForType(value.Type())
+ if err != nil {
+ return "", err
+ }
+ unquotedValueStr, err := valueFormat(value, locale)
+ if err != nil {
+ return "", err
+ }
+ valueStr := quoteForCEL(value, unquotedValueStr)
+ argPairs[i] = mapPair{keyStr, valueStr}
+ i++
+ }
+ sort.SliceStable(argPairs, func(x, y int) bool {
+ return argPairs[x].key < argPairs[y].key
+ })
+ var mapStrBuilder strings.Builder
+ _, err := mapStrBuilder.WriteRune('{')
+ if err != nil {
+ return "", fmt.Errorf("error writing to map string: %w", err)
+ }
+ for i, entry := range argPairs {
+ _, err = mapStrBuilder.WriteString(fmt.Sprintf("%s:%s", entry.key, entry.value))
+ if err != nil {
+ return "", fmt.Errorf("error writing to map string: %w", err)
+ }
+ if i < len(argPairs)-1 {
+ _, err = mapStrBuilder.WriteString(", ")
+ if err != nil {
+ return "", fmt.Errorf("error writing to map string: %w", err)
+ }
+ }
+ }
+ _, err = mapStrBuilder.WriteRune('}')
+ if err != nil {
+ return "", fmt.Errorf("error writing to map string: %w", err)
+ }
+ return mapStrBuilder.String(), nil
+}
+
+// quoteForCEL takes a formatted, unquoted value and quotes it in a manner
+// suitable for embedding directly in CEL.
+func quoteForCEL(refVal ref.Val, unquotedValue string) string {
+ switch refVal.Type() {
+ case types.StringType:
+ return fmt.Sprintf("%q", unquotedValue)
+ case types.BytesType:
+ return fmt.Sprintf("b%q", unquotedValue)
+ case types.DoubleType:
+ // special case to handle infinity/NaN
+ num := refVal.Value().(float64)
+ if math.IsInf(num, 1) || math.IsInf(num, -1) || math.IsNaN(num) {
+ return fmt.Sprintf("%q", unquotedValue)
+ }
+ return unquotedValue
+ default:
+ return unquotedValue
+ }
+}
+
+// FormatString returns the string representation of a CEL value.
+// It is used to implement the %s specifier in the (string).format() extension
+// function.
+func FormatString(arg ref.Val, locale string) (string, error) {
+ switch arg.Type() {
+ case types.ListType:
+ return formatList(arg, locale)
+ case types.MapType:
+ return formatMap(arg, locale)
+ case types.IntType, types.UintType, types.DoubleType,
+ types.BoolType, types.StringType, types.TimestampType, types.BytesType, types.DurationType, types.TypeType:
+ argStrVal := arg.ConvertToType(types.StringType)
+ argStr, ok := argStrVal.Value().(string)
+ if !ok {
+ return "", fmt.Errorf("could not convert argument %q to string", argStrVal)
+ }
+ return argStr, nil
+ case types.NullType:
+ return "null", nil
+ default:
+ return "", fmt.Errorf("string clause can only be used on strings, bools, bytes, ints, doubles, maps, lists, types, durations, and timestamps, was given %s", arg.Type().TypeName())
+ }
+}
+
+func formatDecimal(arg ref.Val, locale string) (string, error) {
+ switch arg.Type() {
+ case types.IntType:
+ argInt, ok := arg.ConvertToType(types.IntType).Value().(int64)
+ if !ok {
+ return "", fmt.Errorf("could not convert \"%s\" to int64", arg.Value())
+ }
+ return fmt.Sprintf("%d", argInt), nil
+ case types.UintType:
+ argInt, ok := arg.ConvertToType(types.UintType).Value().(uint64)
+ if !ok {
+ return "", fmt.Errorf("could not convert \"%s\" to uint64", arg.Value())
+ }
+ return fmt.Sprintf("%d", argInt), nil
+ default:
+ return "", fmt.Errorf("decimal clause can only be used on integers, was given %s", arg.Type().TypeName())
+ }
+}
+
+func matchLanguage(locale string) (language.Tag, error) {
+ matcher, err := makeMatcher(locale)
+ if err != nil {
+ return language.Und, err
+ }
+ tag, _ := language.MatchStrings(matcher, locale)
+ return tag, nil
+}
+
+func makeMatcher(locale string) (language.Matcher, error) {
+ tags := make([]language.Tag, 0)
+ tag, err := language.Parse(locale)
+ if err != nil {
+ return nil, err
+ }
+ tags = append(tags, tag)
+ return language.NewMatcher(tags), nil
+}
+
+// quote implements a string quoting function. The string will be wrapped in
+// double quotes, and all valid CEL escape sequences will be escaped to show up
+// literally if printed. If the input contains any invalid UTF-8, the invalid runes
+// will be replaced with utf8.RuneError.
+func quote(s string) (string, error) {
+ var quotedStrBuilder strings.Builder
+ for _, c := range sanitize(s) {
+ switch c {
+ case '\a':
+ quotedStrBuilder.WriteString("\\a")
+ case '\b':
+ quotedStrBuilder.WriteString("\\b")
+ case '\f':
+ quotedStrBuilder.WriteString("\\f")
+ case '\n':
+ quotedStrBuilder.WriteString("\\n")
+ case '\r':
+ quotedStrBuilder.WriteString("\\r")
+ case '\t':
+ quotedStrBuilder.WriteString("\\t")
+ case '\v':
+ quotedStrBuilder.WriteString("\\v")
+ case '\\':
+ quotedStrBuilder.WriteString("\\\\")
+ case '"':
+ quotedStrBuilder.WriteString("\\\"")
+ default:
+ quotedStrBuilder.WriteRune(c)
+ }
+ }
+ escapedStr := quotedStrBuilder.String()
+ return "\"" + escapedStr + "\"", nil
+}
+
+// sanitize replaces all invalid runes in the given string with utf8.RuneError.
+func sanitize(s string) string {
+ var sanitizedStringBuilder strings.Builder
+ for _, r := range s {
+ if !utf8.ValidRune(r) {
+ sanitizedStringBuilder.WriteRune(utf8.RuneError)
+ } else {
+ sanitizedStringBuilder.WriteRune(r)
+ }
+ }
+ return sanitizedStringBuilder.String()
+}
+
+type stringFormatter struct{}
+
+func (c *stringFormatter) String(arg ref.Val, locale string) (string, error) {
+ return FormatString(arg, locale)
+}
+
+func (c *stringFormatter) Decimal(arg ref.Val, locale string) (string, error) {
+ return formatDecimal(arg, locale)
+}
+
+func (c *stringFormatter) Fixed(precision *int) func(ref.Val, string) (string, error) {
+ if precision == nil {
+ precision = new(int)
+ *precision = defaultPrecision
+ }
+ return func(arg ref.Val, locale string) (string, error) {
+ strException := false
+ if arg.Type() == types.StringType {
+ argStr := arg.Value().(string)
+ if argStr == "NaN" || argStr == "Infinity" || argStr == "-Infinity" {
+ strException = true
+ }
+ }
+ if arg.Type() != types.DoubleType && !strException {
+ return "", fmt.Errorf("fixed-point clause can only be used on doubles, was given %s", arg.Type().TypeName())
+ }
+ argFloatVal := arg.ConvertToType(types.DoubleType)
+ argFloat, ok := argFloatVal.Value().(float64)
+ if !ok {
+ return "", fmt.Errorf("could not convert \"%s\" to float64", argFloatVal.Value())
+ }
+ fmtStr := fmt.Sprintf("%%.%df", *precision)
+
+ matchedLocale, err := matchLanguage(locale)
+ if err != nil {
+ return "", fmt.Errorf("error matching locale: %w", err)
+ }
+ return message.NewPrinter(matchedLocale).Sprintf(fmtStr, argFloat), nil
+ }
+}
+
+func (c *stringFormatter) Scientific(precision *int) func(ref.Val, string) (string, error) {
+ if precision == nil {
+ precision = new(int)
+ *precision = defaultPrecision
+ }
+ return func(arg ref.Val, locale string) (string, error) {
+ strException := false
+ if arg.Type() == types.StringType {
+ argStr := arg.Value().(string)
+ if argStr == "NaN" || argStr == "Infinity" || argStr == "-Infinity" {
+ strException = true
+ }
+ }
+ if arg.Type() != types.DoubleType && !strException {
+ return "", fmt.Errorf("scientific clause can only be used on doubles, was given %s", arg.Type().TypeName())
+ }
+ argFloatVal := arg.ConvertToType(types.DoubleType)
+ argFloat, ok := argFloatVal.Value().(float64)
+ if !ok {
+ return "", fmt.Errorf("could not convert \"%s\" to float64", argFloatVal.Value())
+ }
+ matchedLocale, err := matchLanguage(locale)
+ if err != nil {
+ return "", fmt.Errorf("error matching locale: %w", err)
+ }
+ fmtStr := fmt.Sprintf("%%%de", *precision)
+ return message.NewPrinter(matchedLocale).Sprintf(fmtStr, argFloat), nil
+ }
+}
+
+func (c *stringFormatter) Binary(arg ref.Val, locale string) (string, error) {
+ switch arg.Type() {
+ case types.IntType:
+ argInt := arg.Value().(int64)
+ // locale is intentionally unused as integers formatted as binary
+ // strings are locale-independent
+ return fmt.Sprintf("%b", argInt), nil
+ case types.UintType:
+ argInt := arg.Value().(uint64)
+ return fmt.Sprintf("%b", argInt), nil
+ case types.BoolType:
+ argBool := arg.Value().(bool)
+ if argBool {
+ return "1", nil
+ }
+ return "0", nil
+ default:
+ return "", fmt.Errorf("only integers and bools can be formatted as binary, was given %s", arg.Type().TypeName())
+ }
+}
+
+func (c *stringFormatter) Hex(useUpper bool) func(ref.Val, string) (string, error) {
+ return func(arg ref.Val, locale string) (string, error) {
+ fmtStr := "%x"
+ if useUpper {
+ fmtStr = "%X"
+ }
+ switch arg.Type() {
+ case types.StringType, types.BytesType:
+ if arg.Type() == types.BytesType {
+ return fmt.Sprintf(fmtStr, arg.Value().([]byte)), nil
+ }
+ return fmt.Sprintf(fmtStr, arg.Value().(string)), nil
+ case types.IntType:
+ argInt, ok := arg.Value().(int64)
+ if !ok {
+ return "", fmt.Errorf("could not convert \"%s\" to int64", arg.Value())
+ }
+ return fmt.Sprintf(fmtStr, argInt), nil
+ case types.UintType:
+ argInt, ok := arg.Value().(uint64)
+ if !ok {
+ return "", fmt.Errorf("could not convert \"%s\" to uint64", arg.Value())
+ }
+ return fmt.Sprintf(fmtStr, argInt), nil
+ default:
+ return "", fmt.Errorf("only integers, byte buffers, and strings can be formatted as hex, was given %s", arg.Type().TypeName())
+ }
+ }
+}
+
+func (c *stringFormatter) Octal(arg ref.Val, locale string) (string, error) {
+ switch arg.Type() {
+ case types.IntType:
+ argInt := arg.Value().(int64)
+ return fmt.Sprintf("%o", argInt), nil
+ case types.UintType:
+ argInt := arg.Value().(uint64)
+ return fmt.Sprintf("%o", argInt), nil
+ default:
+ return "", fmt.Errorf("octal clause can only be used on integers, was given %s", arg.Type().TypeName())
+ }
+}
+
+type stringArgList struct {
+ args traits.Lister
+}
+
+func (c *stringArgList) Arg(index int64) (ref.Val, error) {
+ if index >= c.args.Size().Value().(int64) {
+ return nil, fmt.Errorf("index %d out of range", index)
+ }
+ return c.args.Get(types.Int(index)), nil
+}
+
+func (c *stringArgList) ArgSize() int64 {
+ return c.args.Size().Value().(int64)
+}
+
+var (
+ stringListType = reflect.TypeOf([]string{})
+)
diff --git a/vendor/github.com/google/cel-go/interpreter/BUILD.bazel b/vendor/github.com/google/cel-go/interpreter/BUILD.bazel
index 04a3ec744..3a5219eb5 100644
--- a/vendor/github.com/google/cel-go/interpreter/BUILD.bazel
+++ b/vendor/github.com/google/cel-go/interpreter/BUILD.bazel
@@ -11,10 +11,10 @@ go_library(
"activation.go",
"attribute_patterns.go",
"attributes.go",
- "coster.go",
"decorators.go",
"dispatcher.go",
"evalstate.go",
+ "formatting.go",
"interpretable.go",
"interpreter.go",
"optimizations.go",
@@ -25,14 +25,15 @@ go_library(
importpath = "github.com/google/cel-go/interpreter",
deps = [
"//common:go_default_library",
+ "//common/ast:go_default_library",
"//common/containers:go_default_library",
+ "//common/functions:go_default_library",
"//common/operators:go_default_library",
"//common/overloads:go_default_library",
"//common/types:go_default_library",
"//common/types/ref:go_default_library",
"//common/types/traits:go_default_library",
- "//interpreter/functions:go_default_library",
- "@org_golang_google_genproto//googleapis/api/expr/v1alpha1:go_default_library",
+ "@org_golang_google_genproto_googleapis_api//expr/v1alpha1:go_default_library",
"@org_golang_google_protobuf//proto:go_default_library",
"@org_golang_google_protobuf//types/known/durationpb:go_default_library",
"@org_golang_google_protobuf//types/known/structpb:go_default_library",
@@ -49,23 +50,25 @@ go_test(
"attributes_test.go",
"interpreter_test.go",
"prune_test.go",
+ "runtimecost_test.go",
],
embed = [
":go_default_library",
],
deps = [
"//checker:go_default_library",
- "//checker/decls:go_default_library",
"//common/containers:go_default_library",
"//common/debug:go_default_library",
+ "//common/decls:go_default_library",
+ "//common/functions:go_default_library",
"//common/operators:go_default_library",
+ "//common/stdlib:go_default_library",
"//common/types:go_default_library",
- "//interpreter/functions:go_default_library",
"//parser:go_default_library",
"//test:go_default_library",
"//test/proto2pb:go_default_library",
"//test/proto3pb:go_default_library",
- "@org_golang_google_genproto//googleapis/api/expr/v1alpha1:go_default_library",
+ "@org_golang_google_genproto_googleapis_api//expr/v1alpha1:go_default_library",
"@org_golang_google_protobuf//proto:go_default_library",
"@org_golang_google_protobuf//types/known/anypb:go_default_library",
],
diff --git a/vendor/github.com/google/cel-go/interpreter/activation.go b/vendor/github.com/google/cel-go/interpreter/activation.go
index f82e4e903..a80264451 100644
--- a/vendor/github.com/google/cel-go/interpreter/activation.go
+++ b/vendor/github.com/google/cel-go/interpreter/activation.go
@@ -58,7 +58,7 @@ func (emptyActivation) Parent() Activation { return nil }
// The output of the lazy binding will overwrite the variable reference in the internal map.
//
// Values which are not represented as ref.Val types on input may be adapted to a ref.Val using
-// the ref.TypeAdapter configured in the environment.
+// the types.Adapter configured in the environment.
func NewActivation(bindings any) (Activation, error) {
if bindings == nil {
return nil, errors.New("bindings must be non-nil")
diff --git a/vendor/github.com/google/cel-go/interpreter/attribute_patterns.go b/vendor/github.com/google/cel-go/interpreter/attribute_patterns.go
index afb7c8d5b..1fbaaf17e 100644
--- a/vendor/github.com/google/cel-go/interpreter/attribute_patterns.go
+++ b/vendor/github.com/google/cel-go/interpreter/attribute_patterns.go
@@ -15,6 +15,8 @@
package interpreter
import (
+ "fmt"
+
"github.com/google/cel-go/common/containers"
"github.com/google/cel-go/common/types"
"github.com/google/cel-go/common/types/ref"
@@ -177,8 +179,8 @@ func numericValueEquals(value any, celValue ref.Val) bool {
// NewPartialAttributeFactory returns an AttributeFactory implementation capable of performing
// AttributePattern matches with PartialActivation inputs.
func NewPartialAttributeFactory(container *containers.Container,
- adapter ref.TypeAdapter,
- provider ref.TypeProvider) AttributeFactory {
+ adapter types.Adapter,
+ provider types.Provider) AttributeFactory {
fac := NewAttributeFactory(container, adapter, provider)
return &partialAttributeFactory{
AttributeFactory: fac,
@@ -191,8 +193,8 @@ func NewPartialAttributeFactory(container *containers.Container,
type partialAttributeFactory struct {
AttributeFactory
container *containers.Container
- adapter ref.TypeAdapter
- provider ref.TypeProvider
+ adapter types.Adapter
+ provider types.Provider
}
// AbsoluteAttribute implementation of the AttributeFactory interface which wraps the
@@ -241,12 +243,15 @@ func (fac *partialAttributeFactory) matchesUnknownPatterns(
vars PartialActivation,
attrID int64,
variableNames []string,
- qualifiers []Qualifier) (types.Unknown, error) {
+ qualifiers []Qualifier) (*types.Unknown, error) {
patterns := vars.UnknownAttributePatterns()
candidateIndices := map[int]struct{}{}
for _, variable := range variableNames {
for i, pat := range patterns {
if pat.VariableMatches(variable) {
+ if len(qualifiers) == 0 {
+ return types.NewUnknown(attrID, types.NewAttributeTrail(variable)), nil
+ }
candidateIndices[i] = struct{}{}
}
}
@@ -255,10 +260,6 @@ func (fac *partialAttributeFactory) matchesUnknownPatterns(
if len(candidateIndices) == 0 {
return nil, nil
}
- // Determine whether to return early if there are no qualifiers.
- if len(qualifiers) == 0 {
- return types.Unknown{attrID}, nil
- }
// Resolve the attribute qualifiers into a static set. This prevents more dynamic
// Attribute resolutions than necessary when there are multiple unknown patterns
// that traverse the same Attribute-based qualifier field.
@@ -300,7 +301,28 @@ func (fac *partialAttributeFactory) matchesUnknownPatterns(
}
}
if isUnk {
- return types.Unknown{matchExprID}, nil
+ attr := types.NewAttributeTrail(pat.variable)
+ for i := 0; i < len(qualPats) && i < len(newQuals); i++ {
+ if qual, ok := newQuals[i].(ConstantQualifier); ok {
+ switch v := qual.Value().Value().(type) {
+ case bool:
+ types.QualifyAttribute[bool](attr, v)
+ case float64:
+ types.QualifyAttribute[int64](attr, int64(v))
+ case int64:
+ types.QualifyAttribute[int64](attr, v)
+ case string:
+ types.QualifyAttribute[string](attr, v)
+ case uint64:
+ types.QualifyAttribute[uint64](attr, v)
+ default:
+ types.QualifyAttribute[string](attr, fmt.Sprintf("%v", v))
+ }
+ } else {
+ types.QualifyAttribute[string](attr, "*")
+ }
+ }
+ return types.NewUnknown(matchExprID, attr), nil
}
}
return nil, nil
diff --git a/vendor/github.com/google/cel-go/interpreter/attributes.go b/vendor/github.com/google/cel-go/interpreter/attributes.go
index fa1c2f985..ca97bdfcf 100644
--- a/vendor/github.com/google/cel-go/interpreter/attributes.go
+++ b/vendor/github.com/google/cel-go/interpreter/attributes.go
@@ -16,14 +16,12 @@ package interpreter
import (
"fmt"
- "math"
+ "strings"
"github.com/google/cel-go/common/containers"
"github.com/google/cel-go/common/types"
"github.com/google/cel-go/common/types/ref"
"github.com/google/cel-go/common/types/traits"
-
- exprpb "google.golang.org/genproto/googleapis/api/expr/v1alpha1"
)
// AttributeFactory provides methods creating Attribute and Qualifier values.
@@ -61,7 +59,7 @@ type AttributeFactory interface {
// The qualifier may consider the object type being qualified, if present. If absent, the
// qualification should be considered dynamic and the qualification should still work, though
// it may be sub-optimal.
- NewQualifier(objType *exprpb.Type, qualID int64, val any, opt bool) (Qualifier, error)
+ NewQualifier(objType *types.Type, qualID int64, val any, opt bool) (Qualifier, error)
}
// Qualifier marker interface for designating different qualifier values and where they appear
@@ -131,7 +129,7 @@ type NamespacedAttribute interface {
// NewAttributeFactory returns a default AttributeFactory which is produces Attribute values
// capable of resolving types by simple names and qualify the values using the supported qualifier
// types: bool, int, string, and uint.
-func NewAttributeFactory(cont *containers.Container, a ref.TypeAdapter, p ref.TypeProvider) AttributeFactory {
+func NewAttributeFactory(cont *containers.Container, a types.Adapter, p types.Provider) AttributeFactory {
return &attrFactory{
container: cont,
adapter: a,
@@ -141,8 +139,8 @@ func NewAttributeFactory(cont *containers.Container, a ref.TypeAdapter, p ref.Ty
type attrFactory struct {
container *containers.Container
- adapter ref.TypeAdapter
- provider ref.TypeProvider
+ adapter types.Adapter
+ provider types.Provider
}
// AbsoluteAttribute refers to a variable value and an optional qualifier path.
@@ -199,13 +197,13 @@ func (r *attrFactory) RelativeAttribute(id int64, operand Interpretable) Attribu
}
// NewQualifier is an implementation of the AttributeFactory interface.
-func (r *attrFactory) NewQualifier(objType *exprpb.Type, qualID int64, val any, opt bool) (Qualifier, error) {
+func (r *attrFactory) NewQualifier(objType *types.Type, qualID int64, val any, opt bool) (Qualifier, error) {
// Before creating a new qualifier check to see if this is a protobuf message field access.
// If so, use the precomputed GetFrom qualification method rather than the standard
// stringQualifier.
str, isStr := val.(string)
- if isStr && objType != nil && objType.GetMessageType() != "" {
- ft, found := r.provider.FindFieldType(objType.GetMessageType(), str)
+ if isStr && objType != nil && objType.Kind() == types.StructKind {
+ ft, found := r.provider.FindStructFieldType(objType.TypeName(), str)
if found && ft.IsSet != nil && ft.GetFrom != nil {
return &fieldQualifier{
id: qualID,
@@ -225,14 +223,18 @@ type absoluteAttribute struct {
// (package) of the expression.
namespaceNames []string
qualifiers []Qualifier
- adapter ref.TypeAdapter
- provider ref.TypeProvider
+ adapter types.Adapter
+ provider types.Provider
fac AttributeFactory
}
// ID implements the Attribute interface method.
func (a *absoluteAttribute) ID() int64 {
- return a.id
+ qualCount := len(a.qualifiers)
+ if qualCount == 0 {
+ return a.id
+ }
+ return a.qualifiers[qualCount-1].ID()
}
// IsOptional returns trivially false for an attribute as the attribute represents a fully
@@ -242,18 +244,6 @@ func (a *absoluteAttribute) IsOptional() bool {
return false
}
-// Cost implements the Coster interface method.
-func (a *absoluteAttribute) Cost() (min, max int64) {
- for _, q := range a.qualifiers {
- minQ, maxQ := estimateCost(q)
- min += minQ
- max += maxQ
- }
- min++ // For object retrieval.
- max++
- return
-}
-
// AddQualifier implements the Attribute interface method.
func (a *absoluteAttribute) AddQualifier(qual Qualifier) (Attribute, error) {
a.qualifiers = append(a.qualifiers, qual)
@@ -302,7 +292,11 @@ func (a *absoluteAttribute) Resolve(vars Activation) (any, error) {
return nil, err
}
if isOpt {
- return types.OptionalOf(a.adapter.NativeToValue(obj)), nil
+ val := a.adapter.NativeToValue(obj)
+ if types.IsUnknown(val) {
+ return val, nil
+ }
+ return types.OptionalOf(val), nil
}
return obj, nil
}
@@ -314,7 +308,14 @@ func (a *absoluteAttribute) Resolve(vars Activation) (any, error) {
}
}
}
- return nil, missingAttribute(a.String())
+ var attrNames strings.Builder
+ for i, nm := range a.namespaceNames {
+ if i != 0 {
+ attrNames.WriteString(", ")
+ }
+ attrNames.WriteString(nm)
+ }
+ return nil, missingAttribute(attrNames.String())
}
type conditionalAttribute struct {
@@ -322,12 +323,17 @@ type conditionalAttribute struct {
expr Interpretable
truthy Attribute
falsy Attribute
- adapter ref.TypeAdapter
+ adapter types.Adapter
fac AttributeFactory
}
// ID is an implementation of the Attribute interface method.
func (a *conditionalAttribute) ID() int64 {
+ // There's a field access after the conditional.
+ if a.truthy.ID() == a.falsy.ID() {
+ return a.truthy.ID()
+ }
+ // Otherwise return the conditional id as the consistent id being tracked.
return a.id
}
@@ -338,16 +344,6 @@ func (a *conditionalAttribute) IsOptional() bool {
return false
}
-// Cost provides the heuristic cost of a ternary operation ? : .
-// The cost is computed as cost(expr) plus the min/max costs of evaluating either
-// `t` or `f`.
-func (a *conditionalAttribute) Cost() (min, max int64) {
- tMin, tMax := estimateCost(a.truthy)
- fMin, fMax := estimateCost(a.falsy)
- eMin, eMax := estimateCost(a.expr)
- return eMin + findMin(tMin, fMin), eMax + findMax(tMax, fMax)
-}
-
// AddQualifier appends the same qualifier to both sides of the conditional, in effect managing
// the qualification of alternate attributes.
func (a *conditionalAttribute) AddQualifier(qual Qualifier) (Attribute, error) {
@@ -395,14 +391,14 @@ func (a *conditionalAttribute) String() string {
type maybeAttribute struct {
id int64
attrs []NamespacedAttribute
- adapter ref.TypeAdapter
- provider ref.TypeProvider
+ adapter types.Adapter
+ provider types.Provider
fac AttributeFactory
}
// ID is an implementation of the Attribute interface method.
func (a *maybeAttribute) ID() int64 {
- return a.id
+ return a.attrs[0].ID()
}
// IsOptional returns trivially false for an attribute as the attribute represents a fully
@@ -412,18 +408,6 @@ func (a *maybeAttribute) IsOptional() bool {
return false
}
-// Cost implements the Coster interface method. The min cost is computed as the minimal cost among
-// all the possible attributes, the max cost ditto.
-func (a *maybeAttribute) Cost() (min, max int64) {
- min, max = math.MaxInt64, 0
- for _, a := range a.attrs {
- minA, maxA := estimateCost(a)
- min = findMin(min, minA)
- max = findMax(max, maxA)
- }
- return
-}
-
// AddQualifier adds a qualifier to each possible attribute variant, and also creates
// a new namespaced variable from the qualified value.
//
@@ -471,7 +455,9 @@ func (a *maybeAttribute) AddQualifier(qual Qualifier) (Attribute, error) {
}
}
// Next, ensure the most specific variable / type reference is searched first.
- a.attrs = append([]NamespacedAttribute{a.fac.AbsoluteAttribute(qual.ID(), augmentedNames...)}, a.attrs...)
+ if len(augmentedNames) != 0 {
+ a.attrs = append([]NamespacedAttribute{a.fac.AbsoluteAttribute(qual.ID(), augmentedNames...)}, a.attrs...)
+ }
return a, nil
}
@@ -523,13 +509,17 @@ type relativeAttribute struct {
id int64
operand Interpretable
qualifiers []Qualifier
- adapter ref.TypeAdapter
+ adapter types.Adapter
fac AttributeFactory
}
// ID is an implementation of the Attribute interface method.
func (a *relativeAttribute) ID() int64 {
- return a.id
+ qualCount := len(a.qualifiers)
+ if qualCount == 0 {
+ return a.id
+ }
+ return a.qualifiers[qualCount-1].ID()
}
// IsOptional returns trivially false for an attribute as the attribute represents a fully
@@ -539,17 +529,6 @@ func (a *relativeAttribute) IsOptional() bool {
return false
}
-// Cost implements the Coster interface method.
-func (a *relativeAttribute) Cost() (min, max int64) {
- min, max = estimateCost(a.operand)
- for _, qual := range a.qualifiers {
- minQ, maxQ := estimateCost(qual)
- min += minQ
- max += maxQ
- }
- return
-}
-
// AddQualifier implements the Attribute interface method.
func (a *relativeAttribute) AddQualifier(qual Qualifier) (Attribute, error) {
a.qualifiers = append(a.qualifiers, qual)
@@ -581,7 +560,11 @@ func (a *relativeAttribute) Resolve(vars Activation) (any, error) {
return nil, err
}
if isOpt {
- return types.OptionalOf(a.adapter.NativeToValue(obj)), nil
+ val := a.adapter.NativeToValue(obj)
+ if types.IsUnknown(val) {
+ return val, nil
+ }
+ return types.OptionalOf(val), nil
}
return obj, nil
}
@@ -591,7 +574,7 @@ func (a *relativeAttribute) String() string {
return fmt.Sprintf("id: %v, operand: %v", a.id, a.operand)
}
-func newQualifier(adapter ref.TypeAdapter, id int64, v any, opt bool) (Qualifier, error) {
+func newQualifier(adapter types.Adapter, id int64, v any, opt bool) (Qualifier, error) {
var qual Qualifier
switch val := v.(type) {
case Attribute:
@@ -672,7 +655,7 @@ func newQualifier(adapter ref.TypeAdapter, id int64, v any, opt bool) (Qualifier
qual = &doubleQualifier{
id: id, value: float64(val), celValue: val, adapter: adapter, optional: opt,
}
- case types.Unknown:
+ case *types.Unknown:
qual = &unknownQualifier{id: id, value: val}
default:
if q, ok := v.(Qualifier); ok {
@@ -700,16 +683,11 @@ func (q *attrQualifier) IsOptional() bool {
return q.optional
}
-// Cost returns zero for constant field qualifiers
-func (q *attrQualifier) Cost() (min, max int64) {
- return estimateCost(q.Attribute)
-}
-
type stringQualifier struct {
id int64
value string
celValue ref.Val
- adapter ref.TypeAdapter
+ adapter types.Adapter
optional bool
}
@@ -806,16 +784,11 @@ func (q *stringQualifier) Value() ref.Val {
return q.celValue
}
-// Cost returns zero for constant field qualifiers
-func (q *stringQualifier) Cost() (min, max int64) {
- return 0, 0
-}
-
type intQualifier struct {
id int64
value int64
celValue ref.Val
- adapter ref.TypeAdapter
+ adapter types.Adapter
optional bool
}
@@ -938,16 +911,11 @@ func (q *intQualifier) Value() ref.Val {
return q.celValue
}
-// Cost returns zero for constant field qualifiers
-func (q *intQualifier) Cost() (min, max int64) {
- return 0, 0
-}
-
type uintQualifier struct {
id int64
value uint64
celValue ref.Val
- adapter ref.TypeAdapter
+ adapter types.Adapter
optional bool
}
@@ -1008,16 +976,11 @@ func (q *uintQualifier) Value() ref.Val {
return q.celValue
}
-// Cost returns zero for constant field qualifiers
-func (q *uintQualifier) Cost() (min, max int64) {
- return 0, 0
-}
-
type boolQualifier struct {
id int64
value bool
celValue ref.Val
- adapter ref.TypeAdapter
+ adapter types.Adapter
optional bool
}
@@ -1064,19 +1027,14 @@ func (q *boolQualifier) Value() ref.Val {
return q.celValue
}
-// Cost returns zero for constant field qualifiers
-func (q *boolQualifier) Cost() (min, max int64) {
- return 0, 0
-}
-
// fieldQualifier indicates that the qualification is a well-defined field with a known
// field type. When the field type is known this can be used to improve the speed and
// efficiency of field resolution.
type fieldQualifier struct {
id int64
Name string
- FieldType *ref.FieldType
- adapter ref.TypeAdapter
+ FieldType *types.FieldType
+ adapter types.Adapter
optional bool
}
@@ -1125,11 +1083,6 @@ func (q *fieldQualifier) Value() ref.Val {
return types.String(q.Name)
}
-// Cost returns zero for constant field qualifiers
-func (q *fieldQualifier) Cost() (min, max int64) {
- return 0, 0
-}
-
// doubleQualifier qualifies a CEL object, map, or list using a double value.
//
// This qualifier is used for working with dynamic data like JSON or protobuf.Any where the value
@@ -1139,7 +1092,7 @@ type doubleQualifier struct {
id int64
value float64
celValue ref.Val
- adapter ref.TypeAdapter
+ adapter types.Adapter
optional bool
}
@@ -1176,7 +1129,7 @@ func (q *doubleQualifier) Value() ref.Val {
// for any value subject to qualification. This is consistent with CEL's unknown handling elsewhere.
type unknownQualifier struct {
id int64
- value types.Unknown
+ value *types.Unknown
}
// ID is an implementation of the Qualifier interface method.
@@ -1224,6 +1177,9 @@ func applyQualifiers(vars Activation, obj any, qualifiers []Qualifier) (any, boo
return nil, false, err
}
if !present {
+ // We return optional none here with a presence of 'false' as the layers
+ // above will attempt to call types.OptionalOf() on a present value if any
+ // of the qualifiers is optional.
return types.OptionalNone, false, nil
}
} else {
@@ -1267,15 +1223,17 @@ func attrQualifyIfPresent(fac AttributeFactory, vars Activation, obj any, qualAt
// refQualify attempts to convert the value to a CEL value and then uses reflection methods to try and
// apply the qualifier with the option to presence test field accesses before retrieving field values.
-func refQualify(adapter ref.TypeAdapter, obj any, idx ref.Val, presenceTest, presenceOnly bool) (ref.Val, bool, error) {
+func refQualify(adapter types.Adapter, obj any, idx ref.Val, presenceTest, presenceOnly bool) (ref.Val, bool, error) {
celVal := adapter.NativeToValue(obj)
switch v := celVal.(type) {
- case types.Unknown:
+ case *types.Unknown:
return v, true, nil
case *types.Err:
return nil, false, v
case traits.Mapper:
val, found := v.Find(idx)
+ // If the index is of the wrong type for the map, then it is possible
+ // for the Find call to produce an error.
if types.IsError(val) {
return nil, false, val.(*types.Err)
}
@@ -1287,6 +1245,8 @@ func refQualify(adapter ref.TypeAdapter, obj any, idx ref.Val, presenceTest, pre
}
return nil, false, missingKey(idx)
case traits.Lister:
+ // If the index argument is not a valid numeric type, then it is possible
+ // for the index operation to produce an error.
i, err := types.IndexOrError(idx)
if err != nil {
return nil, false, err
@@ -1307,6 +1267,8 @@ func refQualify(adapter ref.TypeAdapter, obj any, idx ref.Val, presenceTest, pre
if types.IsError(presence) {
return nil, false, presence.(*types.Err)
}
+ // If not found or presence only test, then return.
+ // Otherwise, if found, obtain the value later on.
if presenceOnly || presence == types.False {
return nil, presence == types.True, nil
}
@@ -1364,7 +1326,7 @@ func (e *resolutionError) Error() string {
return fmt.Sprintf("index out of bounds: %v", e.missingIndex)
}
if e.missingAttribute != "" {
- return fmt.Sprintf("no such attribute: %s", e.missingAttribute)
+ return fmt.Sprintf("no such attribute(s): %s", e.missingAttribute)
}
return "invalid attribute"
}
@@ -1373,17 +1335,3 @@ func (e *resolutionError) Error() string {
func (e *resolutionError) Is(err error) bool {
return err.Error() == e.Error()
}
-
-func findMin(x, y int64) int64 {
- if x < y {
- return x
- }
- return y
-}
-
-func findMax(x, y int64) int64 {
- if x > y {
- return x
- }
- return y
-}
diff --git a/vendor/github.com/google/cel-go/interpreter/coster.go b/vendor/github.com/google/cel-go/interpreter/coster.go
deleted file mode 100644
index c79862c49..000000000
--- a/vendor/github.com/google/cel-go/interpreter/coster.go
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2020 Google LLC
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package interpreter
-
-import "math"
-
-// TODO: remove Coster.
-
-// Coster calculates the heuristic cost incurred during evaluation.
-// Deprecated: Please migrate cel.EstimateCost, it supports length estimates for input data and cost estimates for
-// extension functions.
-type Coster interface {
- Cost() (min, max int64)
-}
-
-// estimateCost returns the heuristic cost interval for the program.
-func estimateCost(i any) (min, max int64) {
- c, ok := i.(Coster)
- if !ok {
- return 0, math.MaxInt64
- }
- return c.Cost()
-}
diff --git a/vendor/github.com/google/cel-go/interpreter/decorators.go b/vendor/github.com/google/cel-go/interpreter/decorators.go
index bdbbad43e..502db35fc 100644
--- a/vendor/github.com/google/cel-go/interpreter/decorators.go
+++ b/vendor/github.com/google/cel-go/interpreter/decorators.go
@@ -29,7 +29,7 @@ type InterpretableDecorator func(Interpretable) (Interpretable, error)
func decObserveEval(observer EvalObserver) InterpretableDecorator {
return func(i Interpretable) (Interpretable, error) {
switch inst := i.(type) {
- case *evalWatch, *evalWatchAttr, *evalWatchConst:
+ case *evalWatch, *evalWatchAttr, *evalWatchConst, *evalWatchConstructor:
// these instruction are already watching, return straight-away.
return i, nil
case InterpretableAttribute:
@@ -42,6 +42,11 @@ func decObserveEval(observer EvalObserver) InterpretableDecorator {
InterpretableConst: inst,
observer: observer,
}, nil
+ case InterpretableConstructor:
+ return &evalWatchConstructor{
+ constructor: inst,
+ observer: observer,
+ }, nil
default:
return &evalWatch{
Interpretable: i,
@@ -70,15 +75,13 @@ func decDisableShortcircuits() InterpretableDecorator {
switch expr := i.(type) {
case *evalOr:
return &evalExhaustiveOr{
- id: expr.id,
- lhs: expr.lhs,
- rhs: expr.rhs,
+ id: expr.id,
+ terms: expr.terms,
}, nil
case *evalAnd:
return &evalExhaustiveAnd{
- id: expr.id,
- lhs: expr.lhs,
- rhs: expr.rhs,
+ id: expr.id,
+ terms: expr.terms,
}, nil
case *evalFold:
expr.exhaustive = true
@@ -224,8 +227,8 @@ func maybeOptimizeSetMembership(i Interpretable, inlist InterpretableCall) (Inte
valueSet := make(map[ref.Val]ref.Val)
for it.HasNext() == types.True {
elem := it.Next()
- if !types.IsPrimitiveType(elem) {
- // Note, non-primitive type are not yet supported.
+ if !types.IsPrimitiveType(elem) || elem.Type() == types.BytesType {
+ // Note, non-primitive type are not yet supported, and []byte isn't hashable.
return i, nil
}
valueSet[elem] = types.True
diff --git a/vendor/github.com/google/cel-go/interpreter/dispatcher.go b/vendor/github.com/google/cel-go/interpreter/dispatcher.go
index febf9d8a8..8f0bdb7b8 100644
--- a/vendor/github.com/google/cel-go/interpreter/dispatcher.go
+++ b/vendor/github.com/google/cel-go/interpreter/dispatcher.go
@@ -17,7 +17,7 @@ package interpreter
import (
"fmt"
- "github.com/google/cel-go/interpreter/functions"
+ "github.com/google/cel-go/common/functions"
)
// Dispatcher resolves function calls to their appropriate overload.
diff --git a/vendor/github.com/google/cel-go/interpreter/evalstate.go b/vendor/github.com/google/cel-go/interpreter/evalstate.go
index cc0d3e6f9..4bdd1fdc7 100644
--- a/vendor/github.com/google/cel-go/interpreter/evalstate.go
+++ b/vendor/github.com/google/cel-go/interpreter/evalstate.go
@@ -66,7 +66,11 @@ func (s *evalState) Value(exprID int64) (ref.Val, bool) {
// SetValue is an implementation of the EvalState interface method.
func (s *evalState) SetValue(exprID int64, val ref.Val) {
- s.values[exprID] = val
+ if val == nil {
+ delete(s.values, exprID)
+ } else {
+ s.values[exprID] = val
+ }
}
// Reset implements the EvalState interface method.
diff --git a/vendor/github.com/google/cel-go/interpreter/formatting.go b/vendor/github.com/google/cel-go/interpreter/formatting.go
new file mode 100644
index 000000000..e3f753374
--- /dev/null
+++ b/vendor/github.com/google/cel-go/interpreter/formatting.go
@@ -0,0 +1,383 @@
+// Copyright 2023 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package interpreter
+
+import (
+ "errors"
+ "fmt"
+ "strconv"
+ "strings"
+ "unicode"
+
+ "github.com/google/cel-go/common/types"
+ "github.com/google/cel-go/common/types/ref"
+)
+
+type typeVerifier func(int64, ...ref.Type) (bool, error)
+
+// InterpolateFormattedString checks the syntax and cardinality of any string.format calls present in the expression and reports
+// any errors at compile time.
+func InterpolateFormattedString(verifier typeVerifier) InterpretableDecorator {
+ return func(inter Interpretable) (Interpretable, error) {
+ call, ok := inter.(InterpretableCall)
+ if !ok {
+ return inter, nil
+ }
+ if call.OverloadID() != "string_format" {
+ return inter, nil
+ }
+ args := call.Args()
+ if len(args) != 2 {
+ return nil, fmt.Errorf("wrong number of arguments to string.format (expected 2, got %d)", len(args))
+ }
+ fmtStrInter, ok := args[0].(InterpretableConst)
+ if !ok {
+ return inter, nil
+ }
+ var fmtArgsInter InterpretableConstructor
+ fmtArgsInter, ok = args[1].(InterpretableConstructor)
+ if !ok {
+ return inter, nil
+ }
+ if fmtArgsInter.Type() != types.ListType {
+ // don't necessarily return an error since the list may be DynType
+ return inter, nil
+ }
+ formatStr := fmtStrInter.Value().Value().(string)
+ initVals := fmtArgsInter.InitVals()
+
+ formatCheck := &formatCheck{
+ args: initVals,
+ verifier: verifier,
+ }
+ // use a placeholder locale, since locale doesn't affect syntax
+ _, err := ParseFormatString(formatStr, formatCheck, formatCheck, "en_US")
+ if err != nil {
+ return nil, err
+ }
+ seenArgs := formatCheck.argsRequested
+ if len(initVals) > seenArgs {
+ return nil, fmt.Errorf("too many arguments supplied to string.format (expected %d, got %d)", seenArgs, len(initVals))
+ }
+ return inter, nil
+ }
+}
+
+type formatCheck struct {
+ args []Interpretable
+ argsRequested int
+ curArgIndex int64
+ enableCheckArgTypes bool
+ verifier typeVerifier
+}
+
+func (c *formatCheck) String(arg ref.Val, locale string) (string, error) {
+ valid, err := verifyString(c.args[c.curArgIndex], c.verifier)
+ if err != nil {
+ return "", err
+ }
+ if !valid {
+ return "", errors.New("string clause can only be used on strings, bools, bytes, ints, doubles, maps, lists, types, durations, and timestamps")
+ }
+ return "", nil
+}
+
+func (c *formatCheck) Decimal(arg ref.Val, locale string) (string, error) {
+ id := c.args[c.curArgIndex].ID()
+ valid, err := c.verifier(id, types.IntType, types.UintType)
+ if err != nil {
+ return "", err
+ }
+ if !valid {
+ return "", errors.New("integer clause can only be used on integers")
+ }
+ return "", nil
+}
+
+func (c *formatCheck) Fixed(precision *int) func(ref.Val, string) (string, error) {
+ return func(arg ref.Val, locale string) (string, error) {
+ id := c.args[c.curArgIndex].ID()
+ // we allow StringType since "NaN", "Infinity", and "-Infinity" are also valid values
+ valid, err := c.verifier(id, types.DoubleType, types.StringType)
+ if err != nil {
+ return "", err
+ }
+ if !valid {
+ return "", errors.New("fixed-point clause can only be used on doubles")
+ }
+ return "", nil
+ }
+}
+
+func (c *formatCheck) Scientific(precision *int) func(ref.Val, string) (string, error) {
+ return func(arg ref.Val, locale string) (string, error) {
+ id := c.args[c.curArgIndex].ID()
+ valid, err := c.verifier(id, types.DoubleType, types.StringType)
+ if err != nil {
+ return "", err
+ }
+ if !valid {
+ return "", errors.New("scientific clause can only be used on doubles")
+ }
+ return "", nil
+ }
+}
+
+func (c *formatCheck) Binary(arg ref.Val, locale string) (string, error) {
+ id := c.args[c.curArgIndex].ID()
+ valid, err := c.verifier(id, types.IntType, types.UintType, types.BoolType)
+ if err != nil {
+ return "", err
+ }
+ if !valid {
+ return "", errors.New("only integers and bools can be formatted as binary")
+ }
+ return "", nil
+}
+
+func (c *formatCheck) Hex(useUpper bool) func(ref.Val, string) (string, error) {
+ return func(arg ref.Val, locale string) (string, error) {
+ id := c.args[c.curArgIndex].ID()
+ valid, err := c.verifier(id, types.IntType, types.UintType, types.StringType, types.BytesType)
+ if err != nil {
+ return "", err
+ }
+ if !valid {
+ return "", errors.New("only integers, byte buffers, and strings can be formatted as hex")
+ }
+ return "", nil
+ }
+}
+
+func (c *formatCheck) Octal(arg ref.Val, locale string) (string, error) {
+ id := c.args[c.curArgIndex].ID()
+ valid, err := c.verifier(id, types.IntType, types.UintType)
+ if err != nil {
+ return "", err
+ }
+ if !valid {
+ return "", errors.New("octal clause can only be used on integers")
+ }
+ return "", nil
+}
+
+func (c *formatCheck) Arg(index int64) (ref.Val, error) {
+ c.argsRequested++
+ c.curArgIndex = index
+ // return a dummy value - this is immediately passed to back to us
+ // through one of the FormatCallback functions, so anything will do
+ return types.Int(0), nil
+}
+
+func (c *formatCheck) ArgSize() int64 {
+ return int64(len(c.args))
+}
+
+func verifyString(sub Interpretable, verifier typeVerifier) (bool, error) {
+ subVerified, err := verifier(sub.ID(),
+ types.ListType, types.MapType, types.IntType, types.UintType, types.DoubleType,
+ types.BoolType, types.StringType, types.TimestampType, types.BytesType, types.DurationType, types.TypeType, types.NullType)
+ if err != nil {
+ return false, err
+ }
+ if !subVerified {
+ return false, nil
+ }
+ con, ok := sub.(InterpretableConstructor)
+ if ok {
+ members := con.InitVals()
+ for _, m := range members {
+ // recursively verify if we're dealing with a list/map
+ verified, err := verifyString(m, verifier)
+ if err != nil {
+ return false, err
+ }
+ if !verified {
+ return false, nil
+ }
+ }
+ }
+ return true, nil
+
+}
+
+// FormatStringInterpolator is an interface that allows user-defined behavior
+// for formatting clause implementations, as well as argument retrieval.
+// Each function is expected to support the appropriate types as laid out in
+// the string.format documentation, and to return an error if given an inappropriate type.
+type FormatStringInterpolator interface {
+ // String takes a ref.Val and a string representing the current locale identifier
+ // and returns the Val formatted as a string, or an error if one occurred.
+ String(ref.Val, string) (string, error)
+
+ // Decimal takes a ref.Val and a string representing the current locale identifier
+ // and returns the Val formatted as a decimal integer, or an error if one occurred.
+ Decimal(ref.Val, string) (string, error)
+
+ // Fixed takes an int pointer representing precision (or nil if none was given) and
+ // returns a function operating in a similar manner to String and Decimal, taking a
+ // ref.Val and locale and returning the appropriate string. A closure is returned
+ // so precision can be set without needing an additional function call/configuration.
+ Fixed(*int) func(ref.Val, string) (string, error)
+
+ // Scientific functions identically to Fixed, except the string returned from the closure
+ // is expected to be in scientific notation.
+ Scientific(*int) func(ref.Val, string) (string, error)
+
+ // Binary takes a ref.Val and a string representing the current locale identifier
+ // and returns the Val formatted as a binary integer, or an error if one occurred.
+ Binary(ref.Val, string) (string, error)
+
+ // Hex takes a boolean that, if true, indicates the hex string output by the returned
+ // closure should use uppercase letters for A-F.
+ Hex(bool) func(ref.Val, string) (string, error)
+
+ // Octal takes a ref.Val and a string representing the current locale identifier and
+ // returns the Val formatted in octal, or an error if one occurred.
+ Octal(ref.Val, string) (string, error)
+}
+
+// FormatList is an interface that allows user-defined list-like datatypes to be used
+// for formatting clause implementations.
+type FormatList interface {
+ // Arg returns the ref.Val at the given index, or an error if one occurred.
+ Arg(int64) (ref.Val, error)
+ // ArgSize returns the length of the argument list.
+ ArgSize() int64
+}
+
+type clauseImpl func(ref.Val, string) (string, error)
+
+// ParseFormatString formats a string according to the string.format syntax, taking the clause implementations
+// from the provided FormatCallback and the args from the given FormatList.
+func ParseFormatString(formatStr string, callback FormatStringInterpolator, list FormatList, locale string) (string, error) {
+ i := 0
+ argIndex := 0
+ var builtStr strings.Builder
+ for i < len(formatStr) {
+ if formatStr[i] == '%' {
+ if i+1 < len(formatStr) && formatStr[i+1] == '%' {
+ err := builtStr.WriteByte('%')
+ if err != nil {
+ return "", fmt.Errorf("error writing format string: %w", err)
+ }
+ i += 2
+ continue
+ } else {
+ argAny, err := list.Arg(int64(argIndex))
+ if err != nil {
+ return "", err
+ }
+ if i+1 >= len(formatStr) {
+ return "", errors.New("unexpected end of string")
+ }
+ if int64(argIndex) >= list.ArgSize() {
+ return "", fmt.Errorf("index %d out of range", argIndex)
+ }
+ numRead, val, refErr := parseAndFormatClause(formatStr[i:], argAny, callback, list, locale)
+ if refErr != nil {
+ return "", refErr
+ }
+ _, err = builtStr.WriteString(val)
+ if err != nil {
+ return "", fmt.Errorf("error writing format string: %w", err)
+ }
+ i += numRead
+ argIndex++
+ }
+ } else {
+ err := builtStr.WriteByte(formatStr[i])
+ if err != nil {
+ return "", fmt.Errorf("error writing format string: %w", err)
+ }
+ i++
+ }
+ }
+ return builtStr.String(), nil
+}
+
+// parseAndFormatClause parses the format clause at the start of the given string with val, and returns
+// how many characters were consumed and the substituted string form of val, or an error if one occurred.
+func parseAndFormatClause(formatStr string, val ref.Val, callback FormatStringInterpolator, list FormatList, locale string) (int, string, error) {
+ i := 1
+ read, formatter, err := parseFormattingClause(formatStr[i:], callback)
+ i += read
+ if err != nil {
+ return -1, "", fmt.Errorf("could not parse formatting clause: %s", err)
+ }
+
+ valStr, err := formatter(val, locale)
+ if err != nil {
+ return -1, "", fmt.Errorf("error during formatting: %s", err)
+ }
+ return i, valStr, nil
+}
+
+func parseFormattingClause(formatStr string, callback FormatStringInterpolator) (int, clauseImpl, error) {
+ i := 0
+ read, precision, err := parsePrecision(formatStr[i:])
+ i += read
+ if err != nil {
+ return -1, nil, fmt.Errorf("error while parsing precision: %w", err)
+ }
+ r := rune(formatStr[i])
+ i++
+ switch r {
+ case 's':
+ return i, callback.String, nil
+ case 'd':
+ return i, callback.Decimal, nil
+ case 'f':
+ return i, callback.Fixed(precision), nil
+ case 'e':
+ return i, callback.Scientific(precision), nil
+ case 'b':
+ return i, callback.Binary, nil
+ case 'x', 'X':
+ return i, callback.Hex(unicode.IsUpper(r)), nil
+ case 'o':
+ return i, callback.Octal, nil
+ default:
+ return -1, nil, fmt.Errorf("unrecognized formatting clause \"%c\"", r)
+ }
+}
+
+func parsePrecision(formatStr string) (int, *int, error) {
+ i := 0
+ if formatStr[i] != '.' {
+ return i, nil, nil
+ }
+ i++
+ var buffer strings.Builder
+ for {
+ if i >= len(formatStr) {
+ return -1, nil, errors.New("could not find end of precision specifier")
+ }
+ if !isASCIIDigit(rune(formatStr[i])) {
+ break
+ }
+ buffer.WriteByte(formatStr[i])
+ i++
+ }
+ precision, err := strconv.Atoi(buffer.String())
+ if err != nil {
+ return -1, nil, fmt.Errorf("error while converting precision to integer: %w", err)
+ }
+ return i, &precision, nil
+}
+
+func isASCIIDigit(r rune) bool {
+ return r <= unicode.MaxASCII && unicode.IsDigit(r)
+}
diff --git a/vendor/github.com/google/cel-go/interpreter/functions/BUILD.bazel b/vendor/github.com/google/cel-go/interpreter/functions/BUILD.bazel
index 846d11bf4..4a80c3ea0 100644
--- a/vendor/github.com/google/cel-go/interpreter/functions/BUILD.bazel
+++ b/vendor/github.com/google/cel-go/interpreter/functions/BUILD.bazel
@@ -7,16 +7,11 @@ package(
go_library(
name = "go_default_library",
- srcs = [
+ srcs = [
"functions.go",
- "standard.go",
],
importpath = "github.com/google/cel-go/interpreter/functions",
deps = [
- "//common/operators:go_default_library",
- "//common/overloads:go_default_library",
- "//common/types:go_default_library",
- "//common/types/ref:go_default_library",
- "//common/types/traits:go_default_library",
+ "//common/functions:go_default_library",
],
)
diff --git a/vendor/github.com/google/cel-go/interpreter/functions/functions.go b/vendor/github.com/google/cel-go/interpreter/functions/functions.go
index 981601752..21ffb6924 100644
--- a/vendor/github.com/google/cel-go/interpreter/functions/functions.go
+++ b/vendor/github.com/google/cel-go/interpreter/functions/functions.go
@@ -16,7 +16,7 @@
// interpreter and as declared within the checker#StandardDeclarations.
package functions
-import "github.com/google/cel-go/common/types/ref"
+import fn "github.com/google/cel-go/common/functions"
// Overload defines a named overload of a function, indicating an operand trait
// which must be present on the first argument to the overload as well as one
@@ -26,37 +26,14 @@ import "github.com/google/cel-go/common/types/ref"
// and the specializations simplify the call contract for implementers of
// types with operator overloads. Any added complexity is assumed to be handled
// by the generic FunctionOp.
-type Overload struct {
- // Operator name as written in an expression or defined within
- // operators.go.
- Operator string
-
- // Operand trait used to dispatch the call. The zero-value indicates a
- // global function overload or that one of the Unary / Binary / Function
- // definitions should be used to execute the call.
- OperandTrait int
-
- // Unary defines the overload with a UnaryOp implementation. May be nil.
- Unary UnaryOp
-
- // Binary defines the overload with a BinaryOp implementation. May be nil.
- Binary BinaryOp
-
- // Function defines the overload with a FunctionOp implementation. May be
- // nil.
- Function FunctionOp
-
- // NonStrict specifies whether the Overload will tolerate arguments that
- // are types.Err or types.Unknown.
- NonStrict bool
-}
+type Overload = fn.Overload
// UnaryOp is a function that takes a single value and produces an output.
-type UnaryOp func(value ref.Val) ref.Val
+type UnaryOp = fn.UnaryOp
// BinaryOp is a function that takes two values and produces an output.
-type BinaryOp func(lhs ref.Val, rhs ref.Val) ref.Val
+type BinaryOp = fn.BinaryOp
// FunctionOp is a function with accepts zero or more arguments and produces
// a value or error as a result.
-type FunctionOp func(values ...ref.Val) ref.Val
+type FunctionOp = fn.FunctionOp
diff --git a/vendor/github.com/google/cel-go/interpreter/functions/standard.go b/vendor/github.com/google/cel-go/interpreter/functions/standard.go
deleted file mode 100644
index 73e936114..000000000
--- a/vendor/github.com/google/cel-go/interpreter/functions/standard.go
+++ /dev/null
@@ -1,270 +0,0 @@
-// Copyright 2018 Google LLC
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package functions
-
-import (
- "github.com/google/cel-go/common/operators"
- "github.com/google/cel-go/common/overloads"
- "github.com/google/cel-go/common/types"
- "github.com/google/cel-go/common/types/ref"
- "github.com/google/cel-go/common/types/traits"
-)
-
-// StandardOverloads returns the definitions of the built-in overloads.
-func StandardOverloads() []*Overload {
- return []*Overload{
- // Logical not (!a)
- {
- Operator: operators.LogicalNot,
- OperandTrait: traits.NegatorType,
- Unary: func(value ref.Val) ref.Val {
- if !types.IsBool(value) {
- return types.ValOrErr(value, "no such overload")
- }
- return value.(traits.Negater).Negate()
- }},
- // Not strictly false: IsBool(a) ? a : true
- {
- Operator: operators.NotStrictlyFalse,
- Unary: notStrictlyFalse},
- // Deprecated: not strictly false, may be overridden in the environment.
- {
- Operator: operators.OldNotStrictlyFalse,
- Unary: notStrictlyFalse},
-
- // Less than operator
- {Operator: operators.Less,
- OperandTrait: traits.ComparerType,
- Binary: func(lhs ref.Val, rhs ref.Val) ref.Val {
- cmp := lhs.(traits.Comparer).Compare(rhs)
- if cmp == types.IntNegOne {
- return types.True
- }
- if cmp == types.IntOne || cmp == types.IntZero {
- return types.False
- }
- return cmp
- }},
-
- // Less than or equal operator
- {Operator: operators.LessEquals,
- OperandTrait: traits.ComparerType,
- Binary: func(lhs ref.Val, rhs ref.Val) ref.Val {
- cmp := lhs.(traits.Comparer).Compare(rhs)
- if cmp == types.IntNegOne || cmp == types.IntZero {
- return types.True
- }
- if cmp == types.IntOne {
- return types.False
- }
- return cmp
- }},
-
- // Greater than operator
- {Operator: operators.Greater,
- OperandTrait: traits.ComparerType,
- Binary: func(lhs ref.Val, rhs ref.Val) ref.Val {
- cmp := lhs.(traits.Comparer).Compare(rhs)
- if cmp == types.IntOne {
- return types.True
- }
- if cmp == types.IntNegOne || cmp == types.IntZero {
- return types.False
- }
- return cmp
- }},
-
- // Greater than equal operators
- {Operator: operators.GreaterEquals,
- OperandTrait: traits.ComparerType,
- Binary: func(lhs ref.Val, rhs ref.Val) ref.Val {
- cmp := lhs.(traits.Comparer).Compare(rhs)
- if cmp == types.IntOne || cmp == types.IntZero {
- return types.True
- }
- if cmp == types.IntNegOne {
- return types.False
- }
- return cmp
- }},
-
- // Add operator
- {Operator: operators.Add,
- OperandTrait: traits.AdderType,
- Binary: func(lhs ref.Val, rhs ref.Val) ref.Val {
- return lhs.(traits.Adder).Add(rhs)
- }},
-
- // Subtract operators
- {Operator: operators.Subtract,
- OperandTrait: traits.SubtractorType,
- Binary: func(lhs ref.Val, rhs ref.Val) ref.Val {
- return lhs.(traits.Subtractor).Subtract(rhs)
- }},
-
- // Multiply operator
- {Operator: operators.Multiply,
- OperandTrait: traits.MultiplierType,
- Binary: func(lhs ref.Val, rhs ref.Val) ref.Val {
- return lhs.(traits.Multiplier).Multiply(rhs)
- }},
-
- // Divide operator
- {Operator: operators.Divide,
- OperandTrait: traits.DividerType,
- Binary: func(lhs ref.Val, rhs ref.Val) ref.Val {
- return lhs.(traits.Divider).Divide(rhs)
- }},
-
- // Modulo operator
- {Operator: operators.Modulo,
- OperandTrait: traits.ModderType,
- Binary: func(lhs ref.Val, rhs ref.Val) ref.Val {
- return lhs.(traits.Modder).Modulo(rhs)
- }},
-
- // Negate operator
- {Operator: operators.Negate,
- OperandTrait: traits.NegatorType,
- Unary: func(value ref.Val) ref.Val {
- if types.IsBool(value) {
- return types.ValOrErr(value, "no such overload")
- }
- return value.(traits.Negater).Negate()
- }},
-
- // Index operator
- {Operator: operators.Index,
- OperandTrait: traits.IndexerType,
- Binary: func(lhs ref.Val, rhs ref.Val) ref.Val {
- return lhs.(traits.Indexer).Get(rhs)
- }},
-
- // Size function
- {Operator: overloads.Size,
- OperandTrait: traits.SizerType,
- Unary: func(value ref.Val) ref.Val {
- return value.(traits.Sizer).Size()
- }},
-
- // In operator
- {Operator: operators.In, Binary: inAggregate},
- // Deprecated: in operator, may be overridden in the environment.
- {Operator: operators.OldIn, Binary: inAggregate},
-
- // Matches function
- {Operator: overloads.Matches,
- OperandTrait: traits.MatcherType,
- Binary: func(lhs ref.Val, rhs ref.Val) ref.Val {
- return lhs.(traits.Matcher).Match(rhs)
- }},
-
- // Type conversion functions
- // TODO: verify type conversion safety of numeric values.
-
- // Int conversions.
- {Operator: overloads.TypeConvertInt,
- Unary: func(value ref.Val) ref.Val {
- return value.ConvertToType(types.IntType)
- }},
-
- // Uint conversions.
- {Operator: overloads.TypeConvertUint,
- Unary: func(value ref.Val) ref.Val {
- return value.ConvertToType(types.UintType)
- }},
-
- // Double conversions.
- {Operator: overloads.TypeConvertDouble,
- Unary: func(value ref.Val) ref.Val {
- return value.ConvertToType(types.DoubleType)
- }},
-
- // Bool conversions.
- {Operator: overloads.TypeConvertBool,
- Unary: func(value ref.Val) ref.Val {
- return value.ConvertToType(types.BoolType)
- }},
-
- // Bytes conversions.
- {Operator: overloads.TypeConvertBytes,
- Unary: func(value ref.Val) ref.Val {
- return value.ConvertToType(types.BytesType)
- }},
-
- // String conversions.
- {Operator: overloads.TypeConvertString,
- Unary: func(value ref.Val) ref.Val {
- return value.ConvertToType(types.StringType)
- }},
-
- // Timestamp conversions.
- {Operator: overloads.TypeConvertTimestamp,
- Unary: func(value ref.Val) ref.Val {
- return value.ConvertToType(types.TimestampType)
- }},
-
- // Duration conversions.
- {Operator: overloads.TypeConvertDuration,
- Unary: func(value ref.Val) ref.Val {
- return value.ConvertToType(types.DurationType)
- }},
-
- // Type operations.
- {Operator: overloads.TypeConvertType,
- Unary: func(value ref.Val) ref.Val {
- return value.ConvertToType(types.TypeType)
- }},
-
- // Dyn conversion (identity function).
- {Operator: overloads.TypeConvertDyn,
- Unary: func(value ref.Val) ref.Val {
- return value
- }},
-
- {Operator: overloads.Iterator,
- OperandTrait: traits.IterableType,
- Unary: func(value ref.Val) ref.Val {
- return value.(traits.Iterable).Iterator()
- }},
-
- {Operator: overloads.HasNext,
- OperandTrait: traits.IteratorType,
- Unary: func(value ref.Val) ref.Val {
- return value.(traits.Iterator).HasNext()
- }},
-
- {Operator: overloads.Next,
- OperandTrait: traits.IteratorType,
- Unary: func(value ref.Val) ref.Val {
- return value.(traits.Iterator).Next()
- }},
- }
-
-}
-
-func notStrictlyFalse(value ref.Val) ref.Val {
- if types.IsBool(value) {
- return value
- }
- return types.True
-}
-
-func inAggregate(lhs ref.Val, rhs ref.Val) ref.Val {
- if rhs.Type().HasTrait(traits.ContainerType) {
- return rhs.(traits.Container).Contains(lhs)
- }
- return types.ValOrErr(rhs, "no such overload")
-}
diff --git a/vendor/github.com/google/cel-go/interpreter/interpretable.go b/vendor/github.com/google/cel-go/interpreter/interpretable.go
index 2011080d5..c4598dfa7 100644
--- a/vendor/github.com/google/cel-go/interpreter/interpretable.go
+++ b/vendor/github.com/google/cel-go/interpreter/interpretable.go
@@ -15,14 +15,14 @@
package interpreter
import (
- "math"
+ "fmt"
+ "github.com/google/cel-go/common/functions"
"github.com/google/cel-go/common/operators"
"github.com/google/cel-go/common/overloads"
"github.com/google/cel-go/common/types"
"github.com/google/cel-go/common/types/ref"
"github.com/google/cel-go/common/types/traits"
- "github.com/google/cel-go/interpreter/functions"
)
// Interpretable can accept a given Activation and produce a value along with
@@ -52,7 +52,7 @@ type InterpretableAttribute interface {
Attr() Attribute
// Adapter returns the type adapter to be used for adapting resolved Attribute values.
- Adapter() ref.TypeAdapter
+ Adapter() types.Adapter
// AddQualifier proxies the Attribute.AddQualifier method.
//
@@ -71,6 +71,7 @@ type InterpretableAttribute interface {
// to whether the qualifier is present.
QualifyIfPresent(vars Activation, obj any, presenceOnly bool) (any, bool, error)
+ // IsOptional indicates whether the resulting value is an optional type.
IsOptional() bool
// Resolve returns the value of the Attribute given the current Activation.
@@ -110,10 +111,8 @@ type InterpretableConstructor interface {
// Core Interpretable implementations used during the program planning phase.
type evalTestOnly struct {
- id int64
- attr InterpretableAttribute
- qual Qualifier
- field types.String
+ id int64
+ InterpretableAttribute
}
// ID implements the Interpretable interface method.
@@ -123,37 +122,55 @@ func (test *evalTestOnly) ID() int64 {
// Eval implements the Interpretable interface method.
func (test *evalTestOnly) Eval(ctx Activation) ref.Val {
- val, err := test.attr.Resolve(ctx)
+ val, err := test.Resolve(ctx)
+ // Return an error if the resolve step fails
if err != nil {
- return types.NewErr(err.Error())
+ return types.WrapErr(err)
}
- optVal, isOpt := val.(*types.Optional)
- if isOpt {
- if !optVal.HasValue() {
- return types.False
- }
- val = optVal.GetValue()
+ if optVal, isOpt := val.(*types.Optional); isOpt {
+ return types.Bool(optVal.HasValue())
+ }
+ return test.Adapter().NativeToValue(val)
+}
+
+// AddQualifier appends a qualifier that will always and only perform a presence test.
+func (test *evalTestOnly) AddQualifier(q Qualifier) (Attribute, error) {
+ cq, ok := q.(ConstantQualifier)
+ if !ok {
+ return nil, fmt.Errorf("test only expressions must have constant qualifiers: %v", q)
}
- out, found, err := test.qual.QualifyIfPresent(ctx, val, true)
+ return test.InterpretableAttribute.AddQualifier(&testOnlyQualifier{ConstantQualifier: cq})
+}
+
+type testOnlyQualifier struct {
+ ConstantQualifier
+}
+
+// Qualify determines whether the test-only qualifier is present on the input object.
+func (q *testOnlyQualifier) Qualify(vars Activation, obj any) (any, error) {
+ out, present, err := q.ConstantQualifier.QualifyIfPresent(vars, obj, true)
if err != nil {
- return types.NewErr(err.Error())
+ return nil, err
}
if unk, isUnk := out.(types.Unknown); isUnk {
- return unk
+ return unk, nil
}
- if found {
- return types.True
+ if opt, isOpt := out.(types.Optional); isOpt {
+ return opt.HasValue(), nil
}
- return types.False
+ return present, nil
+}
+
+// QualifyIfPresent returns whether the target field in the test-only expression is present.
+func (q *testOnlyQualifier) QualifyIfPresent(vars Activation, obj any, presenceOnly bool) (any, bool, error) {
+ // Only ever test for presence.
+ return q.ConstantQualifier.QualifyIfPresent(vars, obj, true)
}
-// Cost provides the heuristic cost of a `has(field)` macro. The cost has at least 1 for determining
-// if the field exists, apart from the cost of accessing the field.
-func (test *evalTestOnly) Cost() (min, max int64) {
- min, max = estimateCost(test.attr)
- min++
- max++
- return
+// QualifierValueEquals determines whether the test-only constant qualifier equals the input value.
+func (q *testOnlyQualifier) QualifierValueEquals(value any) bool {
+ // The input qualifier will always be of type string
+ return q.ConstantQualifier.Value().Value() == value
}
// NewConstValue creates a new constant valued Interpretable.
@@ -179,20 +196,14 @@ func (cons *evalConst) Eval(ctx Activation) ref.Val {
return cons.val
}
-// Cost returns zero for a constant valued Interpretable.
-func (cons *evalConst) Cost() (min, max int64) {
- return 0, 0
-}
-
// Value implements the InterpretableConst interface method.
func (cons *evalConst) Value() ref.Val {
return cons.val
}
type evalOr struct {
- id int64
- lhs Interpretable
- rhs Interpretable
+ id int64
+ terms []Interpretable
}
// ID implements the Interpretable interface method.
@@ -202,47 +213,39 @@ func (or *evalOr) ID() int64 {
// Eval implements the Interpretable interface method.
func (or *evalOr) Eval(ctx Activation) ref.Val {
- // short-circuit lhs.
- lVal := or.lhs.Eval(ctx)
- lBool, lok := lVal.(types.Bool)
- if lok && lBool == types.True {
- return types.True
- }
- // short-circuit on rhs.
- rVal := or.rhs.Eval(ctx)
- rBool, rok := rVal.(types.Bool)
- if rok && rBool == types.True {
- return types.True
- }
- // return if both sides are bool false.
- if lok && rok {
- return types.False
- }
- // TODO: return both values as a set if both are unknown or error.
- // prefer left unknown to right unknown.
- if types.IsUnknown(lVal) {
- return lVal
+ var err ref.Val = nil
+ var unk *types.Unknown
+ for _, term := range or.terms {
+ val := term.Eval(ctx)
+ boolVal, ok := val.(types.Bool)
+ // short-circuit on true.
+ if ok && boolVal == types.True {
+ return types.True
+ }
+ if !ok {
+ isUnk := false
+ unk, isUnk = types.MaybeMergeUnknowns(val, unk)
+ if !isUnk && err == nil {
+ if types.IsError(val) {
+ err = val
+ } else {
+ err = types.MaybeNoSuchOverloadErr(val)
+ }
+ }
+ }
}
- if types.IsUnknown(rVal) {
- return rVal
+ if unk != nil {
+ return unk
}
- // If the left-hand side is non-boolean return it as the error.
- if types.IsError(lVal) {
- return lVal
+ if err != nil {
+ return err
}
- return types.ValOrErr(rVal, "no such overload")
-}
-
-// Cost implements the Coster interface method. The minimum possible cost incurs when the left-hand
-// side expr is sufficient in determining the evaluation result.
-func (or *evalOr) Cost() (min, max int64) {
- return calShortCircuitBinaryOpsCost(or.lhs, or.rhs)
+ return types.False
}
type evalAnd struct {
- id int64
- lhs Interpretable
- rhs Interpretable
+ id int64
+ terms []Interpretable
}
// ID implements the Interpretable interface method.
@@ -252,47 +255,34 @@ func (and *evalAnd) ID() int64 {
// Eval implements the Interpretable interface method.
func (and *evalAnd) Eval(ctx Activation) ref.Val {
- // short-circuit lhs.
- lVal := and.lhs.Eval(ctx)
- lBool, lok := lVal.(types.Bool)
- if lok && lBool == types.False {
- return types.False
- }
- // short-circuit on rhs.
- rVal := and.rhs.Eval(ctx)
- rBool, rok := rVal.(types.Bool)
- if rok && rBool == types.False {
- return types.False
- }
- // return if both sides are bool true.
- if lok && rok {
- return types.True
- }
- // TODO: return both values as a set if both are unknown or error.
- // prefer left unknown to right unknown.
- if types.IsUnknown(lVal) {
- return lVal
+ var err ref.Val = nil
+ var unk *types.Unknown
+ for _, term := range and.terms {
+ val := term.Eval(ctx)
+ boolVal, ok := val.(types.Bool)
+ // short-circuit on false.
+ if ok && boolVal == types.False {
+ return types.False
+ }
+ if !ok {
+ isUnk := false
+ unk, isUnk = types.MaybeMergeUnknowns(val, unk)
+ if !isUnk && err == nil {
+ if types.IsError(val) {
+ err = val
+ } else {
+ err = types.MaybeNoSuchOverloadErr(val)
+ }
+ }
+ }
}
- if types.IsUnknown(rVal) {
- return rVal
+ if unk != nil {
+ return unk
}
- // If the left-hand side is non-boolean return it as the error.
- if types.IsError(lVal) {
- return lVal
+ if err != nil {
+ return err
}
- return types.ValOrErr(rVal, "no such overload")
-}
-
-// Cost implements the Coster interface method. The minimum possible cost incurs when the left-hand
-// side expr is sufficient in determining the evaluation result.
-func (and *evalAnd) Cost() (min, max int64) {
- return calShortCircuitBinaryOpsCost(and.lhs, and.rhs)
-}
-
-func calShortCircuitBinaryOpsCost(lhs, rhs Interpretable) (min, max int64) {
- lMin, lMax := estimateCost(lhs)
- _, rMax := estimateCost(rhs)
- return lMin, lMax + rMax + 1
+ return types.True
}
type evalEq struct {
@@ -319,11 +309,6 @@ func (eq *evalEq) Eval(ctx Activation) ref.Val {
return types.Equal(lVal, rVal)
}
-// Cost implements the Coster interface method.
-func (eq *evalEq) Cost() (min, max int64) {
- return calExhaustiveBinaryOpsCost(eq.lhs, eq.rhs)
-}
-
// Function implements the InterpretableCall interface method.
func (*evalEq) Function() string {
return operators.Equals
@@ -363,11 +348,6 @@ func (ne *evalNe) Eval(ctx Activation) ref.Val {
return types.Bool(types.Equal(lVal, rVal) != types.True)
}
-// Cost implements the Coster interface method.
-func (ne *evalNe) Cost() (min, max int64) {
- return calExhaustiveBinaryOpsCost(ne.lhs, ne.rhs)
-}
-
// Function implements the InterpretableCall interface method.
func (*evalNe) Function() string {
return operators.NotEquals
@@ -400,11 +380,6 @@ func (zero *evalZeroArity) Eval(ctx Activation) ref.Val {
return zero.impl()
}
-// Cost returns 1 representing the heuristic cost of the function.
-func (zero *evalZeroArity) Cost() (min, max int64) {
- return 1, 1
-}
-
// Function implements the InterpretableCall interface method.
func (zero *evalZeroArity) Function() string {
return zero.function
@@ -456,14 +431,6 @@ func (un *evalUnary) Eval(ctx Activation) ref.Val {
return types.NewErr("no such overload: %s", un.function)
}
-// Cost implements the Coster interface method.
-func (un *evalUnary) Cost() (min, max int64) {
- min, max = estimateCost(un.arg)
- min++ // add cost for function
- max++
- return
-}
-
// Function implements the InterpretableCall interface method.
func (un *evalUnary) Function() string {
return un.function
@@ -522,11 +489,6 @@ func (bin *evalBinary) Eval(ctx Activation) ref.Val {
return types.NewErr("no such overload: %s", bin.function)
}
-// Cost implements the Coster interface method.
-func (bin *evalBinary) Cost() (min, max int64) {
- return calExhaustiveBinaryOpsCost(bin.lhs, bin.rhs)
-}
-
// Function implements the InterpretableCall interface method.
func (bin *evalBinary) Function() string {
return bin.function
@@ -593,14 +555,6 @@ func (fn *evalVarArgs) Eval(ctx Activation) ref.Val {
return types.NewErr("no such overload: %s", fn.function)
}
-// Cost implements the Coster interface method.
-func (fn *evalVarArgs) Cost() (min, max int64) {
- min, max = sumOfCost(fn.args)
- min++ // add cost for function
- max++
- return
-}
-
// Function implements the InterpretableCall interface method.
func (fn *evalVarArgs) Function() string {
return fn.function
@@ -617,9 +571,11 @@ func (fn *evalVarArgs) Args() []Interpretable {
}
type evalList struct {
- id int64
- elems []Interpretable
- adapter ref.TypeAdapter
+ id int64
+ elems []Interpretable
+ optionals []bool
+ hasOptionals bool
+ adapter types.Adapter
}
// ID implements the Interpretable interface method.
@@ -629,14 +585,24 @@ func (l *evalList) ID() int64 {
// Eval implements the Interpretable interface method.
func (l *evalList) Eval(ctx Activation) ref.Val {
- elemVals := make([]ref.Val, len(l.elems))
+ elemVals := make([]ref.Val, 0, len(l.elems))
// If any argument is unknown or error early terminate.
for i, elem := range l.elems {
elemVal := elem.Eval(ctx)
if types.IsUnknownOrError(elemVal) {
return elemVal
}
- elemVals[i] = elemVal
+ if l.hasOptionals && l.optionals[i] {
+ optVal, ok := elemVal.(*types.Optional)
+ if !ok {
+ return invalidOptionalElementInit(elemVal)
+ }
+ if !optVal.HasValue() {
+ continue
+ }
+ elemVal = optVal.GetValue()
+ }
+ elemVals = append(elemVals, elemVal)
}
return l.adapter.NativeToValue(elemVals)
}
@@ -649,17 +615,13 @@ func (l *evalList) Type() ref.Type {
return types.ListType
}
-// Cost implements the Coster interface method.
-func (l *evalList) Cost() (min, max int64) {
- return sumOfCost(l.elems)
-}
-
type evalMap struct {
- id int64
- keys []Interpretable
- vals []Interpretable
- optionals []bool
- adapter ref.TypeAdapter
+ id int64
+ keys []Interpretable
+ vals []Interpretable
+ optionals []bool
+ hasOptionals bool
+ adapter types.Adapter
}
// ID implements the Interpretable interface method.
@@ -680,8 +642,7 @@ func (m *evalMap) Eval(ctx Activation) ref.Val {
if types.IsUnknownOrError(valVal) {
return valVal
}
- isOpt := m.optionals[i]
- if isOpt {
+ if m.hasOptionals && m.optionals[i] {
optVal, ok := valVal.(*types.Optional)
if !ok {
return invalidOptionalEntryInit(keyVal, valVal)
@@ -717,20 +678,14 @@ func (m *evalMap) Type() ref.Type {
return types.MapType
}
-// Cost implements the Coster interface method.
-func (m *evalMap) Cost() (min, max int64) {
- kMin, kMax := sumOfCost(m.keys)
- vMin, vMax := sumOfCost(m.vals)
- return kMin + vMin, kMax + vMax
-}
-
type evalObj struct {
- id int64
- typeName string
- fields []string
- vals []Interpretable
- optionals []bool
- provider ref.TypeProvider
+ id int64
+ typeName string
+ fields []string
+ vals []Interpretable
+ optionals []bool
+ hasOptionals bool
+ provider types.Provider
}
// ID implements the Interpretable interface method.
@@ -747,8 +702,7 @@ func (o *evalObj) Eval(ctx Activation) ref.Val {
if types.IsUnknownOrError(val) {
return val
}
- isOpt := o.optionals[i]
- if isOpt {
+ if o.hasOptionals && o.optionals[i] {
optVal, ok := val.(*types.Optional)
if !ok {
return invalidOptionalEntryInit(field, val)
@@ -772,21 +726,6 @@ func (o *evalObj) Type() ref.Type {
return types.NewObjectTypeValue(o.typeName)
}
-// Cost implements the Coster interface method.
-func (o *evalObj) Cost() (min, max int64) {
- return sumOfCost(o.vals)
-}
-
-func sumOfCost(interps []Interpretable) (min, max int64) {
- min, max = 0, 0
- for _, in := range interps {
- minT, maxT := estimateCost(in)
- min += minT
- max += maxT
- }
- return
-}
-
type evalFold struct {
id int64
accuVar string
@@ -796,7 +735,7 @@ type evalFold struct {
cond Interpretable
step Interpretable
result Interpretable
- adapter ref.TypeAdapter
+ adapter types.Adapter
exhaustive bool
interruptable bool
}
@@ -868,38 +807,6 @@ func (fold *evalFold) Eval(ctx Activation) ref.Val {
return res
}
-// Cost implements the Coster interface method.
-func (fold *evalFold) Cost() (min, max int64) {
- // Compute the cost for evaluating iterRange.
- iMin, iMax := estimateCost(fold.iterRange)
-
- // Compute the size of iterRange. If the size depends on the input, return the maximum possible
- // cost range.
- foldRange := fold.iterRange.Eval(EmptyActivation())
- if !foldRange.Type().HasTrait(traits.IterableType) {
- return 0, math.MaxInt64
- }
- var rangeCnt int64
- it := foldRange.(traits.Iterable).Iterator()
- for it.HasNext() == types.True {
- it.Next()
- rangeCnt++
- }
- aMin, aMax := estimateCost(fold.accu)
- cMin, cMax := estimateCost(fold.cond)
- sMin, sMax := estimateCost(fold.step)
- rMin, rMax := estimateCost(fold.result)
- if fold.exhaustive {
- cMin = cMin * rangeCnt
- sMin = sMin * rangeCnt
- }
-
- // The cond and step costs are multiplied by size(iterRange). The minimum possible cost incurs
- // when the evaluation result can be determined by the first iteration.
- return iMin + aMin + cMin + sMin + rMin,
- iMax + aMax + cMax*rangeCnt + sMax*rangeCnt + rMax
-}
-
// Optional Interpretable implementations that specialize, subsume, or extend the core evaluation
// plan via decorators.
@@ -919,17 +826,15 @@ func (e *evalSetMembership) ID() int64 {
// Eval implements the Interpretable interface method.
func (e *evalSetMembership) Eval(ctx Activation) ref.Val {
val := e.arg.Eval(ctx)
+ if types.IsUnknownOrError(val) {
+ return val
+ }
if ret, found := e.valueSet[val]; found {
return ret
}
return types.False
}
-// Cost implements the Coster interface method.
-func (e *evalSetMembership) Cost() (min, max int64) {
- return estimateCost(e.arg)
-}
-
// evalWatch is an Interpretable implementation that wraps the execution of a given
// expression so that it may observe the computed value and send it to an observer.
type evalWatch struct {
@@ -944,11 +849,6 @@ func (e *evalWatch) Eval(ctx Activation) ref.Val {
return val
}
-// Cost implements the Coster interface method.
-func (e *evalWatch) Cost() (min, max int64) {
- return estimateCost(e.Interpretable)
-}
-
// evalWatchAttr describes a watcher of an InterpretableAttribute Interpretable.
//
// Since the watcher may be selected against at a later stage in program planning, the watcher
@@ -961,29 +861,46 @@ type evalWatchAttr struct {
// AddQualifier creates a wrapper over the incoming qualifier which observes the qualification
// result.
func (e *evalWatchAttr) AddQualifier(q Qualifier) (Attribute, error) {
- cq, isConst := q.(ConstantQualifier)
- if isConst {
+ switch qual := q.(type) {
+ // By default, the qualifier is either a constant or an attribute
+ // There may be some custom cases where the attribute is neither.
+ case ConstantQualifier:
+ // Expose a method to test whether the qualifier matches the input pattern.
q = &evalWatchConstQual{
- ConstantQualifier: cq,
+ ConstantQualifier: qual,
observer: e.observer,
- adapter: e.InterpretableAttribute.Adapter(),
+ adapter: e.Adapter(),
}
- } else {
+ case *evalWatchAttr:
+ // Unwrap the evalWatchAttr since the observation will be applied during Qualify or
+ // QualifyIfPresent rather than Eval.
+ q = &evalWatchAttrQual{
+ Attribute: qual.InterpretableAttribute,
+ observer: e.observer,
+ adapter: e.Adapter(),
+ }
+ case Attribute:
+ // Expose methods which intercept the qualification prior to being applied as a qualifier.
+ // Using this interface ensures that the qualifier is converted to a constant value one
+ // time during attribute pattern matching as the method embeds the Attribute interface
+ // needed to trip the conversion to a constant.
+ q = &evalWatchAttrQual{
+ Attribute: qual,
+ observer: e.observer,
+ adapter: e.Adapter(),
+ }
+ default:
+ // This is likely a custom qualifier type.
q = &evalWatchQual{
- Qualifier: q,
+ Qualifier: qual,
observer: e.observer,
- adapter: e.InterpretableAttribute.Adapter(),
+ adapter: e.Adapter(),
}
}
_, err := e.InterpretableAttribute.AddQualifier(q)
return e, err
}
-// Cost implements the Coster interface method.
-func (e *evalWatchAttr) Cost() (min, max int64) {
- return estimateCost(e.InterpretableAttribute)
-}
-
// Eval implements the Interpretable interface method.
func (e *evalWatchAttr) Eval(vars Activation) ref.Val {
val := e.InterpretableAttribute.Eval(vars)
@@ -996,12 +913,7 @@ func (e *evalWatchAttr) Eval(vars Activation) ref.Val {
type evalWatchConstQual struct {
ConstantQualifier
observer EvalObserver
- adapter ref.TypeAdapter
-}
-
-// Cost implements the Coster interface method.
-func (e *evalWatchConstQual) Cost() (min, max int64) {
- return estimateCost(e.ConstantQualifier)
+ adapter types.Adapter
}
// Qualify observes the qualification of a object via a constant boolean, int, string, or uint.
@@ -1009,7 +921,7 @@ func (e *evalWatchConstQual) Qualify(vars Activation, obj any) (any, error) {
out, err := e.ConstantQualifier.Qualify(vars, obj)
var val ref.Val
if err != nil {
- val = types.NewErr(err.Error())
+ val = types.WrapErr(err)
} else {
val = e.adapter.NativeToValue(out)
}
@@ -1017,22 +929,71 @@ func (e *evalWatchConstQual) Qualify(vars Activation, obj any) (any, error) {
return out, err
}
+// QualifyIfPresent conditionally qualifies the variable and only records a value if one is present.
+func (e *evalWatchConstQual) QualifyIfPresent(vars Activation, obj any, presenceOnly bool) (any, bool, error) {
+ out, present, err := e.ConstantQualifier.QualifyIfPresent(vars, obj, presenceOnly)
+ var val ref.Val
+ if err != nil {
+ val = types.WrapErr(err)
+ } else if out != nil {
+ val = e.adapter.NativeToValue(out)
+ } else if presenceOnly {
+ val = types.Bool(present)
+ }
+ if present || presenceOnly {
+ e.observer(e.ID(), e.ConstantQualifier, val)
+ }
+ return out, present, err
+}
+
// QualifierValueEquals tests whether the incoming value is equal to the qualifying constant.
func (e *evalWatchConstQual) QualifierValueEquals(value any) bool {
qve, ok := e.ConstantQualifier.(qualifierValueEquator)
return ok && qve.QualifierValueEquals(value)
}
-// evalWatchQual observes the qualification of an object by a value computed at runtime.
-type evalWatchQual struct {
- Qualifier
+// evalWatchAttrQual observes the qualification of an object by a value computed at runtime.
+type evalWatchAttrQual struct {
+ Attribute
observer EvalObserver
adapter ref.TypeAdapter
}
-// Cost implements the Coster interface method.
-func (e *evalWatchQual) Cost() (min, max int64) {
- return estimateCost(e.Qualifier)
+// Qualify observes the qualification of a object via a value computed at runtime.
+func (e *evalWatchAttrQual) Qualify(vars Activation, obj any) (any, error) {
+ out, err := e.Attribute.Qualify(vars, obj)
+ var val ref.Val
+ if err != nil {
+ val = types.WrapErr(err)
+ } else {
+ val = e.adapter.NativeToValue(out)
+ }
+ e.observer(e.ID(), e.Attribute, val)
+ return out, err
+}
+
+// QualifyIfPresent conditionally qualifies the variable and only records a value if one is present.
+func (e *evalWatchAttrQual) QualifyIfPresent(vars Activation, obj any, presenceOnly bool) (any, bool, error) {
+ out, present, err := e.Attribute.QualifyIfPresent(vars, obj, presenceOnly)
+ var val ref.Val
+ if err != nil {
+ val = types.WrapErr(err)
+ } else if out != nil {
+ val = e.adapter.NativeToValue(out)
+ } else if presenceOnly {
+ val = types.Bool(present)
+ }
+ if present || presenceOnly {
+ e.observer(e.ID(), e.Attribute, val)
+ }
+ return out, present, err
+}
+
+// evalWatchQual observes the qualification of an object by a value computed at runtime.
+type evalWatchQual struct {
+ Qualifier
+ observer EvalObserver
+ adapter types.Adapter
}
// Qualify observes the qualification of a object via a value computed at runtime.
@@ -1040,7 +1001,7 @@ func (e *evalWatchQual) Qualify(vars Activation, obj any) (any, error) {
out, err := e.Qualifier.Qualify(vars, obj)
var val ref.Val
if err != nil {
- val = types.NewErr(err.Error())
+ val = types.WrapErr(err)
} else {
val = e.adapter.NativeToValue(out)
}
@@ -1048,6 +1009,23 @@ func (e *evalWatchQual) Qualify(vars Activation, obj any) (any, error) {
return out, err
}
+// QualifyIfPresent conditionally qualifies the variable and only records a value if one is present.
+func (e *evalWatchQual) QualifyIfPresent(vars Activation, obj any, presenceOnly bool) (any, bool, error) {
+ out, present, err := e.Qualifier.QualifyIfPresent(vars, obj, presenceOnly)
+ var val ref.Val
+ if err != nil {
+ val = types.WrapErr(err)
+ } else if out != nil {
+ val = e.adapter.NativeToValue(out)
+ } else if presenceOnly {
+ val = types.Bool(present)
+ }
+ if present || presenceOnly {
+ e.observer(e.ID(), e.Qualifier, val)
+ }
+ return out, present, err
+}
+
// evalWatchConst describes a watcher of an instConst Interpretable.
type evalWatchConst struct {
InterpretableConst
@@ -1061,16 +1039,10 @@ func (e *evalWatchConst) Eval(vars Activation) ref.Val {
return val
}
-// Cost implements the Coster interface method.
-func (e *evalWatchConst) Cost() (min, max int64) {
- return estimateCost(e.InterpretableConst)
-}
-
// evalExhaustiveOr is just like evalOr, but does not short-circuit argument evaluation.
type evalExhaustiveOr struct {
- id int64
- lhs Interpretable
- rhs Interpretable
+ id int64
+ terms []Interpretable
}
// ID implements the Interpretable interface method.
@@ -1080,43 +1052,44 @@ func (or *evalExhaustiveOr) ID() int64 {
// Eval implements the Interpretable interface method.
func (or *evalExhaustiveOr) Eval(ctx Activation) ref.Val {
- lVal := or.lhs.Eval(ctx)
- rVal := or.rhs.Eval(ctx)
- lBool, lok := lVal.(types.Bool)
- if lok && lBool == types.True {
- return types.True
+ var err ref.Val = nil
+ var unk *types.Unknown
+ isTrue := false
+ for _, term := range or.terms {
+ val := term.Eval(ctx)
+ boolVal, ok := val.(types.Bool)
+ // flag the result as true
+ if ok && boolVal == types.True {
+ isTrue = true
+ }
+ if !ok && !isTrue {
+ isUnk := false
+ unk, isUnk = types.MaybeMergeUnknowns(val, unk)
+ if !isUnk && err == nil {
+ if types.IsError(val) {
+ err = val
+ } else {
+ err = types.MaybeNoSuchOverloadErr(val)
+ }
+ }
+ }
}
- rBool, rok := rVal.(types.Bool)
- if rok && rBool == types.True {
+ if isTrue {
return types.True
}
- if lok && rok {
- return types.False
- }
- if types.IsUnknown(lVal) {
- return lVal
- }
- if types.IsUnknown(rVal) {
- return rVal
+ if unk != nil {
+ return unk
}
- // TODO: Combine the errors into a set in the future.
- // If the left-hand side is non-boolean return it as the error.
- if types.IsError(lVal) {
- return lVal
+ if err != nil {
+ return err
}
- return types.MaybeNoSuchOverloadErr(rVal)
-}
-
-// Cost implements the Coster interface method.
-func (or *evalExhaustiveOr) Cost() (min, max int64) {
- return calExhaustiveBinaryOpsCost(or.lhs, or.rhs)
+ return types.False
}
// evalExhaustiveAnd is just like evalAnd, but does not short-circuit argument evaluation.
type evalExhaustiveAnd struct {
- id int64
- lhs Interpretable
- rhs Interpretable
+ id int64
+ terms []Interpretable
}
// ID implements the Interpretable interface method.
@@ -1126,49 +1099,45 @@ func (and *evalExhaustiveAnd) ID() int64 {
// Eval implements the Interpretable interface method.
func (and *evalExhaustiveAnd) Eval(ctx Activation) ref.Val {
- lVal := and.lhs.Eval(ctx)
- rVal := and.rhs.Eval(ctx)
- lBool, lok := lVal.(types.Bool)
- if lok && lBool == types.False {
- return types.False
+ var err ref.Val = nil
+ var unk *types.Unknown
+ isFalse := false
+ for _, term := range and.terms {
+ val := term.Eval(ctx)
+ boolVal, ok := val.(types.Bool)
+ // short-circuit on false.
+ if ok && boolVal == types.False {
+ isFalse = true
+ }
+ if !ok && !isFalse {
+ isUnk := false
+ unk, isUnk = types.MaybeMergeUnknowns(val, unk)
+ if !isUnk && err == nil {
+ if types.IsError(val) {
+ err = val
+ } else {
+ err = types.MaybeNoSuchOverloadErr(val)
+ }
+ }
+ }
}
- rBool, rok := rVal.(types.Bool)
- if rok && rBool == types.False {
+ if isFalse {
return types.False
}
- if lok && rok {
- return types.True
- }
- if types.IsUnknown(lVal) {
- return lVal
- }
- if types.IsUnknown(rVal) {
- return rVal
+ if unk != nil {
+ return unk
}
- // TODO: Combine the errors into a set in the future.
- // If the left-hand side is non-boolean return it as the error.
- if types.IsError(lVal) {
- return lVal
+ if err != nil {
+ return err
}
- return types.MaybeNoSuchOverloadErr(rVal)
-}
-
-// Cost implements the Coster interface method.
-func (and *evalExhaustiveAnd) Cost() (min, max int64) {
- return calExhaustiveBinaryOpsCost(and.lhs, and.rhs)
-}
-
-func calExhaustiveBinaryOpsCost(lhs, rhs Interpretable) (min, max int64) {
- lMin, lMax := estimateCost(lhs)
- rMin, rMax := estimateCost(rhs)
- return lMin + rMin + 1, lMax + rMax + 1
+ return types.True
}
// evalExhaustiveConditional is like evalConditional, but does not short-circuit argument
// evaluation.
type evalExhaustiveConditional struct {
id int64
- adapter ref.TypeAdapter
+ adapter types.Adapter
attr *conditionalAttribute
}
@@ -1188,28 +1157,25 @@ func (cond *evalExhaustiveConditional) Eval(ctx Activation) ref.Val {
}
if cBool {
if tErr != nil {
- return types.NewErr(tErr.Error())
+ return types.WrapErr(tErr)
}
return cond.adapter.NativeToValue(tVal)
}
if fErr != nil {
- return types.NewErr(fErr.Error())
+ return types.WrapErr(fErr)
}
return cond.adapter.NativeToValue(fVal)
}
-// Cost implements the Coster interface method.
-func (cond *evalExhaustiveConditional) Cost() (min, max int64) {
- return cond.attr.Cost()
-}
-
// evalAttr evaluates an Attribute value.
type evalAttr struct {
- adapter ref.TypeAdapter
+ adapter types.Adapter
attr Attribute
optional bool
}
+var _ InterpretableAttribute = &evalAttr{}
+
// ID of the attribute instruction.
func (a *evalAttr) ID() int64 {
return a.attr.ID()
@@ -1228,20 +1194,15 @@ func (a *evalAttr) Attr() Attribute {
}
// Adapter implements the InterpretableAttribute interface method.
-func (a *evalAttr) Adapter() ref.TypeAdapter {
+func (a *evalAttr) Adapter() types.Adapter {
return a.adapter
}
-// Cost implements the Coster interface method.
-func (a *evalAttr) Cost() (min, max int64) {
- return estimateCost(a.attr)
-}
-
// Eval implements the Interpretable interface method.
func (a *evalAttr) Eval(ctx Activation) ref.Val {
v, err := a.attr.Resolve(ctx)
if err != nil {
- return types.NewErr(err.Error())
+ return types.WrapErr(err)
}
return a.adapter.NativeToValue(v)
}
@@ -1265,6 +1226,37 @@ func (a *evalAttr) Resolve(ctx Activation) (any, error) {
return a.attr.Resolve(ctx)
}
+type evalWatchConstructor struct {
+ constructor InterpretableConstructor
+ observer EvalObserver
+}
+
+// InitVals implements the InterpretableConstructor InitVals function.
+func (c *evalWatchConstructor) InitVals() []Interpretable {
+ return c.constructor.InitVals()
+}
+
+// Type implements the InterpretableConstructor Type function.
+func (c *evalWatchConstructor) Type() ref.Type {
+ return c.constructor.Type()
+}
+
+// ID implements the Interpretable ID function.
+func (c *evalWatchConstructor) ID() int64 {
+ return c.constructor.ID()
+}
+
+// Eval implements the Interpretable Eval function.
+func (c *evalWatchConstructor) Eval(ctx Activation) ref.Val {
+ val := c.constructor.Eval(ctx)
+ c.observer(c.ID(), c.constructor, val)
+ return val
+}
+
func invalidOptionalEntryInit(field any, value ref.Val) ref.Val {
return types.NewErr("cannot initialize optional entry '%v' from non-optional value %v", field, value)
}
+
+func invalidOptionalElementInit(value ref.Val) ref.Val {
+ return types.NewErr("cannot initialize optional list element from non-optional value %v", value)
+}
diff --git a/vendor/github.com/google/cel-go/interpreter/interpreter.go b/vendor/github.com/google/cel-go/interpreter/interpreter.go
index 707a6105a..00fc74732 100644
--- a/vendor/github.com/google/cel-go/interpreter/interpreter.go
+++ b/vendor/github.com/google/cel-go/interpreter/interpreter.go
@@ -18,9 +18,10 @@
package interpreter
import (
+ "github.com/google/cel-go/common/ast"
"github.com/google/cel-go/common/containers"
+ "github.com/google/cel-go/common/types"
"github.com/google/cel-go/common/types/ref"
- "github.com/google/cel-go/interpreter/functions"
exprpb "google.golang.org/genproto/googleapis/api/expr/v1alpha1"
)
@@ -29,7 +30,7 @@ import (
type Interpreter interface {
// NewInterpretable creates an Interpretable from a checked expression and an
// optional list of InterpretableDecorator values.
- NewInterpretable(checked *exprpb.CheckedExpr, decorators ...InterpretableDecorator) (Interpretable, error)
+ NewInterpretable(checked *ast.CheckedAST, decorators ...InterpretableDecorator) (Interpretable, error)
// NewUncheckedInterpretable returns an Interpretable from a parsed expression
// and an optional list of InterpretableDecorator values.
@@ -154,8 +155,8 @@ func CompileRegexConstants(regexOptimizations ...*RegexOptimization) Interpretab
type exprInterpreter struct {
dispatcher Dispatcher
container *containers.Container
- provider ref.TypeProvider
- adapter ref.TypeAdapter
+ provider types.Provider
+ adapter types.Adapter
attrFactory AttributeFactory
}
@@ -163,8 +164,8 @@ type exprInterpreter struct {
// throughout the Eval of all Interpretable instances generated from it.
func NewInterpreter(dispatcher Dispatcher,
container *containers.Container,
- provider ref.TypeProvider,
- adapter ref.TypeAdapter,
+ provider types.Provider,
+ adapter types.Adapter,
attrFactory AttributeFactory) Interpreter {
return &exprInterpreter{
dispatcher: dispatcher,
@@ -174,20 +175,9 @@ func NewInterpreter(dispatcher Dispatcher,
attrFactory: attrFactory}
}
-// NewStandardInterpreter builds a Dispatcher and TypeProvider with support for all of the CEL
-// builtins defined in the language definition.
-func NewStandardInterpreter(container *containers.Container,
- provider ref.TypeProvider,
- adapter ref.TypeAdapter,
- resolver AttributeFactory) Interpreter {
- dispatcher := NewDispatcher()
- dispatcher.Add(functions.StandardOverloads()...)
- return NewInterpreter(dispatcher, container, provider, adapter, resolver)
-}
-
// NewIntepretable implements the Interpreter interface method.
func (i *exprInterpreter) NewInterpretable(
- checked *exprpb.CheckedExpr,
+ checked *ast.CheckedAST,
decorators ...InterpretableDecorator) (Interpretable, error) {
p := newPlanner(
i.dispatcher,
@@ -197,7 +187,7 @@ func (i *exprInterpreter) NewInterpretable(
i.container,
checked,
decorators...)
- return p.Plan(checked.GetExpr())
+ return p.Plan(checked.Expr)
}
// NewUncheckedIntepretable implements the Interpreter interface method.
diff --git a/vendor/github.com/google/cel-go/interpreter/planner.go b/vendor/github.com/google/cel-go/interpreter/planner.go
index 9c6bbb622..757cd080e 100644
--- a/vendor/github.com/google/cel-go/interpreter/planner.go
+++ b/vendor/github.com/google/cel-go/interpreter/planner.go
@@ -18,11 +18,12 @@ import (
"fmt"
"strings"
+ "github.com/google/cel-go/common/ast"
"github.com/google/cel-go/common/containers"
+ "github.com/google/cel-go/common/functions"
"github.com/google/cel-go/common/operators"
"github.com/google/cel-go/common/types"
"github.com/google/cel-go/common/types/ref"
- "github.com/google/cel-go/interpreter/functions"
exprpb "google.golang.org/genproto/googleapis/api/expr/v1alpha1"
)
@@ -38,11 +39,11 @@ type interpretablePlanner interface {
// functions, types, and namespaced identifiers at plan time rather than at runtime since
// it only needs to be done once and may be semi-expensive to compute.
func newPlanner(disp Dispatcher,
- provider ref.TypeProvider,
- adapter ref.TypeAdapter,
+ provider types.Provider,
+ adapter types.Adapter,
attrFactory AttributeFactory,
cont *containers.Container,
- checked *exprpb.CheckedExpr,
+ checked *ast.CheckedAST,
decorators ...InterpretableDecorator) interpretablePlanner {
return &planner{
disp: disp,
@@ -50,8 +51,8 @@ func newPlanner(disp Dispatcher,
adapter: adapter,
attrFactory: attrFactory,
container: cont,
- refMap: checked.GetReferenceMap(),
- typeMap: checked.GetTypeMap(),
+ refMap: checked.ReferenceMap,
+ typeMap: checked.TypeMap,
decorators: decorators,
}
}
@@ -60,8 +61,8 @@ func newPlanner(disp Dispatcher,
// TypeAdapter, and Container to resolve functions and types at plan time. Namespaces present in
// Select expressions are resolved lazily at evaluation time.
func newUncheckedPlanner(disp Dispatcher,
- provider ref.TypeProvider,
- adapter ref.TypeAdapter,
+ provider types.Provider,
+ adapter types.Adapter,
attrFactory AttributeFactory,
cont *containers.Container,
decorators ...InterpretableDecorator) interpretablePlanner {
@@ -71,8 +72,8 @@ func newUncheckedPlanner(disp Dispatcher,
adapter: adapter,
attrFactory: attrFactory,
container: cont,
- refMap: make(map[int64]*exprpb.Reference),
- typeMap: make(map[int64]*exprpb.Type),
+ refMap: make(map[int64]*ast.ReferenceInfo),
+ typeMap: make(map[int64]*types.Type),
decorators: decorators,
}
}
@@ -80,12 +81,12 @@ func newUncheckedPlanner(disp Dispatcher,
// planner is an implementation of the interpretablePlanner interface.
type planner struct {
disp Dispatcher
- provider ref.TypeProvider
- adapter ref.TypeAdapter
+ provider types.Provider
+ adapter types.Adapter
attrFactory AttributeFactory
container *containers.Container
- refMap map[int64]*exprpb.Reference
- typeMap map[int64]*exprpb.Type
+ refMap map[int64]*ast.ReferenceInfo
+ typeMap map[int64]*types.Type
decorators []InterpretableDecorator
}
@@ -144,22 +145,19 @@ func (p *planner) planIdent(expr *exprpb.Expr) (Interpretable, error) {
}, nil
}
-func (p *planner) planCheckedIdent(id int64, identRef *exprpb.Reference) (Interpretable, error) {
+func (p *planner) planCheckedIdent(id int64, identRef *ast.ReferenceInfo) (Interpretable, error) {
// Plan a constant reference if this is the case for this simple identifier.
- if identRef.GetValue() != nil {
- return p.Plan(&exprpb.Expr{Id: id,
- ExprKind: &exprpb.Expr_ConstExpr{
- ConstExpr: identRef.GetValue(),
- }})
+ if identRef.Value != nil {
+ return NewConstValue(id, identRef.Value), nil
}
// Check to see whether the type map indicates this is a type name. All types should be
// registered with the provider.
cType := p.typeMap[id]
- if cType.GetType() != nil {
- cVal, found := p.provider.FindIdent(identRef.GetName())
+ if cType.Kind() == types.TypeKind {
+ cVal, found := p.provider.FindIdent(identRef.Name)
if !found {
- return nil, fmt.Errorf("reference to undefined type: %s", identRef.GetName())
+ return nil, fmt.Errorf("reference to undefined type: %s", identRef.Name)
}
return NewConstValue(id, cVal), nil
}
@@ -167,7 +165,7 @@ func (p *planner) planCheckedIdent(id int64, identRef *exprpb.Reference) (Interp
// Otherwise, return the attribute for the resolved identifier name.
return &evalAttr{
adapter: p.adapter,
- attr: p.attrFactory.AbsoluteAttribute(id, identRef.GetName()),
+ attr: p.attrFactory.AbsoluteAttribute(id, identRef.Name),
}, nil
}
@@ -217,18 +215,14 @@ func (p *planner) planSelect(expr *exprpb.Expr) (Interpretable, error) {
if err != nil {
return nil, err
}
-
- // Return the test only eval expression.
+ // Modify the attribute to be test-only.
if sel.GetTestOnly() {
- return &evalTestOnly{
- id: expr.GetId(),
- field: types.String(sel.GetField()),
- attr: attr,
- qual: qual,
- }, nil
+ attr = &evalTestOnly{
+ id: expr.GetId(),
+ InterpretableAttribute: attr,
+ }
}
-
- // Otherwise, append the qualifier on the attribute.
+ // Append the qualifier on the attribute.
_, err = attr.AddQualifier(qual)
return attr, err
}
@@ -434,18 +428,16 @@ func (p *planner) planCallNotEqual(expr *exprpb.Expr, args []Interpretable) (Int
// planCallLogicalAnd generates a logical and (&&) Interpretable.
func (p *planner) planCallLogicalAnd(expr *exprpb.Expr, args []Interpretable) (Interpretable, error) {
return &evalAnd{
- id: expr.GetId(),
- lhs: args[0],
- rhs: args[1],
+ id: expr.GetId(),
+ terms: args,
}, nil
}
// planCallLogicalOr generates a logical or (||) Interpretable.
func (p *planner) planCallLogicalOr(expr *exprpb.Expr, args []Interpretable) (Interpretable, error) {
return &evalOr{
- id: expr.GetId(),
- lhs: args[0],
- rhs: args[1],
+ id: expr.GetId(),
+ terms: args,
}, nil
}
@@ -481,7 +473,7 @@ func (p *planner) planCallConditional(expr *exprpb.Expr, args []Interpretable) (
func (p *planner) planCallIndex(expr *exprpb.Expr, args []Interpretable, optional bool) (Interpretable, error) {
op := args[0]
ind := args[1]
- opType := p.typeMap[expr.GetCallExpr().GetTarget().GetId()]
+ opType := p.typeMap[op.ID()]
// Establish the attribute reference.
var err error
@@ -515,8 +507,17 @@ func (p *planner) planCallIndex(expr *exprpb.Expr, args []Interpretable, optiona
// planCreateList generates a list construction Interpretable.
func (p *planner) planCreateList(expr *exprpb.Expr) (Interpretable, error) {
list := expr.GetListExpr()
- elems := make([]Interpretable, len(list.GetElements()))
- for i, elem := range list.GetElements() {
+ optionalIndices := list.GetOptionalIndices()
+ elements := list.GetElements()
+ optionals := make([]bool, len(elements))
+ for _, index := range optionalIndices {
+ if index < 0 || index >= int32(len(elements)) {
+ return nil, fmt.Errorf("optional index %d out of element bounds [0, %d]", index, len(elements))
+ }
+ optionals[index] = true
+ }
+ elems := make([]Interpretable, len(elements))
+ for i, elem := range elements {
elemVal, err := p.Plan(elem)
if err != nil {
return nil, err
@@ -524,9 +525,11 @@ func (p *planner) planCreateList(expr *exprpb.Expr) (Interpretable, error) {
elems[i] = elemVal
}
return &evalList{
- id: expr.GetId(),
- elems: elems,
- adapter: p.adapter,
+ id: expr.GetId(),
+ elems: elems,
+ optionals: optionals,
+ hasOptionals: len(optionals) != 0,
+ adapter: p.adapter,
}, nil
}
@@ -555,11 +558,12 @@ func (p *planner) planCreateStruct(expr *exprpb.Expr) (Interpretable, error) {
optionals[i] = entry.GetOptionalEntry()
}
return &evalMap{
- id: expr.GetId(),
- keys: keys,
- vals: vals,
- optionals: optionals,
- adapter: p.adapter,
+ id: expr.GetId(),
+ keys: keys,
+ vals: vals,
+ optionals: optionals,
+ hasOptionals: len(optionals) != 0,
+ adapter: p.adapter,
}, nil
}
@@ -584,12 +588,13 @@ func (p *planner) planCreateObj(expr *exprpb.Expr) (Interpretable, error) {
optionals[i] = entry.GetOptionalEntry()
}
return &evalObj{
- id: expr.GetId(),
- typeName: typeName,
- fields: fields,
- vals: vals,
- optionals: optionals,
- provider: p.provider,
+ id: expr.GetId(),
+ typeName: typeName,
+ fields: fields,
+ vals: vals,
+ optionals: optionals,
+ hasOptionals: len(optionals) != 0,
+ provider: p.provider,
}, nil
}
@@ -667,7 +672,7 @@ func (p *planner) constValue(c *exprpb.Constant) (ref.Val, error) {
// namespace resolution rules to it in a scan over possible matching types in the TypeProvider.
func (p *planner) resolveTypeName(typeName string) (string, bool) {
for _, qualifiedTypeName := range p.container.ResolveCandidateNames(typeName) {
- if _, found := p.provider.FindType(qualifiedTypeName); found {
+ if _, found := p.provider.FindStructType(qualifiedTypeName); found {
return qualifiedTypeName, true
}
}
@@ -694,8 +699,8 @@ func (p *planner) resolveFunction(expr *exprpb.Expr) (*exprpb.Expr, string, stri
// function name as the fnName value.
oRef, hasOverload := p.refMap[expr.GetId()]
if hasOverload {
- if len(oRef.GetOverloadId()) == 1 {
- return target, fnName, oRef.GetOverloadId()[0]
+ if len(oRef.OverloadIDs) == 1 {
+ return target, fnName, oRef.OverloadIDs[0]
}
// Note, this namespaced function name will not appear as a fully qualified name in ASTs
// built and stored before cel-go v0.5.0; however, this functionality did not work at all
diff --git a/vendor/github.com/google/cel-go/interpreter/prune.go b/vendor/github.com/google/cel-go/interpreter/prune.go
index eab46e0c0..b8834b1cb 100644
--- a/vendor/github.com/google/cel-go/interpreter/prune.go
+++ b/vendor/github.com/google/cel-go/interpreter/prune.go
@@ -16,6 +16,7 @@ package interpreter
import (
"github.com/google/cel-go/common/operators"
+ "github.com/google/cel-go/common/overloads"
"github.com/google/cel-go/common/types"
"github.com/google/cel-go/common/types/ref"
"github.com/google/cel-go/common/types/traits"
@@ -26,6 +27,7 @@ import (
type astPruner struct {
expr *exprpb.Expr
+ macroCalls map[int64]*exprpb.Expr
state EvalState
nextExprID int64
}
@@ -65,13 +67,22 @@ type astPruner struct {
// compiled and constant folded expressions, but is not willing to constant
// fold(and thus cache results of) some external calls, then they can prepare
// the overloads accordingly.
-func PruneAst(expr *exprpb.Expr, state EvalState) *exprpb.Expr {
+func PruneAst(expr *exprpb.Expr, macroCalls map[int64]*exprpb.Expr, state EvalState) *exprpb.ParsedExpr {
+ pruneState := NewEvalState()
+ for _, id := range state.IDs() {
+ v, _ := state.Value(id)
+ pruneState.SetValue(id, v)
+ }
pruner := &astPruner{
expr: expr,
- state: state,
- nextExprID: 1}
- newExpr, _ := pruner.prune(expr)
- return newExpr
+ macroCalls: macroCalls,
+ state: pruneState,
+ nextExprID: getMaxID(expr)}
+ newExpr, _ := pruner.maybePrune(expr)
+ return &exprpb.ParsedExpr{
+ Expr: newExpr,
+ SourceInfo: &exprpb.SourceInfo{MacroCalls: pruner.macroCalls},
+ }
}
func (p *astPruner) createLiteral(id int64, val *exprpb.Constant) *exprpb.Expr {
@@ -84,28 +95,50 @@ func (p *astPruner) createLiteral(id int64, val *exprpb.Constant) *exprpb.Expr {
}
func (p *astPruner) maybeCreateLiteral(id int64, val ref.Val) (*exprpb.Expr, bool) {
- switch val.Type() {
- case types.BoolType:
+ switch v := val.(type) {
+ case types.Bool:
+ p.state.SetValue(id, val)
return p.createLiteral(id,
- &exprpb.Constant{ConstantKind: &exprpb.Constant_BoolValue{BoolValue: val.Value().(bool)}}), true
- case types.IntType:
+ &exprpb.Constant{ConstantKind: &exprpb.Constant_BoolValue{BoolValue: bool(v)}}), true
+ case types.Bytes:
+ p.state.SetValue(id, val)
return p.createLiteral(id,
- &exprpb.Constant{ConstantKind: &exprpb.Constant_Int64Value{Int64Value: val.Value().(int64)}}), true
- case types.UintType:
+ &exprpb.Constant{ConstantKind: &exprpb.Constant_BytesValue{BytesValue: []byte(v)}}), true
+ case types.Double:
+ p.state.SetValue(id, val)
return p.createLiteral(id,
- &exprpb.Constant{ConstantKind: &exprpb.Constant_Uint64Value{Uint64Value: val.Value().(uint64)}}), true
- case types.StringType:
+ &exprpb.Constant{ConstantKind: &exprpb.Constant_DoubleValue{DoubleValue: float64(v)}}), true
+ case types.Duration:
+ p.state.SetValue(id, val)
+ durationString := string(v.ConvertToType(types.StringType).(types.String))
+ return &exprpb.Expr{
+ Id: id,
+ ExprKind: &exprpb.Expr_CallExpr{
+ CallExpr: &exprpb.Expr_Call{
+ Function: overloads.TypeConvertDuration,
+ Args: []*exprpb.Expr{
+ p.createLiteral(p.nextID(),
+ &exprpb.Constant{ConstantKind: &exprpb.Constant_StringValue{StringValue: durationString}}),
+ },
+ },
+ },
+ }, true
+ case types.Int:
+ p.state.SetValue(id, val)
return p.createLiteral(id,
- &exprpb.Constant{ConstantKind: &exprpb.Constant_StringValue{StringValue: val.Value().(string)}}), true
- case types.DoubleType:
+ &exprpb.Constant{ConstantKind: &exprpb.Constant_Int64Value{Int64Value: int64(v)}}), true
+ case types.Uint:
+ p.state.SetValue(id, val)
return p.createLiteral(id,
- &exprpb.Constant{ConstantKind: &exprpb.Constant_DoubleValue{DoubleValue: val.Value().(float64)}}), true
- case types.BytesType:
+ &exprpb.Constant{ConstantKind: &exprpb.Constant_Uint64Value{Uint64Value: uint64(v)}}), true
+ case types.String:
+ p.state.SetValue(id, val)
return p.createLiteral(id,
- &exprpb.Constant{ConstantKind: &exprpb.Constant_BytesValue{BytesValue: val.Value().([]byte)}}), true
- case types.NullType:
+ &exprpb.Constant{ConstantKind: &exprpb.Constant_StringValue{StringValue: string(v)}}), true
+ case types.Null:
+ p.state.SetValue(id, val)
return p.createLiteral(id,
- &exprpb.Constant{ConstantKind: &exprpb.Constant_NullValue{NullValue: val.Value().(structpb.NullValue)}}), true
+ &exprpb.Constant{ConstantKind: &exprpb.Constant_NullValue{NullValue: v.Value().(structpb.NullValue)}}), true
}
// Attempt to build a list literal.
@@ -123,6 +156,7 @@ func (p *astPruner) maybeCreateLiteral(id int64, val ref.Val) (*exprpb.Expr, boo
}
elemExprs[i] = elemExpr
}
+ p.state.SetValue(id, val)
return &exprpb.Expr{
Id: id,
ExprKind: &exprpb.Expr_ListExpr{
@@ -162,6 +196,7 @@ func (p *astPruner) maybeCreateLiteral(id int64, val ref.Val) (*exprpb.Expr, boo
entries[i] = entry
i++
}
+ p.state.SetValue(id, val)
return &exprpb.Expr{
Id: id,
ExprKind: &exprpb.Expr_StructExpr{
@@ -177,70 +212,152 @@ func (p *astPruner) maybeCreateLiteral(id int64, val ref.Val) (*exprpb.Expr, boo
return nil, false
}
-func (p *astPruner) maybePruneAndOr(node *exprpb.Expr) (*exprpb.Expr, bool) {
- if !p.existsWithUnknownValue(node.GetId()) {
+func (p *astPruner) maybePruneOptional(elem *exprpb.Expr) (*exprpb.Expr, bool) {
+ elemVal, found := p.value(elem.GetId())
+ if found && elemVal.Type() == types.OptionalType {
+ opt := elemVal.(*types.Optional)
+ if !opt.HasValue() {
+ return nil, true
+ }
+ if newElem, pruned := p.maybeCreateLiteral(elem.GetId(), opt.GetValue()); pruned {
+ return newElem, true
+ }
+ }
+ return elem, false
+}
+
+func (p *astPruner) maybePruneIn(node *exprpb.Expr) (*exprpb.Expr, bool) {
+ // elem in list
+ call := node.GetCallExpr()
+ val, exists := p.maybeValue(call.GetArgs()[1].GetId())
+ if !exists {
+ return nil, false
+ }
+ if sz, ok := val.(traits.Sizer); ok && sz.Size() == types.IntZero {
+ return p.maybeCreateLiteral(node.GetId(), types.False)
+ }
+ return nil, false
+}
+
+func (p *astPruner) maybePruneLogicalNot(node *exprpb.Expr) (*exprpb.Expr, bool) {
+ call := node.GetCallExpr()
+ arg := call.GetArgs()[0]
+ val, exists := p.maybeValue(arg.GetId())
+ if !exists {
return nil, false
}
+ if b, ok := val.(types.Bool); ok {
+ return p.maybeCreateLiteral(node.GetId(), !b)
+ }
+ return nil, false
+}
+func (p *astPruner) maybePruneOr(node *exprpb.Expr) (*exprpb.Expr, bool) {
call := node.GetCallExpr()
// We know result is unknown, so we have at least one unknown arg
// and if one side is a known value, we know we can ignore it.
- if p.existsWithKnownValue(call.Args[0].GetId()) {
- return call.Args[1], true
+ if v, exists := p.maybeValue(call.GetArgs()[0].GetId()); exists {
+ if v == types.True {
+ return p.maybeCreateLiteral(node.GetId(), types.True)
+ }
+ return call.GetArgs()[1], true
}
- if p.existsWithKnownValue(call.Args[1].GetId()) {
- return call.Args[0], true
+ if v, exists := p.maybeValue(call.GetArgs()[1].GetId()); exists {
+ if v == types.True {
+ return p.maybeCreateLiteral(node.GetId(), types.True)
+ }
+ return call.GetArgs()[0], true
}
return nil, false
}
-func (p *astPruner) maybePruneConditional(node *exprpb.Expr) (*exprpb.Expr, bool) {
- if !p.existsWithUnknownValue(node.GetId()) {
- return nil, false
+func (p *astPruner) maybePruneAnd(node *exprpb.Expr) (*exprpb.Expr, bool) {
+ call := node.GetCallExpr()
+ // We know result is unknown, so we have at least one unknown arg
+ // and if one side is a known value, we know we can ignore it.
+ if v, exists := p.maybeValue(call.GetArgs()[0].GetId()); exists {
+ if v == types.False {
+ return p.maybeCreateLiteral(node.GetId(), types.False)
+ }
+ return call.GetArgs()[1], true
+ }
+ if v, exists := p.maybeValue(call.GetArgs()[1].GetId()); exists {
+ if v == types.False {
+ return p.maybeCreateLiteral(node.GetId(), types.False)
+ }
+ return call.GetArgs()[0], true
}
+ return nil, false
+}
+func (p *astPruner) maybePruneConditional(node *exprpb.Expr) (*exprpb.Expr, bool) {
call := node.GetCallExpr()
- condVal, condValueExists := p.value(call.Args[0].GetId())
- if !condValueExists || types.IsUnknownOrError(condVal) {
+ cond, exists := p.maybeValue(call.GetArgs()[0].GetId())
+ if !exists {
return nil, false
}
-
- if condVal.Value().(bool) {
- return call.Args[1], true
+ if cond.Value().(bool) {
+ return call.GetArgs()[1], true
}
- return call.Args[2], true
+ return call.GetArgs()[2], true
}
func (p *astPruner) maybePruneFunction(node *exprpb.Expr) (*exprpb.Expr, bool) {
+ if _, exists := p.value(node.GetId()); !exists {
+ return nil, false
+ }
call := node.GetCallExpr()
- if call.Function == operators.LogicalOr || call.Function == operators.LogicalAnd {
- return p.maybePruneAndOr(node)
+ if call.Function == operators.LogicalOr {
+ return p.maybePruneOr(node)
+ }
+ if call.Function == operators.LogicalAnd {
+ return p.maybePruneAnd(node)
}
if call.Function == operators.Conditional {
return p.maybePruneConditional(node)
}
-
+ if call.Function == operators.In {
+ return p.maybePruneIn(node)
+ }
+ if call.Function == operators.LogicalNot {
+ return p.maybePruneLogicalNot(node)
+ }
return nil, false
}
+func (p *astPruner) maybePrune(node *exprpb.Expr) (*exprpb.Expr, bool) {
+ return p.prune(node)
+}
+
func (p *astPruner) prune(node *exprpb.Expr) (*exprpb.Expr, bool) {
if node == nil {
return node, false
}
- val, valueExists := p.value(node.GetId())
- if valueExists && !types.IsUnknownOrError(val) {
+ val, valueExists := p.maybeValue(node.GetId())
+ if valueExists {
if newNode, ok := p.maybeCreateLiteral(node.GetId(), val); ok {
+ delete(p.macroCalls, node.GetId())
return newNode, true
}
}
+ if macro, found := p.macroCalls[node.GetId()]; found {
+ // Ensure that intermediate values for the comprehension are cleared during pruning
+ compre := node.GetComprehensionExpr()
+ if compre != nil {
+ visit(macro, clearIterVarVisitor(compre.IterVar, p.state))
+ }
+ // prune the expression in terms of the macro call instead of the expanded form.
+ if newMacro, pruned := p.prune(macro); pruned {
+ p.macroCalls[node.GetId()] = newMacro
+ }
+ }
// We have either an unknown/error value, or something we don't want to
// transform, or expression was not evaluated. If possible, drill down
// more.
-
switch node.GetExprKind().(type) {
case *exprpb.Expr_SelectExpr:
- if operand, pruned := p.prune(node.GetSelectExpr().GetOperand()); pruned {
+ if operand, pruned := p.maybePrune(node.GetSelectExpr().GetOperand()); pruned {
return &exprpb.Expr{
Id: node.GetId(),
ExprKind: &exprpb.Expr_SelectExpr{
@@ -253,10 +370,6 @@ func (p *astPruner) prune(node *exprpb.Expr) (*exprpb.Expr, bool) {
}, true
}
case *exprpb.Expr_CallExpr:
- if newExpr, pruned := p.maybePruneFunction(node); pruned {
- newExpr, _ = p.prune(newExpr)
- return newExpr, true
- }
var prunedCall bool
call := node.GetCallExpr()
args := call.GetArgs()
@@ -268,40 +381,75 @@ func (p *astPruner) prune(node *exprpb.Expr) (*exprpb.Expr, bool) {
}
for i, arg := range args {
newArgs[i] = arg
- if newArg, prunedArg := p.prune(arg); prunedArg {
+ if newArg, prunedArg := p.maybePrune(arg); prunedArg {
prunedCall = true
newArgs[i] = newArg
}
}
- if newTarget, prunedTarget := p.prune(call.GetTarget()); prunedTarget {
+ if newTarget, prunedTarget := p.maybePrune(call.GetTarget()); prunedTarget {
prunedCall = true
newCall.Target = newTarget
}
+ newNode := &exprpb.Expr{
+ Id: node.GetId(),
+ ExprKind: &exprpb.Expr_CallExpr{
+ CallExpr: newCall,
+ },
+ }
+ if newExpr, pruned := p.maybePruneFunction(newNode); pruned {
+ newExpr, _ = p.maybePrune(newExpr)
+ return newExpr, true
+ }
if prunedCall {
- return &exprpb.Expr{
- Id: node.GetId(),
- ExprKind: &exprpb.Expr_CallExpr{
- CallExpr: newCall,
- },
- }, true
+ return newNode, true
}
case *exprpb.Expr_ListExpr:
elems := node.GetListExpr().GetElements()
- newElems := make([]*exprpb.Expr, len(elems))
+ optIndices := node.GetListExpr().GetOptionalIndices()
+ optIndexMap := map[int32]bool{}
+ for _, i := range optIndices {
+ optIndexMap[i] = true
+ }
+ newOptIndexMap := make(map[int32]bool, len(optIndexMap))
+ newElems := make([]*exprpb.Expr, 0, len(elems))
var prunedList bool
+
+ prunedIdx := 0
for i, elem := range elems {
- newElems[i] = elem
- if newElem, prunedElem := p.prune(elem); prunedElem {
- newElems[i] = newElem
+ _, isOpt := optIndexMap[int32(i)]
+ if isOpt {
+ newElem, pruned := p.maybePruneOptional(elem)
+ if pruned {
+ prunedList = true
+ if newElem != nil {
+ newElems = append(newElems, newElem)
+ prunedIdx++
+ }
+ continue
+ }
+ newOptIndexMap[int32(prunedIdx)] = true
+ }
+ if newElem, prunedElem := p.maybePrune(elem); prunedElem {
+ newElems = append(newElems, newElem)
prunedList = true
+ } else {
+ newElems = append(newElems, elem)
}
+ prunedIdx++
+ }
+ optIndices = make([]int32, len(newOptIndexMap))
+ idx := 0
+ for i := range newOptIndexMap {
+ optIndices[idx] = i
+ idx++
}
if prunedList {
return &exprpb.Expr{
Id: node.GetId(),
ExprKind: &exprpb.Expr_ListExpr{
ListExpr: &exprpb.Expr_CreateList{
- Elements: newElems,
+ Elements: newElems,
+ OptionalIndices: optIndices,
},
},
}, true
@@ -313,8 +461,8 @@ func (p *astPruner) prune(node *exprpb.Expr) (*exprpb.Expr, bool) {
newEntries := make([]*exprpb.Expr_CreateStruct_Entry, len(entries))
for i, entry := range entries {
newEntries[i] = entry
- newKey, prunedKey := p.prune(entry.GetMapKey())
- newValue, prunedValue := p.prune(entry.GetValue())
+ newKey, prunedKey := p.maybePrune(entry.GetMapKey())
+ newValue, prunedValue := p.maybePrune(entry.GetValue())
if !prunedKey && !prunedValue {
continue
}
@@ -331,6 +479,7 @@ func (p *astPruner) prune(node *exprpb.Expr) (*exprpb.Expr, bool) {
MapKey: newKey,
}
}
+ newEntry.OptionalEntry = entry.GetOptionalEntry()
newEntries[i] = newEntry
}
if prunedStruct {
@@ -349,7 +498,7 @@ func (p *astPruner) prune(node *exprpb.Expr) (*exprpb.Expr, bool) {
// Only the range of the comprehension is pruned since the state tracking only records
// the last iteration of the comprehension and not each step in the evaluation which
// means that the any residuals computed in between might be inaccurate.
- if newRange, pruned := p.prune(compre.GetIterRange()); pruned {
+ if newRange, pruned := p.maybePrune(compre.GetIterRange()); pruned {
return &exprpb.Expr{
Id: node.GetId(),
ExprKind: &exprpb.Expr_ComprehensionExpr{
@@ -374,24 +523,97 @@ func (p *astPruner) value(id int64) (ref.Val, bool) {
return val, (found && val != nil)
}
-func (p *astPruner) existsWithUnknownValue(id int64) bool {
- val, valueExists := p.value(id)
- return valueExists && types.IsUnknown(val)
+func (p *astPruner) maybeValue(id int64) (ref.Val, bool) {
+ val, found := p.value(id)
+ if !found || types.IsUnknownOrError(val) {
+ return nil, false
+ }
+ return val, true
+}
+
+func (p *astPruner) nextID() int64 {
+ next := p.nextExprID
+ p.nextExprID++
+ return next
+}
+
+type astVisitor struct {
+ // visitEntry is called on every expr node, including those within a map/struct entry.
+ visitExpr func(expr *exprpb.Expr)
+ // visitEntry is called before entering the key, value of a map/struct entry.
+ visitEntry func(entry *exprpb.Expr_CreateStruct_Entry)
}
-func (p *astPruner) existsWithKnownValue(id int64) bool {
- val, valueExists := p.value(id)
- return valueExists && !types.IsUnknown(val)
+func getMaxID(expr *exprpb.Expr) int64 {
+ maxID := int64(1)
+ visit(expr, maxIDVisitor(&maxID))
+ return maxID
}
-func (p *astPruner) nextID() int64 {
- for {
- _, found := p.state.Value(p.nextExprID)
- if !found {
- next := p.nextExprID
- p.nextExprID++
- return next
+func clearIterVarVisitor(varName string, state EvalState) astVisitor {
+ return astVisitor{
+ visitExpr: func(e *exprpb.Expr) {
+ ident := e.GetIdentExpr()
+ if ident != nil && ident.GetName() == varName {
+ state.SetValue(e.GetId(), nil)
+ }
+ },
+ }
+}
+
+func maxIDVisitor(maxID *int64) astVisitor {
+ return astVisitor{
+ visitExpr: func(e *exprpb.Expr) {
+ if e.GetId() >= *maxID {
+ *maxID = e.GetId() + 1
+ }
+ },
+ visitEntry: func(e *exprpb.Expr_CreateStruct_Entry) {
+ if e.GetId() >= *maxID {
+ *maxID = e.GetId() + 1
+ }
+ },
+ }
+}
+
+func visit(expr *exprpb.Expr, visitor astVisitor) {
+ exprs := []*exprpb.Expr{expr}
+ for len(exprs) != 0 {
+ e := exprs[0]
+ if visitor.visitExpr != nil {
+ visitor.visitExpr(e)
+ }
+ exprs = exprs[1:]
+ switch e.GetExprKind().(type) {
+ case *exprpb.Expr_SelectExpr:
+ exprs = append(exprs, e.GetSelectExpr().GetOperand())
+ case *exprpb.Expr_CallExpr:
+ call := e.GetCallExpr()
+ if call.GetTarget() != nil {
+ exprs = append(exprs, call.GetTarget())
+ }
+ exprs = append(exprs, call.GetArgs()...)
+ case *exprpb.Expr_ComprehensionExpr:
+ compre := e.GetComprehensionExpr()
+ exprs = append(exprs,
+ compre.GetIterRange(),
+ compre.GetAccuInit(),
+ compre.GetLoopCondition(),
+ compre.GetLoopStep(),
+ compre.GetResult())
+ case *exprpb.Expr_ListExpr:
+ list := e.GetListExpr()
+ exprs = append(exprs, list.GetElements()...)
+ case *exprpb.Expr_StructExpr:
+ for _, entry := range e.GetStructExpr().GetEntries() {
+ if visitor.visitEntry != nil {
+ visitor.visitEntry(entry)
+ }
+ if entry.GetMapKey() != nil {
+ exprs = append(exprs, entry.GetMapKey())
+ }
+ exprs = append(exprs, entry.GetValue())
+ }
}
- p.nextExprID++
}
}
diff --git a/vendor/github.com/google/cel-go/interpreter/runtimecost.go b/vendor/github.com/google/cel-go/interpreter/runtimecost.go
index 42e64a44e..96faed2e5 100644
--- a/vendor/github.com/google/cel-go/interpreter/runtimecost.go
+++ b/vendor/github.com/google/cel-go/interpreter/runtimecost.go
@@ -53,6 +53,11 @@ func CostObserver(tracker *CostTracker) EvalObserver {
tracker.stack.drop(t.Attr().ID())
tracker.cost += common.SelectAndIdentCost
}
+ if !tracker.presenceTestHasCost {
+ if _, isTestOnly := programStep.(*evalTestOnly); isTestOnly {
+ tracker.cost -= common.SelectAndIdentCost
+ }
+ }
case *evalExhaustiveConditional:
// Ternary has no direct cost. All cost is from the conditional and the true/false branch expressions.
tracker.stack.drop(t.attr.falsy.ID(), t.attr.truthy.ID(), t.attr.expr.ID())
@@ -60,13 +65,21 @@ func CostObserver(tracker *CostTracker) EvalObserver {
// While the field names are identical, the boolean operation eval structs do not share an interface and so
// must be handled individually.
case *evalOr:
- tracker.stack.drop(t.rhs.ID(), t.lhs.ID())
+ for _, term := range t.terms {
+ tracker.stack.drop(term.ID())
+ }
case *evalAnd:
- tracker.stack.drop(t.rhs.ID(), t.lhs.ID())
+ for _, term := range t.terms {
+ tracker.stack.drop(term.ID())
+ }
case *evalExhaustiveOr:
- tracker.stack.drop(t.rhs.ID(), t.lhs.ID())
+ for _, term := range t.terms {
+ tracker.stack.drop(term.ID())
+ }
case *evalExhaustiveAnd:
- tracker.stack.drop(t.rhs.ID(), t.lhs.ID())
+ for _, term := range t.terms {
+ tracker.stack.drop(term.ID())
+ }
case *evalFold:
tracker.stack.drop(t.iterRange.ID())
case Qualifier:
@@ -95,21 +108,58 @@ func CostObserver(tracker *CostTracker) EvalObserver {
return observer
}
-// CostTracker represents the information needed for tacking runtime cost
+// CostTrackerOption configures the behavior of CostTracker objects.
+type CostTrackerOption func(*CostTracker) error
+
+// CostTrackerLimit sets the runtime limit on the evaluation cost during execution and will terminate the expression
+// evaluation if the limit is exceeded.
+func CostTrackerLimit(limit uint64) CostTrackerOption {
+ return func(tracker *CostTracker) error {
+ tracker.Limit = &limit
+ return nil
+ }
+}
+
+// PresenceTestHasCost determines whether presence testing has a cost of one or zero.
+// Defaults to presence test has a cost of one.
+func PresenceTestHasCost(hasCost bool) CostTrackerOption {
+ return func(tracker *CostTracker) error {
+ tracker.presenceTestHasCost = hasCost
+ return nil
+ }
+}
+
+// NewCostTracker creates a new CostTracker with a given estimator and a set of functional CostTrackerOption values.
+func NewCostTracker(estimator ActualCostEstimator, opts ...CostTrackerOption) (*CostTracker, error) {
+ tracker := &CostTracker{
+ Estimator: estimator,
+ presenceTestHasCost: true,
+ }
+ for _, opt := range opts {
+ err := opt(tracker)
+ if err != nil {
+ return nil, err
+ }
+ }
+ return tracker, nil
+}
+
+// CostTracker represents the information needed for tracking runtime cost.
type CostTracker struct {
- Estimator ActualCostEstimator
- Limit *uint64
+ Estimator ActualCostEstimator
+ Limit *uint64
+ presenceTestHasCost bool
cost uint64
stack refValStack
}
// ActualCost returns the runtime cost
-func (c CostTracker) ActualCost() uint64 {
+func (c *CostTracker) ActualCost() uint64 {
return c.cost
}
-func (c CostTracker) costCall(call InterpretableCall, argValues []ref.Val, result ref.Val) uint64 {
+func (c *CostTracker) costCall(call InterpretableCall, argValues []ref.Val, result ref.Val) uint64 {
var cost uint64
if c.Estimator != nil {
callCost := c.Estimator.CallCost(call.Function(), call.OverloadID(), argValues, result)
@@ -122,7 +172,7 @@ func (c CostTracker) costCall(call InterpretableCall, argValues []ref.Val, resul
// if user has their own implementation of ActualCostEstimator, make sure to cover the mapping between overloadId and cost calculation
switch call.OverloadID() {
// O(n) functions
- case overloads.StartsWithString, overloads.EndsWithString, overloads.StringToBytes, overloads.BytesToString:
+ case overloads.StartsWithString, overloads.EndsWithString, overloads.StringToBytes, overloads.BytesToString, overloads.ExtQuoteString, overloads.ExtFormatString:
cost += uint64(math.Ceil(float64(c.actualSize(argValues[0])) * common.StringTraversalCostFactor))
case overloads.InList:
// If a list is composed entirely of constant values this is O(1), but we don't account for that here.
@@ -179,7 +229,7 @@ func (c CostTracker) costCall(call InterpretableCall, argValues []ref.Val, resul
}
// actualSize returns the size of value
-func (c CostTracker) actualSize(value ref.Val) uint64 {
+func (c *CostTracker) actualSize(value ref.Val) uint64 {
if sz, ok := value.(traits.Sizer); ok {
return uint64(sz.Size().(types.Int))
}
diff --git a/vendor/github.com/google/cel-go/parser/BUILD.bazel b/vendor/github.com/google/cel-go/parser/BUILD.bazel
index b5c15fa57..67ecc9554 100644
--- a/vendor/github.com/google/cel-go/parser/BUILD.bazel
+++ b/vendor/github.com/google/cel-go/parser/BUILD.bazel
@@ -23,8 +23,8 @@ go_library(
"//common/operators:go_default_library",
"//common/runes:go_default_library",
"//parser/gen:go_default_library",
- "@com_github_antlr_antlr4_runtime_go_antlr//:go_default_library",
- "@org_golang_google_genproto//googleapis/api/expr/v1alpha1:go_default_library",
+ "@com_github_antlr_antlr4_runtime_go_antlr_v4//:go_default_library",
+ "@org_golang_google_genproto_googleapis_api//expr/v1alpha1:go_default_library",
"@org_golang_google_protobuf//proto:go_default_library",
"@org_golang_google_protobuf//types/known/structpb:go_default_library",
],
@@ -46,7 +46,7 @@ go_test(
"//common/debug:go_default_library",
"//parser/gen:go_default_library",
"//test:go_default_library",
- "@com_github_antlr_antlr4_runtime_go_antlr//:go_default_library",
+ "@com_github_antlr_antlr4_runtime_go_antlr_v4//:go_default_library",
"@org_golang_google_protobuf//proto:go_default_library",
"@org_golang_google_protobuf//testing/protocmp:go_default_library",
],
diff --git a/vendor/github.com/google/cel-go/parser/errors.go b/vendor/github.com/google/cel-go/parser/errors.go
index ce49bb87f..93ae7a3ad 100644
--- a/vendor/github.com/google/cel-go/parser/errors.go
+++ b/vendor/github.com/google/cel-go/parser/errors.go
@@ -22,9 +22,22 @@ import (
// parseErrors is a specialization of Errors.
type parseErrors struct {
- *common.Errors
+ errs *common.Errors
+}
+
+// errorCount indicates the number of errors reported.
+func (e *parseErrors) errorCount() int {
+ return len(e.errs.GetErrors())
+}
+
+func (e *parseErrors) internalError(message string) {
+ e.errs.ReportErrorAtID(0, common.NoLocation, message)
}
func (e *parseErrors) syntaxError(l common.Location, message string) {
- e.ReportError(l, fmt.Sprintf("Syntax error: %s", message))
+ e.errs.ReportErrorAtID(0, l, fmt.Sprintf("Syntax error: %s", message))
+}
+
+func (e *parseErrors) reportErrorAtID(id int64, l common.Location, message string, args ...any) {
+ e.errs.ReportErrorAtID(id, l, message, args...)
}
diff --git a/vendor/github.com/google/cel-go/parser/gen/BUILD.bazel b/vendor/github.com/google/cel-go/parser/gen/BUILD.bazel
index 22711310c..654d1de7a 100644
--- a/vendor/github.com/google/cel-go/parser/gen/BUILD.bazel
+++ b/vendor/github.com/google/cel-go/parser/gen/BUILD.bazel
@@ -21,6 +21,6 @@ go_library(
],
importpath = "github.com/google/cel-go/parser/gen",
deps = [
- "@com_github_antlr_antlr4_runtime_go_antlr//:go_default_library",
+ "@com_github_antlr_antlr4_runtime_go_antlr_v4//:go_default_library",
],
)
diff --git a/vendor/github.com/google/cel-go/parser/gen/CEL.g4 b/vendor/github.com/google/cel-go/parser/gen/CEL.g4
index dada9e9f3..b011da803 100644
--- a/vendor/github.com/google/cel-go/parser/gen/CEL.g4
+++ b/vendor/github.com/google/cel-go/parser/gen/CEL.g4
@@ -52,15 +52,15 @@ unary
member
: primary # PrimaryExpr
- | member op=('.'|'.?') id=IDENTIFIER # Select
+ | member op='.' (opt='?')? id=IDENTIFIER # Select
| member op='.' id=IDENTIFIER open='(' args=exprList? ')' # MemberCall
- | member op=('['|'[?') index=expr ']' # Index
+ | member op='[' (opt='?')? index=expr ']' # Index
;
primary
: leadingDot='.'? id=IDENTIFIER (op='(' args=exprList? ')')? # IdentOrGlobalCall
| '(' e=expr ')' # Nested
- | op='[' elems=exprList? ','? ']' # CreateList
+ | op='[' elems=listInit? ','? ']' # CreateList
| op='{' entries=mapInitializerList? ','? '}' # CreateStruct
| leadingDot='.'? ids+=IDENTIFIER (ops+='.' ids+=IDENTIFIER)*
op='{' entries=fieldInitializerList? ','? '}' # CreateMessage
@@ -71,6 +71,10 @@ exprList
: e+=expr (',' e+=expr)*
;
+listInit
+ : elems+=optExpr (',' elems+=optExpr)*
+ ;
+
fieldInitializerList
: fields+=optField cols+=':' values+=expr (',' fields+=optField cols+=':' values+=expr)*
;
@@ -80,22 +84,22 @@ optField
;
mapInitializerList
- : keys+=optKey cols+=':' values+=expr (',' keys+=optKey cols+=':' values+=expr)*
+ : keys+=optExpr cols+=':' values+=expr (',' keys+=optExpr cols+=':' values+=expr)*
;
-optKey
- : (opt='?')? expr
+optExpr
+ : (opt='?')? e=expr
;
literal
: sign=MINUS? tok=NUM_INT # Int
- | tok=NUM_UINT # Uint
+ | tok=NUM_UINT # Uint
| sign=MINUS? tok=NUM_FLOAT # Double
- | tok=STRING # String
- | tok=BYTES # Bytes
- | tok=CEL_TRUE # BoolTrue
- | tok=CEL_FALSE # BoolFalse
- | tok=NUL # Null
+ | tok=STRING # String
+ | tok=BYTES # Bytes
+ | tok=CEL_TRUE # BoolTrue
+ | tok=CEL_FALSE # BoolFalse
+ | tok=NUL # Null
;
// Lexer Rules
diff --git a/vendor/github.com/google/cel-go/parser/gen/CEL.interp b/vendor/github.com/google/cel-go/parser/gen/CEL.interp
index 6d3b68bb4..75b8bb3e2 100644
--- a/vendor/github.com/google/cel-go/parser/gen/CEL.interp
+++ b/vendor/github.com/google/cel-go/parser/gen/CEL.interp
@@ -1,7 +1,5 @@
token literal names:
null
-'.?'
-'[?'
'=='
'!='
'in'
@@ -41,8 +39,6 @@ null
token symbolic names:
null
-null
-null
EQUALS
NOT_EQUALS
IN
@@ -91,12 +87,13 @@ unary
member
primary
exprList
+listInit
fieldInitializerList
optField
mapInitializerList
-optKey
+optExpr
literal
atn:
-[4, 1, 38, 235, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 40, 8, 1, 1, 2, 1, 2, 1, 2, 5, 2, 45, 8, 2, 10, 2, 12, 2, 48, 9, 2, 1, 3, 1, 3, 1, 3, 5, 3, 53, 8, 3, 10, 3, 12, 3, 56, 9, 3, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 5, 4, 64, 8, 4, 10, 4, 12, 4, 67, 9, 4, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 5, 5, 78, 8, 5, 10, 5, 12, 5, 81, 9, 5, 1, 6, 1, 6, 4, 6, 85, 8, 6, 11, 6, 12, 6, 86, 1, 6, 1, 6, 4, 6, 91, 8, 6, 11, 6, 12, 6, 92, 1, 6, 3, 6, 96, 8, 6, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 3, 7, 109, 8, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 5, 7, 117, 8, 7, 10, 7, 12, 7, 120, 9, 7, 1, 8, 3, 8, 123, 8, 8, 1, 8, 1, 8, 1, 8, 3, 8, 128, 8, 8, 1, 8, 3, 8, 131, 8, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 3, 8, 139, 8, 8, 1, 8, 3, 8, 142, 8, 8, 1, 8, 1, 8, 1, 8, 3, 8, 147, 8, 8, 1, 8, 3, 8, 150, 8, 8, 1, 8, 1, 8, 3, 8, 154, 8, 8, 1, 8, 1, 8, 1, 8, 5, 8, 159, 8, 8, 10, 8, 12, 8, 162, 9, 8, 1, 8, 1, 8, 3, 8, 166, 8, 8, 1, 8, 3, 8, 169, 8, 8, 1, 8, 1, 8, 3, 8, 173, 8, 8, 1, 9, 1, 9, 1, 9, 5, 9, 178, 8, 9, 10, 9, 12, 9, 181, 9, 9, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 5, 10, 191, 8, 10, 10, 10, 12, 10, 194, 9, 10, 1, 11, 3, 11, 197, 8, 11, 1, 11, 1, 11, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 5, 12, 209, 8, 12, 10, 12, 12, 12, 212, 9, 12, 1, 13, 3, 13, 215, 8, 13, 1, 13, 1, 13, 1, 14, 3, 14, 220, 8, 14, 1, 14, 1, 14, 1, 14, 3, 14, 225, 8, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 3, 14, 233, 8, 14, 1, 14, 0, 3, 8, 10, 14, 15, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 0, 5, 1, 0, 3, 9, 1, 0, 25, 27, 2, 0, 20, 20, 24, 24, 2, 0, 1, 1, 18, 18, 2, 0, 2, 2, 12, 12, 263, 0, 30, 1, 0, 0, 0, 2, 33, 1, 0, 0, 0, 4, 41, 1, 0, 0, 0, 6, 49, 1, 0, 0, 0, 8, 57, 1, 0, 0, 0, 10, 68, 1, 0, 0, 0, 12, 95, 1, 0, 0, 0, 14, 97, 1, 0, 0, 0, 16, 172, 1, 0, 0, 0, 18, 174, 1, 0, 0, 0, 20, 182, 1, 0, 0, 0, 22, 196, 1, 0, 0, 0, 24, 200, 1, 0, 0, 0, 26, 214, 1, 0, 0, 0, 28, 232, 1, 0, 0, 0, 30, 31, 3, 2, 1, 0, 31, 32, 5, 0, 0, 1, 32, 1, 1, 0, 0, 0, 33, 39, 3, 4, 2, 0, 34, 35, 5, 22, 0, 0, 35, 36, 3, 4, 2, 0, 36, 37, 5, 23, 0, 0, 37, 38, 3, 2, 1, 0, 38, 40, 1, 0, 0, 0, 39, 34, 1, 0, 0, 0, 39, 40, 1, 0, 0, 0, 40, 3, 1, 0, 0, 0, 41, 46, 3, 6, 3, 0, 42, 43, 5, 11, 0, 0, 43, 45, 3, 6, 3, 0, 44, 42, 1, 0, 0, 0, 45, 48, 1, 0, 0, 0, 46, 44, 1, 0, 0, 0, 46, 47, 1, 0, 0, 0, 47, 5, 1, 0, 0, 0, 48, 46, 1, 0, 0, 0, 49, 54, 3, 8, 4, 0, 50, 51, 5, 10, 0, 0, 51, 53, 3, 8, 4, 0, 52, 50, 1, 0, 0, 0, 53, 56, 1, 0, 0, 0, 54, 52, 1, 0, 0, 0, 54, 55, 1, 0, 0, 0, 55, 7, 1, 0, 0, 0, 56, 54, 1, 0, 0, 0, 57, 58, 6, 4, -1, 0, 58, 59, 3, 10, 5, 0, 59, 65, 1, 0, 0, 0, 60, 61, 10, 1, 0, 0, 61, 62, 7, 0, 0, 0, 62, 64, 3, 8, 4, 2, 63, 60, 1, 0, 0, 0, 64, 67, 1, 0, 0, 0, 65, 63, 1, 0, 0, 0, 65, 66, 1, 0, 0, 0, 66, 9, 1, 0, 0, 0, 67, 65, 1, 0, 0, 0, 68, 69, 6, 5, -1, 0, 69, 70, 3, 12, 6, 0, 70, 79, 1, 0, 0, 0, 71, 72, 10, 2, 0, 0, 72, 73, 7, 1, 0, 0, 73, 78, 3, 10, 5, 3, 74, 75, 10, 1, 0, 0, 75, 76, 7, 2, 0, 0, 76, 78, 3, 10, 5, 2, 77, 71, 1, 0, 0, 0, 77, 74, 1, 0, 0, 0, 78, 81, 1, 0, 0, 0, 79, 77, 1, 0, 0, 0, 79, 80, 1, 0, 0, 0, 80, 11, 1, 0, 0, 0, 81, 79, 1, 0, 0, 0, 82, 96, 3, 14, 7, 0, 83, 85, 5, 21, 0, 0, 84, 83, 1, 0, 0, 0, 85, 86, 1, 0, 0, 0, 86, 84, 1, 0, 0, 0, 86, 87, 1, 0, 0, 0, 87, 88, 1, 0, 0, 0, 88, 96, 3, 14, 7, 0, 89, 91, 5, 20, 0, 0, 90, 89, 1, 0, 0, 0, 91, 92, 1, 0, 0, 0, 92, 90, 1, 0, 0, 0, 92, 93, 1, 0, 0, 0, 93, 94, 1, 0, 0, 0, 94, 96, 3, 14, 7, 0, 95, 82, 1, 0, 0, 0, 95, 84, 1, 0, 0, 0, 95, 90, 1, 0, 0, 0, 96, 13, 1, 0, 0, 0, 97, 98, 6, 7, -1, 0, 98, 99, 3, 16, 8, 0, 99, 118, 1, 0, 0, 0, 100, 101, 10, 3, 0, 0, 101, 102, 7, 3, 0, 0, 102, 117, 5, 38, 0, 0, 103, 104, 10, 2, 0, 0, 104, 105, 5, 18, 0, 0, 105, 106, 5, 38, 0, 0, 106, 108, 5, 16, 0, 0, 107, 109, 3, 18, 9, 0, 108, 107, 1, 0, 0, 0, 108, 109, 1, 0, 0, 0, 109, 110, 1, 0, 0, 0, 110, 117, 5, 17, 0, 0, 111, 112, 10, 1, 0, 0, 112, 113, 7, 4, 0, 0, 113, 114, 3, 2, 1, 0, 114, 115, 5, 13, 0, 0, 115, 117, 1, 0, 0, 0, 116, 100, 1, 0, 0, 0, 116, 103, 1, 0, 0, 0, 116, 111, 1, 0, 0, 0, 117, 120, 1, 0, 0, 0, 118, 116, 1, 0, 0, 0, 118, 119, 1, 0, 0, 0, 119, 15, 1, 0, 0, 0, 120, 118, 1, 0, 0, 0, 121, 123, 5, 18, 0, 0, 122, 121, 1, 0, 0, 0, 122, 123, 1, 0, 0, 0, 123, 124, 1, 0, 0, 0, 124, 130, 5, 38, 0, 0, 125, 127, 5, 16, 0, 0, 126, 128, 3, 18, 9, 0, 127, 126, 1, 0, 0, 0, 127, 128, 1, 0, 0, 0, 128, 129, 1, 0, 0, 0, 129, 131, 5, 17, 0, 0, 130, 125, 1, 0, 0, 0, 130, 131, 1, 0, 0, 0, 131, 173, 1, 0, 0, 0, 132, 133, 5, 16, 0, 0, 133, 134, 3, 2, 1, 0, 134, 135, 5, 17, 0, 0, 135, 173, 1, 0, 0, 0, 136, 138, 5, 12, 0, 0, 137, 139, 3, 18, 9, 0, 138, 137, 1, 0, 0, 0, 138, 139, 1, 0, 0, 0, 139, 141, 1, 0, 0, 0, 140, 142, 5, 19, 0, 0, 141, 140, 1, 0, 0, 0, 141, 142, 1, 0, 0, 0, 142, 143, 1, 0, 0, 0, 143, 173, 5, 13, 0, 0, 144, 146, 5, 14, 0, 0, 145, 147, 3, 24, 12, 0, 146, 145, 1, 0, 0, 0, 146, 147, 1, 0, 0, 0, 147, 149, 1, 0, 0, 0, 148, 150, 5, 19, 0, 0, 149, 148, 1, 0, 0, 0, 149, 150, 1, 0, 0, 0, 150, 151, 1, 0, 0, 0, 151, 173, 5, 15, 0, 0, 152, 154, 5, 18, 0, 0, 153, 152, 1, 0, 0, 0, 153, 154, 1, 0, 0, 0, 154, 155, 1, 0, 0, 0, 155, 160, 5, 38, 0, 0, 156, 157, 5, 18, 0, 0, 157, 159, 5, 38, 0, 0, 158, 156, 1, 0, 0, 0, 159, 162, 1, 0, 0, 0, 160, 158, 1, 0, 0, 0, 160, 161, 1, 0, 0, 0, 161, 163, 1, 0, 0, 0, 162, 160, 1, 0, 0, 0, 163, 165, 5, 14, 0, 0, 164, 166, 3, 20, 10, 0, 165, 164, 1, 0, 0, 0, 165, 166, 1, 0, 0, 0, 166, 168, 1, 0, 0, 0, 167, 169, 5, 19, 0, 0, 168, 167, 1, 0, 0, 0, 168, 169, 1, 0, 0, 0, 169, 170, 1, 0, 0, 0, 170, 173, 5, 15, 0, 0, 171, 173, 3, 28, 14, 0, 172, 122, 1, 0, 0, 0, 172, 132, 1, 0, 0, 0, 172, 136, 1, 0, 0, 0, 172, 144, 1, 0, 0, 0, 172, 153, 1, 0, 0, 0, 172, 171, 1, 0, 0, 0, 173, 17, 1, 0, 0, 0, 174, 179, 3, 2, 1, 0, 175, 176, 5, 19, 0, 0, 176, 178, 3, 2, 1, 0, 177, 175, 1, 0, 0, 0, 178, 181, 1, 0, 0, 0, 179, 177, 1, 0, 0, 0, 179, 180, 1, 0, 0, 0, 180, 19, 1, 0, 0, 0, 181, 179, 1, 0, 0, 0, 182, 183, 3, 22, 11, 0, 183, 184, 5, 23, 0, 0, 184, 192, 3, 2, 1, 0, 185, 186, 5, 19, 0, 0, 186, 187, 3, 22, 11, 0, 187, 188, 5, 23, 0, 0, 188, 189, 3, 2, 1, 0, 189, 191, 1, 0, 0, 0, 190, 185, 1, 0, 0, 0, 191, 194, 1, 0, 0, 0, 192, 190, 1, 0, 0, 0, 192, 193, 1, 0, 0, 0, 193, 21, 1, 0, 0, 0, 194, 192, 1, 0, 0, 0, 195, 197, 5, 22, 0, 0, 196, 195, 1, 0, 0, 0, 196, 197, 1, 0, 0, 0, 197, 198, 1, 0, 0, 0, 198, 199, 5, 38, 0, 0, 199, 23, 1, 0, 0, 0, 200, 201, 3, 26, 13, 0, 201, 202, 5, 23, 0, 0, 202, 210, 3, 2, 1, 0, 203, 204, 5, 19, 0, 0, 204, 205, 3, 26, 13, 0, 205, 206, 5, 23, 0, 0, 206, 207, 3, 2, 1, 0, 207, 209, 1, 0, 0, 0, 208, 203, 1, 0, 0, 0, 209, 212, 1, 0, 0, 0, 210, 208, 1, 0, 0, 0, 210, 211, 1, 0, 0, 0, 211, 25, 1, 0, 0, 0, 212, 210, 1, 0, 0, 0, 213, 215, 5, 22, 0, 0, 214, 213, 1, 0, 0, 0, 214, 215, 1, 0, 0, 0, 215, 216, 1, 0, 0, 0, 216, 217, 3, 2, 1, 0, 217, 27, 1, 0, 0, 0, 218, 220, 5, 20, 0, 0, 219, 218, 1, 0, 0, 0, 219, 220, 1, 0, 0, 0, 220, 221, 1, 0, 0, 0, 221, 233, 5, 34, 0, 0, 222, 233, 5, 35, 0, 0, 223, 225, 5, 20, 0, 0, 224, 223, 1, 0, 0, 0, 224, 225, 1, 0, 0, 0, 225, 226, 1, 0, 0, 0, 226, 233, 5, 33, 0, 0, 227, 233, 5, 36, 0, 0, 228, 233, 5, 37, 0, 0, 229, 233, 5, 28, 0, 0, 230, 233, 5, 29, 0, 0, 231, 233, 5, 30, 0, 0, 232, 219, 1, 0, 0, 0, 232, 222, 1, 0, 0, 0, 232, 224, 1, 0, 0, 0, 232, 227, 1, 0, 0, 0, 232, 228, 1, 0, 0, 0, 232, 229, 1, 0, 0, 0, 232, 230, 1, 0, 0, 0, 232, 231, 1, 0, 0, 0, 233, 29, 1, 0, 0, 0, 32, 39, 46, 54, 65, 77, 79, 86, 92, 95, 108, 116, 118, 122, 127, 130, 138, 141, 146, 149, 153, 160, 165, 168, 172, 179, 192, 196, 210, 214, 219, 224, 232]
\ No newline at end of file
+[4, 1, 36, 251, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 42, 8, 1, 1, 2, 1, 2, 1, 2, 5, 2, 47, 8, 2, 10, 2, 12, 2, 50, 9, 2, 1, 3, 1, 3, 1, 3, 5, 3, 55, 8, 3, 10, 3, 12, 3, 58, 9, 3, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 5, 4, 66, 8, 4, 10, 4, 12, 4, 69, 9, 4, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 5, 5, 80, 8, 5, 10, 5, 12, 5, 83, 9, 5, 1, 6, 1, 6, 4, 6, 87, 8, 6, 11, 6, 12, 6, 88, 1, 6, 1, 6, 4, 6, 93, 8, 6, 11, 6, 12, 6, 94, 1, 6, 3, 6, 98, 8, 6, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 3, 7, 106, 8, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 3, 7, 114, 8, 7, 1, 7, 1, 7, 1, 7, 1, 7, 3, 7, 120, 8, 7, 1, 7, 1, 7, 1, 7, 5, 7, 125, 8, 7, 10, 7, 12, 7, 128, 9, 7, 1, 8, 3, 8, 131, 8, 8, 1, 8, 1, 8, 1, 8, 3, 8, 136, 8, 8, 1, 8, 3, 8, 139, 8, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 3, 8, 147, 8, 8, 1, 8, 3, 8, 150, 8, 8, 1, 8, 1, 8, 1, 8, 3, 8, 155, 8, 8, 1, 8, 3, 8, 158, 8, 8, 1, 8, 1, 8, 3, 8, 162, 8, 8, 1, 8, 1, 8, 1, 8, 5, 8, 167, 8, 8, 10, 8, 12, 8, 170, 9, 8, 1, 8, 1, 8, 3, 8, 174, 8, 8, 1, 8, 3, 8, 177, 8, 8, 1, 8, 1, 8, 3, 8, 181, 8, 8, 1, 9, 1, 9, 1, 9, 5, 9, 186, 8, 9, 10, 9, 12, 9, 189, 9, 9, 1, 10, 1, 10, 1, 10, 5, 10, 194, 8, 10, 10, 10, 12, 10, 197, 9, 10, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 5, 11, 207, 8, 11, 10, 11, 12, 11, 210, 9, 11, 1, 12, 3, 12, 213, 8, 12, 1, 12, 1, 12, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 5, 13, 225, 8, 13, 10, 13, 12, 13, 228, 9, 13, 1, 14, 3, 14, 231, 8, 14, 1, 14, 1, 14, 1, 15, 3, 15, 236, 8, 15, 1, 15, 1, 15, 1, 15, 3, 15, 241, 8, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 3, 15, 249, 8, 15, 1, 15, 0, 3, 8, 10, 14, 16, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 0, 3, 1, 0, 1, 7, 1, 0, 23, 25, 2, 0, 18, 18, 22, 22, 281, 0, 32, 1, 0, 0, 0, 2, 35, 1, 0, 0, 0, 4, 43, 1, 0, 0, 0, 6, 51, 1, 0, 0, 0, 8, 59, 1, 0, 0, 0, 10, 70, 1, 0, 0, 0, 12, 97, 1, 0, 0, 0, 14, 99, 1, 0, 0, 0, 16, 180, 1, 0, 0, 0, 18, 182, 1, 0, 0, 0, 20, 190, 1, 0, 0, 0, 22, 198, 1, 0, 0, 0, 24, 212, 1, 0, 0, 0, 26, 216, 1, 0, 0, 0, 28, 230, 1, 0, 0, 0, 30, 248, 1, 0, 0, 0, 32, 33, 3, 2, 1, 0, 33, 34, 5, 0, 0, 1, 34, 1, 1, 0, 0, 0, 35, 41, 3, 4, 2, 0, 36, 37, 5, 20, 0, 0, 37, 38, 3, 4, 2, 0, 38, 39, 5, 21, 0, 0, 39, 40, 3, 2, 1, 0, 40, 42, 1, 0, 0, 0, 41, 36, 1, 0, 0, 0, 41, 42, 1, 0, 0, 0, 42, 3, 1, 0, 0, 0, 43, 48, 3, 6, 3, 0, 44, 45, 5, 9, 0, 0, 45, 47, 3, 6, 3, 0, 46, 44, 1, 0, 0, 0, 47, 50, 1, 0, 0, 0, 48, 46, 1, 0, 0, 0, 48, 49, 1, 0, 0, 0, 49, 5, 1, 0, 0, 0, 50, 48, 1, 0, 0, 0, 51, 56, 3, 8, 4, 0, 52, 53, 5, 8, 0, 0, 53, 55, 3, 8, 4, 0, 54, 52, 1, 0, 0, 0, 55, 58, 1, 0, 0, 0, 56, 54, 1, 0, 0, 0, 56, 57, 1, 0, 0, 0, 57, 7, 1, 0, 0, 0, 58, 56, 1, 0, 0, 0, 59, 60, 6, 4, -1, 0, 60, 61, 3, 10, 5, 0, 61, 67, 1, 0, 0, 0, 62, 63, 10, 1, 0, 0, 63, 64, 7, 0, 0, 0, 64, 66, 3, 8, 4, 2, 65, 62, 1, 0, 0, 0, 66, 69, 1, 0, 0, 0, 67, 65, 1, 0, 0, 0, 67, 68, 1, 0, 0, 0, 68, 9, 1, 0, 0, 0, 69, 67, 1, 0, 0, 0, 70, 71, 6, 5, -1, 0, 71, 72, 3, 12, 6, 0, 72, 81, 1, 0, 0, 0, 73, 74, 10, 2, 0, 0, 74, 75, 7, 1, 0, 0, 75, 80, 3, 10, 5, 3, 76, 77, 10, 1, 0, 0, 77, 78, 7, 2, 0, 0, 78, 80, 3, 10, 5, 2, 79, 73, 1, 0, 0, 0, 79, 76, 1, 0, 0, 0, 80, 83, 1, 0, 0, 0, 81, 79, 1, 0, 0, 0, 81, 82, 1, 0, 0, 0, 82, 11, 1, 0, 0, 0, 83, 81, 1, 0, 0, 0, 84, 98, 3, 14, 7, 0, 85, 87, 5, 19, 0, 0, 86, 85, 1, 0, 0, 0, 87, 88, 1, 0, 0, 0, 88, 86, 1, 0, 0, 0, 88, 89, 1, 0, 0, 0, 89, 90, 1, 0, 0, 0, 90, 98, 3, 14, 7, 0, 91, 93, 5, 18, 0, 0, 92, 91, 1, 0, 0, 0, 93, 94, 1, 0, 0, 0, 94, 92, 1, 0, 0, 0, 94, 95, 1, 0, 0, 0, 95, 96, 1, 0, 0, 0, 96, 98, 3, 14, 7, 0, 97, 84, 1, 0, 0, 0, 97, 86, 1, 0, 0, 0, 97, 92, 1, 0, 0, 0, 98, 13, 1, 0, 0, 0, 99, 100, 6, 7, -1, 0, 100, 101, 3, 16, 8, 0, 101, 126, 1, 0, 0, 0, 102, 103, 10, 3, 0, 0, 103, 105, 5, 16, 0, 0, 104, 106, 5, 20, 0, 0, 105, 104, 1, 0, 0, 0, 105, 106, 1, 0, 0, 0, 106, 107, 1, 0, 0, 0, 107, 125, 5, 36, 0, 0, 108, 109, 10, 2, 0, 0, 109, 110, 5, 16, 0, 0, 110, 111, 5, 36, 0, 0, 111, 113, 5, 14, 0, 0, 112, 114, 3, 18, 9, 0, 113, 112, 1, 0, 0, 0, 113, 114, 1, 0, 0, 0, 114, 115, 1, 0, 0, 0, 115, 125, 5, 15, 0, 0, 116, 117, 10, 1, 0, 0, 117, 119, 5, 10, 0, 0, 118, 120, 5, 20, 0, 0, 119, 118, 1, 0, 0, 0, 119, 120, 1, 0, 0, 0, 120, 121, 1, 0, 0, 0, 121, 122, 3, 2, 1, 0, 122, 123, 5, 11, 0, 0, 123, 125, 1, 0, 0, 0, 124, 102, 1, 0, 0, 0, 124, 108, 1, 0, 0, 0, 124, 116, 1, 0, 0, 0, 125, 128, 1, 0, 0, 0, 126, 124, 1, 0, 0, 0, 126, 127, 1, 0, 0, 0, 127, 15, 1, 0, 0, 0, 128, 126, 1, 0, 0, 0, 129, 131, 5, 16, 0, 0, 130, 129, 1, 0, 0, 0, 130, 131, 1, 0, 0, 0, 131, 132, 1, 0, 0, 0, 132, 138, 5, 36, 0, 0, 133, 135, 5, 14, 0, 0, 134, 136, 3, 18, 9, 0, 135, 134, 1, 0, 0, 0, 135, 136, 1, 0, 0, 0, 136, 137, 1, 0, 0, 0, 137, 139, 5, 15, 0, 0, 138, 133, 1, 0, 0, 0, 138, 139, 1, 0, 0, 0, 139, 181, 1, 0, 0, 0, 140, 141, 5, 14, 0, 0, 141, 142, 3, 2, 1, 0, 142, 143, 5, 15, 0, 0, 143, 181, 1, 0, 0, 0, 144, 146, 5, 10, 0, 0, 145, 147, 3, 20, 10, 0, 146, 145, 1, 0, 0, 0, 146, 147, 1, 0, 0, 0, 147, 149, 1, 0, 0, 0, 148, 150, 5, 17, 0, 0, 149, 148, 1, 0, 0, 0, 149, 150, 1, 0, 0, 0, 150, 151, 1, 0, 0, 0, 151, 181, 5, 11, 0, 0, 152, 154, 5, 12, 0, 0, 153, 155, 3, 26, 13, 0, 154, 153, 1, 0, 0, 0, 154, 155, 1, 0, 0, 0, 155, 157, 1, 0, 0, 0, 156, 158, 5, 17, 0, 0, 157, 156, 1, 0, 0, 0, 157, 158, 1, 0, 0, 0, 158, 159, 1, 0, 0, 0, 159, 181, 5, 13, 0, 0, 160, 162, 5, 16, 0, 0, 161, 160, 1, 0, 0, 0, 161, 162, 1, 0, 0, 0, 162, 163, 1, 0, 0, 0, 163, 168, 5, 36, 0, 0, 164, 165, 5, 16, 0, 0, 165, 167, 5, 36, 0, 0, 166, 164, 1, 0, 0, 0, 167, 170, 1, 0, 0, 0, 168, 166, 1, 0, 0, 0, 168, 169, 1, 0, 0, 0, 169, 171, 1, 0, 0, 0, 170, 168, 1, 0, 0, 0, 171, 173, 5, 12, 0, 0, 172, 174, 3, 22, 11, 0, 173, 172, 1, 0, 0, 0, 173, 174, 1, 0, 0, 0, 174, 176, 1, 0, 0, 0, 175, 177, 5, 17, 0, 0, 176, 175, 1, 0, 0, 0, 176, 177, 1, 0, 0, 0, 177, 178, 1, 0, 0, 0, 178, 181, 5, 13, 0, 0, 179, 181, 3, 30, 15, 0, 180, 130, 1, 0, 0, 0, 180, 140, 1, 0, 0, 0, 180, 144, 1, 0, 0, 0, 180, 152, 1, 0, 0, 0, 180, 161, 1, 0, 0, 0, 180, 179, 1, 0, 0, 0, 181, 17, 1, 0, 0, 0, 182, 187, 3, 2, 1, 0, 183, 184, 5, 17, 0, 0, 184, 186, 3, 2, 1, 0, 185, 183, 1, 0, 0, 0, 186, 189, 1, 0, 0, 0, 187, 185, 1, 0, 0, 0, 187, 188, 1, 0, 0, 0, 188, 19, 1, 0, 0, 0, 189, 187, 1, 0, 0, 0, 190, 195, 3, 28, 14, 0, 191, 192, 5, 17, 0, 0, 192, 194, 3, 28, 14, 0, 193, 191, 1, 0, 0, 0, 194, 197, 1, 0, 0, 0, 195, 193, 1, 0, 0, 0, 195, 196, 1, 0, 0, 0, 196, 21, 1, 0, 0, 0, 197, 195, 1, 0, 0, 0, 198, 199, 3, 24, 12, 0, 199, 200, 5, 21, 0, 0, 200, 208, 3, 2, 1, 0, 201, 202, 5, 17, 0, 0, 202, 203, 3, 24, 12, 0, 203, 204, 5, 21, 0, 0, 204, 205, 3, 2, 1, 0, 205, 207, 1, 0, 0, 0, 206, 201, 1, 0, 0, 0, 207, 210, 1, 0, 0, 0, 208, 206, 1, 0, 0, 0, 208, 209, 1, 0, 0, 0, 209, 23, 1, 0, 0, 0, 210, 208, 1, 0, 0, 0, 211, 213, 5, 20, 0, 0, 212, 211, 1, 0, 0, 0, 212, 213, 1, 0, 0, 0, 213, 214, 1, 0, 0, 0, 214, 215, 5, 36, 0, 0, 215, 25, 1, 0, 0, 0, 216, 217, 3, 28, 14, 0, 217, 218, 5, 21, 0, 0, 218, 226, 3, 2, 1, 0, 219, 220, 5, 17, 0, 0, 220, 221, 3, 28, 14, 0, 221, 222, 5, 21, 0, 0, 222, 223, 3, 2, 1, 0, 223, 225, 1, 0, 0, 0, 224, 219, 1, 0, 0, 0, 225, 228, 1, 0, 0, 0, 226, 224, 1, 0, 0, 0, 226, 227, 1, 0, 0, 0, 227, 27, 1, 0, 0, 0, 228, 226, 1, 0, 0, 0, 229, 231, 5, 20, 0, 0, 230, 229, 1, 0, 0, 0, 230, 231, 1, 0, 0, 0, 231, 232, 1, 0, 0, 0, 232, 233, 3, 2, 1, 0, 233, 29, 1, 0, 0, 0, 234, 236, 5, 18, 0, 0, 235, 234, 1, 0, 0, 0, 235, 236, 1, 0, 0, 0, 236, 237, 1, 0, 0, 0, 237, 249, 5, 32, 0, 0, 238, 249, 5, 33, 0, 0, 239, 241, 5, 18, 0, 0, 240, 239, 1, 0, 0, 0, 240, 241, 1, 0, 0, 0, 241, 242, 1, 0, 0, 0, 242, 249, 5, 31, 0, 0, 243, 249, 5, 34, 0, 0, 244, 249, 5, 35, 0, 0, 245, 249, 5, 26, 0, 0, 246, 249, 5, 27, 0, 0, 247, 249, 5, 28, 0, 0, 248, 235, 1, 0, 0, 0, 248, 238, 1, 0, 0, 0, 248, 240, 1, 0, 0, 0, 248, 243, 1, 0, 0, 0, 248, 244, 1, 0, 0, 0, 248, 245, 1, 0, 0, 0, 248, 246, 1, 0, 0, 0, 248, 247, 1, 0, 0, 0, 249, 31, 1, 0, 0, 0, 35, 41, 48, 56, 67, 79, 81, 88, 94, 97, 105, 113, 119, 124, 126, 130, 135, 138, 146, 149, 154, 157, 161, 168, 173, 176, 180, 187, 195, 208, 212, 226, 230, 235, 240, 248]
\ No newline at end of file
diff --git a/vendor/github.com/google/cel-go/parser/gen/CEL.tokens b/vendor/github.com/google/cel-go/parser/gen/CEL.tokens
index c80bfb323..b305bdad3 100644
--- a/vendor/github.com/google/cel-go/parser/gen/CEL.tokens
+++ b/vendor/github.com/google/cel-go/parser/gen/CEL.tokens
@@ -1,68 +1,64 @@
-T__0=1
-T__1=2
-EQUALS=3
-NOT_EQUALS=4
-IN=5
-LESS=6
-LESS_EQUALS=7
-GREATER_EQUALS=8
-GREATER=9
-LOGICAL_AND=10
-LOGICAL_OR=11
-LBRACKET=12
-RPRACKET=13
-LBRACE=14
-RBRACE=15
-LPAREN=16
-RPAREN=17
-DOT=18
-COMMA=19
-MINUS=20
-EXCLAM=21
-QUESTIONMARK=22
-COLON=23
-PLUS=24
-STAR=25
-SLASH=26
-PERCENT=27
-CEL_TRUE=28
-CEL_FALSE=29
-NUL=30
-WHITESPACE=31
-COMMENT=32
-NUM_FLOAT=33
-NUM_INT=34
-NUM_UINT=35
-STRING=36
-BYTES=37
-IDENTIFIER=38
-'.?'=1
-'[?'=2
-'=='=3
-'!='=4
-'in'=5
-'<'=6
-'<='=7
-'>='=8
-'>'=9
-'&&'=10
-'||'=11
-'['=12
-']'=13
-'{'=14
-'}'=15
-'('=16
-')'=17
-'.'=18
-','=19
-'-'=20
-'!'=21
-'?'=22
-':'=23
-'+'=24
-'*'=25
-'/'=26
-'%'=27
-'true'=28
-'false'=29
-'null'=30
+EQUALS=1
+NOT_EQUALS=2
+IN=3
+LESS=4
+LESS_EQUALS=5
+GREATER_EQUALS=6
+GREATER=7
+LOGICAL_AND=8
+LOGICAL_OR=9
+LBRACKET=10
+RPRACKET=11
+LBRACE=12
+RBRACE=13
+LPAREN=14
+RPAREN=15
+DOT=16
+COMMA=17
+MINUS=18
+EXCLAM=19
+QUESTIONMARK=20
+COLON=21
+PLUS=22
+STAR=23
+SLASH=24
+PERCENT=25
+CEL_TRUE=26
+CEL_FALSE=27
+NUL=28
+WHITESPACE=29
+COMMENT=30
+NUM_FLOAT=31
+NUM_INT=32
+NUM_UINT=33
+STRING=34
+BYTES=35
+IDENTIFIER=36
+'=='=1
+'!='=2
+'in'=3
+'<'=4
+'<='=5
+'>='=6
+'>'=7
+'&&'=8
+'||'=9
+'['=10
+']'=11
+'{'=12
+'}'=13
+'('=14
+')'=15
+'.'=16
+','=17
+'-'=18
+'!'=19
+'?'=20
+':'=21
+'+'=22
+'*'=23
+'/'=24
+'%'=25
+'true'=26
+'false'=27
+'null'=28
diff --git a/vendor/github.com/google/cel-go/parser/gen/CELLexer.interp b/vendor/github.com/google/cel-go/parser/gen/CELLexer.interp
index b94305cea..26e7f471e 100644
--- a/vendor/github.com/google/cel-go/parser/gen/CELLexer.interp
+++ b/vendor/github.com/google/cel-go/parser/gen/CELLexer.interp
@@ -1,7 +1,5 @@
token literal names:
null
-'.?'
-'[?'
'=='
'!='
'in'
@@ -41,8 +39,6 @@ null
token symbolic names:
null
-null
-null
EQUALS
NOT_EQUALS
IN
@@ -81,8 +77,6 @@ BYTES
IDENTIFIER
rule names:
-T__0
-T__1
EQUALS
NOT_EQUALS
IN
@@ -139,4 +133,4 @@ mode names:
DEFAULT_MODE
atn:
-[4, 0, 38, 433, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, 20, 2, 21, 7, 21, 2, 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25, 2, 26, 7, 26, 2, 27, 7, 27, 2, 28, 7, 28, 2, 29, 7, 29, 2, 30, 7, 30, 2, 31, 7, 31, 2, 32, 7, 32, 2, 33, 7, 33, 2, 34, 7, 34, 2, 35, 7, 35, 2, 36, 7, 36, 2, 37, 7, 37, 2, 38, 7, 38, 2, 39, 7, 39, 2, 40, 7, 40, 2, 41, 7, 41, 2, 42, 7, 42, 2, 43, 7, 43, 2, 44, 7, 44, 2, 45, 7, 45, 2, 46, 7, 46, 2, 47, 7, 47, 2, 48, 7, 48, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 2, 1, 3, 1, 3, 1, 3, 1, 4, 1, 4, 1, 4, 1, 5, 1, 5, 1, 6, 1, 6, 1, 6, 1, 7, 1, 7, 1, 7, 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 1, 10, 1, 10, 1, 10, 1, 11, 1, 11, 1, 12, 1, 12, 1, 13, 1, 13, 1, 14, 1, 14, 1, 15, 1, 15, 1, 16, 1, 16, 1, 17, 1, 17, 1, 18, 1, 18, 1, 19, 1, 19, 1, 20, 1, 20, 1, 21, 1, 21, 1, 22, 1, 22, 1, 23, 1, 23, 1, 24, 1, 24, 1, 25, 1, 25, 1, 26, 1, 26, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 28, 1, 28, 1, 28, 1, 28, 1, 28, 1, 28, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 30, 1, 30, 1, 31, 1, 31, 1, 32, 1, 32, 1, 33, 1, 33, 3, 33, 187, 8, 33, 1, 33, 4, 33, 190, 8, 33, 11, 33, 12, 33, 191, 1, 34, 1, 34, 1, 35, 1, 35, 1, 36, 1, 36, 1, 36, 1, 36, 3, 36, 202, 8, 36, 1, 37, 1, 37, 1, 37, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 3, 40, 235, 8, 40, 1, 41, 4, 41, 238, 8, 41, 11, 41, 12, 41, 239, 1, 41, 1, 41, 1, 42, 1, 42, 1, 42, 1, 42, 5, 42, 248, 8, 42, 10, 42, 12, 42, 251, 9, 42, 1, 42, 1, 42, 1, 43, 4, 43, 256, 8, 43, 11, 43, 12, 43, 257, 1, 43, 1, 43, 4, 43, 262, 8, 43, 11, 43, 12, 43, 263, 1, 43, 3, 43, 267, 8, 43, 1, 43, 4, 43, 270, 8, 43, 11, 43, 12, 43, 271, 1, 43, 1, 43, 1, 43, 1, 43, 4, 43, 278, 8, 43, 11, 43, 12, 43, 279, 1, 43, 3, 43, 283, 8, 43, 3, 43, 285, 8, 43, 1, 44, 4, 44, 288, 8, 44, 11, 44, 12, 44, 289, 1, 44, 1, 44, 1, 44, 1, 44, 4, 44, 296, 8, 44, 11, 44, 12, 44, 297, 3, 44, 300, 8, 44, 1, 45, 4, 45, 303, 8, 45, 11, 45, 12, 45, 304, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 4, 45, 313, 8, 45, 11, 45, 12, 45, 314, 1, 45, 1, 45, 3, 45, 319, 8, 45, 1, 46, 1, 46, 1, 46, 5, 46, 324, 8, 46, 10, 46, 12, 46, 327, 9, 46, 1, 46, 1, 46, 1, 46, 1, 46, 5, 46, 333, 8, 46, 10, 46, 12, 46, 336, 9, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 5, 46, 345, 8, 46, 10, 46, 12, 46, 348, 9, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 5, 46, 359, 8, 46, 10, 46, 12, 46, 362, 9, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 5, 46, 370, 8, 46, 10, 46, 12, 46, 373, 9, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 5, 46, 380, 8, 46, 10, 46, 12, 46, 383, 9, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 5, 46, 393, 8, 46, 10, 46, 12, 46, 396, 9, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 5, 46, 408, 8, 46, 10, 46, 12, 46, 411, 9, 46, 1, 46, 1, 46, 1, 46, 1, 46, 3, 46, 417, 8, 46, 1, 47, 1, 47, 1, 47, 1, 48, 1, 48, 3, 48, 424, 8, 48, 1, 48, 1, 48, 1, 48, 5, 48, 429, 8, 48, 10, 48, 12, 48, 432, 9, 48, 4, 346, 360, 394, 409, 0, 49, 1, 1, 3, 2, 5, 3, 7, 4, 9, 5, 11, 6, 13, 7, 15, 8, 17, 9, 19, 10, 21, 11, 23, 12, 25, 13, 27, 14, 29, 15, 31, 16, 33, 17, 35, 18, 37, 19, 39, 20, 41, 21, 43, 22, 45, 23, 47, 24, 49, 25, 51, 26, 53, 27, 55, 28, 57, 29, 59, 30, 61, 0, 63, 0, 65, 0, 67, 0, 69, 0, 71, 0, 73, 0, 75, 0, 77, 0, 79, 0, 81, 0, 83, 31, 85, 32, 87, 33, 89, 34, 91, 35, 93, 36, 95, 37, 97, 38, 1, 0, 16, 2, 0, 65, 90, 97, 122, 2, 0, 69, 69, 101, 101, 2, 0, 43, 43, 45, 45, 3, 0, 48, 57, 65, 70, 97, 102, 2, 0, 82, 82, 114, 114, 10, 0, 34, 34, 39, 39, 63, 63, 92, 92, 96, 98, 102, 102, 110, 110, 114, 114, 116, 116, 118, 118, 2, 0, 88, 88, 120, 120, 3, 0, 9, 10, 12, 13, 32, 32, 1, 0, 10, 10, 2, 0, 85, 85, 117, 117, 4, 0, 10, 10, 13, 13, 34, 34, 92, 92, 4, 0, 10, 10, 13, 13, 39, 39, 92, 92, 1, 0, 92, 92, 3, 0, 10, 10, 13, 13, 34, 34, 3, 0, 10, 10, 13, 13, 39, 39, 2, 0, 66, 66, 98, 98, 466, 0, 1, 1, 0, 0, 0, 0, 3, 1, 0, 0, 0, 0, 5, 1, 0, 0, 0, 0, 7, 1, 0, 0, 0, 0, 9, 1, 0, 0, 0, 0, 11, 1, 0, 0, 0, 0, 13, 1, 0, 0, 0, 0, 15, 1, 0, 0, 0, 0, 17, 1, 0, 0, 0, 0, 19, 1, 0, 0, 0, 0, 21, 1, 0, 0, 0, 0, 23, 1, 0, 0, 0, 0, 25, 1, 0, 0, 0, 0, 27, 1, 0, 0, 0, 0, 29, 1, 0, 0, 0, 0, 31, 1, 0, 0, 0, 0, 33, 1, 0, 0, 0, 0, 35, 1, 0, 0, 0, 0, 37, 1, 0, 0, 0, 0, 39, 1, 0, 0, 0, 0, 41, 1, 0, 0, 0, 0, 43, 1, 0, 0, 0, 0, 45, 1, 0, 0, 0, 0, 47, 1, 0, 0, 0, 0, 49, 1, 0, 0, 0, 0, 51, 1, 0, 0, 0, 0, 53, 1, 0, 0, 0, 0, 55, 1, 0, 0, 0, 0, 57, 1, 0, 0, 0, 0, 59, 1, 0, 0, 0, 0, 83, 1, 0, 0, 0, 0, 85, 1, 0, 0, 0, 0, 87, 1, 0, 0, 0, 0, 89, 1, 0, 0, 0, 0, 91, 1, 0, 0, 0, 0, 93, 1, 0, 0, 0, 0, 95, 1, 0, 0, 0, 0, 97, 1, 0, 0, 0, 1, 99, 1, 0, 0, 0, 3, 102, 1, 0, 0, 0, 5, 105, 1, 0, 0, 0, 7, 108, 1, 0, 0, 0, 9, 111, 1, 0, 0, 0, 11, 114, 1, 0, 0, 0, 13, 116, 1, 0, 0, 0, 15, 119, 1, 0, 0, 0, 17, 122, 1, 0, 0, 0, 19, 124, 1, 0, 0, 0, 21, 127, 1, 0, 0, 0, 23, 130, 1, 0, 0, 0, 25, 132, 1, 0, 0, 0, 27, 134, 1, 0, 0, 0, 29, 136, 1, 0, 0, 0, 31, 138, 1, 0, 0, 0, 33, 140, 1, 0, 0, 0, 35, 142, 1, 0, 0, 0, 37, 144, 1, 0, 0, 0, 39, 146, 1, 0, 0, 0, 41, 148, 1, 0, 0, 0, 43, 150, 1, 0, 0, 0, 45, 152, 1, 0, 0, 0, 47, 154, 1, 0, 0, 0, 49, 156, 1, 0, 0, 0, 51, 158, 1, 0, 0, 0, 53, 160, 1, 0, 0, 0, 55, 162, 1, 0, 0, 0, 57, 167, 1, 0, 0, 0, 59, 173, 1, 0, 0, 0, 61, 178, 1, 0, 0, 0, 63, 180, 1, 0, 0, 0, 65, 182, 1, 0, 0, 0, 67, 184, 1, 0, 0, 0, 69, 193, 1, 0, 0, 0, 71, 195, 1, 0, 0, 0, 73, 201, 1, 0, 0, 0, 75, 203, 1, 0, 0, 0, 77, 206, 1, 0, 0, 0, 79, 211, 1, 0, 0, 0, 81, 234, 1, 0, 0, 0, 83, 237, 1, 0, 0, 0, 85, 243, 1, 0, 0, 0, 87, 284, 1, 0, 0, 0, 89, 299, 1, 0, 0, 0, 91, 318, 1, 0, 0, 0, 93, 416, 1, 0, 0, 0, 95, 418, 1, 0, 0, 0, 97, 423, 1, 0, 0, 0, 99, 100, 5, 46, 0, 0, 100, 101, 5, 63, 0, 0, 101, 2, 1, 0, 0, 0, 102, 103, 5, 91, 0, 0, 103, 104, 5, 63, 0, 0, 104, 4, 1, 0, 0, 0, 105, 106, 5, 61, 0, 0, 106, 107, 5, 61, 0, 0, 107, 6, 1, 0, 0, 0, 108, 109, 5, 33, 0, 0, 109, 110, 5, 61, 0, 0, 110, 8, 1, 0, 0, 0, 111, 112, 5, 105, 0, 0, 112, 113, 5, 110, 0, 0, 113, 10, 1, 0, 0, 0, 114, 115, 5, 60, 0, 0, 115, 12, 1, 0, 0, 0, 116, 117, 5, 60, 0, 0, 117, 118, 5, 61, 0, 0, 118, 14, 1, 0, 0, 0, 119, 120, 5, 62, 0, 0, 120, 121, 5, 61, 0, 0, 121, 16, 1, 0, 0, 0, 122, 123, 5, 62, 0, 0, 123, 18, 1, 0, 0, 0, 124, 125, 5, 38, 0, 0, 125, 126, 5, 38, 0, 0, 126, 20, 1, 0, 0, 0, 127, 128, 5, 124, 0, 0, 128, 129, 5, 124, 0, 0, 129, 22, 1, 0, 0, 0, 130, 131, 5, 91, 0, 0, 131, 24, 1, 0, 0, 0, 132, 133, 5, 93, 0, 0, 133, 26, 1, 0, 0, 0, 134, 135, 5, 123, 0, 0, 135, 28, 1, 0, 0, 0, 136, 137, 5, 125, 0, 0, 137, 30, 1, 0, 0, 0, 138, 139, 5, 40, 0, 0, 139, 32, 1, 0, 0, 0, 140, 141, 5, 41, 0, 0, 141, 34, 1, 0, 0, 0, 142, 143, 5, 46, 0, 0, 143, 36, 1, 0, 0, 0, 144, 145, 5, 44, 0, 0, 145, 38, 1, 0, 0, 0, 146, 147, 5, 45, 0, 0, 147, 40, 1, 0, 0, 0, 148, 149, 5, 33, 0, 0, 149, 42, 1, 0, 0, 0, 150, 151, 5, 63, 0, 0, 151, 44, 1, 0, 0, 0, 152, 153, 5, 58, 0, 0, 153, 46, 1, 0, 0, 0, 154, 155, 5, 43, 0, 0, 155, 48, 1, 0, 0, 0, 156, 157, 5, 42, 0, 0, 157, 50, 1, 0, 0, 0, 158, 159, 5, 47, 0, 0, 159, 52, 1, 0, 0, 0, 160, 161, 5, 37, 0, 0, 161, 54, 1, 0, 0, 0, 162, 163, 5, 116, 0, 0, 163, 164, 5, 114, 0, 0, 164, 165, 5, 117, 0, 0, 165, 166, 5, 101, 0, 0, 166, 56, 1, 0, 0, 0, 167, 168, 5, 102, 0, 0, 168, 169, 5, 97, 0, 0, 169, 170, 5, 108, 0, 0, 170, 171, 5, 115, 0, 0, 171, 172, 5, 101, 0, 0, 172, 58, 1, 0, 0, 0, 173, 174, 5, 110, 0, 0, 174, 175, 5, 117, 0, 0, 175, 176, 5, 108, 0, 0, 176, 177, 5, 108, 0, 0, 177, 60, 1, 0, 0, 0, 178, 179, 5, 92, 0, 0, 179, 62, 1, 0, 0, 0, 180, 181, 7, 0, 0, 0, 181, 64, 1, 0, 0, 0, 182, 183, 2, 48, 57, 0, 183, 66, 1, 0, 0, 0, 184, 186, 7, 1, 0, 0, 185, 187, 7, 2, 0, 0, 186, 185, 1, 0, 0, 0, 186, 187, 1, 0, 0, 0, 187, 189, 1, 0, 0, 0, 188, 190, 3, 65, 32, 0, 189, 188, 1, 0, 0, 0, 190, 191, 1, 0, 0, 0, 191, 189, 1, 0, 0, 0, 191, 192, 1, 0, 0, 0, 192, 68, 1, 0, 0, 0, 193, 194, 7, 3, 0, 0, 194, 70, 1, 0, 0, 0, 195, 196, 7, 4, 0, 0, 196, 72, 1, 0, 0, 0, 197, 202, 3, 75, 37, 0, 198, 202, 3, 79, 39, 0, 199, 202, 3, 81, 40, 0, 200, 202, 3, 77, 38, 0, 201, 197, 1, 0, 0, 0, 201, 198, 1, 0, 0, 0, 201, 199, 1, 0, 0, 0, 201, 200, 1, 0, 0, 0, 202, 74, 1, 0, 0, 0, 203, 204, 3, 61, 30, 0, 204, 205, 7, 5, 0, 0, 205, 76, 1, 0, 0, 0, 206, 207, 3, 61, 30, 0, 207, 208, 2, 48, 51, 0, 208, 209, 2, 48, 55, 0, 209, 210, 2, 48, 55, 0, 210, 78, 1, 0, 0, 0, 211, 212, 3, 61, 30, 0, 212, 213, 7, 6, 0, 0, 213, 214, 3, 69, 34, 0, 214, 215, 3, 69, 34, 0, 215, 80, 1, 0, 0, 0, 216, 217, 3, 61, 30, 0, 217, 218, 5, 117, 0, 0, 218, 219, 3, 69, 34, 0, 219, 220, 3, 69, 34, 0, 220, 221, 3, 69, 34, 0, 221, 222, 3, 69, 34, 0, 222, 235, 1, 0, 0, 0, 223, 224, 3, 61, 30, 0, 224, 225, 5, 85, 0, 0, 225, 226, 3, 69, 34, 0, 226, 227, 3, 69, 34, 0, 227, 228, 3, 69, 34, 0, 228, 229, 3, 69, 34, 0, 229, 230, 3, 69, 34, 0, 230, 231, 3, 69, 34, 0, 231, 232, 3, 69, 34, 0, 232, 233, 3, 69, 34, 0, 233, 235, 1, 0, 0, 0, 234, 216, 1, 0, 0, 0, 234, 223, 1, 0, 0, 0, 235, 82, 1, 0, 0, 0, 236, 238, 7, 7, 0, 0, 237, 236, 1, 0, 0, 0, 238, 239, 1, 0, 0, 0, 239, 237, 1, 0, 0, 0, 239, 240, 1, 0, 0, 0, 240, 241, 1, 0, 0, 0, 241, 242, 6, 41, 0, 0, 242, 84, 1, 0, 0, 0, 243, 244, 5, 47, 0, 0, 244, 245, 5, 47, 0, 0, 245, 249, 1, 0, 0, 0, 246, 248, 8, 8, 0, 0, 247, 246, 1, 0, 0, 0, 248, 251, 1, 0, 0, 0, 249, 247, 1, 0, 0, 0, 249, 250, 1, 0, 0, 0, 250, 252, 1, 0, 0, 0, 251, 249, 1, 0, 0, 0, 252, 253, 6, 42, 0, 0, 253, 86, 1, 0, 0, 0, 254, 256, 3, 65, 32, 0, 255, 254, 1, 0, 0, 0, 256, 257, 1, 0, 0, 0, 257, 255, 1, 0, 0, 0, 257, 258, 1, 0, 0, 0, 258, 259, 1, 0, 0, 0, 259, 261, 5, 46, 0, 0, 260, 262, 3, 65, 32, 0, 261, 260, 1, 0, 0, 0, 262, 263, 1, 0, 0, 0, 263, 261, 1, 0, 0, 0, 263, 264, 1, 0, 0, 0, 264, 266, 1, 0, 0, 0, 265, 267, 3, 67, 33, 0, 266, 265, 1, 0, 0, 0, 266, 267, 1, 0, 0, 0, 267, 285, 1, 0, 0, 0, 268, 270, 3, 65, 32, 0, 269, 268, 1, 0, 0, 0, 270, 271, 1, 0, 0, 0, 271, 269, 1, 0, 0, 0, 271, 272, 1, 0, 0, 0, 272, 273, 1, 0, 0, 0, 273, 274, 3, 67, 33, 0, 274, 285, 1, 0, 0, 0, 275, 277, 5, 46, 0, 0, 276, 278, 3, 65, 32, 0, 277, 276, 1, 0, 0, 0, 278, 279, 1, 0, 0, 0, 279, 277, 1, 0, 0, 0, 279, 280, 1, 0, 0, 0, 280, 282, 1, 0, 0, 0, 281, 283, 3, 67, 33, 0, 282, 281, 1, 0, 0, 0, 282, 283, 1, 0, 0, 0, 283, 285, 1, 0, 0, 0, 284, 255, 1, 0, 0, 0, 284, 269, 1, 0, 0, 0, 284, 275, 1, 0, 0, 0, 285, 88, 1, 0, 0, 0, 286, 288, 3, 65, 32, 0, 287, 286, 1, 0, 0, 0, 288, 289, 1, 0, 0, 0, 289, 287, 1, 0, 0, 0, 289, 290, 1, 0, 0, 0, 290, 300, 1, 0, 0, 0, 291, 292, 5, 48, 0, 0, 292, 293, 5, 120, 0, 0, 293, 295, 1, 0, 0, 0, 294, 296, 3, 69, 34, 0, 295, 294, 1, 0, 0, 0, 296, 297, 1, 0, 0, 0, 297, 295, 1, 0, 0, 0, 297, 298, 1, 0, 0, 0, 298, 300, 1, 0, 0, 0, 299, 287, 1, 0, 0, 0, 299, 291, 1, 0, 0, 0, 300, 90, 1, 0, 0, 0, 301, 303, 3, 65, 32, 0, 302, 301, 1, 0, 0, 0, 303, 304, 1, 0, 0, 0, 304, 302, 1, 0, 0, 0, 304, 305, 1, 0, 0, 0, 305, 306, 1, 0, 0, 0, 306, 307, 7, 9, 0, 0, 307, 319, 1, 0, 0, 0, 308, 309, 5, 48, 0, 0, 309, 310, 5, 120, 0, 0, 310, 312, 1, 0, 0, 0, 311, 313, 3, 69, 34, 0, 312, 311, 1, 0, 0, 0, 313, 314, 1, 0, 0, 0, 314, 312, 1, 0, 0, 0, 314, 315, 1, 0, 0, 0, 315, 316, 1, 0, 0, 0, 316, 317, 7, 9, 0, 0, 317, 319, 1, 0, 0, 0, 318, 302, 1, 0, 0, 0, 318, 308, 1, 0, 0, 0, 319, 92, 1, 0, 0, 0, 320, 325, 5, 34, 0, 0, 321, 324, 3, 73, 36, 0, 322, 324, 8, 10, 0, 0, 323, 321, 1, 0, 0, 0, 323, 322, 1, 0, 0, 0, 324, 327, 1, 0, 0, 0, 325, 323, 1, 0, 0, 0, 325, 326, 1, 0, 0, 0, 326, 328, 1, 0, 0, 0, 327, 325, 1, 0, 0, 0, 328, 417, 5, 34, 0, 0, 329, 334, 5, 39, 0, 0, 330, 333, 3, 73, 36, 0, 331, 333, 8, 11, 0, 0, 332, 330, 1, 0, 0, 0, 332, 331, 1, 0, 0, 0, 333, 336, 1, 0, 0, 0, 334, 332, 1, 0, 0, 0, 334, 335, 1, 0, 0, 0, 335, 337, 1, 0, 0, 0, 336, 334, 1, 0, 0, 0, 337, 417, 5, 39, 0, 0, 338, 339, 5, 34, 0, 0, 339, 340, 5, 34, 0, 0, 340, 341, 5, 34, 0, 0, 341, 346, 1, 0, 0, 0, 342, 345, 3, 73, 36, 0, 343, 345, 8, 12, 0, 0, 344, 342, 1, 0, 0, 0, 344, 343, 1, 0, 0, 0, 345, 348, 1, 0, 0, 0, 346, 347, 1, 0, 0, 0, 346, 344, 1, 0, 0, 0, 347, 349, 1, 0, 0, 0, 348, 346, 1, 0, 0, 0, 349, 350, 5, 34, 0, 0, 350, 351, 5, 34, 0, 0, 351, 417, 5, 34, 0, 0, 352, 353, 5, 39, 0, 0, 353, 354, 5, 39, 0, 0, 354, 355, 5, 39, 0, 0, 355, 360, 1, 0, 0, 0, 356, 359, 3, 73, 36, 0, 357, 359, 8, 12, 0, 0, 358, 356, 1, 0, 0, 0, 358, 357, 1, 0, 0, 0, 359, 362, 1, 0, 0, 0, 360, 361, 1, 0, 0, 0, 360, 358, 1, 0, 0, 0, 361, 363, 1, 0, 0, 0, 362, 360, 1, 0, 0, 0, 363, 364, 5, 39, 0, 0, 364, 365, 5, 39, 0, 0, 365, 417, 5, 39, 0, 0, 366, 367, 3, 71, 35, 0, 367, 371, 5, 34, 0, 0, 368, 370, 8, 13, 0, 0, 369, 368, 1, 0, 0, 0, 370, 373, 1, 0, 0, 0, 371, 369, 1, 0, 0, 0, 371, 372, 1, 0, 0, 0, 372, 374, 1, 0, 0, 0, 373, 371, 1, 0, 0, 0, 374, 375, 5, 34, 0, 0, 375, 417, 1, 0, 0, 0, 376, 377, 3, 71, 35, 0, 377, 381, 5, 39, 0, 0, 378, 380, 8, 14, 0, 0, 379, 378, 1, 0, 0, 0, 380, 383, 1, 0, 0, 0, 381, 379, 1, 0, 0, 0, 381, 382, 1, 0, 0, 0, 382, 384, 1, 0, 0, 0, 383, 381, 1, 0, 0, 0, 384, 385, 5, 39, 0, 0, 385, 417, 1, 0, 0, 0, 386, 387, 3, 71, 35, 0, 387, 388, 5, 34, 0, 0, 388, 389, 5, 34, 0, 0, 389, 390, 5, 34, 0, 0, 390, 394, 1, 0, 0, 0, 391, 393, 9, 0, 0, 0, 392, 391, 1, 0, 0, 0, 393, 396, 1, 0, 0, 0, 394, 395, 1, 0, 0, 0, 394, 392, 1, 0, 0, 0, 395, 397, 1, 0, 0, 0, 396, 394, 1, 0, 0, 0, 397, 398, 5, 34, 0, 0, 398, 399, 5, 34, 0, 0, 399, 400, 5, 34, 0, 0, 400, 417, 1, 0, 0, 0, 401, 402, 3, 71, 35, 0, 402, 403, 5, 39, 0, 0, 403, 404, 5, 39, 0, 0, 404, 405, 5, 39, 0, 0, 405, 409, 1, 0, 0, 0, 406, 408, 9, 0, 0, 0, 407, 406, 1, 0, 0, 0, 408, 411, 1, 0, 0, 0, 409, 410, 1, 0, 0, 0, 409, 407, 1, 0, 0, 0, 410, 412, 1, 0, 0, 0, 411, 409, 1, 0, 0, 0, 412, 413, 5, 39, 0, 0, 413, 414, 5, 39, 0, 0, 414, 415, 5, 39, 0, 0, 415, 417, 1, 0, 0, 0, 416, 320, 1, 0, 0, 0, 416, 329, 1, 0, 0, 0, 416, 338, 1, 0, 0, 0, 416, 352, 1, 0, 0, 0, 416, 366, 1, 0, 0, 0, 416, 376, 1, 0, 0, 0, 416, 386, 1, 0, 0, 0, 416, 401, 1, 0, 0, 0, 417, 94, 1, 0, 0, 0, 418, 419, 7, 15, 0, 0, 419, 420, 3, 93, 46, 0, 420, 96, 1, 0, 0, 0, 421, 424, 3, 63, 31, 0, 422, 424, 5, 95, 0, 0, 423, 421, 1, 0, 0, 0, 423, 422, 1, 0, 0, 0, 424, 430, 1, 0, 0, 0, 425, 429, 3, 63, 31, 0, 426, 429, 3, 65, 32, 0, 427, 429, 5, 95, 0, 0, 428, 425, 1, 0, 0, 0, 428, 426, 1, 0, 0, 0, 428, 427, 1, 0, 0, 0, 429, 432, 1, 0, 0, 0, 430, 428, 1, 0, 0, 0, 430, 431, 1, 0, 0, 0, 431, 98, 1, 0, 0, 0, 432, 430, 1, 0, 0, 0, 36, 0, 186, 191, 201, 234, 239, 249, 257, 263, 266, 271, 279, 282, 284, 289, 297, 299, 304, 314, 318, 323, 325, 332, 334, 344, 346, 358, 360, 371, 381, 394, 409, 416, 423, 428, 430, 1, 0, 1, 0]
\ No newline at end of file
+[4, 0, 36, 423, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, 20, 2, 21, 7, 21, 2, 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25, 2, 26, 7, 26, 2, 27, 7, 27, 2, 28, 7, 28, 2, 29, 7, 29, 2, 30, 7, 30, 2, 31, 7, 31, 2, 32, 7, 32, 2, 33, 7, 33, 2, 34, 7, 34, 2, 35, 7, 35, 2, 36, 7, 36, 2, 37, 7, 37, 2, 38, 7, 38, 2, 39, 7, 39, 2, 40, 7, 40, 2, 41, 7, 41, 2, 42, 7, 42, 2, 43, 7, 43, 2, 44, 7, 44, 2, 45, 7, 45, 2, 46, 7, 46, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 2, 1, 3, 1, 3, 1, 4, 1, 4, 1, 4, 1, 5, 1, 5, 1, 5, 1, 6, 1, 6, 1, 7, 1, 7, 1, 7, 1, 8, 1, 8, 1, 8, 1, 9, 1, 9, 1, 10, 1, 10, 1, 11, 1, 11, 1, 12, 1, 12, 1, 13, 1, 13, 1, 14, 1, 14, 1, 15, 1, 15, 1, 16, 1, 16, 1, 17, 1, 17, 1, 18, 1, 18, 1, 19, 1, 19, 1, 20, 1, 20, 1, 21, 1, 21, 1, 22, 1, 22, 1, 23, 1, 23, 1, 24, 1, 24, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 28, 1, 28, 1, 29, 1, 29, 1, 30, 1, 30, 1, 31, 1, 31, 3, 31, 177, 8, 31, 1, 31, 4, 31, 180, 8, 31, 11, 31, 12, 31, 181, 1, 32, 1, 32, 1, 33, 1, 33, 1, 34, 1, 34, 1, 34, 1, 34, 3, 34, 192, 8, 34, 1, 35, 1, 35, 1, 35, 1, 36, 1, 36, 1, 36, 1, 36, 1, 36, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 3, 38, 225, 8, 38, 1, 39, 4, 39, 228, 8, 39, 11, 39, 12, 39, 229, 1, 39, 1, 39, 1, 40, 1, 40, 1, 40, 1, 40, 5, 40, 238, 8, 40, 10, 40, 12, 40, 241, 9, 40, 1, 40, 1, 40, 1, 41, 4, 41, 246, 8, 41, 11, 41, 12, 41, 247, 1, 41, 1, 41, 4, 41, 252, 8, 41, 11, 41, 12, 41, 253, 1, 41, 3, 41, 257, 8, 41, 1, 41, 4, 41, 260, 8, 41, 11, 41, 12, 41, 261, 1, 41, 1, 41, 1, 41, 1, 41, 4, 41, 268, 8, 41, 11, 41, 12, 41, 269, 1, 41, 3, 41, 273, 8, 41, 3, 41, 275, 8, 41, 1, 42, 4, 42, 278, 8, 42, 11, 42, 12, 42, 279, 1, 42, 1, 42, 1, 42, 1, 42, 4, 42, 286, 8, 42, 11, 42, 12, 42, 287, 3, 42, 290, 8, 42, 1, 43, 4, 43, 293, 8, 43, 11, 43, 12, 43, 294, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 4, 43, 303, 8, 43, 11, 43, 12, 43, 304, 1, 43, 1, 43, 3, 43, 309, 8, 43, 1, 44, 1, 44, 1, 44, 5, 44, 314, 8, 44, 10, 44, 12, 44, 317, 9, 44, 1, 44, 1, 44, 1, 44, 1, 44, 5, 44, 323, 8, 44, 10, 44, 12, 44, 326, 9, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 5, 44, 335, 8, 44, 10, 44, 12, 44, 338, 9, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 5, 44, 349, 8, 44, 10, 44, 12, 44, 352, 9, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 5, 44, 360, 8, 44, 10, 44, 12, 44, 363, 9, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 5, 44, 370, 8, 44, 10, 44, 12, 44, 373, 9, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 5, 44, 383, 8, 44, 10, 44, 12, 44, 386, 9, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 5, 44, 398, 8, 44, 10, 44, 12, 44, 401, 9, 44, 1, 44, 1, 44, 1, 44, 1, 44, 3, 44, 407, 8, 44, 1, 45, 1, 45, 1, 45, 1, 46, 1, 46, 3, 46, 414, 8, 46, 1, 46, 1, 46, 1, 46, 5, 46, 419, 8, 46, 10, 46, 12, 46, 422, 9, 46, 4, 336, 350, 384, 399, 0, 47, 1, 1, 3, 2, 5, 3, 7, 4, 9, 5, 11, 6, 13, 7, 15, 8, 17, 9, 19, 10, 21, 11, 23, 12, 25, 13, 27, 14, 29, 15, 31, 16, 33, 17, 35, 18, 37, 19, 39, 20, 41, 21, 43, 22, 45, 23, 47, 24, 49, 25, 51, 26, 53, 27, 55, 28, 57, 0, 59, 0, 61, 0, 63, 0, 65, 0, 67, 0, 69, 0, 71, 0, 73, 0, 75, 0, 77, 0, 79, 29, 81, 30, 83, 31, 85, 32, 87, 33, 89, 34, 91, 35, 93, 36, 1, 0, 16, 2, 0, 65, 90, 97, 122, 2, 0, 69, 69, 101, 101, 2, 0, 43, 43, 45, 45, 3, 0, 48, 57, 65, 70, 97, 102, 2, 0, 82, 82, 114, 114, 10, 0, 34, 34, 39, 39, 63, 63, 92, 92, 96, 98, 102, 102, 110, 110, 114, 114, 116, 116, 118, 118, 2, 0, 88, 88, 120, 120, 3, 0, 9, 10, 12, 13, 32, 32, 1, 0, 10, 10, 2, 0, 85, 85, 117, 117, 4, 0, 10, 10, 13, 13, 34, 34, 92, 92, 4, 0, 10, 10, 13, 13, 39, 39, 92, 92, 1, 0, 92, 92, 3, 0, 10, 10, 13, 13, 34, 34, 3, 0, 10, 10, 13, 13, 39, 39, 2, 0, 66, 66, 98, 98, 456, 0, 1, 1, 0, 0, 0, 0, 3, 1, 0, 0, 0, 0, 5, 1, 0, 0, 0, 0, 7, 1, 0, 0, 0, 0, 9, 1, 0, 0, 0, 0, 11, 1, 0, 0, 0, 0, 13, 1, 0, 0, 0, 0, 15, 1, 0, 0, 0, 0, 17, 1, 0, 0, 0, 0, 19, 1, 0, 0, 0, 0, 21, 1, 0, 0, 0, 0, 23, 1, 0, 0, 0, 0, 25, 1, 0, 0, 0, 0, 27, 1, 0, 0, 0, 0, 29, 1, 0, 0, 0, 0, 31, 1, 0, 0, 0, 0, 33, 1, 0, 0, 0, 0, 35, 1, 0, 0, 0, 0, 37, 1, 0, 0, 0, 0, 39, 1, 0, 0, 0, 0, 41, 1, 0, 0, 0, 0, 43, 1, 0, 0, 0, 0, 45, 1, 0, 0, 0, 0, 47, 1, 0, 0, 0, 0, 49, 1, 0, 0, 0, 0, 51, 1, 0, 0, 0, 0, 53, 1, 0, 0, 0, 0, 55, 1, 0, 0, 0, 0, 79, 1, 0, 0, 0, 0, 81, 1, 0, 0, 0, 0, 83, 1, 0, 0, 0, 0, 85, 1, 0, 0, 0, 0, 87, 1, 0, 0, 0, 0, 89, 1, 0, 0, 0, 0, 91, 1, 0, 0, 0, 0, 93, 1, 0, 0, 0, 1, 95, 1, 0, 0, 0, 3, 98, 1, 0, 0, 0, 5, 101, 1, 0, 0, 0, 7, 104, 1, 0, 0, 0, 9, 106, 1, 0, 0, 0, 11, 109, 1, 0, 0, 0, 13, 112, 1, 0, 0, 0, 15, 114, 1, 0, 0, 0, 17, 117, 1, 0, 0, 0, 19, 120, 1, 0, 0, 0, 21, 122, 1, 0, 0, 0, 23, 124, 1, 0, 0, 0, 25, 126, 1, 0, 0, 0, 27, 128, 1, 0, 0, 0, 29, 130, 1, 0, 0, 0, 31, 132, 1, 0, 0, 0, 33, 134, 1, 0, 0, 0, 35, 136, 1, 0, 0, 0, 37, 138, 1, 0, 0, 0, 39, 140, 1, 0, 0, 0, 41, 142, 1, 0, 0, 0, 43, 144, 1, 0, 0, 0, 45, 146, 1, 0, 0, 0, 47, 148, 1, 0, 0, 0, 49, 150, 1, 0, 0, 0, 51, 152, 1, 0, 0, 0, 53, 157, 1, 0, 0, 0, 55, 163, 1, 0, 0, 0, 57, 168, 1, 0, 0, 0, 59, 170, 1, 0, 0, 0, 61, 172, 1, 0, 0, 0, 63, 174, 1, 0, 0, 0, 65, 183, 1, 0, 0, 0, 67, 185, 1, 0, 0, 0, 69, 191, 1, 0, 0, 0, 71, 193, 1, 0, 0, 0, 73, 196, 1, 0, 0, 0, 75, 201, 1, 0, 0, 0, 77, 224, 1, 0, 0, 0, 79, 227, 1, 0, 0, 0, 81, 233, 1, 0, 0, 0, 83, 274, 1, 0, 0, 0, 85, 289, 1, 0, 0, 0, 87, 308, 1, 0, 0, 0, 89, 406, 1, 0, 0, 0, 91, 408, 1, 0, 0, 0, 93, 413, 1, 0, 0, 0, 95, 96, 5, 61, 0, 0, 96, 97, 5, 61, 0, 0, 97, 2, 1, 0, 0, 0, 98, 99, 5, 33, 0, 0, 99, 100, 5, 61, 0, 0, 100, 4, 1, 0, 0, 0, 101, 102, 5, 105, 0, 0, 102, 103, 5, 110, 0, 0, 103, 6, 1, 0, 0, 0, 104, 105, 5, 60, 0, 0, 105, 8, 1, 0, 0, 0, 106, 107, 5, 60, 0, 0, 107, 108, 5, 61, 0, 0, 108, 10, 1, 0, 0, 0, 109, 110, 5, 62, 0, 0, 110, 111, 5, 61, 0, 0, 111, 12, 1, 0, 0, 0, 112, 113, 5, 62, 0, 0, 113, 14, 1, 0, 0, 0, 114, 115, 5, 38, 0, 0, 115, 116, 5, 38, 0, 0, 116, 16, 1, 0, 0, 0, 117, 118, 5, 124, 0, 0, 118, 119, 5, 124, 0, 0, 119, 18, 1, 0, 0, 0, 120, 121, 5, 91, 0, 0, 121, 20, 1, 0, 0, 0, 122, 123, 5, 93, 0, 0, 123, 22, 1, 0, 0, 0, 124, 125, 5, 123, 0, 0, 125, 24, 1, 0, 0, 0, 126, 127, 5, 125, 0, 0, 127, 26, 1, 0, 0, 0, 128, 129, 5, 40, 0, 0, 129, 28, 1, 0, 0, 0, 130, 131, 5, 41, 0, 0, 131, 30, 1, 0, 0, 0, 132, 133, 5, 46, 0, 0, 133, 32, 1, 0, 0, 0, 134, 135, 5, 44, 0, 0, 135, 34, 1, 0, 0, 0, 136, 137, 5, 45, 0, 0, 137, 36, 1, 0, 0, 0, 138, 139, 5, 33, 0, 0, 139, 38, 1, 0, 0, 0, 140, 141, 5, 63, 0, 0, 141, 40, 1, 0, 0, 0, 142, 143, 5, 58, 0, 0, 143, 42, 1, 0, 0, 0, 144, 145, 5, 43, 0, 0, 145, 44, 1, 0, 0, 0, 146, 147, 5, 42, 0, 0, 147, 46, 1, 0, 0, 0, 148, 149, 5, 47, 0, 0, 149, 48, 1, 0, 0, 0, 150, 151, 5, 37, 0, 0, 151, 50, 1, 0, 0, 0, 152, 153, 5, 116, 0, 0, 153, 154, 5, 114, 0, 0, 154, 155, 5, 117, 0, 0, 155, 156, 5, 101, 0, 0, 156, 52, 1, 0, 0, 0, 157, 158, 5, 102, 0, 0, 158, 159, 5, 97, 0, 0, 159, 160, 5, 108, 0, 0, 160, 161, 5, 115, 0, 0, 161, 162, 5, 101, 0, 0, 162, 54, 1, 0, 0, 0, 163, 164, 5, 110, 0, 0, 164, 165, 5, 117, 0, 0, 165, 166, 5, 108, 0, 0, 166, 167, 5, 108, 0, 0, 167, 56, 1, 0, 0, 0, 168, 169, 5, 92, 0, 0, 169, 58, 1, 0, 0, 0, 170, 171, 7, 0, 0, 0, 171, 60, 1, 0, 0, 0, 172, 173, 2, 48, 57, 0, 173, 62, 1, 0, 0, 0, 174, 176, 7, 1, 0, 0, 175, 177, 7, 2, 0, 0, 176, 175, 1, 0, 0, 0, 176, 177, 1, 0, 0, 0, 177, 179, 1, 0, 0, 0, 178, 180, 3, 61, 30, 0, 179, 178, 1, 0, 0, 0, 180, 181, 1, 0, 0, 0, 181, 179, 1, 0, 0, 0, 181, 182, 1, 0, 0, 0, 182, 64, 1, 0, 0, 0, 183, 184, 7, 3, 0, 0, 184, 66, 1, 0, 0, 0, 185, 186, 7, 4, 0, 0, 186, 68, 1, 0, 0, 0, 187, 192, 3, 71, 35, 0, 188, 192, 3, 75, 37, 0, 189, 192, 3, 77, 38, 0, 190, 192, 3, 73, 36, 0, 191, 187, 1, 0, 0, 0, 191, 188, 1, 0, 0, 0, 191, 189, 1, 0, 0, 0, 191, 190, 1, 0, 0, 0, 192, 70, 1, 0, 0, 0, 193, 194, 3, 57, 28, 0, 194, 195, 7, 5, 0, 0, 195, 72, 1, 0, 0, 0, 196, 197, 3, 57, 28, 0, 197, 198, 2, 48, 51, 0, 198, 199, 2, 48, 55, 0, 199, 200, 2, 48, 55, 0, 200, 74, 1, 0, 0, 0, 201, 202, 3, 57, 28, 0, 202, 203, 7, 6, 0, 0, 203, 204, 3, 65, 32, 0, 204, 205, 3, 65, 32, 0, 205, 76, 1, 0, 0, 0, 206, 207, 3, 57, 28, 0, 207, 208, 5, 117, 0, 0, 208, 209, 3, 65, 32, 0, 209, 210, 3, 65, 32, 0, 210, 211, 3, 65, 32, 0, 211, 212, 3, 65, 32, 0, 212, 225, 1, 0, 0, 0, 213, 214, 3, 57, 28, 0, 214, 215, 5, 85, 0, 0, 215, 216, 3, 65, 32, 0, 216, 217, 3, 65, 32, 0, 217, 218, 3, 65, 32, 0, 218, 219, 3, 65, 32, 0, 219, 220, 3, 65, 32, 0, 220, 221, 3, 65, 32, 0, 221, 222, 3, 65, 32, 0, 222, 223, 3, 65, 32, 0, 223, 225, 1, 0, 0, 0, 224, 206, 1, 0, 0, 0, 224, 213, 1, 0, 0, 0, 225, 78, 1, 0, 0, 0, 226, 228, 7, 7, 0, 0, 227, 226, 1, 0, 0, 0, 228, 229, 1, 0, 0, 0, 229, 227, 1, 0, 0, 0, 229, 230, 1, 0, 0, 0, 230, 231, 1, 0, 0, 0, 231, 232, 6, 39, 0, 0, 232, 80, 1, 0, 0, 0, 233, 234, 5, 47, 0, 0, 234, 235, 5, 47, 0, 0, 235, 239, 1, 0, 0, 0, 236, 238, 8, 8, 0, 0, 237, 236, 1, 0, 0, 0, 238, 241, 1, 0, 0, 0, 239, 237, 1, 0, 0, 0, 239, 240, 1, 0, 0, 0, 240, 242, 1, 0, 0, 0, 241, 239, 1, 0, 0, 0, 242, 243, 6, 40, 0, 0, 243, 82, 1, 0, 0, 0, 244, 246, 3, 61, 30, 0, 245, 244, 1, 0, 0, 0, 246, 247, 1, 0, 0, 0, 247, 245, 1, 0, 0, 0, 247, 248, 1, 0, 0, 0, 248, 249, 1, 0, 0, 0, 249, 251, 5, 46, 0, 0, 250, 252, 3, 61, 30, 0, 251, 250, 1, 0, 0, 0, 252, 253, 1, 0, 0, 0, 253, 251, 1, 0, 0, 0, 253, 254, 1, 0, 0, 0, 254, 256, 1, 0, 0, 0, 255, 257, 3, 63, 31, 0, 256, 255, 1, 0, 0, 0, 256, 257, 1, 0, 0, 0, 257, 275, 1, 0, 0, 0, 258, 260, 3, 61, 30, 0, 259, 258, 1, 0, 0, 0, 260, 261, 1, 0, 0, 0, 261, 259, 1, 0, 0, 0, 261, 262, 1, 0, 0, 0, 262, 263, 1, 0, 0, 0, 263, 264, 3, 63, 31, 0, 264, 275, 1, 0, 0, 0, 265, 267, 5, 46, 0, 0, 266, 268, 3, 61, 30, 0, 267, 266, 1, 0, 0, 0, 268, 269, 1, 0, 0, 0, 269, 267, 1, 0, 0, 0, 269, 270, 1, 0, 0, 0, 270, 272, 1, 0, 0, 0, 271, 273, 3, 63, 31, 0, 272, 271, 1, 0, 0, 0, 272, 273, 1, 0, 0, 0, 273, 275, 1, 0, 0, 0, 274, 245, 1, 0, 0, 0, 274, 259, 1, 0, 0, 0, 274, 265, 1, 0, 0, 0, 275, 84, 1, 0, 0, 0, 276, 278, 3, 61, 30, 0, 277, 276, 1, 0, 0, 0, 278, 279, 1, 0, 0, 0, 279, 277, 1, 0, 0, 0, 279, 280, 1, 0, 0, 0, 280, 290, 1, 0, 0, 0, 281, 282, 5, 48, 0, 0, 282, 283, 5, 120, 0, 0, 283, 285, 1, 0, 0, 0, 284, 286, 3, 65, 32, 0, 285, 284, 1, 0, 0, 0, 286, 287, 1, 0, 0, 0, 287, 285, 1, 0, 0, 0, 287, 288, 1, 0, 0, 0, 288, 290, 1, 0, 0, 0, 289, 277, 1, 0, 0, 0, 289, 281, 1, 0, 0, 0, 290, 86, 1, 0, 0, 0, 291, 293, 3, 61, 30, 0, 292, 291, 1, 0, 0, 0, 293, 294, 1, 0, 0, 0, 294, 292, 1, 0, 0, 0, 294, 295, 1, 0, 0, 0, 295, 296, 1, 0, 0, 0, 296, 297, 7, 9, 0, 0, 297, 309, 1, 0, 0, 0, 298, 299, 5, 48, 0, 0, 299, 300, 5, 120, 0, 0, 300, 302, 1, 0, 0, 0, 301, 303, 3, 65, 32, 0, 302, 301, 1, 0, 0, 0, 303, 304, 1, 0, 0, 0, 304, 302, 1, 0, 0, 0, 304, 305, 1, 0, 0, 0, 305, 306, 1, 0, 0, 0, 306, 307, 7, 9, 0, 0, 307, 309, 1, 0, 0, 0, 308, 292, 1, 0, 0, 0, 308, 298, 1, 0, 0, 0, 309, 88, 1, 0, 0, 0, 310, 315, 5, 34, 0, 0, 311, 314, 3, 69, 34, 0, 312, 314, 8, 10, 0, 0, 313, 311, 1, 0, 0, 0, 313, 312, 1, 0, 0, 0, 314, 317, 1, 0, 0, 0, 315, 313, 1, 0, 0, 0, 315, 316, 1, 0, 0, 0, 316, 318, 1, 0, 0, 0, 317, 315, 1, 0, 0, 0, 318, 407, 5, 34, 0, 0, 319, 324, 5, 39, 0, 0, 320, 323, 3, 69, 34, 0, 321, 323, 8, 11, 0, 0, 322, 320, 1, 0, 0, 0, 322, 321, 1, 0, 0, 0, 323, 326, 1, 0, 0, 0, 324, 322, 1, 0, 0, 0, 324, 325, 1, 0, 0, 0, 325, 327, 1, 0, 0, 0, 326, 324, 1, 0, 0, 0, 327, 407, 5, 39, 0, 0, 328, 329, 5, 34, 0, 0, 329, 330, 5, 34, 0, 0, 330, 331, 5, 34, 0, 0, 331, 336, 1, 0, 0, 0, 332, 335, 3, 69, 34, 0, 333, 335, 8, 12, 0, 0, 334, 332, 1, 0, 0, 0, 334, 333, 1, 0, 0, 0, 335, 338, 1, 0, 0, 0, 336, 337, 1, 0, 0, 0, 336, 334, 1, 0, 0, 0, 337, 339, 1, 0, 0, 0, 338, 336, 1, 0, 0, 0, 339, 340, 5, 34, 0, 0, 340, 341, 5, 34, 0, 0, 341, 407, 5, 34, 0, 0, 342, 343, 5, 39, 0, 0, 343, 344, 5, 39, 0, 0, 344, 345, 5, 39, 0, 0, 345, 350, 1, 0, 0, 0, 346, 349, 3, 69, 34, 0, 347, 349, 8, 12, 0, 0, 348, 346, 1, 0, 0, 0, 348, 347, 1, 0, 0, 0, 349, 352, 1, 0, 0, 0, 350, 351, 1, 0, 0, 0, 350, 348, 1, 0, 0, 0, 351, 353, 1, 0, 0, 0, 352, 350, 1, 0, 0, 0, 353, 354, 5, 39, 0, 0, 354, 355, 5, 39, 0, 0, 355, 407, 5, 39, 0, 0, 356, 357, 3, 67, 33, 0, 357, 361, 5, 34, 0, 0, 358, 360, 8, 13, 0, 0, 359, 358, 1, 0, 0, 0, 360, 363, 1, 0, 0, 0, 361, 359, 1, 0, 0, 0, 361, 362, 1, 0, 0, 0, 362, 364, 1, 0, 0, 0, 363, 361, 1, 0, 0, 0, 364, 365, 5, 34, 0, 0, 365, 407, 1, 0, 0, 0, 366, 367, 3, 67, 33, 0, 367, 371, 5, 39, 0, 0, 368, 370, 8, 14, 0, 0, 369, 368, 1, 0, 0, 0, 370, 373, 1, 0, 0, 0, 371, 369, 1, 0, 0, 0, 371, 372, 1, 0, 0, 0, 372, 374, 1, 0, 0, 0, 373, 371, 1, 0, 0, 0, 374, 375, 5, 39, 0, 0, 375, 407, 1, 0, 0, 0, 376, 377, 3, 67, 33, 0, 377, 378, 5, 34, 0, 0, 378, 379, 5, 34, 0, 0, 379, 380, 5, 34, 0, 0, 380, 384, 1, 0, 0, 0, 381, 383, 9, 0, 0, 0, 382, 381, 1, 0, 0, 0, 383, 386, 1, 0, 0, 0, 384, 385, 1, 0, 0, 0, 384, 382, 1, 0, 0, 0, 385, 387, 1, 0, 0, 0, 386, 384, 1, 0, 0, 0, 387, 388, 5, 34, 0, 0, 388, 389, 5, 34, 0, 0, 389, 390, 5, 34, 0, 0, 390, 407, 1, 0, 0, 0, 391, 392, 3, 67, 33, 0, 392, 393, 5, 39, 0, 0, 393, 394, 5, 39, 0, 0, 394, 395, 5, 39, 0, 0, 395, 399, 1, 0, 0, 0, 396, 398, 9, 0, 0, 0, 397, 396, 1, 0, 0, 0, 398, 401, 1, 0, 0, 0, 399, 400, 1, 0, 0, 0, 399, 397, 1, 0, 0, 0, 400, 402, 1, 0, 0, 0, 401, 399, 1, 0, 0, 0, 402, 403, 5, 39, 0, 0, 403, 404, 5, 39, 0, 0, 404, 405, 5, 39, 0, 0, 405, 407, 1, 0, 0, 0, 406, 310, 1, 0, 0, 0, 406, 319, 1, 0, 0, 0, 406, 328, 1, 0, 0, 0, 406, 342, 1, 0, 0, 0, 406, 356, 1, 0, 0, 0, 406, 366, 1, 0, 0, 0, 406, 376, 1, 0, 0, 0, 406, 391, 1, 0, 0, 0, 407, 90, 1, 0, 0, 0, 408, 409, 7, 15, 0, 0, 409, 410, 3, 89, 44, 0, 410, 92, 1, 0, 0, 0, 411, 414, 3, 59, 29, 0, 412, 414, 5, 95, 0, 0, 413, 411, 1, 0, 0, 0, 413, 412, 1, 0, 0, 0, 414, 420, 1, 0, 0, 0, 415, 419, 3, 59, 29, 0, 416, 419, 3, 61, 30, 0, 417, 419, 5, 95, 0, 0, 418, 415, 1, 0, 0, 0, 418, 416, 1, 0, 0, 0, 418, 417, 1, 0, 0, 0, 419, 422, 1, 0, 0, 0, 420, 418, 1, 0, 0, 0, 420, 421, 1, 0, 0, 0, 421, 94, 1, 0, 0, 0, 422, 420, 1, 0, 0, 0, 36, 0, 176, 181, 191, 224, 229, 239, 247, 253, 256, 261, 269, 272, 274, 279, 287, 289, 294, 304, 308, 313, 315, 322, 324, 334, 336, 348, 350, 361, 371, 384, 399, 406, 413, 418, 420, 1, 0, 1, 0]
\ No newline at end of file
diff --git a/vendor/github.com/google/cel-go/parser/gen/CELLexer.tokens b/vendor/github.com/google/cel-go/parser/gen/CELLexer.tokens
index c80bfb323..b305bdad3 100644
--- a/vendor/github.com/google/cel-go/parser/gen/CELLexer.tokens
+++ b/vendor/github.com/google/cel-go/parser/gen/CELLexer.tokens
@@ -1,68 +1,64 @@
-T__0=1
-T__1=2
-EQUALS=3
-NOT_EQUALS=4
-IN=5
-LESS=6
-LESS_EQUALS=7
-GREATER_EQUALS=8
-GREATER=9
-LOGICAL_AND=10
-LOGICAL_OR=11
-LBRACKET=12
-RPRACKET=13
-LBRACE=14
-RBRACE=15
-LPAREN=16
-RPAREN=17
-DOT=18
-COMMA=19
-MINUS=20
-EXCLAM=21
-QUESTIONMARK=22
-COLON=23
-PLUS=24
-STAR=25
-SLASH=26
-PERCENT=27
-CEL_TRUE=28
-CEL_FALSE=29
-NUL=30
-WHITESPACE=31
-COMMENT=32
-NUM_FLOAT=33
-NUM_INT=34
-NUM_UINT=35
-STRING=36
-BYTES=37
-IDENTIFIER=38
-'.?'=1
-'[?'=2
-'=='=3
-'!='=4
-'in'=5
-'<'=6
-'<='=7
-'>='=8
-'>'=9
-'&&'=10
-'||'=11
-'['=12
-']'=13
-'{'=14
-'}'=15
-'('=16
-')'=17
-'.'=18
-','=19
-'-'=20
-'!'=21
-'?'=22
-':'=23
-'+'=24
-'*'=25
-'/'=26
-'%'=27
-'true'=28
-'false'=29
-'null'=30
+EQUALS=1
+NOT_EQUALS=2
+IN=3
+LESS=4
+LESS_EQUALS=5
+GREATER_EQUALS=6
+GREATER=7
+LOGICAL_AND=8
+LOGICAL_OR=9
+LBRACKET=10
+RPRACKET=11
+LBRACE=12
+RBRACE=13
+LPAREN=14
+RPAREN=15
+DOT=16
+COMMA=17
+MINUS=18
+EXCLAM=19
+QUESTIONMARK=20
+COLON=21
+PLUS=22
+STAR=23
+SLASH=24
+PERCENT=25
+CEL_TRUE=26
+CEL_FALSE=27
+NUL=28
+WHITESPACE=29
+COMMENT=30
+NUM_FLOAT=31
+NUM_INT=32
+NUM_UINT=33
+STRING=34
+BYTES=35
+IDENTIFIER=36
+'=='=1
+'!='=2
+'in'=3
+'<'=4
+'<='=5
+'>='=6
+'>'=7
+'&&'=8
+'||'=9
+'['=10
+']'=11
+'{'=12
+'}'=13
+'('=14
+')'=15
+'.'=16
+','=17
+'-'=18
+'!'=19
+'?'=20
+':'=21
+'+'=22
+'*'=23
+'/'=24
+'%'=25
+'true'=26
+'false'=27
+'null'=28
diff --git a/vendor/github.com/google/cel-go/parser/gen/cel_base_listener.go b/vendor/github.com/google/cel-go/parser/gen/cel_base_listener.go
index f4b9b08da..0247f470a 100644
--- a/vendor/github.com/google/cel-go/parser/gen/cel_base_listener.go
+++ b/vendor/github.com/google/cel-go/parser/gen/cel_base_listener.go
@@ -1,7 +1,7 @@
-// Code generated from /Users/tswadell/go/src/github.com/google/cel-go/parser/gen/CEL.g4 by ANTLR 4.10.1. DO NOT EDIT.
+// Code generated from /Users/tswadell/go/src/github.com/google/cel-go/parser/gen/CEL.g4 by ANTLR 4.12.0. DO NOT EDIT.
package gen // CEL
-import "github.com/antlr/antlr4/runtime/Go/antlr"
+import "github.com/antlr/antlr4/runtime/Go/antlr/v4"
// BaseCELListener is a complete listener for a parse tree produced by CELParser.
type BaseCELListener struct{}
@@ -140,6 +140,12 @@ func (s *BaseCELListener) EnterExprList(ctx *ExprListContext) {}
// ExitExprList is called when production exprList is exited.
func (s *BaseCELListener) ExitExprList(ctx *ExprListContext) {}
+// EnterListInit is called when production listInit is entered.
+func (s *BaseCELListener) EnterListInit(ctx *ListInitContext) {}
+
+// ExitListInit is called when production listInit is exited.
+func (s *BaseCELListener) ExitListInit(ctx *ListInitContext) {}
+
// EnterFieldInitializerList is called when production fieldInitializerList is entered.
func (s *BaseCELListener) EnterFieldInitializerList(ctx *FieldInitializerListContext) {}
@@ -158,11 +164,11 @@ func (s *BaseCELListener) EnterMapInitializerList(ctx *MapInitializerListContext
// ExitMapInitializerList is called when production mapInitializerList is exited.
func (s *BaseCELListener) ExitMapInitializerList(ctx *MapInitializerListContext) {}
-// EnterOptKey is called when production optKey is entered.
-func (s *BaseCELListener) EnterOptKey(ctx *OptKeyContext) {}
+// EnterOptExpr is called when production optExpr is entered.
+func (s *BaseCELListener) EnterOptExpr(ctx *OptExprContext) {}
-// ExitOptKey is called when production optKey is exited.
-func (s *BaseCELListener) ExitOptKey(ctx *OptKeyContext) {}
+// ExitOptExpr is called when production optExpr is exited.
+func (s *BaseCELListener) ExitOptExpr(ctx *OptExprContext) {}
// EnterInt is called when production Int is entered.
func (s *BaseCELListener) EnterInt(ctx *IntContext) {}
diff --git a/vendor/github.com/google/cel-go/parser/gen/cel_base_visitor.go b/vendor/github.com/google/cel-go/parser/gen/cel_base_visitor.go
index 98f9f993e..52a7f4dc5 100644
--- a/vendor/github.com/google/cel-go/parser/gen/cel_base_visitor.go
+++ b/vendor/github.com/google/cel-go/parser/gen/cel_base_visitor.go
@@ -1,7 +1,7 @@
-// Code generated from /Users/tswadell/go/src/github.com/google/cel-go/parser/gen/CEL.g4 by ANTLR 4.10.1. DO NOT EDIT.
+// Code generated from /Users/tswadell/go/src/github.com/google/cel-go/parser/gen/CEL.g4 by ANTLR 4.12.0. DO NOT EDIT.
package gen // CEL
-import "github.com/antlr/antlr4/runtime/Go/antlr"
+import "github.com/antlr/antlr4/runtime/Go/antlr/v4"
type BaseCELVisitor struct {
*antlr.BaseParseTreeVisitor
@@ -87,6 +87,10 @@ func (v *BaseCELVisitor) VisitExprList(ctx *ExprListContext) interface{} {
return v.VisitChildren(ctx)
}
+func (v *BaseCELVisitor) VisitListInit(ctx *ListInitContext) interface{} {
+ return v.VisitChildren(ctx)
+}
+
func (v *BaseCELVisitor) VisitFieldInitializerList(ctx *FieldInitializerListContext) interface{} {
return v.VisitChildren(ctx)
}
@@ -99,7 +103,7 @@ func (v *BaseCELVisitor) VisitMapInitializerList(ctx *MapInitializerListContext)
return v.VisitChildren(ctx)
}
-func (v *BaseCELVisitor) VisitOptKey(ctx *OptKeyContext) interface{} {
+func (v *BaseCELVisitor) VisitOptExpr(ctx *OptExprContext) interface{} {
return v.VisitChildren(ctx)
}
diff --git a/vendor/github.com/google/cel-go/parser/gen/cel_lexer.go b/vendor/github.com/google/cel-go/parser/gen/cel_lexer.go
index 63319af75..98ddc06d0 100644
--- a/vendor/github.com/google/cel-go/parser/gen/cel_lexer.go
+++ b/vendor/github.com/google/cel-go/parser/gen/cel_lexer.go
@@ -1,4 +1,4 @@
-// Code generated from /Users/tswadell/go/src/github.com/google/cel-go/parser/gen/CEL.g4 by ANTLR 4.10.1. DO NOT EDIT.
+// Code generated from /Users/tswadell/go/src/github.com/google/cel-go/parser/gen/CEL.g4 by ANTLR 4.12.0. DO NOT EDIT.
package gen
@@ -7,7 +7,7 @@ import (
"sync"
"unicode"
- "github.com/antlr/antlr4/runtime/Go/antlr"
+ "github.com/antlr/antlr4/runtime/Go/antlr/v4"
)
// Suppress unused import error
@@ -44,13 +44,12 @@ func cellexerLexerInit() {
"DEFAULT_MODE",
}
staticData.literalNames = []string{
- "", "'.?'", "'[?'", "'=='", "'!='", "'in'", "'<'", "'<='", "'>='", "'>'",
- "'&&'", "'||'", "'['", "']'", "'{'", "'}'", "'('", "')'", "'.'", "','",
- "'-'", "'!'", "'?'", "':'", "'+'", "'*'", "'/'", "'%'", "'true'", "'false'",
- "'null'",
+ "", "'=='", "'!='", "'in'", "'<'", "'<='", "'>='", "'>'", "'&&'", "'||'",
+ "'['", "']'", "'{'", "'}'", "'('", "')'", "'.'", "','", "'-'", "'!'",
+ "'?'", "':'", "'+'", "'*'", "'/'", "'%'", "'true'", "'false'", "'null'",
}
staticData.symbolicNames = []string{
- "", "", "", "EQUALS", "NOT_EQUALS", "IN", "LESS", "LESS_EQUALS", "GREATER_EQUALS",
+ "", "EQUALS", "NOT_EQUALS", "IN", "LESS", "LESS_EQUALS", "GREATER_EQUALS",
"GREATER", "LOGICAL_AND", "LOGICAL_OR", "LBRACKET", "RPRACKET", "LBRACE",
"RBRACE", "LPAREN", "RPAREN", "DOT", "COMMA", "MINUS", "EXCLAM", "QUESTIONMARK",
"COLON", "PLUS", "STAR", "SLASH", "PERCENT", "CEL_TRUE", "CEL_FALSE",
@@ -58,18 +57,18 @@ func cellexerLexerInit() {
"STRING", "BYTES", "IDENTIFIER",
}
staticData.ruleNames = []string{
- "T__0", "T__1", "EQUALS", "NOT_EQUALS", "IN", "LESS", "LESS_EQUALS",
- "GREATER_EQUALS", "GREATER", "LOGICAL_AND", "LOGICAL_OR", "LBRACKET",
- "RPRACKET", "LBRACE", "RBRACE", "LPAREN", "RPAREN", "DOT", "COMMA",
- "MINUS", "EXCLAM", "QUESTIONMARK", "COLON", "PLUS", "STAR", "SLASH",
- "PERCENT", "CEL_TRUE", "CEL_FALSE", "NUL", "BACKSLASH", "LETTER", "DIGIT",
- "EXPONENT", "HEXDIGIT", "RAW", "ESC_SEQ", "ESC_CHAR_SEQ", "ESC_OCT_SEQ",
- "ESC_BYTE_SEQ", "ESC_UNI_SEQ", "WHITESPACE", "COMMENT", "NUM_FLOAT",
- "NUM_INT", "NUM_UINT", "STRING", "BYTES", "IDENTIFIER",
+ "EQUALS", "NOT_EQUALS", "IN", "LESS", "LESS_EQUALS", "GREATER_EQUALS",
+ "GREATER", "LOGICAL_AND", "LOGICAL_OR", "LBRACKET", "RPRACKET", "LBRACE",
+ "RBRACE", "LPAREN", "RPAREN", "DOT", "COMMA", "MINUS", "EXCLAM", "QUESTIONMARK",
+ "COLON", "PLUS", "STAR", "SLASH", "PERCENT", "CEL_TRUE", "CEL_FALSE",
+ "NUL", "BACKSLASH", "LETTER", "DIGIT", "EXPONENT", "HEXDIGIT", "RAW",
+ "ESC_SEQ", "ESC_CHAR_SEQ", "ESC_OCT_SEQ", "ESC_BYTE_SEQ", "ESC_UNI_SEQ",
+ "WHITESPACE", "COMMENT", "NUM_FLOAT", "NUM_INT", "NUM_UINT", "STRING",
+ "BYTES", "IDENTIFIER",
}
staticData.predictionContextCache = antlr.NewPredictionContextCache()
staticData.serializedATN = []int32{
- 4, 0, 38, 433, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2,
+ 4, 0, 36, 423, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2,
4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2,
10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15,
7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7,
@@ -78,199 +77,195 @@ func cellexerLexerInit() {
31, 7, 31, 2, 32, 7, 32, 2, 33, 7, 33, 2, 34, 7, 34, 2, 35, 7, 35, 2, 36,
7, 36, 2, 37, 7, 37, 2, 38, 7, 38, 2, 39, 7, 39, 2, 40, 7, 40, 2, 41, 7,
41, 2, 42, 7, 42, 2, 43, 7, 43, 2, 44, 7, 44, 2, 45, 7, 45, 2, 46, 7, 46,
- 2, 47, 7, 47, 2, 48, 7, 48, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 2, 1,
- 2, 1, 2, 1, 3, 1, 3, 1, 3, 1, 4, 1, 4, 1, 4, 1, 5, 1, 5, 1, 6, 1, 6, 1,
- 6, 1, 7, 1, 7, 1, 7, 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 1, 10, 1, 10, 1, 10,
- 1, 11, 1, 11, 1, 12, 1, 12, 1, 13, 1, 13, 1, 14, 1, 14, 1, 15, 1, 15, 1,
- 16, 1, 16, 1, 17, 1, 17, 1, 18, 1, 18, 1, 19, 1, 19, 1, 20, 1, 20, 1, 21,
- 1, 21, 1, 22, 1, 22, 1, 23, 1, 23, 1, 24, 1, 24, 1, 25, 1, 25, 1, 26, 1,
- 26, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 28, 1, 28, 1, 28, 1, 28, 1, 28,
- 1, 28, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 30, 1, 30, 1, 31, 1, 31, 1,
- 32, 1, 32, 1, 33, 1, 33, 3, 33, 187, 8, 33, 1, 33, 4, 33, 190, 8, 33, 11,
- 33, 12, 33, 191, 1, 34, 1, 34, 1, 35, 1, 35, 1, 36, 1, 36, 1, 36, 1, 36,
- 3, 36, 202, 8, 36, 1, 37, 1, 37, 1, 37, 1, 38, 1, 38, 1, 38, 1, 38, 1,
- 38, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40,
- 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1,
- 40, 1, 40, 1, 40, 3, 40, 235, 8, 40, 1, 41, 4, 41, 238, 8, 41, 11, 41,
- 12, 41, 239, 1, 41, 1, 41, 1, 42, 1, 42, 1, 42, 1, 42, 5, 42, 248, 8, 42,
- 10, 42, 12, 42, 251, 9, 42, 1, 42, 1, 42, 1, 43, 4, 43, 256, 8, 43, 11,
- 43, 12, 43, 257, 1, 43, 1, 43, 4, 43, 262, 8, 43, 11, 43, 12, 43, 263,
- 1, 43, 3, 43, 267, 8, 43, 1, 43, 4, 43, 270, 8, 43, 11, 43, 12, 43, 271,
- 1, 43, 1, 43, 1, 43, 1, 43, 4, 43, 278, 8, 43, 11, 43, 12, 43, 279, 1,
- 43, 3, 43, 283, 8, 43, 3, 43, 285, 8, 43, 1, 44, 4, 44, 288, 8, 44, 11,
- 44, 12, 44, 289, 1, 44, 1, 44, 1, 44, 1, 44, 4, 44, 296, 8, 44, 11, 44,
- 12, 44, 297, 3, 44, 300, 8, 44, 1, 45, 4, 45, 303, 8, 45, 11, 45, 12, 45,
- 304, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 4, 45, 313, 8, 45, 11, 45,
- 12, 45, 314, 1, 45, 1, 45, 3, 45, 319, 8, 45, 1, 46, 1, 46, 1, 46, 5, 46,
- 324, 8, 46, 10, 46, 12, 46, 327, 9, 46, 1, 46, 1, 46, 1, 46, 1, 46, 5,
- 46, 333, 8, 46, 10, 46, 12, 46, 336, 9, 46, 1, 46, 1, 46, 1, 46, 1, 46,
- 1, 46, 1, 46, 1, 46, 5, 46, 345, 8, 46, 10, 46, 12, 46, 348, 9, 46, 1,
- 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 5, 46, 359,
- 8, 46, 10, 46, 12, 46, 362, 9, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1,
- 46, 5, 46, 370, 8, 46, 10, 46, 12, 46, 373, 9, 46, 1, 46, 1, 46, 1, 46,
- 1, 46, 1, 46, 5, 46, 380, 8, 46, 10, 46, 12, 46, 383, 9, 46, 1, 46, 1,
- 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 5, 46, 393, 8, 46, 10, 46,
- 12, 46, 396, 9, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1,
- 46, 1, 46, 1, 46, 5, 46, 408, 8, 46, 10, 46, 12, 46, 411, 9, 46, 1, 46,
- 1, 46, 1, 46, 1, 46, 3, 46, 417, 8, 46, 1, 47, 1, 47, 1, 47, 1, 48, 1,
- 48, 3, 48, 424, 8, 48, 1, 48, 1, 48, 1, 48, 5, 48, 429, 8, 48, 10, 48,
- 12, 48, 432, 9, 48, 4, 346, 360, 394, 409, 0, 49, 1, 1, 3, 2, 5, 3, 7,
+ 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 2, 1, 3, 1, 3, 1, 4,
+ 1, 4, 1, 4, 1, 5, 1, 5, 1, 5, 1, 6, 1, 6, 1, 7, 1, 7, 1, 7, 1, 8, 1, 8,
+ 1, 8, 1, 9, 1, 9, 1, 10, 1, 10, 1, 11, 1, 11, 1, 12, 1, 12, 1, 13, 1, 13,
+ 1, 14, 1, 14, 1, 15, 1, 15, 1, 16, 1, 16, 1, 17, 1, 17, 1, 18, 1, 18, 1,
+ 19, 1, 19, 1, 20, 1, 20, 1, 21, 1, 21, 1, 22, 1, 22, 1, 23, 1, 23, 1, 24,
+ 1, 24, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 1, 26, 1, 26, 1, 26, 1, 26, 1,
+ 26, 1, 26, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 28, 1, 28, 1, 29, 1, 29,
+ 1, 30, 1, 30, 1, 31, 1, 31, 3, 31, 177, 8, 31, 1, 31, 4, 31, 180, 8, 31,
+ 11, 31, 12, 31, 181, 1, 32, 1, 32, 1, 33, 1, 33, 1, 34, 1, 34, 1, 34, 1,
+ 34, 3, 34, 192, 8, 34, 1, 35, 1, 35, 1, 35, 1, 36, 1, 36, 1, 36, 1, 36,
+ 1, 36, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 38, 1, 38, 1, 38, 1, 38, 1,
+ 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38,
+ 1, 38, 1, 38, 1, 38, 3, 38, 225, 8, 38, 1, 39, 4, 39, 228, 8, 39, 11, 39,
+ 12, 39, 229, 1, 39, 1, 39, 1, 40, 1, 40, 1, 40, 1, 40, 5, 40, 238, 8, 40,
+ 10, 40, 12, 40, 241, 9, 40, 1, 40, 1, 40, 1, 41, 4, 41, 246, 8, 41, 11,
+ 41, 12, 41, 247, 1, 41, 1, 41, 4, 41, 252, 8, 41, 11, 41, 12, 41, 253,
+ 1, 41, 3, 41, 257, 8, 41, 1, 41, 4, 41, 260, 8, 41, 11, 41, 12, 41, 261,
+ 1, 41, 1, 41, 1, 41, 1, 41, 4, 41, 268, 8, 41, 11, 41, 12, 41, 269, 1,
+ 41, 3, 41, 273, 8, 41, 3, 41, 275, 8, 41, 1, 42, 4, 42, 278, 8, 42, 11,
+ 42, 12, 42, 279, 1, 42, 1, 42, 1, 42, 1, 42, 4, 42, 286, 8, 42, 11, 42,
+ 12, 42, 287, 3, 42, 290, 8, 42, 1, 43, 4, 43, 293, 8, 43, 11, 43, 12, 43,
+ 294, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 4, 43, 303, 8, 43, 11, 43,
+ 12, 43, 304, 1, 43, 1, 43, 3, 43, 309, 8, 43, 1, 44, 1, 44, 1, 44, 5, 44,
+ 314, 8, 44, 10, 44, 12, 44, 317, 9, 44, 1, 44, 1, 44, 1, 44, 1, 44, 5,
+ 44, 323, 8, 44, 10, 44, 12, 44, 326, 9, 44, 1, 44, 1, 44, 1, 44, 1, 44,
+ 1, 44, 1, 44, 1, 44, 5, 44, 335, 8, 44, 10, 44, 12, 44, 338, 9, 44, 1,
+ 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 5, 44, 349,
+ 8, 44, 10, 44, 12, 44, 352, 9, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1,
+ 44, 5, 44, 360, 8, 44, 10, 44, 12, 44, 363, 9, 44, 1, 44, 1, 44, 1, 44,
+ 1, 44, 1, 44, 5, 44, 370, 8, 44, 10, 44, 12, 44, 373, 9, 44, 1, 44, 1,
+ 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 5, 44, 383, 8, 44, 10, 44,
+ 12, 44, 386, 9, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1,
+ 44, 1, 44, 1, 44, 5, 44, 398, 8, 44, 10, 44, 12, 44, 401, 9, 44, 1, 44,
+ 1, 44, 1, 44, 1, 44, 3, 44, 407, 8, 44, 1, 45, 1, 45, 1, 45, 1, 46, 1,
+ 46, 3, 46, 414, 8, 46, 1, 46, 1, 46, 1, 46, 5, 46, 419, 8, 46, 10, 46,
+ 12, 46, 422, 9, 46, 4, 336, 350, 384, 399, 0, 47, 1, 1, 3, 2, 5, 3, 7,
4, 9, 5, 11, 6, 13, 7, 15, 8, 17, 9, 19, 10, 21, 11, 23, 12, 25, 13, 27,
14, 29, 15, 31, 16, 33, 17, 35, 18, 37, 19, 39, 20, 41, 21, 43, 22, 45,
- 23, 47, 24, 49, 25, 51, 26, 53, 27, 55, 28, 57, 29, 59, 30, 61, 0, 63,
- 0, 65, 0, 67, 0, 69, 0, 71, 0, 73, 0, 75, 0, 77, 0, 79, 0, 81, 0, 83, 31,
- 85, 32, 87, 33, 89, 34, 91, 35, 93, 36, 95, 37, 97, 38, 1, 0, 16, 2, 0,
- 65, 90, 97, 122, 2, 0, 69, 69, 101, 101, 2, 0, 43, 43, 45, 45, 3, 0, 48,
- 57, 65, 70, 97, 102, 2, 0, 82, 82, 114, 114, 10, 0, 34, 34, 39, 39, 63,
- 63, 92, 92, 96, 98, 102, 102, 110, 110, 114, 114, 116, 116, 118, 118, 2,
- 0, 88, 88, 120, 120, 3, 0, 9, 10, 12, 13, 32, 32, 1, 0, 10, 10, 2, 0, 85,
- 85, 117, 117, 4, 0, 10, 10, 13, 13, 34, 34, 92, 92, 4, 0, 10, 10, 13, 13,
- 39, 39, 92, 92, 1, 0, 92, 92, 3, 0, 10, 10, 13, 13, 34, 34, 3, 0, 10, 10,
- 13, 13, 39, 39, 2, 0, 66, 66, 98, 98, 466, 0, 1, 1, 0, 0, 0, 0, 3, 1, 0,
- 0, 0, 0, 5, 1, 0, 0, 0, 0, 7, 1, 0, 0, 0, 0, 9, 1, 0, 0, 0, 0, 11, 1, 0,
- 0, 0, 0, 13, 1, 0, 0, 0, 0, 15, 1, 0, 0, 0, 0, 17, 1, 0, 0, 0, 0, 19, 1,
- 0, 0, 0, 0, 21, 1, 0, 0, 0, 0, 23, 1, 0, 0, 0, 0, 25, 1, 0, 0, 0, 0, 27,
- 1, 0, 0, 0, 0, 29, 1, 0, 0, 0, 0, 31, 1, 0, 0, 0, 0, 33, 1, 0, 0, 0, 0,
- 35, 1, 0, 0, 0, 0, 37, 1, 0, 0, 0, 0, 39, 1, 0, 0, 0, 0, 41, 1, 0, 0, 0,
- 0, 43, 1, 0, 0, 0, 0, 45, 1, 0, 0, 0, 0, 47, 1, 0, 0, 0, 0, 49, 1, 0, 0,
- 0, 0, 51, 1, 0, 0, 0, 0, 53, 1, 0, 0, 0, 0, 55, 1, 0, 0, 0, 0, 57, 1, 0,
- 0, 0, 0, 59, 1, 0, 0, 0, 0, 83, 1, 0, 0, 0, 0, 85, 1, 0, 0, 0, 0, 87, 1,
- 0, 0, 0, 0, 89, 1, 0, 0, 0, 0, 91, 1, 0, 0, 0, 0, 93, 1, 0, 0, 0, 0, 95,
- 1, 0, 0, 0, 0, 97, 1, 0, 0, 0, 1, 99, 1, 0, 0, 0, 3, 102, 1, 0, 0, 0, 5,
- 105, 1, 0, 0, 0, 7, 108, 1, 0, 0, 0, 9, 111, 1, 0, 0, 0, 11, 114, 1, 0,
- 0, 0, 13, 116, 1, 0, 0, 0, 15, 119, 1, 0, 0, 0, 17, 122, 1, 0, 0, 0, 19,
- 124, 1, 0, 0, 0, 21, 127, 1, 0, 0, 0, 23, 130, 1, 0, 0, 0, 25, 132, 1,
- 0, 0, 0, 27, 134, 1, 0, 0, 0, 29, 136, 1, 0, 0, 0, 31, 138, 1, 0, 0, 0,
- 33, 140, 1, 0, 0, 0, 35, 142, 1, 0, 0, 0, 37, 144, 1, 0, 0, 0, 39, 146,
- 1, 0, 0, 0, 41, 148, 1, 0, 0, 0, 43, 150, 1, 0, 0, 0, 45, 152, 1, 0, 0,
- 0, 47, 154, 1, 0, 0, 0, 49, 156, 1, 0, 0, 0, 51, 158, 1, 0, 0, 0, 53, 160,
- 1, 0, 0, 0, 55, 162, 1, 0, 0, 0, 57, 167, 1, 0, 0, 0, 59, 173, 1, 0, 0,
- 0, 61, 178, 1, 0, 0, 0, 63, 180, 1, 0, 0, 0, 65, 182, 1, 0, 0, 0, 67, 184,
- 1, 0, 0, 0, 69, 193, 1, 0, 0, 0, 71, 195, 1, 0, 0, 0, 73, 201, 1, 0, 0,
- 0, 75, 203, 1, 0, 0, 0, 77, 206, 1, 0, 0, 0, 79, 211, 1, 0, 0, 0, 81, 234,
- 1, 0, 0, 0, 83, 237, 1, 0, 0, 0, 85, 243, 1, 0, 0, 0, 87, 284, 1, 0, 0,
- 0, 89, 299, 1, 0, 0, 0, 91, 318, 1, 0, 0, 0, 93, 416, 1, 0, 0, 0, 95, 418,
- 1, 0, 0, 0, 97, 423, 1, 0, 0, 0, 99, 100, 5, 46, 0, 0, 100, 101, 5, 63,
- 0, 0, 101, 2, 1, 0, 0, 0, 102, 103, 5, 91, 0, 0, 103, 104, 5, 63, 0, 0,
- 104, 4, 1, 0, 0, 0, 105, 106, 5, 61, 0, 0, 106, 107, 5, 61, 0, 0, 107,
- 6, 1, 0, 0, 0, 108, 109, 5, 33, 0, 0, 109, 110, 5, 61, 0, 0, 110, 8, 1,
- 0, 0, 0, 111, 112, 5, 105, 0, 0, 112, 113, 5, 110, 0, 0, 113, 10, 1, 0,
- 0, 0, 114, 115, 5, 60, 0, 0, 115, 12, 1, 0, 0, 0, 116, 117, 5, 60, 0, 0,
- 117, 118, 5, 61, 0, 0, 118, 14, 1, 0, 0, 0, 119, 120, 5, 62, 0, 0, 120,
- 121, 5, 61, 0, 0, 121, 16, 1, 0, 0, 0, 122, 123, 5, 62, 0, 0, 123, 18,
- 1, 0, 0, 0, 124, 125, 5, 38, 0, 0, 125, 126, 5, 38, 0, 0, 126, 20, 1, 0,
- 0, 0, 127, 128, 5, 124, 0, 0, 128, 129, 5, 124, 0, 0, 129, 22, 1, 0, 0,
- 0, 130, 131, 5, 91, 0, 0, 131, 24, 1, 0, 0, 0, 132, 133, 5, 93, 0, 0, 133,
- 26, 1, 0, 0, 0, 134, 135, 5, 123, 0, 0, 135, 28, 1, 0, 0, 0, 136, 137,
- 5, 125, 0, 0, 137, 30, 1, 0, 0, 0, 138, 139, 5, 40, 0, 0, 139, 32, 1, 0,
- 0, 0, 140, 141, 5, 41, 0, 0, 141, 34, 1, 0, 0, 0, 142, 143, 5, 46, 0, 0,
- 143, 36, 1, 0, 0, 0, 144, 145, 5, 44, 0, 0, 145, 38, 1, 0, 0, 0, 146, 147,
- 5, 45, 0, 0, 147, 40, 1, 0, 0, 0, 148, 149, 5, 33, 0, 0, 149, 42, 1, 0,
- 0, 0, 150, 151, 5, 63, 0, 0, 151, 44, 1, 0, 0, 0, 152, 153, 5, 58, 0, 0,
- 153, 46, 1, 0, 0, 0, 154, 155, 5, 43, 0, 0, 155, 48, 1, 0, 0, 0, 156, 157,
- 5, 42, 0, 0, 157, 50, 1, 0, 0, 0, 158, 159, 5, 47, 0, 0, 159, 52, 1, 0,
- 0, 0, 160, 161, 5, 37, 0, 0, 161, 54, 1, 0, 0, 0, 162, 163, 5, 116, 0,
- 0, 163, 164, 5, 114, 0, 0, 164, 165, 5, 117, 0, 0, 165, 166, 5, 101, 0,
- 0, 166, 56, 1, 0, 0, 0, 167, 168, 5, 102, 0, 0, 168, 169, 5, 97, 0, 0,
- 169, 170, 5, 108, 0, 0, 170, 171, 5, 115, 0, 0, 171, 172, 5, 101, 0, 0,
- 172, 58, 1, 0, 0, 0, 173, 174, 5, 110, 0, 0, 174, 175, 5, 117, 0, 0, 175,
- 176, 5, 108, 0, 0, 176, 177, 5, 108, 0, 0, 177, 60, 1, 0, 0, 0, 178, 179,
- 5, 92, 0, 0, 179, 62, 1, 0, 0, 0, 180, 181, 7, 0, 0, 0, 181, 64, 1, 0,
- 0, 0, 182, 183, 2, 48, 57, 0, 183, 66, 1, 0, 0, 0, 184, 186, 7, 1, 0, 0,
- 185, 187, 7, 2, 0, 0, 186, 185, 1, 0, 0, 0, 186, 187, 1, 0, 0, 0, 187,
- 189, 1, 0, 0, 0, 188, 190, 3, 65, 32, 0, 189, 188, 1, 0, 0, 0, 190, 191,
- 1, 0, 0, 0, 191, 189, 1, 0, 0, 0, 191, 192, 1, 0, 0, 0, 192, 68, 1, 0,
- 0, 0, 193, 194, 7, 3, 0, 0, 194, 70, 1, 0, 0, 0, 195, 196, 7, 4, 0, 0,
- 196, 72, 1, 0, 0, 0, 197, 202, 3, 75, 37, 0, 198, 202, 3, 79, 39, 0, 199,
- 202, 3, 81, 40, 0, 200, 202, 3, 77, 38, 0, 201, 197, 1, 0, 0, 0, 201, 198,
- 1, 0, 0, 0, 201, 199, 1, 0, 0, 0, 201, 200, 1, 0, 0, 0, 202, 74, 1, 0,
- 0, 0, 203, 204, 3, 61, 30, 0, 204, 205, 7, 5, 0, 0, 205, 76, 1, 0, 0, 0,
- 206, 207, 3, 61, 30, 0, 207, 208, 2, 48, 51, 0, 208, 209, 2, 48, 55, 0,
- 209, 210, 2, 48, 55, 0, 210, 78, 1, 0, 0, 0, 211, 212, 3, 61, 30, 0, 212,
- 213, 7, 6, 0, 0, 213, 214, 3, 69, 34, 0, 214, 215, 3, 69, 34, 0, 215, 80,
- 1, 0, 0, 0, 216, 217, 3, 61, 30, 0, 217, 218, 5, 117, 0, 0, 218, 219, 3,
- 69, 34, 0, 219, 220, 3, 69, 34, 0, 220, 221, 3, 69, 34, 0, 221, 222, 3,
- 69, 34, 0, 222, 235, 1, 0, 0, 0, 223, 224, 3, 61, 30, 0, 224, 225, 5, 85,
- 0, 0, 225, 226, 3, 69, 34, 0, 226, 227, 3, 69, 34, 0, 227, 228, 3, 69,
- 34, 0, 228, 229, 3, 69, 34, 0, 229, 230, 3, 69, 34, 0, 230, 231, 3, 69,
- 34, 0, 231, 232, 3, 69, 34, 0, 232, 233, 3, 69, 34, 0, 233, 235, 1, 0,
- 0, 0, 234, 216, 1, 0, 0, 0, 234, 223, 1, 0, 0, 0, 235, 82, 1, 0, 0, 0,
- 236, 238, 7, 7, 0, 0, 237, 236, 1, 0, 0, 0, 238, 239, 1, 0, 0, 0, 239,
- 237, 1, 0, 0, 0, 239, 240, 1, 0, 0, 0, 240, 241, 1, 0, 0, 0, 241, 242,
- 6, 41, 0, 0, 242, 84, 1, 0, 0, 0, 243, 244, 5, 47, 0, 0, 244, 245, 5, 47,
- 0, 0, 245, 249, 1, 0, 0, 0, 246, 248, 8, 8, 0, 0, 247, 246, 1, 0, 0, 0,
- 248, 251, 1, 0, 0, 0, 249, 247, 1, 0, 0, 0, 249, 250, 1, 0, 0, 0, 250,
- 252, 1, 0, 0, 0, 251, 249, 1, 0, 0, 0, 252, 253, 6, 42, 0, 0, 253, 86,
- 1, 0, 0, 0, 254, 256, 3, 65, 32, 0, 255, 254, 1, 0, 0, 0, 256, 257, 1,
- 0, 0, 0, 257, 255, 1, 0, 0, 0, 257, 258, 1, 0, 0, 0, 258, 259, 1, 0, 0,
- 0, 259, 261, 5, 46, 0, 0, 260, 262, 3, 65, 32, 0, 261, 260, 1, 0, 0, 0,
- 262, 263, 1, 0, 0, 0, 263, 261, 1, 0, 0, 0, 263, 264, 1, 0, 0, 0, 264,
- 266, 1, 0, 0, 0, 265, 267, 3, 67, 33, 0, 266, 265, 1, 0, 0, 0, 266, 267,
- 1, 0, 0, 0, 267, 285, 1, 0, 0, 0, 268, 270, 3, 65, 32, 0, 269, 268, 1,
- 0, 0, 0, 270, 271, 1, 0, 0, 0, 271, 269, 1, 0, 0, 0, 271, 272, 1, 0, 0,
- 0, 272, 273, 1, 0, 0, 0, 273, 274, 3, 67, 33, 0, 274, 285, 1, 0, 0, 0,
- 275, 277, 5, 46, 0, 0, 276, 278, 3, 65, 32, 0, 277, 276, 1, 0, 0, 0, 278,
- 279, 1, 0, 0, 0, 279, 277, 1, 0, 0, 0, 279, 280, 1, 0, 0, 0, 280, 282,
- 1, 0, 0, 0, 281, 283, 3, 67, 33, 0, 282, 281, 1, 0, 0, 0, 282, 283, 1,
- 0, 0, 0, 283, 285, 1, 0, 0, 0, 284, 255, 1, 0, 0, 0, 284, 269, 1, 0, 0,
- 0, 284, 275, 1, 0, 0, 0, 285, 88, 1, 0, 0, 0, 286, 288, 3, 65, 32, 0, 287,
- 286, 1, 0, 0, 0, 288, 289, 1, 0, 0, 0, 289, 287, 1, 0, 0, 0, 289, 290,
- 1, 0, 0, 0, 290, 300, 1, 0, 0, 0, 291, 292, 5, 48, 0, 0, 292, 293, 5, 120,
- 0, 0, 293, 295, 1, 0, 0, 0, 294, 296, 3, 69, 34, 0, 295, 294, 1, 0, 0,
- 0, 296, 297, 1, 0, 0, 0, 297, 295, 1, 0, 0, 0, 297, 298, 1, 0, 0, 0, 298,
- 300, 1, 0, 0, 0, 299, 287, 1, 0, 0, 0, 299, 291, 1, 0, 0, 0, 300, 90, 1,
- 0, 0, 0, 301, 303, 3, 65, 32, 0, 302, 301, 1, 0, 0, 0, 303, 304, 1, 0,
- 0, 0, 304, 302, 1, 0, 0, 0, 304, 305, 1, 0, 0, 0, 305, 306, 1, 0, 0, 0,
- 306, 307, 7, 9, 0, 0, 307, 319, 1, 0, 0, 0, 308, 309, 5, 48, 0, 0, 309,
- 310, 5, 120, 0, 0, 310, 312, 1, 0, 0, 0, 311, 313, 3, 69, 34, 0, 312, 311,
- 1, 0, 0, 0, 313, 314, 1, 0, 0, 0, 314, 312, 1, 0, 0, 0, 314, 315, 1, 0,
- 0, 0, 315, 316, 1, 0, 0, 0, 316, 317, 7, 9, 0, 0, 317, 319, 1, 0, 0, 0,
- 318, 302, 1, 0, 0, 0, 318, 308, 1, 0, 0, 0, 319, 92, 1, 0, 0, 0, 320, 325,
- 5, 34, 0, 0, 321, 324, 3, 73, 36, 0, 322, 324, 8, 10, 0, 0, 323, 321, 1,
- 0, 0, 0, 323, 322, 1, 0, 0, 0, 324, 327, 1, 0, 0, 0, 325, 323, 1, 0, 0,
- 0, 325, 326, 1, 0, 0, 0, 326, 328, 1, 0, 0, 0, 327, 325, 1, 0, 0, 0, 328,
- 417, 5, 34, 0, 0, 329, 334, 5, 39, 0, 0, 330, 333, 3, 73, 36, 0, 331, 333,
- 8, 11, 0, 0, 332, 330, 1, 0, 0, 0, 332, 331, 1, 0, 0, 0, 333, 336, 1, 0,
- 0, 0, 334, 332, 1, 0, 0, 0, 334, 335, 1, 0, 0, 0, 335, 337, 1, 0, 0, 0,
- 336, 334, 1, 0, 0, 0, 337, 417, 5, 39, 0, 0, 338, 339, 5, 34, 0, 0, 339,
- 340, 5, 34, 0, 0, 340, 341, 5, 34, 0, 0, 341, 346, 1, 0, 0, 0, 342, 345,
- 3, 73, 36, 0, 343, 345, 8, 12, 0, 0, 344, 342, 1, 0, 0, 0, 344, 343, 1,
- 0, 0, 0, 345, 348, 1, 0, 0, 0, 346, 347, 1, 0, 0, 0, 346, 344, 1, 0, 0,
- 0, 347, 349, 1, 0, 0, 0, 348, 346, 1, 0, 0, 0, 349, 350, 5, 34, 0, 0, 350,
- 351, 5, 34, 0, 0, 351, 417, 5, 34, 0, 0, 352, 353, 5, 39, 0, 0, 353, 354,
- 5, 39, 0, 0, 354, 355, 5, 39, 0, 0, 355, 360, 1, 0, 0, 0, 356, 359, 3,
- 73, 36, 0, 357, 359, 8, 12, 0, 0, 358, 356, 1, 0, 0, 0, 358, 357, 1, 0,
- 0, 0, 359, 362, 1, 0, 0, 0, 360, 361, 1, 0, 0, 0, 360, 358, 1, 0, 0, 0,
- 361, 363, 1, 0, 0, 0, 362, 360, 1, 0, 0, 0, 363, 364, 5, 39, 0, 0, 364,
- 365, 5, 39, 0, 0, 365, 417, 5, 39, 0, 0, 366, 367, 3, 71, 35, 0, 367, 371,
- 5, 34, 0, 0, 368, 370, 8, 13, 0, 0, 369, 368, 1, 0, 0, 0, 370, 373, 1,
- 0, 0, 0, 371, 369, 1, 0, 0, 0, 371, 372, 1, 0, 0, 0, 372, 374, 1, 0, 0,
- 0, 373, 371, 1, 0, 0, 0, 374, 375, 5, 34, 0, 0, 375, 417, 1, 0, 0, 0, 376,
- 377, 3, 71, 35, 0, 377, 381, 5, 39, 0, 0, 378, 380, 8, 14, 0, 0, 379, 378,
- 1, 0, 0, 0, 380, 383, 1, 0, 0, 0, 381, 379, 1, 0, 0, 0, 381, 382, 1, 0,
- 0, 0, 382, 384, 1, 0, 0, 0, 383, 381, 1, 0, 0, 0, 384, 385, 5, 39, 0, 0,
- 385, 417, 1, 0, 0, 0, 386, 387, 3, 71, 35, 0, 387, 388, 5, 34, 0, 0, 388,
- 389, 5, 34, 0, 0, 389, 390, 5, 34, 0, 0, 390, 394, 1, 0, 0, 0, 391, 393,
- 9, 0, 0, 0, 392, 391, 1, 0, 0, 0, 393, 396, 1, 0, 0, 0, 394, 395, 1, 0,
- 0, 0, 394, 392, 1, 0, 0, 0, 395, 397, 1, 0, 0, 0, 396, 394, 1, 0, 0, 0,
- 397, 398, 5, 34, 0, 0, 398, 399, 5, 34, 0, 0, 399, 400, 5, 34, 0, 0, 400,
- 417, 1, 0, 0, 0, 401, 402, 3, 71, 35, 0, 402, 403, 5, 39, 0, 0, 403, 404,
- 5, 39, 0, 0, 404, 405, 5, 39, 0, 0, 405, 409, 1, 0, 0, 0, 406, 408, 9,
- 0, 0, 0, 407, 406, 1, 0, 0, 0, 408, 411, 1, 0, 0, 0, 409, 410, 1, 0, 0,
- 0, 409, 407, 1, 0, 0, 0, 410, 412, 1, 0, 0, 0, 411, 409, 1, 0, 0, 0, 412,
- 413, 5, 39, 0, 0, 413, 414, 5, 39, 0, 0, 414, 415, 5, 39, 0, 0, 415, 417,
- 1, 0, 0, 0, 416, 320, 1, 0, 0, 0, 416, 329, 1, 0, 0, 0, 416, 338, 1, 0,
- 0, 0, 416, 352, 1, 0, 0, 0, 416, 366, 1, 0, 0, 0, 416, 376, 1, 0, 0, 0,
- 416, 386, 1, 0, 0, 0, 416, 401, 1, 0, 0, 0, 417, 94, 1, 0, 0, 0, 418, 419,
- 7, 15, 0, 0, 419, 420, 3, 93, 46, 0, 420, 96, 1, 0, 0, 0, 421, 424, 3,
- 63, 31, 0, 422, 424, 5, 95, 0, 0, 423, 421, 1, 0, 0, 0, 423, 422, 1, 0,
- 0, 0, 424, 430, 1, 0, 0, 0, 425, 429, 3, 63, 31, 0, 426, 429, 3, 65, 32,
- 0, 427, 429, 5, 95, 0, 0, 428, 425, 1, 0, 0, 0, 428, 426, 1, 0, 0, 0, 428,
- 427, 1, 0, 0, 0, 429, 432, 1, 0, 0, 0, 430, 428, 1, 0, 0, 0, 430, 431,
- 1, 0, 0, 0, 431, 98, 1, 0, 0, 0, 432, 430, 1, 0, 0, 0, 36, 0, 186, 191,
- 201, 234, 239, 249, 257, 263, 266, 271, 279, 282, 284, 289, 297, 299, 304,
- 314, 318, 323, 325, 332, 334, 344, 346, 358, 360, 371, 381, 394, 409, 416,
- 423, 428, 430, 1, 0, 1, 0,
+ 23, 47, 24, 49, 25, 51, 26, 53, 27, 55, 28, 57, 0, 59, 0, 61, 0, 63, 0,
+ 65, 0, 67, 0, 69, 0, 71, 0, 73, 0, 75, 0, 77, 0, 79, 29, 81, 30, 83, 31,
+ 85, 32, 87, 33, 89, 34, 91, 35, 93, 36, 1, 0, 16, 2, 0, 65, 90, 97, 122,
+ 2, 0, 69, 69, 101, 101, 2, 0, 43, 43, 45, 45, 3, 0, 48, 57, 65, 70, 97,
+ 102, 2, 0, 82, 82, 114, 114, 10, 0, 34, 34, 39, 39, 63, 63, 92, 92, 96,
+ 98, 102, 102, 110, 110, 114, 114, 116, 116, 118, 118, 2, 0, 88, 88, 120,
+ 120, 3, 0, 9, 10, 12, 13, 32, 32, 1, 0, 10, 10, 2, 0, 85, 85, 117, 117,
+ 4, 0, 10, 10, 13, 13, 34, 34, 92, 92, 4, 0, 10, 10, 13, 13, 39, 39, 92,
+ 92, 1, 0, 92, 92, 3, 0, 10, 10, 13, 13, 34, 34, 3, 0, 10, 10, 13, 13, 39,
+ 39, 2, 0, 66, 66, 98, 98, 456, 0, 1, 1, 0, 0, 0, 0, 3, 1, 0, 0, 0, 0, 5,
+ 1, 0, 0, 0, 0, 7, 1, 0, 0, 0, 0, 9, 1, 0, 0, 0, 0, 11, 1, 0, 0, 0, 0, 13,
+ 1, 0, 0, 0, 0, 15, 1, 0, 0, 0, 0, 17, 1, 0, 0, 0, 0, 19, 1, 0, 0, 0, 0,
+ 21, 1, 0, 0, 0, 0, 23, 1, 0, 0, 0, 0, 25, 1, 0, 0, 0, 0, 27, 1, 0, 0, 0,
+ 0, 29, 1, 0, 0, 0, 0, 31, 1, 0, 0, 0, 0, 33, 1, 0, 0, 0, 0, 35, 1, 0, 0,
+ 0, 0, 37, 1, 0, 0, 0, 0, 39, 1, 0, 0, 0, 0, 41, 1, 0, 0, 0, 0, 43, 1, 0,
+ 0, 0, 0, 45, 1, 0, 0, 0, 0, 47, 1, 0, 0, 0, 0, 49, 1, 0, 0, 0, 0, 51, 1,
+ 0, 0, 0, 0, 53, 1, 0, 0, 0, 0, 55, 1, 0, 0, 0, 0, 79, 1, 0, 0, 0, 0, 81,
+ 1, 0, 0, 0, 0, 83, 1, 0, 0, 0, 0, 85, 1, 0, 0, 0, 0, 87, 1, 0, 0, 0, 0,
+ 89, 1, 0, 0, 0, 0, 91, 1, 0, 0, 0, 0, 93, 1, 0, 0, 0, 1, 95, 1, 0, 0, 0,
+ 3, 98, 1, 0, 0, 0, 5, 101, 1, 0, 0, 0, 7, 104, 1, 0, 0, 0, 9, 106, 1, 0,
+ 0, 0, 11, 109, 1, 0, 0, 0, 13, 112, 1, 0, 0, 0, 15, 114, 1, 0, 0, 0, 17,
+ 117, 1, 0, 0, 0, 19, 120, 1, 0, 0, 0, 21, 122, 1, 0, 0, 0, 23, 124, 1,
+ 0, 0, 0, 25, 126, 1, 0, 0, 0, 27, 128, 1, 0, 0, 0, 29, 130, 1, 0, 0, 0,
+ 31, 132, 1, 0, 0, 0, 33, 134, 1, 0, 0, 0, 35, 136, 1, 0, 0, 0, 37, 138,
+ 1, 0, 0, 0, 39, 140, 1, 0, 0, 0, 41, 142, 1, 0, 0, 0, 43, 144, 1, 0, 0,
+ 0, 45, 146, 1, 0, 0, 0, 47, 148, 1, 0, 0, 0, 49, 150, 1, 0, 0, 0, 51, 152,
+ 1, 0, 0, 0, 53, 157, 1, 0, 0, 0, 55, 163, 1, 0, 0, 0, 57, 168, 1, 0, 0,
+ 0, 59, 170, 1, 0, 0, 0, 61, 172, 1, 0, 0, 0, 63, 174, 1, 0, 0, 0, 65, 183,
+ 1, 0, 0, 0, 67, 185, 1, 0, 0, 0, 69, 191, 1, 0, 0, 0, 71, 193, 1, 0, 0,
+ 0, 73, 196, 1, 0, 0, 0, 75, 201, 1, 0, 0, 0, 77, 224, 1, 0, 0, 0, 79, 227,
+ 1, 0, 0, 0, 81, 233, 1, 0, 0, 0, 83, 274, 1, 0, 0, 0, 85, 289, 1, 0, 0,
+ 0, 87, 308, 1, 0, 0, 0, 89, 406, 1, 0, 0, 0, 91, 408, 1, 0, 0, 0, 93, 413,
+ 1, 0, 0, 0, 95, 96, 5, 61, 0, 0, 96, 97, 5, 61, 0, 0, 97, 2, 1, 0, 0, 0,
+ 98, 99, 5, 33, 0, 0, 99, 100, 5, 61, 0, 0, 100, 4, 1, 0, 0, 0, 101, 102,
+ 5, 105, 0, 0, 102, 103, 5, 110, 0, 0, 103, 6, 1, 0, 0, 0, 104, 105, 5,
+ 60, 0, 0, 105, 8, 1, 0, 0, 0, 106, 107, 5, 60, 0, 0, 107, 108, 5, 61, 0,
+ 0, 108, 10, 1, 0, 0, 0, 109, 110, 5, 62, 0, 0, 110, 111, 5, 61, 0, 0, 111,
+ 12, 1, 0, 0, 0, 112, 113, 5, 62, 0, 0, 113, 14, 1, 0, 0, 0, 114, 115, 5,
+ 38, 0, 0, 115, 116, 5, 38, 0, 0, 116, 16, 1, 0, 0, 0, 117, 118, 5, 124,
+ 0, 0, 118, 119, 5, 124, 0, 0, 119, 18, 1, 0, 0, 0, 120, 121, 5, 91, 0,
+ 0, 121, 20, 1, 0, 0, 0, 122, 123, 5, 93, 0, 0, 123, 22, 1, 0, 0, 0, 124,
+ 125, 5, 123, 0, 0, 125, 24, 1, 0, 0, 0, 126, 127, 5, 125, 0, 0, 127, 26,
+ 1, 0, 0, 0, 128, 129, 5, 40, 0, 0, 129, 28, 1, 0, 0, 0, 130, 131, 5, 41,
+ 0, 0, 131, 30, 1, 0, 0, 0, 132, 133, 5, 46, 0, 0, 133, 32, 1, 0, 0, 0,
+ 134, 135, 5, 44, 0, 0, 135, 34, 1, 0, 0, 0, 136, 137, 5, 45, 0, 0, 137,
+ 36, 1, 0, 0, 0, 138, 139, 5, 33, 0, 0, 139, 38, 1, 0, 0, 0, 140, 141, 5,
+ 63, 0, 0, 141, 40, 1, 0, 0, 0, 142, 143, 5, 58, 0, 0, 143, 42, 1, 0, 0,
+ 0, 144, 145, 5, 43, 0, 0, 145, 44, 1, 0, 0, 0, 146, 147, 5, 42, 0, 0, 147,
+ 46, 1, 0, 0, 0, 148, 149, 5, 47, 0, 0, 149, 48, 1, 0, 0, 0, 150, 151, 5,
+ 37, 0, 0, 151, 50, 1, 0, 0, 0, 152, 153, 5, 116, 0, 0, 153, 154, 5, 114,
+ 0, 0, 154, 155, 5, 117, 0, 0, 155, 156, 5, 101, 0, 0, 156, 52, 1, 0, 0,
+ 0, 157, 158, 5, 102, 0, 0, 158, 159, 5, 97, 0, 0, 159, 160, 5, 108, 0,
+ 0, 160, 161, 5, 115, 0, 0, 161, 162, 5, 101, 0, 0, 162, 54, 1, 0, 0, 0,
+ 163, 164, 5, 110, 0, 0, 164, 165, 5, 117, 0, 0, 165, 166, 5, 108, 0, 0,
+ 166, 167, 5, 108, 0, 0, 167, 56, 1, 0, 0, 0, 168, 169, 5, 92, 0, 0, 169,
+ 58, 1, 0, 0, 0, 170, 171, 7, 0, 0, 0, 171, 60, 1, 0, 0, 0, 172, 173, 2,
+ 48, 57, 0, 173, 62, 1, 0, 0, 0, 174, 176, 7, 1, 0, 0, 175, 177, 7, 2, 0,
+ 0, 176, 175, 1, 0, 0, 0, 176, 177, 1, 0, 0, 0, 177, 179, 1, 0, 0, 0, 178,
+ 180, 3, 61, 30, 0, 179, 178, 1, 0, 0, 0, 180, 181, 1, 0, 0, 0, 181, 179,
+ 1, 0, 0, 0, 181, 182, 1, 0, 0, 0, 182, 64, 1, 0, 0, 0, 183, 184, 7, 3,
+ 0, 0, 184, 66, 1, 0, 0, 0, 185, 186, 7, 4, 0, 0, 186, 68, 1, 0, 0, 0, 187,
+ 192, 3, 71, 35, 0, 188, 192, 3, 75, 37, 0, 189, 192, 3, 77, 38, 0, 190,
+ 192, 3, 73, 36, 0, 191, 187, 1, 0, 0, 0, 191, 188, 1, 0, 0, 0, 191, 189,
+ 1, 0, 0, 0, 191, 190, 1, 0, 0, 0, 192, 70, 1, 0, 0, 0, 193, 194, 3, 57,
+ 28, 0, 194, 195, 7, 5, 0, 0, 195, 72, 1, 0, 0, 0, 196, 197, 3, 57, 28,
+ 0, 197, 198, 2, 48, 51, 0, 198, 199, 2, 48, 55, 0, 199, 200, 2, 48, 55,
+ 0, 200, 74, 1, 0, 0, 0, 201, 202, 3, 57, 28, 0, 202, 203, 7, 6, 0, 0, 203,
+ 204, 3, 65, 32, 0, 204, 205, 3, 65, 32, 0, 205, 76, 1, 0, 0, 0, 206, 207,
+ 3, 57, 28, 0, 207, 208, 5, 117, 0, 0, 208, 209, 3, 65, 32, 0, 209, 210,
+ 3, 65, 32, 0, 210, 211, 3, 65, 32, 0, 211, 212, 3, 65, 32, 0, 212, 225,
+ 1, 0, 0, 0, 213, 214, 3, 57, 28, 0, 214, 215, 5, 85, 0, 0, 215, 216, 3,
+ 65, 32, 0, 216, 217, 3, 65, 32, 0, 217, 218, 3, 65, 32, 0, 218, 219, 3,
+ 65, 32, 0, 219, 220, 3, 65, 32, 0, 220, 221, 3, 65, 32, 0, 221, 222, 3,
+ 65, 32, 0, 222, 223, 3, 65, 32, 0, 223, 225, 1, 0, 0, 0, 224, 206, 1, 0,
+ 0, 0, 224, 213, 1, 0, 0, 0, 225, 78, 1, 0, 0, 0, 226, 228, 7, 7, 0, 0,
+ 227, 226, 1, 0, 0, 0, 228, 229, 1, 0, 0, 0, 229, 227, 1, 0, 0, 0, 229,
+ 230, 1, 0, 0, 0, 230, 231, 1, 0, 0, 0, 231, 232, 6, 39, 0, 0, 232, 80,
+ 1, 0, 0, 0, 233, 234, 5, 47, 0, 0, 234, 235, 5, 47, 0, 0, 235, 239, 1,
+ 0, 0, 0, 236, 238, 8, 8, 0, 0, 237, 236, 1, 0, 0, 0, 238, 241, 1, 0, 0,
+ 0, 239, 237, 1, 0, 0, 0, 239, 240, 1, 0, 0, 0, 240, 242, 1, 0, 0, 0, 241,
+ 239, 1, 0, 0, 0, 242, 243, 6, 40, 0, 0, 243, 82, 1, 0, 0, 0, 244, 246,
+ 3, 61, 30, 0, 245, 244, 1, 0, 0, 0, 246, 247, 1, 0, 0, 0, 247, 245, 1,
+ 0, 0, 0, 247, 248, 1, 0, 0, 0, 248, 249, 1, 0, 0, 0, 249, 251, 5, 46, 0,
+ 0, 250, 252, 3, 61, 30, 0, 251, 250, 1, 0, 0, 0, 252, 253, 1, 0, 0, 0,
+ 253, 251, 1, 0, 0, 0, 253, 254, 1, 0, 0, 0, 254, 256, 1, 0, 0, 0, 255,
+ 257, 3, 63, 31, 0, 256, 255, 1, 0, 0, 0, 256, 257, 1, 0, 0, 0, 257, 275,
+ 1, 0, 0, 0, 258, 260, 3, 61, 30, 0, 259, 258, 1, 0, 0, 0, 260, 261, 1,
+ 0, 0, 0, 261, 259, 1, 0, 0, 0, 261, 262, 1, 0, 0, 0, 262, 263, 1, 0, 0,
+ 0, 263, 264, 3, 63, 31, 0, 264, 275, 1, 0, 0, 0, 265, 267, 5, 46, 0, 0,
+ 266, 268, 3, 61, 30, 0, 267, 266, 1, 0, 0, 0, 268, 269, 1, 0, 0, 0, 269,
+ 267, 1, 0, 0, 0, 269, 270, 1, 0, 0, 0, 270, 272, 1, 0, 0, 0, 271, 273,
+ 3, 63, 31, 0, 272, 271, 1, 0, 0, 0, 272, 273, 1, 0, 0, 0, 273, 275, 1,
+ 0, 0, 0, 274, 245, 1, 0, 0, 0, 274, 259, 1, 0, 0, 0, 274, 265, 1, 0, 0,
+ 0, 275, 84, 1, 0, 0, 0, 276, 278, 3, 61, 30, 0, 277, 276, 1, 0, 0, 0, 278,
+ 279, 1, 0, 0, 0, 279, 277, 1, 0, 0, 0, 279, 280, 1, 0, 0, 0, 280, 290,
+ 1, 0, 0, 0, 281, 282, 5, 48, 0, 0, 282, 283, 5, 120, 0, 0, 283, 285, 1,
+ 0, 0, 0, 284, 286, 3, 65, 32, 0, 285, 284, 1, 0, 0, 0, 286, 287, 1, 0,
+ 0, 0, 287, 285, 1, 0, 0, 0, 287, 288, 1, 0, 0, 0, 288, 290, 1, 0, 0, 0,
+ 289, 277, 1, 0, 0, 0, 289, 281, 1, 0, 0, 0, 290, 86, 1, 0, 0, 0, 291, 293,
+ 3, 61, 30, 0, 292, 291, 1, 0, 0, 0, 293, 294, 1, 0, 0, 0, 294, 292, 1,
+ 0, 0, 0, 294, 295, 1, 0, 0, 0, 295, 296, 1, 0, 0, 0, 296, 297, 7, 9, 0,
+ 0, 297, 309, 1, 0, 0, 0, 298, 299, 5, 48, 0, 0, 299, 300, 5, 120, 0, 0,
+ 300, 302, 1, 0, 0, 0, 301, 303, 3, 65, 32, 0, 302, 301, 1, 0, 0, 0, 303,
+ 304, 1, 0, 0, 0, 304, 302, 1, 0, 0, 0, 304, 305, 1, 0, 0, 0, 305, 306,
+ 1, 0, 0, 0, 306, 307, 7, 9, 0, 0, 307, 309, 1, 0, 0, 0, 308, 292, 1, 0,
+ 0, 0, 308, 298, 1, 0, 0, 0, 309, 88, 1, 0, 0, 0, 310, 315, 5, 34, 0, 0,
+ 311, 314, 3, 69, 34, 0, 312, 314, 8, 10, 0, 0, 313, 311, 1, 0, 0, 0, 313,
+ 312, 1, 0, 0, 0, 314, 317, 1, 0, 0, 0, 315, 313, 1, 0, 0, 0, 315, 316,
+ 1, 0, 0, 0, 316, 318, 1, 0, 0, 0, 317, 315, 1, 0, 0, 0, 318, 407, 5, 34,
+ 0, 0, 319, 324, 5, 39, 0, 0, 320, 323, 3, 69, 34, 0, 321, 323, 8, 11, 0,
+ 0, 322, 320, 1, 0, 0, 0, 322, 321, 1, 0, 0, 0, 323, 326, 1, 0, 0, 0, 324,
+ 322, 1, 0, 0, 0, 324, 325, 1, 0, 0, 0, 325, 327, 1, 0, 0, 0, 326, 324,
+ 1, 0, 0, 0, 327, 407, 5, 39, 0, 0, 328, 329, 5, 34, 0, 0, 329, 330, 5,
+ 34, 0, 0, 330, 331, 5, 34, 0, 0, 331, 336, 1, 0, 0, 0, 332, 335, 3, 69,
+ 34, 0, 333, 335, 8, 12, 0, 0, 334, 332, 1, 0, 0, 0, 334, 333, 1, 0, 0,
+ 0, 335, 338, 1, 0, 0, 0, 336, 337, 1, 0, 0, 0, 336, 334, 1, 0, 0, 0, 337,
+ 339, 1, 0, 0, 0, 338, 336, 1, 0, 0, 0, 339, 340, 5, 34, 0, 0, 340, 341,
+ 5, 34, 0, 0, 341, 407, 5, 34, 0, 0, 342, 343, 5, 39, 0, 0, 343, 344, 5,
+ 39, 0, 0, 344, 345, 5, 39, 0, 0, 345, 350, 1, 0, 0, 0, 346, 349, 3, 69,
+ 34, 0, 347, 349, 8, 12, 0, 0, 348, 346, 1, 0, 0, 0, 348, 347, 1, 0, 0,
+ 0, 349, 352, 1, 0, 0, 0, 350, 351, 1, 0, 0, 0, 350, 348, 1, 0, 0, 0, 351,
+ 353, 1, 0, 0, 0, 352, 350, 1, 0, 0, 0, 353, 354, 5, 39, 0, 0, 354, 355,
+ 5, 39, 0, 0, 355, 407, 5, 39, 0, 0, 356, 357, 3, 67, 33, 0, 357, 361, 5,
+ 34, 0, 0, 358, 360, 8, 13, 0, 0, 359, 358, 1, 0, 0, 0, 360, 363, 1, 0,
+ 0, 0, 361, 359, 1, 0, 0, 0, 361, 362, 1, 0, 0, 0, 362, 364, 1, 0, 0, 0,
+ 363, 361, 1, 0, 0, 0, 364, 365, 5, 34, 0, 0, 365, 407, 1, 0, 0, 0, 366,
+ 367, 3, 67, 33, 0, 367, 371, 5, 39, 0, 0, 368, 370, 8, 14, 0, 0, 369, 368,
+ 1, 0, 0, 0, 370, 373, 1, 0, 0, 0, 371, 369, 1, 0, 0, 0, 371, 372, 1, 0,
+ 0, 0, 372, 374, 1, 0, 0, 0, 373, 371, 1, 0, 0, 0, 374, 375, 5, 39, 0, 0,
+ 375, 407, 1, 0, 0, 0, 376, 377, 3, 67, 33, 0, 377, 378, 5, 34, 0, 0, 378,
+ 379, 5, 34, 0, 0, 379, 380, 5, 34, 0, 0, 380, 384, 1, 0, 0, 0, 381, 383,
+ 9, 0, 0, 0, 382, 381, 1, 0, 0, 0, 383, 386, 1, 0, 0, 0, 384, 385, 1, 0,
+ 0, 0, 384, 382, 1, 0, 0, 0, 385, 387, 1, 0, 0, 0, 386, 384, 1, 0, 0, 0,
+ 387, 388, 5, 34, 0, 0, 388, 389, 5, 34, 0, 0, 389, 390, 5, 34, 0, 0, 390,
+ 407, 1, 0, 0, 0, 391, 392, 3, 67, 33, 0, 392, 393, 5, 39, 0, 0, 393, 394,
+ 5, 39, 0, 0, 394, 395, 5, 39, 0, 0, 395, 399, 1, 0, 0, 0, 396, 398, 9,
+ 0, 0, 0, 397, 396, 1, 0, 0, 0, 398, 401, 1, 0, 0, 0, 399, 400, 1, 0, 0,
+ 0, 399, 397, 1, 0, 0, 0, 400, 402, 1, 0, 0, 0, 401, 399, 1, 0, 0, 0, 402,
+ 403, 5, 39, 0, 0, 403, 404, 5, 39, 0, 0, 404, 405, 5, 39, 0, 0, 405, 407,
+ 1, 0, 0, 0, 406, 310, 1, 0, 0, 0, 406, 319, 1, 0, 0, 0, 406, 328, 1, 0,
+ 0, 0, 406, 342, 1, 0, 0, 0, 406, 356, 1, 0, 0, 0, 406, 366, 1, 0, 0, 0,
+ 406, 376, 1, 0, 0, 0, 406, 391, 1, 0, 0, 0, 407, 90, 1, 0, 0, 0, 408, 409,
+ 7, 15, 0, 0, 409, 410, 3, 89, 44, 0, 410, 92, 1, 0, 0, 0, 411, 414, 3,
+ 59, 29, 0, 412, 414, 5, 95, 0, 0, 413, 411, 1, 0, 0, 0, 413, 412, 1, 0,
+ 0, 0, 414, 420, 1, 0, 0, 0, 415, 419, 3, 59, 29, 0, 416, 419, 3, 61, 30,
+ 0, 417, 419, 5, 95, 0, 0, 418, 415, 1, 0, 0, 0, 418, 416, 1, 0, 0, 0, 418,
+ 417, 1, 0, 0, 0, 419, 422, 1, 0, 0, 0, 420, 418, 1, 0, 0, 0, 420, 421,
+ 1, 0, 0, 0, 421, 94, 1, 0, 0, 0, 422, 420, 1, 0, 0, 0, 36, 0, 176, 181,
+ 191, 224, 229, 239, 247, 253, 256, 261, 269, 272, 274, 279, 287, 289, 294,
+ 304, 308, 313, 315, 322, 324, 334, 336, 348, 350, 361, 371, 384, 399, 406,
+ 413, 418, 420, 1, 0, 1, 0,
}
deserializer := antlr.NewATNDeserializer(nil)
staticData.atn = deserializer.Deserialize(staticData.serializedATN)
@@ -311,42 +306,40 @@ func NewCELLexer(input antlr.CharStream) *CELLexer {
// CELLexer tokens.
const (
- CELLexerT__0 = 1
- CELLexerT__1 = 2
- CELLexerEQUALS = 3
- CELLexerNOT_EQUALS = 4
- CELLexerIN = 5
- CELLexerLESS = 6
- CELLexerLESS_EQUALS = 7
- CELLexerGREATER_EQUALS = 8
- CELLexerGREATER = 9
- CELLexerLOGICAL_AND = 10
- CELLexerLOGICAL_OR = 11
- CELLexerLBRACKET = 12
- CELLexerRPRACKET = 13
- CELLexerLBRACE = 14
- CELLexerRBRACE = 15
- CELLexerLPAREN = 16
- CELLexerRPAREN = 17
- CELLexerDOT = 18
- CELLexerCOMMA = 19
- CELLexerMINUS = 20
- CELLexerEXCLAM = 21
- CELLexerQUESTIONMARK = 22
- CELLexerCOLON = 23
- CELLexerPLUS = 24
- CELLexerSTAR = 25
- CELLexerSLASH = 26
- CELLexerPERCENT = 27
- CELLexerCEL_TRUE = 28
- CELLexerCEL_FALSE = 29
- CELLexerNUL = 30
- CELLexerWHITESPACE = 31
- CELLexerCOMMENT = 32
- CELLexerNUM_FLOAT = 33
- CELLexerNUM_INT = 34
- CELLexerNUM_UINT = 35
- CELLexerSTRING = 36
- CELLexerBYTES = 37
- CELLexerIDENTIFIER = 38
+ CELLexerEQUALS = 1
+ CELLexerNOT_EQUALS = 2
+ CELLexerIN = 3
+ CELLexerLESS = 4
+ CELLexerLESS_EQUALS = 5
+ CELLexerGREATER_EQUALS = 6
+ CELLexerGREATER = 7
+ CELLexerLOGICAL_AND = 8
+ CELLexerLOGICAL_OR = 9
+ CELLexerLBRACKET = 10
+ CELLexerRPRACKET = 11
+ CELLexerLBRACE = 12
+ CELLexerRBRACE = 13
+ CELLexerLPAREN = 14
+ CELLexerRPAREN = 15
+ CELLexerDOT = 16
+ CELLexerCOMMA = 17
+ CELLexerMINUS = 18
+ CELLexerEXCLAM = 19
+ CELLexerQUESTIONMARK = 20
+ CELLexerCOLON = 21
+ CELLexerPLUS = 22
+ CELLexerSTAR = 23
+ CELLexerSLASH = 24
+ CELLexerPERCENT = 25
+ CELLexerCEL_TRUE = 26
+ CELLexerCEL_FALSE = 27
+ CELLexerNUL = 28
+ CELLexerWHITESPACE = 29
+ CELLexerCOMMENT = 30
+ CELLexerNUM_FLOAT = 31
+ CELLexerNUM_INT = 32
+ CELLexerNUM_UINT = 33
+ CELLexerSTRING = 34
+ CELLexerBYTES = 35
+ CELLexerIDENTIFIER = 36
)
diff --git a/vendor/github.com/google/cel-go/parser/gen/cel_listener.go b/vendor/github.com/google/cel-go/parser/gen/cel_listener.go
index 8557fbad7..73b7f1d39 100644
--- a/vendor/github.com/google/cel-go/parser/gen/cel_listener.go
+++ b/vendor/github.com/google/cel-go/parser/gen/cel_listener.go
@@ -1,7 +1,7 @@
-// Code generated from /Users/tswadell/go/src/github.com/google/cel-go/parser/gen/CEL.g4 by ANTLR 4.10.1. DO NOT EDIT.
+// Code generated from /Users/tswadell/go/src/github.com/google/cel-go/parser/gen/CEL.g4 by ANTLR 4.12.0. DO NOT EDIT.
package gen // CEL
-import "github.com/antlr/antlr4/runtime/Go/antlr"
+import "github.com/antlr/antlr4/runtime/Go/antlr/v4"
// CELListener is a complete listener for a parse tree produced by CELParser.
type CELListener interface {
@@ -67,6 +67,9 @@ type CELListener interface {
// EnterExprList is called when entering the exprList production.
EnterExprList(c *ExprListContext)
+ // EnterListInit is called when entering the listInit production.
+ EnterListInit(c *ListInitContext)
+
// EnterFieldInitializerList is called when entering the fieldInitializerList production.
EnterFieldInitializerList(c *FieldInitializerListContext)
@@ -76,8 +79,8 @@ type CELListener interface {
// EnterMapInitializerList is called when entering the mapInitializerList production.
EnterMapInitializerList(c *MapInitializerListContext)
- // EnterOptKey is called when entering the optKey production.
- EnterOptKey(c *OptKeyContext)
+ // EnterOptExpr is called when entering the optExpr production.
+ EnterOptExpr(c *OptExprContext)
// EnterInt is called when entering the Int production.
EnterInt(c *IntContext)
@@ -163,6 +166,9 @@ type CELListener interface {
// ExitExprList is called when exiting the exprList production.
ExitExprList(c *ExprListContext)
+ // ExitListInit is called when exiting the listInit production.
+ ExitListInit(c *ListInitContext)
+
// ExitFieldInitializerList is called when exiting the fieldInitializerList production.
ExitFieldInitializerList(c *FieldInitializerListContext)
@@ -172,8 +178,8 @@ type CELListener interface {
// ExitMapInitializerList is called when exiting the mapInitializerList production.
ExitMapInitializerList(c *MapInitializerListContext)
- // ExitOptKey is called when exiting the optKey production.
- ExitOptKey(c *OptKeyContext)
+ // ExitOptExpr is called when exiting the optExpr production.
+ ExitOptExpr(c *OptExprContext)
// ExitInt is called when exiting the Int production.
ExitInt(c *IntContext)
diff --git a/vendor/github.com/google/cel-go/parser/gen/cel_parser.go b/vendor/github.com/google/cel-go/parser/gen/cel_parser.go
index f821f5ae8..0cb6c8eae 100644
--- a/vendor/github.com/google/cel-go/parser/gen/cel_parser.go
+++ b/vendor/github.com/google/cel-go/parser/gen/cel_parser.go
@@ -1,4 +1,4 @@
-// Code generated from /Users/tswadell/go/src/github.com/google/cel-go/parser/gen/CEL.g4 by ANTLR 4.10.1. DO NOT EDIT.
+// Code generated from /Users/tswadell/go/src/github.com/google/cel-go/parser/gen/CEL.g4 by ANTLR 4.12.0. DO NOT EDIT.
package gen // CEL
import (
@@ -6,7 +6,7 @@ import (
"strconv"
"sync"
- "github.com/antlr/antlr4/runtime/Go/antlr"
+ "github.com/antlr/antlr4/runtime/Go/antlr/v4"
)
// Suppress unused import errors
@@ -32,13 +32,12 @@ var celParserStaticData struct {
func celParserInit() {
staticData := &celParserStaticData
staticData.literalNames = []string{
- "", "'.?'", "'[?'", "'=='", "'!='", "'in'", "'<'", "'<='", "'>='", "'>'",
- "'&&'", "'||'", "'['", "']'", "'{'", "'}'", "'('", "')'", "'.'", "','",
- "'-'", "'!'", "'?'", "':'", "'+'", "'*'", "'/'", "'%'", "'true'", "'false'",
- "'null'",
+ "", "'=='", "'!='", "'in'", "'<'", "'<='", "'>='", "'>'", "'&&'", "'||'",
+ "'['", "']'", "'{'", "'}'", "'('", "')'", "'.'", "','", "'-'", "'!'",
+ "'?'", "':'", "'+'", "'*'", "'/'", "'%'", "'true'", "'false'", "'null'",
}
staticData.symbolicNames = []string{
- "", "", "", "EQUALS", "NOT_EQUALS", "IN", "LESS", "LESS_EQUALS", "GREATER_EQUALS",
+ "", "EQUALS", "NOT_EQUALS", "IN", "LESS", "LESS_EQUALS", "GREATER_EQUALS",
"GREATER", "LOGICAL_AND", "LOGICAL_OR", "LBRACKET", "RPRACKET", "LBRACE",
"RBRACE", "LPAREN", "RPAREN", "DOT", "COMMA", "MINUS", "EXCLAM", "QUESTIONMARK",
"COLON", "PLUS", "STAR", "SLASH", "PERCENT", "CEL_TRUE", "CEL_FALSE",
@@ -47,118 +46,125 @@ func celParserInit() {
}
staticData.ruleNames = []string{
"start", "expr", "conditionalOr", "conditionalAnd", "relation", "calc",
- "unary", "member", "primary", "exprList", "fieldInitializerList", "optField",
- "mapInitializerList", "optKey", "literal",
+ "unary", "member", "primary", "exprList", "listInit", "fieldInitializerList",
+ "optField", "mapInitializerList", "optExpr", "literal",
}
staticData.predictionContextCache = antlr.NewPredictionContextCache()
staticData.serializedATN = []int32{
- 4, 1, 38, 235, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7,
+ 4, 1, 36, 251, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7,
4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7,
- 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 1, 0, 1, 0,
- 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 40, 8, 1, 1, 2, 1, 2, 1,
- 2, 5, 2, 45, 8, 2, 10, 2, 12, 2, 48, 9, 2, 1, 3, 1, 3, 1, 3, 5, 3, 53,
- 8, 3, 10, 3, 12, 3, 56, 9, 3, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 5, 4,
- 64, 8, 4, 10, 4, 12, 4, 67, 9, 4, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1,
- 5, 1, 5, 1, 5, 5, 5, 78, 8, 5, 10, 5, 12, 5, 81, 9, 5, 1, 6, 1, 6, 4, 6,
- 85, 8, 6, 11, 6, 12, 6, 86, 1, 6, 1, 6, 4, 6, 91, 8, 6, 11, 6, 12, 6, 92,
- 1, 6, 3, 6, 96, 8, 6, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1,
- 7, 1, 7, 1, 7, 3, 7, 109, 8, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 5,
- 7, 117, 8, 7, 10, 7, 12, 7, 120, 9, 7, 1, 8, 3, 8, 123, 8, 8, 1, 8, 1,
- 8, 1, 8, 3, 8, 128, 8, 8, 1, 8, 3, 8, 131, 8, 8, 1, 8, 1, 8, 1, 8, 1, 8,
- 1, 8, 1, 8, 3, 8, 139, 8, 8, 1, 8, 3, 8, 142, 8, 8, 1, 8, 1, 8, 1, 8, 3,
- 8, 147, 8, 8, 1, 8, 3, 8, 150, 8, 8, 1, 8, 1, 8, 3, 8, 154, 8, 8, 1, 8,
- 1, 8, 1, 8, 5, 8, 159, 8, 8, 10, 8, 12, 8, 162, 9, 8, 1, 8, 1, 8, 3, 8,
- 166, 8, 8, 1, 8, 3, 8, 169, 8, 8, 1, 8, 1, 8, 3, 8, 173, 8, 8, 1, 9, 1,
- 9, 1, 9, 5, 9, 178, 8, 9, 10, 9, 12, 9, 181, 9, 9, 1, 10, 1, 10, 1, 10,
- 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 5, 10, 191, 8, 10, 10, 10, 12, 10, 194,
- 9, 10, 1, 11, 3, 11, 197, 8, 11, 1, 11, 1, 11, 1, 12, 1, 12, 1, 12, 1,
- 12, 1, 12, 1, 12, 1, 12, 1, 12, 5, 12, 209, 8, 12, 10, 12, 12, 12, 212,
- 9, 12, 1, 13, 3, 13, 215, 8, 13, 1, 13, 1, 13, 1, 14, 3, 14, 220, 8, 14,
- 1, 14, 1, 14, 1, 14, 3, 14, 225, 8, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1,
- 14, 1, 14, 3, 14, 233, 8, 14, 1, 14, 0, 3, 8, 10, 14, 15, 0, 2, 4, 6, 8,
- 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 0, 5, 1, 0, 3, 9, 1, 0, 25, 27,
- 2, 0, 20, 20, 24, 24, 2, 0, 1, 1, 18, 18, 2, 0, 2, 2, 12, 12, 263, 0, 30,
- 1, 0, 0, 0, 2, 33, 1, 0, 0, 0, 4, 41, 1, 0, 0, 0, 6, 49, 1, 0, 0, 0, 8,
- 57, 1, 0, 0, 0, 10, 68, 1, 0, 0, 0, 12, 95, 1, 0, 0, 0, 14, 97, 1, 0, 0,
- 0, 16, 172, 1, 0, 0, 0, 18, 174, 1, 0, 0, 0, 20, 182, 1, 0, 0, 0, 22, 196,
- 1, 0, 0, 0, 24, 200, 1, 0, 0, 0, 26, 214, 1, 0, 0, 0, 28, 232, 1, 0, 0,
- 0, 30, 31, 3, 2, 1, 0, 31, 32, 5, 0, 0, 1, 32, 1, 1, 0, 0, 0, 33, 39, 3,
- 4, 2, 0, 34, 35, 5, 22, 0, 0, 35, 36, 3, 4, 2, 0, 36, 37, 5, 23, 0, 0,
- 37, 38, 3, 2, 1, 0, 38, 40, 1, 0, 0, 0, 39, 34, 1, 0, 0, 0, 39, 40, 1,
- 0, 0, 0, 40, 3, 1, 0, 0, 0, 41, 46, 3, 6, 3, 0, 42, 43, 5, 11, 0, 0, 43,
- 45, 3, 6, 3, 0, 44, 42, 1, 0, 0, 0, 45, 48, 1, 0, 0, 0, 46, 44, 1, 0, 0,
- 0, 46, 47, 1, 0, 0, 0, 47, 5, 1, 0, 0, 0, 48, 46, 1, 0, 0, 0, 49, 54, 3,
- 8, 4, 0, 50, 51, 5, 10, 0, 0, 51, 53, 3, 8, 4, 0, 52, 50, 1, 0, 0, 0, 53,
- 56, 1, 0, 0, 0, 54, 52, 1, 0, 0, 0, 54, 55, 1, 0, 0, 0, 55, 7, 1, 0, 0,
- 0, 56, 54, 1, 0, 0, 0, 57, 58, 6, 4, -1, 0, 58, 59, 3, 10, 5, 0, 59, 65,
- 1, 0, 0, 0, 60, 61, 10, 1, 0, 0, 61, 62, 7, 0, 0, 0, 62, 64, 3, 8, 4, 2,
- 63, 60, 1, 0, 0, 0, 64, 67, 1, 0, 0, 0, 65, 63, 1, 0, 0, 0, 65, 66, 1,
- 0, 0, 0, 66, 9, 1, 0, 0, 0, 67, 65, 1, 0, 0, 0, 68, 69, 6, 5, -1, 0, 69,
- 70, 3, 12, 6, 0, 70, 79, 1, 0, 0, 0, 71, 72, 10, 2, 0, 0, 72, 73, 7, 1,
- 0, 0, 73, 78, 3, 10, 5, 3, 74, 75, 10, 1, 0, 0, 75, 76, 7, 2, 0, 0, 76,
- 78, 3, 10, 5, 2, 77, 71, 1, 0, 0, 0, 77, 74, 1, 0, 0, 0, 78, 81, 1, 0,
- 0, 0, 79, 77, 1, 0, 0, 0, 79, 80, 1, 0, 0, 0, 80, 11, 1, 0, 0, 0, 81, 79,
- 1, 0, 0, 0, 82, 96, 3, 14, 7, 0, 83, 85, 5, 21, 0, 0, 84, 83, 1, 0, 0,
- 0, 85, 86, 1, 0, 0, 0, 86, 84, 1, 0, 0, 0, 86, 87, 1, 0, 0, 0, 87, 88,
- 1, 0, 0, 0, 88, 96, 3, 14, 7, 0, 89, 91, 5, 20, 0, 0, 90, 89, 1, 0, 0,
- 0, 91, 92, 1, 0, 0, 0, 92, 90, 1, 0, 0, 0, 92, 93, 1, 0, 0, 0, 93, 94,
- 1, 0, 0, 0, 94, 96, 3, 14, 7, 0, 95, 82, 1, 0, 0, 0, 95, 84, 1, 0, 0, 0,
- 95, 90, 1, 0, 0, 0, 96, 13, 1, 0, 0, 0, 97, 98, 6, 7, -1, 0, 98, 99, 3,
- 16, 8, 0, 99, 118, 1, 0, 0, 0, 100, 101, 10, 3, 0, 0, 101, 102, 7, 3, 0,
- 0, 102, 117, 5, 38, 0, 0, 103, 104, 10, 2, 0, 0, 104, 105, 5, 18, 0, 0,
- 105, 106, 5, 38, 0, 0, 106, 108, 5, 16, 0, 0, 107, 109, 3, 18, 9, 0, 108,
- 107, 1, 0, 0, 0, 108, 109, 1, 0, 0, 0, 109, 110, 1, 0, 0, 0, 110, 117,
- 5, 17, 0, 0, 111, 112, 10, 1, 0, 0, 112, 113, 7, 4, 0, 0, 113, 114, 3,
- 2, 1, 0, 114, 115, 5, 13, 0, 0, 115, 117, 1, 0, 0, 0, 116, 100, 1, 0, 0,
- 0, 116, 103, 1, 0, 0, 0, 116, 111, 1, 0, 0, 0, 117, 120, 1, 0, 0, 0, 118,
- 116, 1, 0, 0, 0, 118, 119, 1, 0, 0, 0, 119, 15, 1, 0, 0, 0, 120, 118, 1,
- 0, 0, 0, 121, 123, 5, 18, 0, 0, 122, 121, 1, 0, 0, 0, 122, 123, 1, 0, 0,
- 0, 123, 124, 1, 0, 0, 0, 124, 130, 5, 38, 0, 0, 125, 127, 5, 16, 0, 0,
- 126, 128, 3, 18, 9, 0, 127, 126, 1, 0, 0, 0, 127, 128, 1, 0, 0, 0, 128,
- 129, 1, 0, 0, 0, 129, 131, 5, 17, 0, 0, 130, 125, 1, 0, 0, 0, 130, 131,
- 1, 0, 0, 0, 131, 173, 1, 0, 0, 0, 132, 133, 5, 16, 0, 0, 133, 134, 3, 2,
- 1, 0, 134, 135, 5, 17, 0, 0, 135, 173, 1, 0, 0, 0, 136, 138, 5, 12, 0,
- 0, 137, 139, 3, 18, 9, 0, 138, 137, 1, 0, 0, 0, 138, 139, 1, 0, 0, 0, 139,
- 141, 1, 0, 0, 0, 140, 142, 5, 19, 0, 0, 141, 140, 1, 0, 0, 0, 141, 142,
- 1, 0, 0, 0, 142, 143, 1, 0, 0, 0, 143, 173, 5, 13, 0, 0, 144, 146, 5, 14,
- 0, 0, 145, 147, 3, 24, 12, 0, 146, 145, 1, 0, 0, 0, 146, 147, 1, 0, 0,
- 0, 147, 149, 1, 0, 0, 0, 148, 150, 5, 19, 0, 0, 149, 148, 1, 0, 0, 0, 149,
- 150, 1, 0, 0, 0, 150, 151, 1, 0, 0, 0, 151, 173, 5, 15, 0, 0, 152, 154,
- 5, 18, 0, 0, 153, 152, 1, 0, 0, 0, 153, 154, 1, 0, 0, 0, 154, 155, 1, 0,
- 0, 0, 155, 160, 5, 38, 0, 0, 156, 157, 5, 18, 0, 0, 157, 159, 5, 38, 0,
- 0, 158, 156, 1, 0, 0, 0, 159, 162, 1, 0, 0, 0, 160, 158, 1, 0, 0, 0, 160,
- 161, 1, 0, 0, 0, 161, 163, 1, 0, 0, 0, 162, 160, 1, 0, 0, 0, 163, 165,
- 5, 14, 0, 0, 164, 166, 3, 20, 10, 0, 165, 164, 1, 0, 0, 0, 165, 166, 1,
- 0, 0, 0, 166, 168, 1, 0, 0, 0, 167, 169, 5, 19, 0, 0, 168, 167, 1, 0, 0,
- 0, 168, 169, 1, 0, 0, 0, 169, 170, 1, 0, 0, 0, 170, 173, 5, 15, 0, 0, 171,
- 173, 3, 28, 14, 0, 172, 122, 1, 0, 0, 0, 172, 132, 1, 0, 0, 0, 172, 136,
- 1, 0, 0, 0, 172, 144, 1, 0, 0, 0, 172, 153, 1, 0, 0, 0, 172, 171, 1, 0,
- 0, 0, 173, 17, 1, 0, 0, 0, 174, 179, 3, 2, 1, 0, 175, 176, 5, 19, 0, 0,
- 176, 178, 3, 2, 1, 0, 177, 175, 1, 0, 0, 0, 178, 181, 1, 0, 0, 0, 179,
- 177, 1, 0, 0, 0, 179, 180, 1, 0, 0, 0, 180, 19, 1, 0, 0, 0, 181, 179, 1,
- 0, 0, 0, 182, 183, 3, 22, 11, 0, 183, 184, 5, 23, 0, 0, 184, 192, 3, 2,
- 1, 0, 185, 186, 5, 19, 0, 0, 186, 187, 3, 22, 11, 0, 187, 188, 5, 23, 0,
- 0, 188, 189, 3, 2, 1, 0, 189, 191, 1, 0, 0, 0, 190, 185, 1, 0, 0, 0, 191,
- 194, 1, 0, 0, 0, 192, 190, 1, 0, 0, 0, 192, 193, 1, 0, 0, 0, 193, 21, 1,
- 0, 0, 0, 194, 192, 1, 0, 0, 0, 195, 197, 5, 22, 0, 0, 196, 195, 1, 0, 0,
- 0, 196, 197, 1, 0, 0, 0, 197, 198, 1, 0, 0, 0, 198, 199, 5, 38, 0, 0, 199,
- 23, 1, 0, 0, 0, 200, 201, 3, 26, 13, 0, 201, 202, 5, 23, 0, 0, 202, 210,
- 3, 2, 1, 0, 203, 204, 5, 19, 0, 0, 204, 205, 3, 26, 13, 0, 205, 206, 5,
- 23, 0, 0, 206, 207, 3, 2, 1, 0, 207, 209, 1, 0, 0, 0, 208, 203, 1, 0, 0,
- 0, 209, 212, 1, 0, 0, 0, 210, 208, 1, 0, 0, 0, 210, 211, 1, 0, 0, 0, 211,
- 25, 1, 0, 0, 0, 212, 210, 1, 0, 0, 0, 213, 215, 5, 22, 0, 0, 214, 213,
- 1, 0, 0, 0, 214, 215, 1, 0, 0, 0, 215, 216, 1, 0, 0, 0, 216, 217, 3, 2,
- 1, 0, 217, 27, 1, 0, 0, 0, 218, 220, 5, 20, 0, 0, 219, 218, 1, 0, 0, 0,
- 219, 220, 1, 0, 0, 0, 220, 221, 1, 0, 0, 0, 221, 233, 5, 34, 0, 0, 222,
- 233, 5, 35, 0, 0, 223, 225, 5, 20, 0, 0, 224, 223, 1, 0, 0, 0, 224, 225,
- 1, 0, 0, 0, 225, 226, 1, 0, 0, 0, 226, 233, 5, 33, 0, 0, 227, 233, 5, 36,
- 0, 0, 228, 233, 5, 37, 0, 0, 229, 233, 5, 28, 0, 0, 230, 233, 5, 29, 0,
- 0, 231, 233, 5, 30, 0, 0, 232, 219, 1, 0, 0, 0, 232, 222, 1, 0, 0, 0, 232,
- 224, 1, 0, 0, 0, 232, 227, 1, 0, 0, 0, 232, 228, 1, 0, 0, 0, 232, 229,
- 1, 0, 0, 0, 232, 230, 1, 0, 0, 0, 232, 231, 1, 0, 0, 0, 233, 29, 1, 0,
- 0, 0, 32, 39, 46, 54, 65, 77, 79, 86, 92, 95, 108, 116, 118, 122, 127,
- 130, 138, 141, 146, 149, 153, 160, 165, 168, 172, 179, 192, 196, 210, 214,
- 219, 224, 232,
+ 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15,
+ 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 42, 8, 1, 1,
+ 2, 1, 2, 1, 2, 5, 2, 47, 8, 2, 10, 2, 12, 2, 50, 9, 2, 1, 3, 1, 3, 1, 3,
+ 5, 3, 55, 8, 3, 10, 3, 12, 3, 58, 9, 3, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1,
+ 4, 5, 4, 66, 8, 4, 10, 4, 12, 4, 69, 9, 4, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5,
+ 1, 5, 1, 5, 1, 5, 1, 5, 5, 5, 80, 8, 5, 10, 5, 12, 5, 83, 9, 5, 1, 6, 1,
+ 6, 4, 6, 87, 8, 6, 11, 6, 12, 6, 88, 1, 6, 1, 6, 4, 6, 93, 8, 6, 11, 6,
+ 12, 6, 94, 1, 6, 3, 6, 98, 8, 6, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 3,
+ 7, 106, 8, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 3, 7, 114, 8, 7, 1, 7,
+ 1, 7, 1, 7, 1, 7, 3, 7, 120, 8, 7, 1, 7, 1, 7, 1, 7, 5, 7, 125, 8, 7, 10,
+ 7, 12, 7, 128, 9, 7, 1, 8, 3, 8, 131, 8, 8, 1, 8, 1, 8, 1, 8, 3, 8, 136,
+ 8, 8, 1, 8, 3, 8, 139, 8, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 3, 8,
+ 147, 8, 8, 1, 8, 3, 8, 150, 8, 8, 1, 8, 1, 8, 1, 8, 3, 8, 155, 8, 8, 1,
+ 8, 3, 8, 158, 8, 8, 1, 8, 1, 8, 3, 8, 162, 8, 8, 1, 8, 1, 8, 1, 8, 5, 8,
+ 167, 8, 8, 10, 8, 12, 8, 170, 9, 8, 1, 8, 1, 8, 3, 8, 174, 8, 8, 1, 8,
+ 3, 8, 177, 8, 8, 1, 8, 1, 8, 3, 8, 181, 8, 8, 1, 9, 1, 9, 1, 9, 5, 9, 186,
+ 8, 9, 10, 9, 12, 9, 189, 9, 9, 1, 10, 1, 10, 1, 10, 5, 10, 194, 8, 10,
+ 10, 10, 12, 10, 197, 9, 10, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1,
+ 11, 1, 11, 5, 11, 207, 8, 11, 10, 11, 12, 11, 210, 9, 11, 1, 12, 3, 12,
+ 213, 8, 12, 1, 12, 1, 12, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1,
+ 13, 1, 13, 5, 13, 225, 8, 13, 10, 13, 12, 13, 228, 9, 13, 1, 14, 3, 14,
+ 231, 8, 14, 1, 14, 1, 14, 1, 15, 3, 15, 236, 8, 15, 1, 15, 1, 15, 1, 15,
+ 3, 15, 241, 8, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 3, 15, 249,
+ 8, 15, 1, 15, 0, 3, 8, 10, 14, 16, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20,
+ 22, 24, 26, 28, 30, 0, 3, 1, 0, 1, 7, 1, 0, 23, 25, 2, 0, 18, 18, 22, 22,
+ 281, 0, 32, 1, 0, 0, 0, 2, 35, 1, 0, 0, 0, 4, 43, 1, 0, 0, 0, 6, 51, 1,
+ 0, 0, 0, 8, 59, 1, 0, 0, 0, 10, 70, 1, 0, 0, 0, 12, 97, 1, 0, 0, 0, 14,
+ 99, 1, 0, 0, 0, 16, 180, 1, 0, 0, 0, 18, 182, 1, 0, 0, 0, 20, 190, 1, 0,
+ 0, 0, 22, 198, 1, 0, 0, 0, 24, 212, 1, 0, 0, 0, 26, 216, 1, 0, 0, 0, 28,
+ 230, 1, 0, 0, 0, 30, 248, 1, 0, 0, 0, 32, 33, 3, 2, 1, 0, 33, 34, 5, 0,
+ 0, 1, 34, 1, 1, 0, 0, 0, 35, 41, 3, 4, 2, 0, 36, 37, 5, 20, 0, 0, 37, 38,
+ 3, 4, 2, 0, 38, 39, 5, 21, 0, 0, 39, 40, 3, 2, 1, 0, 40, 42, 1, 0, 0, 0,
+ 41, 36, 1, 0, 0, 0, 41, 42, 1, 0, 0, 0, 42, 3, 1, 0, 0, 0, 43, 48, 3, 6,
+ 3, 0, 44, 45, 5, 9, 0, 0, 45, 47, 3, 6, 3, 0, 46, 44, 1, 0, 0, 0, 47, 50,
+ 1, 0, 0, 0, 48, 46, 1, 0, 0, 0, 48, 49, 1, 0, 0, 0, 49, 5, 1, 0, 0, 0,
+ 50, 48, 1, 0, 0, 0, 51, 56, 3, 8, 4, 0, 52, 53, 5, 8, 0, 0, 53, 55, 3,
+ 8, 4, 0, 54, 52, 1, 0, 0, 0, 55, 58, 1, 0, 0, 0, 56, 54, 1, 0, 0, 0, 56,
+ 57, 1, 0, 0, 0, 57, 7, 1, 0, 0, 0, 58, 56, 1, 0, 0, 0, 59, 60, 6, 4, -1,
+ 0, 60, 61, 3, 10, 5, 0, 61, 67, 1, 0, 0, 0, 62, 63, 10, 1, 0, 0, 63, 64,
+ 7, 0, 0, 0, 64, 66, 3, 8, 4, 2, 65, 62, 1, 0, 0, 0, 66, 69, 1, 0, 0, 0,
+ 67, 65, 1, 0, 0, 0, 67, 68, 1, 0, 0, 0, 68, 9, 1, 0, 0, 0, 69, 67, 1, 0,
+ 0, 0, 70, 71, 6, 5, -1, 0, 71, 72, 3, 12, 6, 0, 72, 81, 1, 0, 0, 0, 73,
+ 74, 10, 2, 0, 0, 74, 75, 7, 1, 0, 0, 75, 80, 3, 10, 5, 3, 76, 77, 10, 1,
+ 0, 0, 77, 78, 7, 2, 0, 0, 78, 80, 3, 10, 5, 2, 79, 73, 1, 0, 0, 0, 79,
+ 76, 1, 0, 0, 0, 80, 83, 1, 0, 0, 0, 81, 79, 1, 0, 0, 0, 81, 82, 1, 0, 0,
+ 0, 82, 11, 1, 0, 0, 0, 83, 81, 1, 0, 0, 0, 84, 98, 3, 14, 7, 0, 85, 87,
+ 5, 19, 0, 0, 86, 85, 1, 0, 0, 0, 87, 88, 1, 0, 0, 0, 88, 86, 1, 0, 0, 0,
+ 88, 89, 1, 0, 0, 0, 89, 90, 1, 0, 0, 0, 90, 98, 3, 14, 7, 0, 91, 93, 5,
+ 18, 0, 0, 92, 91, 1, 0, 0, 0, 93, 94, 1, 0, 0, 0, 94, 92, 1, 0, 0, 0, 94,
+ 95, 1, 0, 0, 0, 95, 96, 1, 0, 0, 0, 96, 98, 3, 14, 7, 0, 97, 84, 1, 0,
+ 0, 0, 97, 86, 1, 0, 0, 0, 97, 92, 1, 0, 0, 0, 98, 13, 1, 0, 0, 0, 99, 100,
+ 6, 7, -1, 0, 100, 101, 3, 16, 8, 0, 101, 126, 1, 0, 0, 0, 102, 103, 10,
+ 3, 0, 0, 103, 105, 5, 16, 0, 0, 104, 106, 5, 20, 0, 0, 105, 104, 1, 0,
+ 0, 0, 105, 106, 1, 0, 0, 0, 106, 107, 1, 0, 0, 0, 107, 125, 5, 36, 0, 0,
+ 108, 109, 10, 2, 0, 0, 109, 110, 5, 16, 0, 0, 110, 111, 5, 36, 0, 0, 111,
+ 113, 5, 14, 0, 0, 112, 114, 3, 18, 9, 0, 113, 112, 1, 0, 0, 0, 113, 114,
+ 1, 0, 0, 0, 114, 115, 1, 0, 0, 0, 115, 125, 5, 15, 0, 0, 116, 117, 10,
+ 1, 0, 0, 117, 119, 5, 10, 0, 0, 118, 120, 5, 20, 0, 0, 119, 118, 1, 0,
+ 0, 0, 119, 120, 1, 0, 0, 0, 120, 121, 1, 0, 0, 0, 121, 122, 3, 2, 1, 0,
+ 122, 123, 5, 11, 0, 0, 123, 125, 1, 0, 0, 0, 124, 102, 1, 0, 0, 0, 124,
+ 108, 1, 0, 0, 0, 124, 116, 1, 0, 0, 0, 125, 128, 1, 0, 0, 0, 126, 124,
+ 1, 0, 0, 0, 126, 127, 1, 0, 0, 0, 127, 15, 1, 0, 0, 0, 128, 126, 1, 0,
+ 0, 0, 129, 131, 5, 16, 0, 0, 130, 129, 1, 0, 0, 0, 130, 131, 1, 0, 0, 0,
+ 131, 132, 1, 0, 0, 0, 132, 138, 5, 36, 0, 0, 133, 135, 5, 14, 0, 0, 134,
+ 136, 3, 18, 9, 0, 135, 134, 1, 0, 0, 0, 135, 136, 1, 0, 0, 0, 136, 137,
+ 1, 0, 0, 0, 137, 139, 5, 15, 0, 0, 138, 133, 1, 0, 0, 0, 138, 139, 1, 0,
+ 0, 0, 139, 181, 1, 0, 0, 0, 140, 141, 5, 14, 0, 0, 141, 142, 3, 2, 1, 0,
+ 142, 143, 5, 15, 0, 0, 143, 181, 1, 0, 0, 0, 144, 146, 5, 10, 0, 0, 145,
+ 147, 3, 20, 10, 0, 146, 145, 1, 0, 0, 0, 146, 147, 1, 0, 0, 0, 147, 149,
+ 1, 0, 0, 0, 148, 150, 5, 17, 0, 0, 149, 148, 1, 0, 0, 0, 149, 150, 1, 0,
+ 0, 0, 150, 151, 1, 0, 0, 0, 151, 181, 5, 11, 0, 0, 152, 154, 5, 12, 0,
+ 0, 153, 155, 3, 26, 13, 0, 154, 153, 1, 0, 0, 0, 154, 155, 1, 0, 0, 0,
+ 155, 157, 1, 0, 0, 0, 156, 158, 5, 17, 0, 0, 157, 156, 1, 0, 0, 0, 157,
+ 158, 1, 0, 0, 0, 158, 159, 1, 0, 0, 0, 159, 181, 5, 13, 0, 0, 160, 162,
+ 5, 16, 0, 0, 161, 160, 1, 0, 0, 0, 161, 162, 1, 0, 0, 0, 162, 163, 1, 0,
+ 0, 0, 163, 168, 5, 36, 0, 0, 164, 165, 5, 16, 0, 0, 165, 167, 5, 36, 0,
+ 0, 166, 164, 1, 0, 0, 0, 167, 170, 1, 0, 0, 0, 168, 166, 1, 0, 0, 0, 168,
+ 169, 1, 0, 0, 0, 169, 171, 1, 0, 0, 0, 170, 168, 1, 0, 0, 0, 171, 173,
+ 5, 12, 0, 0, 172, 174, 3, 22, 11, 0, 173, 172, 1, 0, 0, 0, 173, 174, 1,
+ 0, 0, 0, 174, 176, 1, 0, 0, 0, 175, 177, 5, 17, 0, 0, 176, 175, 1, 0, 0,
+ 0, 176, 177, 1, 0, 0, 0, 177, 178, 1, 0, 0, 0, 178, 181, 5, 13, 0, 0, 179,
+ 181, 3, 30, 15, 0, 180, 130, 1, 0, 0, 0, 180, 140, 1, 0, 0, 0, 180, 144,
+ 1, 0, 0, 0, 180, 152, 1, 0, 0, 0, 180, 161, 1, 0, 0, 0, 180, 179, 1, 0,
+ 0, 0, 181, 17, 1, 0, 0, 0, 182, 187, 3, 2, 1, 0, 183, 184, 5, 17, 0, 0,
+ 184, 186, 3, 2, 1, 0, 185, 183, 1, 0, 0, 0, 186, 189, 1, 0, 0, 0, 187,
+ 185, 1, 0, 0, 0, 187, 188, 1, 0, 0, 0, 188, 19, 1, 0, 0, 0, 189, 187, 1,
+ 0, 0, 0, 190, 195, 3, 28, 14, 0, 191, 192, 5, 17, 0, 0, 192, 194, 3, 28,
+ 14, 0, 193, 191, 1, 0, 0, 0, 194, 197, 1, 0, 0, 0, 195, 193, 1, 0, 0, 0,
+ 195, 196, 1, 0, 0, 0, 196, 21, 1, 0, 0, 0, 197, 195, 1, 0, 0, 0, 198, 199,
+ 3, 24, 12, 0, 199, 200, 5, 21, 0, 0, 200, 208, 3, 2, 1, 0, 201, 202, 5,
+ 17, 0, 0, 202, 203, 3, 24, 12, 0, 203, 204, 5, 21, 0, 0, 204, 205, 3, 2,
+ 1, 0, 205, 207, 1, 0, 0, 0, 206, 201, 1, 0, 0, 0, 207, 210, 1, 0, 0, 0,
+ 208, 206, 1, 0, 0, 0, 208, 209, 1, 0, 0, 0, 209, 23, 1, 0, 0, 0, 210, 208,
+ 1, 0, 0, 0, 211, 213, 5, 20, 0, 0, 212, 211, 1, 0, 0, 0, 212, 213, 1, 0,
+ 0, 0, 213, 214, 1, 0, 0, 0, 214, 215, 5, 36, 0, 0, 215, 25, 1, 0, 0, 0,
+ 216, 217, 3, 28, 14, 0, 217, 218, 5, 21, 0, 0, 218, 226, 3, 2, 1, 0, 219,
+ 220, 5, 17, 0, 0, 220, 221, 3, 28, 14, 0, 221, 222, 5, 21, 0, 0, 222, 223,
+ 3, 2, 1, 0, 223, 225, 1, 0, 0, 0, 224, 219, 1, 0, 0, 0, 225, 228, 1, 0,
+ 0, 0, 226, 224, 1, 0, 0, 0, 226, 227, 1, 0, 0, 0, 227, 27, 1, 0, 0, 0,
+ 228, 226, 1, 0, 0, 0, 229, 231, 5, 20, 0, 0, 230, 229, 1, 0, 0, 0, 230,
+ 231, 1, 0, 0, 0, 231, 232, 1, 0, 0, 0, 232, 233, 3, 2, 1, 0, 233, 29, 1,
+ 0, 0, 0, 234, 236, 5, 18, 0, 0, 235, 234, 1, 0, 0, 0, 235, 236, 1, 0, 0,
+ 0, 236, 237, 1, 0, 0, 0, 237, 249, 5, 32, 0, 0, 238, 249, 5, 33, 0, 0,
+ 239, 241, 5, 18, 0, 0, 240, 239, 1, 0, 0, 0, 240, 241, 1, 0, 0, 0, 241,
+ 242, 1, 0, 0, 0, 242, 249, 5, 31, 0, 0, 243, 249, 5, 34, 0, 0, 244, 249,
+ 5, 35, 0, 0, 245, 249, 5, 26, 0, 0, 246, 249, 5, 27, 0, 0, 247, 249, 5,
+ 28, 0, 0, 248, 235, 1, 0, 0, 0, 248, 238, 1, 0, 0, 0, 248, 240, 1, 0, 0,
+ 0, 248, 243, 1, 0, 0, 0, 248, 244, 1, 0, 0, 0, 248, 245, 1, 0, 0, 0, 248,
+ 246, 1, 0, 0, 0, 248, 247, 1, 0, 0, 0, 249, 31, 1, 0, 0, 0, 35, 41, 48,
+ 56, 67, 79, 81, 88, 94, 97, 105, 113, 119, 124, 126, 130, 135, 138, 146,
+ 149, 154, 157, 161, 168, 173, 176, 180, 187, 195, 208, 212, 226, 230, 235,
+ 240, 248,
}
deserializer := antlr.NewATNDeserializer(nil)
staticData.atn = deserializer.Deserialize(staticData.serializedATN)
@@ -197,44 +203,42 @@ func NewCELParser(input antlr.TokenStream) *CELParser {
// CELParser tokens.
const (
CELParserEOF = antlr.TokenEOF
- CELParserT__0 = 1
- CELParserT__1 = 2
- CELParserEQUALS = 3
- CELParserNOT_EQUALS = 4
- CELParserIN = 5
- CELParserLESS = 6
- CELParserLESS_EQUALS = 7
- CELParserGREATER_EQUALS = 8
- CELParserGREATER = 9
- CELParserLOGICAL_AND = 10
- CELParserLOGICAL_OR = 11
- CELParserLBRACKET = 12
- CELParserRPRACKET = 13
- CELParserLBRACE = 14
- CELParserRBRACE = 15
- CELParserLPAREN = 16
- CELParserRPAREN = 17
- CELParserDOT = 18
- CELParserCOMMA = 19
- CELParserMINUS = 20
- CELParserEXCLAM = 21
- CELParserQUESTIONMARK = 22
- CELParserCOLON = 23
- CELParserPLUS = 24
- CELParserSTAR = 25
- CELParserSLASH = 26
- CELParserPERCENT = 27
- CELParserCEL_TRUE = 28
- CELParserCEL_FALSE = 29
- CELParserNUL = 30
- CELParserWHITESPACE = 31
- CELParserCOMMENT = 32
- CELParserNUM_FLOAT = 33
- CELParserNUM_INT = 34
- CELParserNUM_UINT = 35
- CELParserSTRING = 36
- CELParserBYTES = 37
- CELParserIDENTIFIER = 38
+ CELParserEQUALS = 1
+ CELParserNOT_EQUALS = 2
+ CELParserIN = 3
+ CELParserLESS = 4
+ CELParserLESS_EQUALS = 5
+ CELParserGREATER_EQUALS = 6
+ CELParserGREATER = 7
+ CELParserLOGICAL_AND = 8
+ CELParserLOGICAL_OR = 9
+ CELParserLBRACKET = 10
+ CELParserRPRACKET = 11
+ CELParserLBRACE = 12
+ CELParserRBRACE = 13
+ CELParserLPAREN = 14
+ CELParserRPAREN = 15
+ CELParserDOT = 16
+ CELParserCOMMA = 17
+ CELParserMINUS = 18
+ CELParserEXCLAM = 19
+ CELParserQUESTIONMARK = 20
+ CELParserCOLON = 21
+ CELParserPLUS = 22
+ CELParserSTAR = 23
+ CELParserSLASH = 24
+ CELParserPERCENT = 25
+ CELParserCEL_TRUE = 26
+ CELParserCEL_FALSE = 27
+ CELParserNUL = 28
+ CELParserWHITESPACE = 29
+ CELParserCOMMENT = 30
+ CELParserNUM_FLOAT = 31
+ CELParserNUM_INT = 32
+ CELParserNUM_UINT = 33
+ CELParserSTRING = 34
+ CELParserBYTES = 35
+ CELParserIDENTIFIER = 36
)
// CELParser rules.
@@ -249,11 +253,12 @@ const (
CELParserRULE_member = 7
CELParserRULE_primary = 8
CELParserRULE_exprList = 9
- CELParserRULE_fieldInitializerList = 10
- CELParserRULE_optField = 11
- CELParserRULE_mapInitializerList = 12
- CELParserRULE_optKey = 13
- CELParserRULE_literal = 14
+ CELParserRULE_listInit = 10
+ CELParserRULE_fieldInitializerList = 11
+ CELParserRULE_optField = 12
+ CELParserRULE_mapInitializerList = 13
+ CELParserRULE_optExpr = 14
+ CELParserRULE_literal = 15
)
// IStartContext is an interface to support dynamic dispatch.
@@ -269,6 +274,10 @@ type IStartContext interface {
// SetE sets the e rule contexts.
SetE(IExprContext)
+ // Getter signatures
+ EOF() antlr.TerminalNode
+ Expr() IExprContext
+
// IsStartContext differentiates from other interfaces.
IsStartContext()
}
@@ -380,14 +389,14 @@ func (p *CELParser) Start() (localctx IStartContext) {
p.EnterOuterAlt(localctx, 1)
{
- p.SetState(30)
+ p.SetState(32)
var _x = p.Expr()
localctx.(*StartContext).e = _x
}
{
- p.SetState(31)
+ p.SetState(33)
p.Match(CELParserEOF)
}
@@ -425,6 +434,13 @@ type IExprContext interface {
// SetE2 sets the e2 rule contexts.
SetE2(IExprContext)
+ // Getter signatures
+ AllConditionalOr() []IConditionalOrContext
+ ConditionalOr(i int) IConditionalOrContext
+ COLON() antlr.TerminalNode
+ QUESTIONMARK() antlr.TerminalNode
+ Expr() IExprContext
+
// IsExprContext differentiates from other interfaces.
IsExprContext()
}
@@ -597,37 +613,37 @@ func (p *CELParser) Expr() (localctx IExprContext) {
p.EnterOuterAlt(localctx, 1)
{
- p.SetState(33)
+ p.SetState(35)
var _x = p.ConditionalOr()
localctx.(*ExprContext).e = _x
}
- p.SetState(39)
+ p.SetState(41)
p.GetErrorHandler().Sync(p)
_la = p.GetTokenStream().LA(1)
if _la == CELParserQUESTIONMARK {
{
- p.SetState(34)
+ p.SetState(36)
var _m = p.Match(CELParserQUESTIONMARK)
localctx.(*ExprContext).op = _m
}
{
- p.SetState(35)
+ p.SetState(37)
var _x = p.ConditionalOr()
localctx.(*ExprContext).e1 = _x
}
{
- p.SetState(36)
+ p.SetState(38)
p.Match(CELParserCOLON)
}
{
- p.SetState(37)
+ p.SetState(39)
var _x = p.Expr()
@@ -646,11 +662,11 @@ type IConditionalOrContext interface {
// GetParser returns the parser.
GetParser() antlr.Parser
- // GetS11 returns the s11 token.
- GetS11() antlr.Token
+ // GetS9 returns the s9 token.
+ GetS9() antlr.Token
- // SetS11 sets the s11 token.
- SetS11(antlr.Token)
+ // SetS9 sets the s9 token.
+ SetS9(antlr.Token)
// GetOps returns the ops token list.
GetOps() []antlr.Token
@@ -676,6 +692,12 @@ type IConditionalOrContext interface {
// SetE1 sets the e1 rule context list.
SetE1([]IConditionalAndContext)
+ // Getter signatures
+ AllConditionalAnd() []IConditionalAndContext
+ ConditionalAnd(i int) IConditionalAndContext
+ AllLOGICAL_OR() []antlr.TerminalNode
+ LOGICAL_OR(i int) antlr.TerminalNode
+
// IsConditionalOrContext differentiates from other interfaces.
IsConditionalOrContext()
}
@@ -684,7 +706,7 @@ type ConditionalOrContext struct {
*antlr.BaseParserRuleContext
parser antlr.Parser
e IConditionalAndContext
- s11 antlr.Token
+ s9 antlr.Token
ops []antlr.Token
_conditionalAnd IConditionalAndContext
e1 []IConditionalAndContext
@@ -712,9 +734,9 @@ func NewConditionalOrContext(parser antlr.Parser, parent antlr.ParserRuleContext
func (s *ConditionalOrContext) GetParser() antlr.Parser { return s.parser }
-func (s *ConditionalOrContext) GetS11() antlr.Token { return s.s11 }
+func (s *ConditionalOrContext) GetS9() antlr.Token { return s.s9 }
-func (s *ConditionalOrContext) SetS11(v antlr.Token) { s.s11 = v }
+func (s *ConditionalOrContext) SetS9(v antlr.Token) { s.s9 = v }
func (s *ConditionalOrContext) GetOps() []antlr.Token { return s.ops }
@@ -837,27 +859,27 @@ func (p *CELParser) ConditionalOr() (localctx IConditionalOrContext) {
p.EnterOuterAlt(localctx, 1)
{
- p.SetState(41)
+ p.SetState(43)
var _x = p.ConditionalAnd()
localctx.(*ConditionalOrContext).e = _x
}
- p.SetState(46)
+ p.SetState(48)
p.GetErrorHandler().Sync(p)
_la = p.GetTokenStream().LA(1)
for _la == CELParserLOGICAL_OR {
{
- p.SetState(42)
+ p.SetState(44)
var _m = p.Match(CELParserLOGICAL_OR)
- localctx.(*ConditionalOrContext).s11 = _m
+ localctx.(*ConditionalOrContext).s9 = _m
}
- localctx.(*ConditionalOrContext).ops = append(localctx.(*ConditionalOrContext).ops, localctx.(*ConditionalOrContext).s11)
+ localctx.(*ConditionalOrContext).ops = append(localctx.(*ConditionalOrContext).ops, localctx.(*ConditionalOrContext).s9)
{
- p.SetState(43)
+ p.SetState(45)
var _x = p.ConditionalAnd()
@@ -865,7 +887,7 @@ func (p *CELParser) ConditionalOr() (localctx IConditionalOrContext) {
}
localctx.(*ConditionalOrContext).e1 = append(localctx.(*ConditionalOrContext).e1, localctx.(*ConditionalOrContext)._conditionalAnd)
- p.SetState(48)
+ p.SetState(50)
p.GetErrorHandler().Sync(p)
_la = p.GetTokenStream().LA(1)
}
@@ -880,11 +902,11 @@ type IConditionalAndContext interface {
// GetParser returns the parser.
GetParser() antlr.Parser
- // GetS10 returns the s10 token.
- GetS10() antlr.Token
+ // GetS8 returns the s8 token.
+ GetS8() antlr.Token
- // SetS10 sets the s10 token.
- SetS10(antlr.Token)
+ // SetS8 sets the s8 token.
+ SetS8(antlr.Token)
// GetOps returns the ops token list.
GetOps() []antlr.Token
@@ -910,6 +932,12 @@ type IConditionalAndContext interface {
// SetE1 sets the e1 rule context list.
SetE1([]IRelationContext)
+ // Getter signatures
+ AllRelation() []IRelationContext
+ Relation(i int) IRelationContext
+ AllLOGICAL_AND() []antlr.TerminalNode
+ LOGICAL_AND(i int) antlr.TerminalNode
+
// IsConditionalAndContext differentiates from other interfaces.
IsConditionalAndContext()
}
@@ -918,7 +946,7 @@ type ConditionalAndContext struct {
*antlr.BaseParserRuleContext
parser antlr.Parser
e IRelationContext
- s10 antlr.Token
+ s8 antlr.Token
ops []antlr.Token
_relation IRelationContext
e1 []IRelationContext
@@ -946,9 +974,9 @@ func NewConditionalAndContext(parser antlr.Parser, parent antlr.ParserRuleContex
func (s *ConditionalAndContext) GetParser() antlr.Parser { return s.parser }
-func (s *ConditionalAndContext) GetS10() antlr.Token { return s.s10 }
+func (s *ConditionalAndContext) GetS8() antlr.Token { return s.s8 }
-func (s *ConditionalAndContext) SetS10(v antlr.Token) { s.s10 = v }
+func (s *ConditionalAndContext) SetS8(v antlr.Token) { s.s8 = v }
func (s *ConditionalAndContext) GetOps() []antlr.Token { return s.ops }
@@ -1071,27 +1099,27 @@ func (p *CELParser) ConditionalAnd() (localctx IConditionalAndContext) {
p.EnterOuterAlt(localctx, 1)
{
- p.SetState(49)
+ p.SetState(51)
var _x = p.relation(0)
localctx.(*ConditionalAndContext).e = _x
}
- p.SetState(54)
+ p.SetState(56)
p.GetErrorHandler().Sync(p)
_la = p.GetTokenStream().LA(1)
for _la == CELParserLOGICAL_AND {
{
- p.SetState(50)
+ p.SetState(52)
var _m = p.Match(CELParserLOGICAL_AND)
- localctx.(*ConditionalAndContext).s10 = _m
+ localctx.(*ConditionalAndContext).s8 = _m
}
- localctx.(*ConditionalAndContext).ops = append(localctx.(*ConditionalAndContext).ops, localctx.(*ConditionalAndContext).s10)
+ localctx.(*ConditionalAndContext).ops = append(localctx.(*ConditionalAndContext).ops, localctx.(*ConditionalAndContext).s8)
{
- p.SetState(51)
+ p.SetState(53)
var _x = p.relation(0)
@@ -1099,7 +1127,7 @@ func (p *CELParser) ConditionalAnd() (localctx IConditionalAndContext) {
}
localctx.(*ConditionalAndContext).e1 = append(localctx.(*ConditionalAndContext).e1, localctx.(*ConditionalAndContext)._relation)
- p.SetState(56)
+ p.SetState(58)
p.GetErrorHandler().Sync(p)
_la = p.GetTokenStream().LA(1)
}
@@ -1120,6 +1148,18 @@ type IRelationContext interface {
// SetOp sets the op token.
SetOp(antlr.Token)
+ // Getter signatures
+ Calc() ICalcContext
+ AllRelation() []IRelationContext
+ Relation(i int) IRelationContext
+ LESS() antlr.TerminalNode
+ LESS_EQUALS() antlr.TerminalNode
+ GREATER_EQUALS() antlr.TerminalNode
+ GREATER() antlr.TerminalNode
+ EQUALS() antlr.TerminalNode
+ NOT_EQUALS() antlr.TerminalNode
+ IN() antlr.TerminalNode
+
// IsRelationContext differentiates from other interfaces.
IsRelationContext()
}
@@ -1308,12 +1348,12 @@ func (p *CELParser) relation(_p int) (localctx IRelationContext) {
p.EnterOuterAlt(localctx, 1)
{
- p.SetState(58)
+ p.SetState(60)
p.calc(0)
}
p.GetParserRuleContext().SetStop(p.GetTokenStream().LT(-1))
- p.SetState(65)
+ p.SetState(67)
p.GetErrorHandler().Sync(p)
_alt = p.GetInterpreter().AdaptivePredict(p.GetTokenStream(), 3, p.GetParserRuleContext())
@@ -1325,13 +1365,13 @@ func (p *CELParser) relation(_p int) (localctx IRelationContext) {
_prevctx = localctx
localctx = NewRelationContext(p, _parentctx, _parentState)
p.PushNewRecursionContext(localctx, _startState, CELParserRULE_relation)
- p.SetState(60)
+ p.SetState(62)
if !(p.Precpred(p.GetParserRuleContext(), 1)) {
panic(antlr.NewFailedPredicateException(p, "p.Precpred(p.GetParserRuleContext(), 1)", ""))
}
{
- p.SetState(61)
+ p.SetState(63)
var _lt = p.GetTokenStream().LT(1)
@@ -1339,7 +1379,7 @@ func (p *CELParser) relation(_p int) (localctx IRelationContext) {
_la = p.GetTokenStream().LA(1)
- if !(((_la)&-(0x1f+1)) == 0 && ((1< 1, and is recommended to be less than the default of 256.
+// The limit must be >= 1, and is recommended to be less than the default of 256.
func ErrorRecoveryLookaheadTokenLimit(limit int) Option {
return func(opts *options) error {
if limit < 1 {
@@ -68,6 +70,19 @@ func ErrorRecoveryLimit(limit int) Option {
}
}
+// ErrorReportingLimit limits the number of syntax error reports before terminating parsing.
+//
+// The limit must be at least 1. If unset, the limit will be 100.
+func ErrorReportingLimit(limit int) Option {
+ return func(opts *options) error {
+ if limit < 1 {
+ return fmt.Errorf("error reporting limit must be at least 1: %d", limit)
+ }
+ opts.errorReportingLimit = limit
+ return nil
+ }
+}
+
// ExpressionSizeCodePointLimit is an option which limits the maximum code point count of an
// expression.
func ExpressionSizeCodePointLimit(expressionSizeCodePointLimit int) Option {
@@ -111,3 +126,15 @@ func EnableOptionalSyntax(optionalSyntax bool) Option {
return nil
}
}
+
+// EnableVariadicOperatorASTs enables a compact representation of chained like-kind commutative
+// operators. e.g. `a || b || c || d` -> `call(op='||', args=[a, b, c, d])`
+//
+// The benefit of enabling variadic operators ASTs is a more compact representation deeply nested
+// logic graphs.
+func EnableVariadicOperatorASTs(varArgASTs bool) Option {
+ return func(opts *options) error {
+ opts.enableVariadicOperatorASTs = varArgASTs
+ return nil
+ }
+}
diff --git a/vendor/github.com/google/cel-go/parser/parser.go b/vendor/github.com/google/cel-go/parser/parser.go
index 0d5679488..109326a93 100644
--- a/vendor/github.com/google/cel-go/parser/parser.go
+++ b/vendor/github.com/google/cel-go/parser/parser.go
@@ -23,7 +23,7 @@ import (
"strings"
"sync"
- "github.com/antlr/antlr4/runtime/Go/antlr"
+ antlr "github.com/antlr/antlr4/runtime/Go/antlr/v4"
"github.com/google/cel-go/common"
"github.com/google/cel-go/common/operators"
@@ -47,6 +47,9 @@ func NewParser(opts ...Option) (*Parser, error) {
return nil, err
}
}
+ if p.errorReportingLimit == 0 {
+ p.errorReportingLimit = 100
+ }
if p.maxRecursionDepth == 0 {
p.maxRecursionDepth = 250
}
@@ -86,15 +89,18 @@ func mustNewParser(opts ...Option) *Parser {
// Parse parses the expression represented by source and returns the result.
func (p *Parser) Parse(source common.Source) (*exprpb.ParsedExpr, *common.Errors) {
+ errs := common.NewErrors(source)
impl := parser{
- errors: &parseErrors{common.NewErrors(source)},
+ errors: &parseErrors{errs},
helper: newParserHelper(source),
macros: p.macros,
maxRecursionDepth: p.maxRecursionDepth,
+ errorReportingLimit: p.errorReportingLimit,
errorRecoveryLimit: p.errorRecoveryLimit,
errorRecoveryLookaheadTokenLimit: p.errorRecoveryTokenLookaheadLimit,
populateMacroCalls: p.populateMacroCalls,
enableOptionalSyntax: p.enableOptionalSyntax,
+ enableVariadicOperatorASTs: p.enableVariadicOperatorASTs,
}
buf, ok := source.(runes.Buffer)
if !ok {
@@ -111,7 +117,7 @@ func (p *Parser) Parse(source common.Source) (*exprpb.ParsedExpr, *common.Errors
return &exprpb.ParsedExpr{
Expr: e,
SourceInfo: impl.helper.getSourceInfo(),
- }, impl.errors.Errors
+ }, errs
}
// reservedIds are not legal to use as variables. We exclude them post-parse, as they *are* valid
@@ -200,6 +206,16 @@ func (rl *recursionListener) ExitEveryRule(ctx antlr.ParserRuleContext) {
var _ antlr.ParseTreeListener = &recursionListener{}
+type tooManyErrors struct {
+ errorReportingLimit int
+}
+
+func (t *tooManyErrors) Error() string {
+ return fmt.Sprintf("More than %d syntax errors", t.errorReportingLimit)
+}
+
+var _ error = &tooManyErrors{}
+
type recoveryLimitError struct {
message string
}
@@ -274,11 +290,14 @@ type parser struct {
helper *parserHelper
macros map[string]Macro
recursionDepth int
+ errorReports int
maxRecursionDepth int
+ errorReportingLimit int
errorRecoveryLimit int
errorRecoveryLookaheadTokenLimit int
populateMacroCalls bool
enableOptionalSyntax bool
+ enableVariadicOperatorASTs bool
}
var (
@@ -306,14 +325,14 @@ func (p *parser) parse(expr runes.Buffer, desc string) *exprpb.Expr {
lexer := lexerPool.Get().(*gen.CELLexer)
prsr := parserPool.Get().(*gen.CELParser)
- // Unfortunately ANTLR Go runtime is missing (*antlr.BaseParser).RemoveParseListeners, so this is
- // good enough until that is exported.
prsrListener := &recursionListener{
maxDepth: p.maxRecursionDepth,
ruleTypeDepth: map[int]*int{},
}
defer func() {
+ // Unfortunately ANTLR Go runtime is missing (*antlr.BaseParser).RemoveParseListeners,
+ // so this is good enough until that is exported.
// Reset the lexer and parser before putting them back in the pool.
lexer.RemoveErrorListeners()
prsr.RemoveParseListener(prsrListener)
@@ -341,9 +360,11 @@ func (p *parser) parse(expr runes.Buffer, desc string) *exprpb.Expr {
if val := recover(); val != nil {
switch err := val.(type) {
case *lookaheadLimitError:
- p.errors.ReportError(common.NoLocation, err.Error())
+ p.errors.internalError(err.Error())
case *recursionError:
- p.errors.ReportError(common.NoLocation, err.Error())
+ p.errors.internalError(err.Error())
+ case *tooManyErrors:
+ // do nothing
case *recoveryLimitError:
// do nothing, listeners already notified and error reported.
default:
@@ -431,7 +452,7 @@ func (p *parser) Visit(tree antlr.ParseTree) any {
// Report at least one error if the parser reaches an unknown parse element.
// Typically, this happens if the parser has already encountered a syntax error elsewhere.
- if len(p.errors.GetErrors()) == 0 {
+ if p.errors.errorCount() == 0 {
txt := "<>"
if t != nil {
txt = fmt.Sprintf("<<%T>>", t)
@@ -462,7 +483,7 @@ func (p *parser) VisitExpr(ctx *gen.ExprContext) any {
// Visit a parse tree produced by CELParser#conditionalOr.
func (p *parser) VisitConditionalOr(ctx *gen.ConditionalOrContext) any {
result := p.Visit(ctx.GetE()).(*exprpb.Expr)
- b := newBalancer(p.helper, operators.LogicalOr, result)
+ l := p.newLogicManager(operators.LogicalOr, result)
rest := ctx.GetE1()
for i, op := range ctx.GetOps() {
if i >= len(rest) {
@@ -470,15 +491,15 @@ func (p *parser) VisitConditionalOr(ctx *gen.ConditionalOrContext) any {
}
next := p.Visit(rest[i]).(*exprpb.Expr)
opID := p.helper.id(op)
- b.addTerm(opID, next)
+ l.addTerm(opID, next)
}
- return b.balance()
+ return l.toExpr()
}
// Visit a parse tree produced by CELParser#conditionalAnd.
func (p *parser) VisitConditionalAnd(ctx *gen.ConditionalAndContext) any {
result := p.Visit(ctx.GetE()).(*exprpb.Expr)
- b := newBalancer(p.helper, operators.LogicalAnd, result)
+ l := p.newLogicManager(operators.LogicalAnd, result)
rest := ctx.GetE1()
for i, op := range ctx.GetOps() {
if i >= len(rest) {
@@ -486,9 +507,9 @@ func (p *parser) VisitConditionalAnd(ctx *gen.ConditionalAndContext) any {
}
next := p.Visit(rest[i]).(*exprpb.Expr)
opID := p.helper.id(op)
- b.addTerm(opID, next)
+ l.addTerm(opID, next)
}
- return b.balance()
+ return l.toExpr()
}
// Visit a parse tree produced by CELParser#relation.
@@ -552,7 +573,7 @@ func (p *parser) VisitSelect(ctx *gen.SelectContext) any {
return p.helper.newExpr(ctx)
}
id := ctx.GetId().GetText()
- if ctx.GetOp().GetText() == ".?" {
+ if ctx.GetOpt() != nil {
if !p.enableOptionalSyntax {
return p.reportError(ctx.GetOp(), "unsupported syntax '.?'")
}
@@ -574,7 +595,7 @@ func (p *parser) VisitMemberCall(ctx *gen.MemberCallContext) any {
}
id := ctx.GetId().GetText()
opID := p.helper.id(ctx.GetOpen())
- return p.receiverCallOrMacro(opID, id, operand, p.visitList(ctx.GetArgs())...)
+ return p.receiverCallOrMacro(opID, id, operand, p.visitExprList(ctx.GetArgs())...)
}
// Visit a parse tree produced by CELParser#Index.
@@ -587,7 +608,7 @@ func (p *parser) VisitIndex(ctx *gen.IndexContext) any {
opID := p.helper.id(ctx.GetOp())
index := p.Visit(ctx.GetIndex()).(*exprpb.Expr)
operator := operators.Index
- if ctx.GetOp().GetText() == "[?" {
+ if ctx.GetOpt() != nil {
if !p.enableOptionalSyntax {
return p.reportError(ctx.GetOp(), "unsupported syntax '[?'")
}
@@ -666,7 +687,7 @@ func (p *parser) VisitIdentOrGlobalCall(ctx *gen.IdentOrGlobalCallContext) any {
identName += id
if ctx.GetOp() != nil {
opID := p.helper.id(ctx.GetOp())
- return p.globalCallOrMacro(opID, identName, p.visitList(ctx.GetArgs())...)
+ return p.globalCallOrMacro(opID, identName, p.visitExprList(ctx.GetArgs())...)
}
return p.helper.newIdent(ctx.GetId(), identName)
}
@@ -674,7 +695,8 @@ func (p *parser) VisitIdentOrGlobalCall(ctx *gen.IdentOrGlobalCallContext) any {
// Visit a parse tree produced by CELParser#CreateList.
func (p *parser) VisitCreateList(ctx *gen.CreateListContext) any {
listID := p.helper.id(ctx.GetOp())
- return p.helper.newList(listID, p.visitList(ctx.GetElems())...)
+ elems, optionals := p.visitListInit(ctx.GetElems())
+ return p.helper.newList(listID, elems, optionals...)
}
// Visit a parse tree produced by CELParser#CreateStruct.
@@ -703,13 +725,13 @@ func (p *parser) VisitMapInitializerList(ctx *gen.MapInitializerListContext) any
// This is the result of a syntax error detected elsewhere.
return []*exprpb.Expr_CreateStruct_Entry{}
}
- optKey := keys[i].(*gen.OptKeyContext)
+ optKey := keys[i]
optional := optKey.GetOpt() != nil
if !p.enableOptionalSyntax && optional {
p.reportError(optKey, "unsupported syntax '?'")
continue
}
- key := p.Visit(optKey.Expr()).(*exprpb.Expr)
+ key := p.Visit(optKey.GetE()).(*exprpb.Expr)
value := p.Visit(vals[i]).(*exprpb.Expr)
entry := p.helper.newMapEntry(colID, key, value, optional)
result[i] = entry
@@ -796,13 +818,37 @@ func (p *parser) VisitNull(ctx *gen.NullContext) any {
NullValue: structpb.NullValue_NULL_VALUE}})
}
-func (p *parser) visitList(ctx gen.IExprListContext) []*exprpb.Expr {
+func (p *parser) visitExprList(ctx gen.IExprListContext) []*exprpb.Expr {
if ctx == nil {
return []*exprpb.Expr{}
}
return p.visitSlice(ctx.GetE())
}
+func (p *parser) visitListInit(ctx gen.IListInitContext) ([]*exprpb.Expr, []int32) {
+ if ctx == nil {
+ return []*exprpb.Expr{}, []int32{}
+ }
+ elements := ctx.GetElems()
+ result := make([]*exprpb.Expr, len(elements))
+ optionals := []int32{}
+ for i, e := range elements {
+ ex := p.Visit(e.GetE()).(*exprpb.Expr)
+ if ex == nil {
+ return []*exprpb.Expr{}, []int32{}
+ }
+ result[i] = ex
+ if e.GetOpt() != nil {
+ if !p.enableOptionalSyntax {
+ p.reportError(e.GetOpt(), "unsupported syntax '?'")
+ continue
+ }
+ optionals = append(optionals, int32(i))
+ }
+ }
+ return result, optionals
+}
+
func (p *parser) visitSlice(expressions []gen.IExprContext) []*exprpb.Expr {
if expressions == nil {
return []*exprpb.Expr{}
@@ -824,24 +870,29 @@ func (p *parser) unquote(ctx any, value string, isBytes bool) string {
return text
}
+func (p *parser) newLogicManager(function string, term *exprpb.Expr) *logicManager {
+ if p.enableVariadicOperatorASTs {
+ return newVariadicLogicManager(p.helper, function, term)
+ }
+ return newBalancingLogicManager(p.helper, function, term)
+}
+
func (p *parser) reportError(ctx any, format string, args ...any) *exprpb.Expr {
var location common.Location
- switch ctx.(type) {
+ err := p.helper.newExpr(ctx)
+ switch c := ctx.(type) {
case common.Location:
- location = ctx.(common.Location)
+ location = c
case antlr.Token, antlr.ParserRuleContext:
- err := p.helper.newExpr(ctx)
location = p.helper.getLocation(err.GetId())
}
- err := p.helper.newExpr(ctx)
// Provide arguments to the report error.
- p.errors.ReportError(location, format, args...)
+ p.errors.reportErrorAtID(err.GetId(), location, format, args...)
return err
}
// ANTLR Parse listener implementations
func (p *parser) SyntaxError(recognizer antlr.Recognizer, offendingSymbol any, line, column int, msg string, e antlr.RecognitionException) {
- // TODO: Snippet
l := p.helper.source.NewLocation(line, column)
// Hack to keep existing error messages consistent with previous versions of CEL when a reserved word
// is used as an identifier. This behavior needs to be overhauled to provide consistent, normalized error
@@ -849,7 +900,16 @@ func (p *parser) SyntaxError(recognizer antlr.Recognizer, offendingSymbol any, l
if strings.Contains(msg, "no viable alternative") {
msg = reservedIdentifier.ReplaceAllString(msg, mismatchedReservedIdentifier)
}
- p.errors.syntaxError(l, msg)
+ // Ensure that no more than 100 syntax errors are reported as this will halt attempts to recover from a
+ // seriously broken expression.
+ if p.errorReports < p.errorReportingLimit {
+ p.errorReports++
+ p.errors.syntaxError(l, msg)
+ } else {
+ tme := &tooManyErrors{errorReportingLimit: p.errorReportingLimit}
+ p.errors.syntaxError(l, tme.Error())
+ panic(tme)
+ }
}
func (p *parser) ReportAmbiguity(recognizer antlr.Parser, dfa *antlr.DFA, startIndex, stopIndex int, exact bool, ambigAlts *antlr.BitSet, configs antlr.ATNConfigSet) {
diff --git a/vendor/github.com/google/cel-go/parser/unparser.go b/vendor/github.com/google/cel-go/parser/unparser.go
index ea20efc98..c3c40a0dd 100644
--- a/vendor/github.com/google/cel-go/parser/unparser.go
+++ b/vendor/github.com/google/cel-go/parser/unparser.go
@@ -106,9 +106,15 @@ func (un *unparser) visitCall(expr *exprpb.Expr) error {
// ternary operator
case operators.Conditional:
return un.visitCallConditional(expr)
+ // optional select operator
+ case operators.OptSelect:
+ return un.visitOptSelect(expr)
// index operator
case operators.Index:
return un.visitCallIndex(expr)
+ // optional index operator
+ case operators.OptIndex:
+ return un.visitCallOptIndex(expr)
// unary operators
case operators.LogicalNot, operators.Negate:
return un.visitCallUnary(expr)
@@ -218,6 +224,14 @@ func (un *unparser) visitCallFunc(expr *exprpb.Expr) error {
}
func (un *unparser) visitCallIndex(expr *exprpb.Expr) error {
+ return un.visitCallIndexInternal(expr, "[")
+}
+
+func (un *unparser) visitCallOptIndex(expr *exprpb.Expr) error {
+ return un.visitCallIndexInternal(expr, "[?")
+}
+
+func (un *unparser) visitCallIndexInternal(expr *exprpb.Expr, op string) error {
c := expr.GetCallExpr()
args := c.GetArgs()
nested := isBinaryOrTernaryOperator(args[0])
@@ -225,7 +239,7 @@ func (un *unparser) visitCallIndex(expr *exprpb.Expr) error {
if err != nil {
return err
}
- un.str.WriteString("[")
+ un.str.WriteString(op)
err = un.visit(args[1])
if err != nil {
return err
@@ -262,6 +276,9 @@ func (un *unparser) visitConst(expr *exprpb.Expr) error {
// represent the float using the minimum required digits
d := strconv.FormatFloat(c.GetDoubleValue(), 'g', -1, 64)
un.str.WriteString(d)
+ if !strings.Contains(d, ".") {
+ un.str.WriteString(".0")
+ }
case *exprpb.Constant_Int64Value:
i := strconv.FormatInt(c.GetInt64Value(), 10)
un.str.WriteString(i)
@@ -289,8 +306,15 @@ func (un *unparser) visitIdent(expr *exprpb.Expr) error {
func (un *unparser) visitList(expr *exprpb.Expr) error {
l := expr.GetListExpr()
elems := l.GetElements()
+ optIndices := make(map[int]bool, len(elems))
+ for _, idx := range l.GetOptionalIndices() {
+ optIndices[int(idx)] = true
+ }
un.str.WriteString("[")
for i, elem := range elems {
+ if optIndices[i] {
+ un.str.WriteString("?")
+ }
err := un.visit(elem)
if err != nil {
return err
@@ -303,20 +327,32 @@ func (un *unparser) visitList(expr *exprpb.Expr) error {
return nil
}
+func (un *unparser) visitOptSelect(expr *exprpb.Expr) error {
+ c := expr.GetCallExpr()
+ args := c.GetArgs()
+ operand := args[0]
+ field := args[1].GetConstExpr().GetStringValue()
+ return un.visitSelectInternal(operand, false, ".?", field)
+}
+
func (un *unparser) visitSelect(expr *exprpb.Expr) error {
sel := expr.GetSelectExpr()
+ return un.visitSelectInternal(sel.GetOperand(), sel.GetTestOnly(), ".", sel.GetField())
+}
+
+func (un *unparser) visitSelectInternal(operand *exprpb.Expr, testOnly bool, op string, field string) error {
// handle the case when the select expression was generated by the has() macro.
- if sel.GetTestOnly() {
+ if testOnly {
un.str.WriteString("has(")
}
- nested := !sel.GetTestOnly() && isBinaryOrTernaryOperator(sel.GetOperand())
- err := un.visitMaybeNested(sel.GetOperand(), nested)
+ nested := !testOnly && isBinaryOrTernaryOperator(operand)
+ err := un.visitMaybeNested(operand, nested)
if err != nil {
return err
}
- un.str.WriteString(".")
- un.str.WriteString(sel.GetField())
- if sel.GetTestOnly() {
+ un.str.WriteString(op)
+ un.str.WriteString(field)
+ if testOnly {
un.str.WriteString(")")
}
return nil
@@ -339,6 +375,9 @@ func (un *unparser) visitStructMsg(expr *exprpb.Expr) error {
un.str.WriteString("{")
for i, entry := range entries {
f := entry.GetFieldKey()
+ if entry.GetOptionalEntry() {
+ un.str.WriteString("?")
+ }
un.str.WriteString(f)
un.str.WriteString(": ")
v := entry.GetValue()
@@ -360,6 +399,9 @@ func (un *unparser) visitStructMap(expr *exprpb.Expr) error {
un.str.WriteString("{")
for i, entry := range entries {
k := entry.GetMapKey()
+ if entry.GetOptionalEntry() {
+ un.str.WriteString("?")
+ }
err := un.visit(k)
if err != nil {
return err
diff --git a/vendor/github.com/tektoncd/triggers/pkg/apis/triggers/v1alpha1/event_listener_validation.go b/vendor/github.com/tektoncd/triggers/pkg/apis/triggers/v1alpha1/event_listener_validation.go
index e80c8263b..18dcfdf74 100644
--- a/vendor/github.com/tektoncd/triggers/pkg/apis/triggers/v1alpha1/event_listener_validation.go
+++ b/vendor/github.com/tektoncd/triggers/pkg/apis/triggers/v1alpha1/event_listener_validation.go
@@ -106,7 +106,7 @@ func validateCustomObject(customData *CustomResource) (errs *apis.FieldError) {
// bounded by condition because containers fields are optional so there is a chance that containers can be nil.
if len(orig.Spec.Template.Spec.Containers) == 1 {
errs = errs.Also(apis.CheckDisallowedFields(orig.Spec.Template.Spec.Containers[0],
- *containerFieldMask(&orig.Spec.Template.Spec.Containers[0])).ViaField("spec.template.spec.containers[0]"))
+ *containerFieldMaskForCustomResource(&orig.Spec.Template.Spec.Containers[0])).ViaField("spec.template.spec.containers[0]"))
// validate env
errs = errs.Also(validateEnv(orig.Spec.Template.Spec.Containers[0].Env).ViaField("spec.template.spec.containers[0].env"))
}
@@ -129,7 +129,7 @@ func validateKubernetesObject(orig *KubernetesResource) (errs *apis.FieldError)
// bounded by condition because containers fields are optional so there is a chance that containers can be nil.
if len(orig.Template.Spec.Containers) == 1 {
errs = errs.Also(apis.CheckDisallowedFields(orig.Template.Spec.Containers[0],
- *containerFieldMask(&orig.Template.Spec.Containers[0])).ViaField("spec.template.spec.containers[0]"))
+ *containerFieldMaskForKubernetes(&orig.Template.Spec.Containers[0])).ViaField("spec.template.spec.containers[0]"))
// validate env
errs = errs.Also(validateEnv(orig.Template.Spec.Containers[0].Env).ViaField("spec.template.spec.containers[0].env"))
}
@@ -206,20 +206,30 @@ func envVarMask(in *corev1.EnvVar) *corev1.EnvVar {
return out
}
-func containerFieldMask(in *corev1.Container) *corev1.Container {
+func containerFieldMaskForKubernetes(in *corev1.Container) *corev1.Container {
out := new(corev1.Container)
out.Resources = in.Resources
out.Env = in.Env
+ out.LivenessProbe = in.LivenessProbe
+ out.ReadinessProbe = in.ReadinessProbe
+ out.StartupProbe = in.StartupProbe
+ return containerFieldMask(out)
+}
+
+func containerFieldMaskForCustomResource(in *corev1.Container) *corev1.Container {
+ out := new(corev1.Container)
+ out.Resources = in.Resources
+ out.Env = in.Env
+ return containerFieldMask(out)
+}
+func containerFieldMask(out *corev1.Container) *corev1.Container {
// Disallowed fields
// This list clarifies which all container attributes are not allowed.
out.Name = ""
out.Image = ""
out.Args = nil
out.Ports = nil
- out.LivenessProbe = nil
- out.ReadinessProbe = nil
- out.StartupProbe = nil
out.Command = nil
out.VolumeMounts = nil
out.ImagePullPolicy = ""
diff --git a/vendor/github.com/tektoncd/triggers/pkg/apis/triggers/v1beta1/event_listener_validation.go b/vendor/github.com/tektoncd/triggers/pkg/apis/triggers/v1beta1/event_listener_validation.go
index 5a63a5621..ce54d5793 100644
--- a/vendor/github.com/tektoncd/triggers/pkg/apis/triggers/v1beta1/event_listener_validation.go
+++ b/vendor/github.com/tektoncd/triggers/pkg/apis/triggers/v1beta1/event_listener_validation.go
@@ -121,7 +121,7 @@ func validateCustomObject(customData *CustomResource) (errs *apis.FieldError) {
// bounded by condition because containers fields are optional so there is a chance that containers can be nil.
if len(orig.Spec.Template.Spec.Containers) == 1 {
errs = errs.Also(apis.CheckDisallowedFields(orig.Spec.Template.Spec.Containers[0],
- *containerFieldMask(&orig.Spec.Template.Spec.Containers[0])).ViaField("spec.template.spec.containers[0]"))
+ *containerFieldMaskForCustomResource(&orig.Spec.Template.Spec.Containers[0])).ViaField("spec.template.spec.containers[0]"))
// validate env
errs = errs.Also(validateEnv(orig.Spec.Template.Spec.Containers[0].Env).ViaField("spec.template.spec.containers[0].env"))
}
@@ -144,7 +144,7 @@ func validateKubernetesObject(orig *KubernetesResource) (errs *apis.FieldError)
// bounded by condition because containers fields are optional so there is a chance that containers can be nil.
if len(orig.Template.Spec.Containers) == 1 {
errs = errs.Also(apis.CheckDisallowedFields(orig.Template.Spec.Containers[0],
- *containerFieldMask(&orig.Template.Spec.Containers[0])).ViaField("spec.template.spec.containers[0]"))
+ *containerFieldMaskForKubernetes(&orig.Template.Spec.Containers[0])).ViaField("spec.template.spec.containers[0]"))
// validate env
errs = errs.Also(validateEnv(orig.Template.Spec.Containers[0].Env).ViaField("spec.template.spec.containers[0].env"))
}
@@ -221,20 +221,30 @@ func envVarMask(in *corev1.EnvVar) *corev1.EnvVar {
return out
}
-func containerFieldMask(in *corev1.Container) *corev1.Container {
+func containerFieldMaskForKubernetes(in *corev1.Container) *corev1.Container {
out := new(corev1.Container)
out.Resources = in.Resources
out.Env = in.Env
+ out.LivenessProbe = in.LivenessProbe
+ out.ReadinessProbe = in.ReadinessProbe
+ out.StartupProbe = in.StartupProbe
+ return containerFieldMask(out)
+}
+
+func containerFieldMaskForCustomResource(in *corev1.Container) *corev1.Container {
+ out := new(corev1.Container)
+ out.Resources = in.Resources
+ out.Env = in.Env
+ return containerFieldMask(out)
+}
+func containerFieldMask(out *corev1.Container) *corev1.Container {
// Disallowed fields
// This list clarifies which all container attributes are not allowed.
out.Name = ""
out.Image = ""
out.Args = nil
out.Ports = nil
- out.LivenessProbe = nil
- out.ReadinessProbe = nil
- out.StartupProbe = nil
out.Command = nil
out.VolumeMounts = nil
out.ImagePullPolicy = ""
diff --git a/vendor/github.com/tektoncd/triggers/pkg/apis/triggers/v1beta1/openapi_generated.go b/vendor/github.com/tektoncd/triggers/pkg/apis/triggers/v1beta1/openapi_generated.go
index 977fc6e97..2e42df5a6 100644
--- a/vendor/github.com/tektoncd/triggers/pkg/apis/triggers/v1beta1/openapi_generated.go
+++ b/vendor/github.com/tektoncd/triggers/pkg/apis/triggers/v1beta1/openapi_generated.go
@@ -30,9 +30,6 @@ import (
func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenAPIDefinition {
return map[string]common.OpenAPIDefinition{
- "github.com/tektoncd/triggers/pkg/apis/triggers/v1beta1.BitbucketInterceptor": schema_pkg_apis_triggers_v1beta1_BitbucketInterceptor(ref),
- "github.com/tektoncd/triggers/pkg/apis/triggers/v1beta1.CELInterceptor": schema_pkg_apis_triggers_v1beta1_CELInterceptor(ref),
- "github.com/tektoncd/triggers/pkg/apis/triggers/v1beta1.CELOverlay": schema_pkg_apis_triggers_v1beta1_CELOverlay(ref),
"github.com/tektoncd/triggers/pkg/apis/triggers/v1beta1.ClusterTriggerBinding": schema_pkg_apis_triggers_v1beta1_ClusterTriggerBinding(ref),
"github.com/tektoncd/triggers/pkg/apis/triggers/v1beta1.ClusterTriggerBindingList": schema_pkg_apis_triggers_v1beta1_ClusterTriggerBindingList(ref),
"github.com/tektoncd/triggers/pkg/apis/triggers/v1beta1.CustomResource": schema_pkg_apis_triggers_v1beta1_CustomResource(ref),
@@ -44,10 +41,6 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA
"github.com/tektoncd/triggers/pkg/apis/triggers/v1beta1.EventListenerTrigger": schema_pkg_apis_triggers_v1beta1_EventListenerTrigger(ref),
"github.com/tektoncd/triggers/pkg/apis/triggers/v1beta1.EventListenerTriggerGroup": schema_pkg_apis_triggers_v1beta1_EventListenerTriggerGroup(ref),
"github.com/tektoncd/triggers/pkg/apis/triggers/v1beta1.EventListenerTriggerSelector": schema_pkg_apis_triggers_v1beta1_EventListenerTriggerSelector(ref),
- "github.com/tektoncd/triggers/pkg/apis/triggers/v1beta1.GitHubInterceptor": schema_pkg_apis_triggers_v1beta1_GitHubInterceptor(ref),
- "github.com/tektoncd/triggers/pkg/apis/triggers/v1beta1.GitLabInterceptor": schema_pkg_apis_triggers_v1beta1_GitLabInterceptor(ref),
- "github.com/tektoncd/triggers/pkg/apis/triggers/v1beta1.GithubAddChangedFiles": schema_pkg_apis_triggers_v1beta1_GithubAddChangedFiles(ref),
- "github.com/tektoncd/triggers/pkg/apis/triggers/v1beta1.GithubOwners": schema_pkg_apis_triggers_v1beta1_GithubOwners(ref),
"github.com/tektoncd/triggers/pkg/apis/triggers/v1beta1.InterceptorParams": schema_pkg_apis_triggers_v1beta1_InterceptorParams(ref),
"github.com/tektoncd/triggers/pkg/apis/triggers/v1beta1.InterceptorRef": schema_pkg_apis_triggers_v1beta1_InterceptorRef(ref),
"github.com/tektoncd/triggers/pkg/apis/triggers/v1beta1.InterceptorRequest": schema_pkg_apis_triggers_v1beta1_InterceptorRequest(ref),
@@ -58,7 +51,6 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA
"github.com/tektoncd/triggers/pkg/apis/triggers/v1beta1.ParamSpec": schema_pkg_apis_triggers_v1beta1_ParamSpec(ref),
"github.com/tektoncd/triggers/pkg/apis/triggers/v1beta1.Resources": schema_pkg_apis_triggers_v1beta1_Resources(ref),
"github.com/tektoncd/triggers/pkg/apis/triggers/v1beta1.SecretRef": schema_pkg_apis_triggers_v1beta1_SecretRef(ref),
- "github.com/tektoncd/triggers/pkg/apis/triggers/v1beta1.SlackInterceptor": schema_pkg_apis_triggers_v1beta1_SlackInterceptor(ref),
"github.com/tektoncd/triggers/pkg/apis/triggers/v1beta1.Status": schema_pkg_apis_triggers_v1beta1_Status(ref),
"github.com/tektoncd/triggers/pkg/apis/triggers/v1beta1.StatusError": schema_pkg_apis_triggers_v1beta1_StatusError(ref),
"github.com/tektoncd/triggers/pkg/apis/triggers/v1beta1.Trigger": schema_pkg_apis_triggers_v1beta1_Trigger(ref),
@@ -81,109 +73,6 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA
}
}
-func schema_pkg_apis_triggers_v1beta1_BitbucketInterceptor(ref common.ReferenceCallback) common.OpenAPIDefinition {
- return common.OpenAPIDefinition{
- Schema: spec.Schema{
- SchemaProps: spec.SchemaProps{
- Description: "BitbucketInterceptor provides a webhook to intercept and pre-process events",
- Type: []string{"object"},
- Properties: map[string]spec.Schema{
- "secretRef": {
- SchemaProps: spec.SchemaProps{
- Ref: ref("github.com/tektoncd/triggers/pkg/apis/triggers/v1beta1.SecretRef"),
- },
- },
- "eventTypes": {
- VendorExtensible: spec.VendorExtensible{
- Extensions: spec.Extensions{
- "x-kubernetes-list-type": "atomic",
- },
- },
- SchemaProps: spec.SchemaProps{
- Type: []string{"array"},
- Items: &spec.SchemaOrArray{
- Schema: &spec.Schema{
- SchemaProps: spec.SchemaProps{
- Default: "",
- Type: []string{"string"},
- Format: "",
- },
- },
- },
- },
- },
- },
- },
- },
- Dependencies: []string{
- "github.com/tektoncd/triggers/pkg/apis/triggers/v1beta1.SecretRef"},
- }
-}
-
-func schema_pkg_apis_triggers_v1beta1_CELInterceptor(ref common.ReferenceCallback) common.OpenAPIDefinition {
- return common.OpenAPIDefinition{
- Schema: spec.Schema{
- SchemaProps: spec.SchemaProps{
- Description: "CELInterceptor provides a webhook to intercept and pre-process events",
- Type: []string{"object"},
- Properties: map[string]spec.Schema{
- "filter": {
- SchemaProps: spec.SchemaProps{
- Type: []string{"string"},
- Format: "",
- },
- },
- "overlays": {
- VendorExtensible: spec.VendorExtensible{
- Extensions: spec.Extensions{
- "x-kubernetes-list-type": "atomic",
- },
- },
- SchemaProps: spec.SchemaProps{
- Type: []string{"array"},
- Items: &spec.SchemaOrArray{
- Schema: &spec.Schema{
- SchemaProps: spec.SchemaProps{
- Default: map[string]interface{}{},
- Ref: ref("github.com/tektoncd/triggers/pkg/apis/triggers/v1beta1.CELOverlay"),
- },
- },
- },
- },
- },
- },
- },
- },
- Dependencies: []string{
- "github.com/tektoncd/triggers/pkg/apis/triggers/v1beta1.CELOverlay"},
- }
-}
-
-func schema_pkg_apis_triggers_v1beta1_CELOverlay(ref common.ReferenceCallback) common.OpenAPIDefinition {
- return common.OpenAPIDefinition{
- Schema: spec.Schema{
- SchemaProps: spec.SchemaProps{
- Description: "CELOverlay provides a way to modify the request body using CEL expressions",
- Type: []string{"object"},
- Properties: map[string]spec.Schema{
- "key": {
- SchemaProps: spec.SchemaProps{
- Type: []string{"string"},
- Format: "",
- },
- },
- "expression": {
- SchemaProps: spec.SchemaProps{
- Type: []string{"string"},
- Format: "",
- },
- },
- },
- },
- },
- }
-}
-
func schema_pkg_apis_triggers_v1beta1_ClusterTriggerBinding(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
@@ -543,7 +432,22 @@ func schema_pkg_apis_triggers_v1beta1_EventListenerStatus(ref common.ReferenceCa
},
"address": {
SchemaProps: spec.SchemaProps{
- Ref: ref("knative.dev/pkg/apis/duck/v1beta1.Addressable"),
+ Description: "Address is a single Addressable address. If Addresses is present, Address will be ignored by clients.",
+ Ref: ref("knative.dev/pkg/apis/duck/v1beta1.Addressable"),
+ },
+ },
+ "addresses": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Addresses is a list of addresses for different protocols (HTTP and HTTPS) If Addresses is present, Address must be ignored by clients.",
+ Type: []string{"array"},
+ Items: &spec.SchemaOrArray{
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("knative.dev/pkg/apis/duck/v1beta1.Addressable"),
+ },
+ },
+ },
},
},
"configuration": {
@@ -707,154 +611,6 @@ func schema_pkg_apis_triggers_v1beta1_EventListenerTriggerSelector(ref common.Re
}
}
-func schema_pkg_apis_triggers_v1beta1_GitHubInterceptor(ref common.ReferenceCallback) common.OpenAPIDefinition {
- return common.OpenAPIDefinition{
- Schema: spec.Schema{
- SchemaProps: spec.SchemaProps{
- Description: "GitHubInterceptor provides a webhook to intercept and pre-process events",
- Type: []string{"object"},
- Properties: map[string]spec.Schema{
- "secretRef": {
- SchemaProps: spec.SchemaProps{
- Ref: ref("github.com/tektoncd/triggers/pkg/apis/triggers/v1beta1.SecretRef"),
- },
- },
- "eventTypes": {
- VendorExtensible: spec.VendorExtensible{
- Extensions: spec.Extensions{
- "x-kubernetes-list-type": "atomic",
- },
- },
- SchemaProps: spec.SchemaProps{
- Type: []string{"array"},
- Items: &spec.SchemaOrArray{
- Schema: &spec.Schema{
- SchemaProps: spec.SchemaProps{
- Default: "",
- Type: []string{"string"},
- Format: "",
- },
- },
- },
- },
- },
- "addChangedFiles": {
- SchemaProps: spec.SchemaProps{
- Default: map[string]interface{}{},
- Ref: ref("github.com/tektoncd/triggers/pkg/apis/triggers/v1beta1.GithubAddChangedFiles"),
- },
- },
- "githubOwners": {
- SchemaProps: spec.SchemaProps{
- Default: map[string]interface{}{},
- Ref: ref("github.com/tektoncd/triggers/pkg/apis/triggers/v1beta1.GithubOwners"),
- },
- },
- },
- },
- },
- Dependencies: []string{
- "github.com/tektoncd/triggers/pkg/apis/triggers/v1beta1.GithubAddChangedFiles", "github.com/tektoncd/triggers/pkg/apis/triggers/v1beta1.GithubOwners", "github.com/tektoncd/triggers/pkg/apis/triggers/v1beta1.SecretRef"},
- }
-}
-
-func schema_pkg_apis_triggers_v1beta1_GitLabInterceptor(ref common.ReferenceCallback) common.OpenAPIDefinition {
- return common.OpenAPIDefinition{
- Schema: spec.Schema{
- SchemaProps: spec.SchemaProps{
- Description: "GitLabInterceptor provides a webhook to intercept and pre-process events",
- Type: []string{"object"},
- Properties: map[string]spec.Schema{
- "secretRef": {
- SchemaProps: spec.SchemaProps{
- Ref: ref("github.com/tektoncd/triggers/pkg/apis/triggers/v1beta1.SecretRef"),
- },
- },
- "eventTypes": {
- VendorExtensible: spec.VendorExtensible{
- Extensions: spec.Extensions{
- "x-kubernetes-list-type": "atomic",
- },
- },
- SchemaProps: spec.SchemaProps{
- Type: []string{"array"},
- Items: &spec.SchemaOrArray{
- Schema: &spec.Schema{
- SchemaProps: spec.SchemaProps{
- Default: "",
- Type: []string{"string"},
- Format: "",
- },
- },
- },
- },
- },
- },
- },
- },
- Dependencies: []string{
- "github.com/tektoncd/triggers/pkg/apis/triggers/v1beta1.SecretRef"},
- }
-}
-
-func schema_pkg_apis_triggers_v1beta1_GithubAddChangedFiles(ref common.ReferenceCallback) common.OpenAPIDefinition {
- return common.OpenAPIDefinition{
- Schema: spec.Schema{
- SchemaProps: spec.SchemaProps{
- Type: []string{"object"},
- Properties: map[string]spec.Schema{
- "enabled": {
- SchemaProps: spec.SchemaProps{
- Type: []string{"boolean"},
- Format: "",
- },
- },
- "personalAccessToken": {
- SchemaProps: spec.SchemaProps{
- Ref: ref("github.com/tektoncd/triggers/pkg/apis/triggers/v1beta1.SecretRef"),
- },
- },
- },
- },
- },
- Dependencies: []string{
- "github.com/tektoncd/triggers/pkg/apis/triggers/v1beta1.SecretRef"},
- }
-}
-
-func schema_pkg_apis_triggers_v1beta1_GithubOwners(ref common.ReferenceCallback) common.OpenAPIDefinition {
- return common.OpenAPIDefinition{
- Schema: spec.Schema{
- SchemaProps: spec.SchemaProps{
- Type: []string{"object"},
- Properties: map[string]spec.Schema{
- "enabled": {
- SchemaProps: spec.SchemaProps{
- Type: []string{"boolean"},
- Format: "",
- },
- },
- "personalAccessToken": {
- SchemaProps: spec.SchemaProps{
- Description: "This param/variable is required for private repos or when checkType is set to orgMembers or repoMembers or all",
- Ref: ref("github.com/tektoncd/triggers/pkg/apis/triggers/v1beta1.SecretRef"),
- },
- },
- "checkType": {
- SchemaProps: spec.SchemaProps{
- Description: "Set the value to one of the supported values (orgMembers, repoMembers, both, none)",
- Type: []string{"string"},
- Format: "",
- },
- },
- },
- },
- },
- Dependencies: []string{
- "github.com/tektoncd/triggers/pkg/apis/triggers/v1beta1.SecretRef"},
- }
-}
-
func schema_pkg_apis_triggers_v1beta1_InterceptorParams(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
@@ -1230,37 +986,6 @@ func schema_pkg_apis_triggers_v1beta1_SecretRef(ref common.ReferenceCallback) co
}
}
-func schema_pkg_apis_triggers_v1beta1_SlackInterceptor(ref common.ReferenceCallback) common.OpenAPIDefinition {
- return common.OpenAPIDefinition{
- Schema: spec.Schema{
- SchemaProps: spec.SchemaProps{
- Type: []string{"object"},
- Properties: map[string]spec.Schema{
- "requestedFields": {
- VendorExtensible: spec.VendorExtensible{
- Extensions: spec.Extensions{
- "x-kubernetes-list-type": "atomic",
- },
- },
- SchemaProps: spec.SchemaProps{
- Type: []string{"array"},
- Items: &spec.SchemaOrArray{
- Schema: &spec.Schema{
- SchemaProps: spec.SchemaProps{
- Default: "",
- Type: []string{"string"},
- Format: "",
- },
- },
- },
- },
- },
- },
- },
- },
- }
-}
-
func schema_pkg_apis_triggers_v1beta1_Status(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
diff --git a/vendor/github.com/tektoncd/triggers/pkg/apis/triggers/v1beta1/swagger.json b/vendor/github.com/tektoncd/triggers/pkg/apis/triggers/v1beta1/swagger.json
index 3e54bf739..2fd5efd57 100644
--- a/vendor/github.com/tektoncd/triggers/pkg/apis/triggers/v1beta1/swagger.json
+++ b/vendor/github.com/tektoncd/triggers/pkg/apis/triggers/v1beta1/swagger.json
@@ -72,7 +72,7 @@
"type": "array",
"items": {
"default": {},
- "$ref": "#/definitions/v1beta1.Param"
+ "$ref": "#/definitions/v1.Param"
},
"x-kubernetes-list-type": "atomic"
}
@@ -117,11 +117,11 @@
},
"refSource": {
"description": "RefSource is the source reference of the remote data that records the url, digest and the entrypoint.",
- "$ref": "#/definitions/v1beta1.RefSource"
+ "$ref": "#/definitions/v1.RefSource"
},
"source": {
"description": "Deprecated: Use RefSource instead",
- "$ref": "#/definitions/v1beta1.ConfigSource"
+ "$ref": "#/definitions/v1.RefSource"
}
}
},
@@ -141,11 +141,11 @@
},
"refSource": {
"description": "RefSource is the source reference of the remote data that records the url, digest and the entrypoint.",
- "$ref": "#/definitions/v1beta1.RefSource"
+ "$ref": "#/definitions/v1.RefSource"
},
"source": {
"description": "Deprecated: Use RefSource instead",
- "$ref": "#/definitions/v1beta1.ConfigSource"
+ "$ref": "#/definitions/v1.RefSource"
}
}
},
@@ -822,7 +822,7 @@
}
},
"v1beta1.Pipeline": {
- "description": "Pipeline describes a list of Tasks to execute. It expresses how outputs of tasks feed into inputs of subsequent tasks.",
+ "description": "Pipeline describes a list of Tasks to execute. It expresses how outputs of tasks feed into inputs of subsequent tasks.\n\nDeprecated: Please use v1.Pipeline instead.",
"type": "object",
"properties": {
"apiVersion": {
@@ -976,7 +976,7 @@
}
},
"v1beta1.PipelineRun": {
- "description": "PipelineRun represents a single execution of a Pipeline. PipelineRuns are how the graph of Tasks declared in a Pipeline are executed; they specify inputs to Pipelines such as parameter values and capture operational aspects of the Tasks execution such as service account and tolerations. Creating a PipelineRun creates TaskRuns for Tasks in the referenced Pipeline.",
+ "description": "PipelineRun represents a single execution of a Pipeline. PipelineRuns are how the graph of Tasks declared in a Pipeline are executed; they specify inputs to Pipelines such as parameter values and capture operational aspects of the Tasks execution such as service account and tolerations. Creating a PipelineRun creates TaskRuns for Tasks in the referenced Pipeline.\n\nDeprecated: Please use v1.PipelineRun instead.",
"type": "object",
"properties": {
"apiVersion": {
@@ -1456,7 +1456,7 @@
"$ref": "#/definitions/v1beta1.EmbeddedTask"
},
"timeout": {
- "description": "Time after which the TaskRun times out. Defaults to 1 hour. Specified TaskRun timeout should be less than 24h. Refer Go's ParseDuration documentation for expected format: https://golang.org/pkg/time/#ParseDuration",
+ "description": "Time after which the TaskRun times out. Defaults to 1 hour. Refer Go's ParseDuration documentation for expected format: https://golang.org/pkg/time/#ParseDuration",
"$ref": "#/definitions/v1.Duration"
},
"when": {
@@ -2329,7 +2329,7 @@
}
},
"v1beta1.Task": {
- "description": "Task represents a collection of sequential steps that are run as part of a Pipeline using a set of inputs and producing a set of outputs. Tasks execute when TaskRuns are created that provide the input parameters and resources and output resources the Task requires.",
+ "description": "Task represents a collection of sequential steps that are run as part of a Pipeline using a set of inputs and producing a set of outputs. Tasks execute when TaskRuns are created that provide the input parameters and resources and output resources the Task requires.\n\nDeprecated: Please use v1.Task instead.",
"type": "object",
"properties": {
"apiVersion": {
@@ -2515,7 +2515,7 @@
}
},
"v1beta1.TaskRun": {
- "description": "TaskRun represents a single execution of a Task. TaskRuns are how the steps specified in a Task are executed; they specify the parameters and resources used to run the steps in a Task.",
+ "description": "TaskRun represents a single execution of a Task. TaskRuns are how the steps specified in a Task are executed; they specify the parameters and resources used to run the steps in a Task.\n\nDeprecated: Please use v1.TaskRun instead.",
"type": "object",
"properties": {
"apiVersion": {
@@ -2756,7 +2756,7 @@
"$ref": "#/definitions/v1beta1.TaskSpec"
},
"timeout": {
- "description": "Time after which one retry attempt times out. Defaults to 1 hour. Specified build timeout should be less than 24h. Refer Go's ParseDuration documentation for expected format: https://golang.org/pkg/time/#ParseDuration",
+ "description": "Time after which one retry attempt times out. Defaults to 1 hour. Refer Go's ParseDuration documentation for expected format: https://golang.org/pkg/time/#ParseDuration",
"$ref": "#/definitions/v1.Duration"
},
"workspaces": {
diff --git a/vendor/github.com/tektoncd/triggers/pkg/apis/triggers/v1beta1/trigger_types.go b/vendor/github.com/tektoncd/triggers/pkg/apis/triggers/v1beta1/trigger_types.go
index b52da4664..4651043aa 100644
--- a/vendor/github.com/tektoncd/triggers/pkg/apis/triggers/v1beta1/trigger_types.go
+++ b/vendor/github.com/tektoncd/triggers/pkg/apis/triggers/v1beta1/trigger_types.go
@@ -155,75 +155,6 @@ type WebhookInterceptor struct {
Header []v1beta1.Param `json:"header,omitempty"`
}
-type SlackInterceptor struct {
- // the Requested fields to be extracted from data form
-
- // +listType=atomic
- RequestedFields []string `json:"requestedFields,omitempty"`
-}
-
-// BitbucketInterceptor provides a webhook to intercept and pre-process events
-type BitbucketInterceptor struct {
- SecretRef *SecretRef `json:"secretRef,omitempty"`
- // +listType=atomic
- EventTypes []string `json:"eventTypes,omitempty"`
-}
-
-// GitHubInterceptor provides a webhook to intercept and pre-process events
-type GitHubInterceptor struct {
- SecretRef *SecretRef `json:"secretRef,omitempty"`
- // +listType=atomic
- EventTypes []string `json:"eventTypes,omitempty"`
- AddChangedFiles GithubAddChangedFiles `json:"addChangedFiles,omitempty"`
- GithubOwners GithubOwners `json:"githubOwners,omitempty"`
-}
-
-type CheckType string
-
-const (
- // Set the checkType to orgMembers to allow org members to submit or comment on PR to proceed
- OrgMembers CheckType = "orgMembers"
- // Set the checkType to repoMembers to allow repo members to submit or comment on PR to proceed
- RepoMembers CheckType = "repoMembers"
- // Set the checkType to all if both repo members or org members can submit or comment on PR to proceed
- All CheckType = "all"
- // Set the checkType to none if neither of repo members or org members can not submit or comment on PR to proceed
- None CheckType = "none"
-)
-
-type GithubOwners struct {
- Enabled bool `json:"enabled,omitempty"`
- // This param/variable is required for private repos or when checkType is set to orgMembers or repoMembers or all
- PersonalAccessToken *SecretRef `json:"personalAccessToken,omitempty"`
- // Set the value to one of the supported values (orgMembers, repoMembers, both, none)
- CheckType CheckType `json:"checkType,omitempty"`
-}
-
-type GithubAddChangedFiles struct {
- Enabled bool `json:"enabled,omitempty"`
- PersonalAccessToken *SecretRef `json:"personalAccessToken,omitempty"`
-}
-
-// GitLabInterceptor provides a webhook to intercept and pre-process events
-type GitLabInterceptor struct {
- SecretRef *SecretRef `json:"secretRef,omitempty"`
- // +listType=atomic
- EventTypes []string `json:"eventTypes,omitempty"`
-}
-
-// CELInterceptor provides a webhook to intercept and pre-process events
-type CELInterceptor struct {
- Filter string `json:"filter,omitempty"`
- // +listType=atomic
- Overlays []CELOverlay `json:"overlays,omitempty"`
-}
-
-// CELOverlay provides a way to modify the request body using CEL expressions
-type CELOverlay struct {
- Key string `json:"key,omitempty"`
- Expression string `json:"expression,omitempty"`
-}
-
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// TriggerList contains a list of Triggers.
diff --git a/vendor/github.com/tektoncd/triggers/pkg/apis/triggers/v1beta1/zz_generated.deepcopy.go b/vendor/github.com/tektoncd/triggers/pkg/apis/triggers/v1beta1/zz_generated.deepcopy.go
index 9e36c7456..29cc4dc06 100644
--- a/vendor/github.com/tektoncd/triggers/pkg/apis/triggers/v1beta1/zz_generated.deepcopy.go
+++ b/vendor/github.com/tektoncd/triggers/pkg/apis/triggers/v1beta1/zz_generated.deepcopy.go
@@ -29,69 +29,6 @@ import (
apis "knative.dev/pkg/apis"
)
-// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *BitbucketInterceptor) DeepCopyInto(out *BitbucketInterceptor) {
- *out = *in
- if in.SecretRef != nil {
- in, out := &in.SecretRef, &out.SecretRef
- *out = new(SecretRef)
- **out = **in
- }
- if in.EventTypes != nil {
- in, out := &in.EventTypes, &out.EventTypes
- *out = make([]string, len(*in))
- copy(*out, *in)
- }
- return
-}
-
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BitbucketInterceptor.
-func (in *BitbucketInterceptor) DeepCopy() *BitbucketInterceptor {
- if in == nil {
- return nil
- }
- out := new(BitbucketInterceptor)
- in.DeepCopyInto(out)
- return out
-}
-
-// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *CELInterceptor) DeepCopyInto(out *CELInterceptor) {
- *out = *in
- if in.Overlays != nil {
- in, out := &in.Overlays, &out.Overlays
- *out = make([]CELOverlay, len(*in))
- copy(*out, *in)
- }
- return
-}
-
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CELInterceptor.
-func (in *CELInterceptor) DeepCopy() *CELInterceptor {
- if in == nil {
- return nil
- }
- out := new(CELInterceptor)
- in.DeepCopyInto(out)
- return out
-}
-
-// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *CELOverlay) DeepCopyInto(out *CELOverlay) {
- *out = *in
- return
-}
-
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CELOverlay.
-func (in *CELOverlay) DeepCopy() *CELOverlay {
- if in == nil {
- return nil
- }
- out := new(CELOverlay)
- in.DeepCopyInto(out)
- return out
-}
-
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ClusterTriggerBinding) DeepCopyInto(out *ClusterTriggerBinding) {
*out = *in
@@ -396,102 +333,6 @@ func (in *EventListenerTriggerSelector) DeepCopy() *EventListenerTriggerSelector
return out
}
-// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *GitHubInterceptor) DeepCopyInto(out *GitHubInterceptor) {
- *out = *in
- if in.SecretRef != nil {
- in, out := &in.SecretRef, &out.SecretRef
- *out = new(SecretRef)
- **out = **in
- }
- if in.EventTypes != nil {
- in, out := &in.EventTypes, &out.EventTypes
- *out = make([]string, len(*in))
- copy(*out, *in)
- }
- in.AddChangedFiles.DeepCopyInto(&out.AddChangedFiles)
- in.GithubOwners.DeepCopyInto(&out.GithubOwners)
- return
-}
-
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GitHubInterceptor.
-func (in *GitHubInterceptor) DeepCopy() *GitHubInterceptor {
- if in == nil {
- return nil
- }
- out := new(GitHubInterceptor)
- in.DeepCopyInto(out)
- return out
-}
-
-// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *GitLabInterceptor) DeepCopyInto(out *GitLabInterceptor) {
- *out = *in
- if in.SecretRef != nil {
- in, out := &in.SecretRef, &out.SecretRef
- *out = new(SecretRef)
- **out = **in
- }
- if in.EventTypes != nil {
- in, out := &in.EventTypes, &out.EventTypes
- *out = make([]string, len(*in))
- copy(*out, *in)
- }
- return
-}
-
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GitLabInterceptor.
-func (in *GitLabInterceptor) DeepCopy() *GitLabInterceptor {
- if in == nil {
- return nil
- }
- out := new(GitLabInterceptor)
- in.DeepCopyInto(out)
- return out
-}
-
-// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *GithubAddChangedFiles) DeepCopyInto(out *GithubAddChangedFiles) {
- *out = *in
- if in.PersonalAccessToken != nil {
- in, out := &in.PersonalAccessToken, &out.PersonalAccessToken
- *out = new(SecretRef)
- **out = **in
- }
- return
-}
-
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GithubAddChangedFiles.
-func (in *GithubAddChangedFiles) DeepCopy() *GithubAddChangedFiles {
- if in == nil {
- return nil
- }
- out := new(GithubAddChangedFiles)
- in.DeepCopyInto(out)
- return out
-}
-
-// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *GithubOwners) DeepCopyInto(out *GithubOwners) {
- *out = *in
- if in.PersonalAccessToken != nil {
- in, out := &in.PersonalAccessToken, &out.PersonalAccessToken
- *out = new(SecretRef)
- **out = **in
- }
- return
-}
-
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GithubOwners.
-func (in *GithubOwners) DeepCopy() *GithubOwners {
- if in == nil {
- return nil
- }
- out := new(GithubOwners)
- in.DeepCopyInto(out)
- return out
-}
-
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *InterceptorParams) DeepCopyInto(out *InterceptorParams) {
*out = *in
@@ -652,27 +493,6 @@ func (in *SecretRef) DeepCopy() *SecretRef {
return out
}
-// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *SlackInterceptor) DeepCopyInto(out *SlackInterceptor) {
- *out = *in
- if in.RequestedFields != nil {
- in, out := &in.RequestedFields, &out.RequestedFields
- *out = make([]string, len(*in))
- copy(*out, *in)
- }
- return
-}
-
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SlackInterceptor.
-func (in *SlackInterceptor) DeepCopy() *SlackInterceptor {
- if in == nil {
- return nil
- }
- out := new(SlackInterceptor)
- in.DeepCopyInto(out)
- return out
-}
-
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Status) DeepCopyInto(out *Status) {
*out = *in
diff --git a/vendor/github.com/tektoncd/triggers/pkg/interceptors/cel/cel.go b/vendor/github.com/tektoncd/triggers/pkg/interceptors/cel/cel.go
new file mode 100644
index 000000000..b70466cbb
--- /dev/null
+++ b/vendor/github.com/tektoncd/triggers/pkg/interceptors/cel/cel.go
@@ -0,0 +1,253 @@
+/*
+Copyright 2019 The Tekton Authors
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package cel
+
+import (
+ "context"
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "reflect"
+
+ "github.com/tektoncd/triggers/pkg/interceptors"
+
+ structpb "github.com/golang/protobuf/ptypes/struct"
+ "github.com/google/cel-go/cel"
+ "github.com/google/cel-go/checker/decls"
+ "github.com/google/cel-go/common/types"
+ "github.com/google/cel-go/common/types/ref"
+ "github.com/google/cel-go/common/types/traits"
+ celext "github.com/google/cel-go/ext"
+ triggersv1 "github.com/tektoncd/triggers/pkg/apis/triggers/v1beta1"
+ "github.com/tidwall/sjson"
+ "google.golang.org/grpc/codes"
+ "google.golang.org/protobuf/encoding/protojson"
+ "google.golang.org/protobuf/proto"
+)
+
+var _ triggersv1.InterceptorInterface = (*InterceptorImpl)(nil)
+
+// InterceptorImpl implements a CEL based interceptor that uses CEL expressions
+// against the incoming body and headers to match, if the expression returns
+// a true value, then the interception is "successful".
+type InterceptorImpl struct {
+ SecretGetter interceptors.SecretGetter
+ CEL *InterceptorParams
+ TriggerNamespace string
+}
+
+var (
+ structType = reflect.TypeOf(&structpb.Value{})
+ listType = reflect.TypeOf(&structpb.ListValue{})
+ mapType = reflect.TypeOf(&structpb.Struct{})
+)
+
+// NewInterceptor creates a prepopulated Interceptor.
+func NewInterceptor(sg interceptors.SecretGetter) *InterceptorImpl {
+ return &InterceptorImpl{
+ SecretGetter: sg,
+ }
+}
+
+// InterceptorParams provides a webhook to intercept and pre-process events
+type InterceptorParams struct {
+ Filter string `json:"filter,omitempty"`
+ // +listType=atomic
+ Overlays []Overlay `json:"overlays,omitempty"`
+}
+
+// Overlay provides a way to modify the request body using CEL expressions
+type Overlay struct {
+ Key string `json:"key,omitempty"`
+ Expression string `json:"expression,omitempty"`
+}
+
+func evaluate(expr string, env *cel.Env, data map[string]interface{}) (ref.Val, error) {
+ parsed, issues := env.Parse(expr)
+ if issues != nil && issues.Err() != nil {
+ return nil, fmt.Errorf("failed to parse expression %#v: %w", expr, issues.Err())
+ }
+
+ checked, issues := env.Check(parsed)
+ if issues != nil && issues.Err() != nil {
+ return nil, fmt.Errorf("expression %#v check failed: %w", expr, issues.Err())
+ }
+
+ prg, err := env.Program(checked, cel.EvalOptions(cel.OptOptimize))
+ if err != nil {
+ return nil, fmt.Errorf("expression %#v failed to create a Program: %w", expr, err)
+ }
+
+ out, _, err := prg.Eval(data)
+ if err != nil {
+ return nil, fmt.Errorf("expression %#v failed to evaluate: %w", expr, err)
+ }
+ return out, nil
+}
+
+func makeCelEnv(ctx context.Context, ns string, sg interceptors.SecretGetter) (*cel.Env, error) {
+ mapStrDyn := decls.NewMapType(decls.String, decls.Dyn)
+ return cel.NewEnv(
+ Triggers(ctx, ns, sg),
+ celext.Strings(),
+ celext.Encoders(),
+ cel.Declarations(
+ decls.NewVar("body", mapStrDyn),
+ decls.NewVar("header", mapStrDyn),
+ decls.NewVar("extensions", mapStrDyn),
+ decls.NewVar("requestURL", decls.String),
+ ))
+}
+
+func makeEvalContext(body []byte, h http.Header, url string, extensions map[string]interface{}) (map[string]interface{}, error) {
+ var jsonMap map[string]interface{}
+ err := json.Unmarshal(body, &jsonMap)
+ if err != nil {
+ return nil, fmt.Errorf("failed to parse the body as JSON: %w", err)
+ }
+ return map[string]interface{}{
+ "body": jsonMap,
+ "header": h,
+ "requestURL": url,
+ "extensions": extensions,
+ }, nil
+}
+
+func (w *InterceptorImpl) Process(ctx context.Context, r *triggersv1.InterceptorRequest) *triggersv1.InterceptorResponse {
+ p := InterceptorParams{}
+ if err := interceptors.UnmarshalParams(r.InterceptorParams, &p); err != nil {
+ return interceptors.Failf(codes.InvalidArgument, "failed to parse interceptor params: %v", err)
+ }
+
+ if r.Context == nil {
+ return interceptors.Failf(codes.InvalidArgument, "no request context passed")
+ }
+
+ ns, _ := triggersv1.ParseTriggerID(r.Context.TriggerID)
+ env, err := makeCelEnv(ctx, ns, w.SecretGetter)
+ if err != nil {
+ return interceptors.Failf(codes.Internal, "error creating cel environment: %v", err)
+ }
+
+ var payload = []byte(`{}`)
+ if r.Body != "" {
+ payload = []byte(r.Body)
+ }
+
+ evalContext, err := makeEvalContext(payload, r.Header, r.Context.EventURL, r.Extensions)
+ if err != nil {
+ return interceptors.Failf(codes.InvalidArgument, "error making the evaluation context: %v", err)
+ }
+
+ if p.Filter != "" {
+ out, err := evaluate(p.Filter, env, evalContext)
+
+ if err != nil {
+ return interceptors.Failf(codes.InvalidArgument, "error evaluating cel expression: %v", err)
+ }
+
+ if out != types.True {
+ return interceptors.Failf(codes.FailedPrecondition, "expression %s did not return true", p.Filter)
+ }
+ }
+
+ // Empty JSON body bytes.
+ // We use []byte instead of map[string]interface{} to allow ovewriting keys using sjson.
+ var extensions []byte
+ for _, u := range p.Overlays {
+ val, err := evaluate(u.Expression, env, evalContext)
+ if err != nil {
+ return interceptors.Failf(codes.InvalidArgument, "error evaluating cel expression: %v", err)
+ }
+
+ var raw interface{}
+ var b []byte
+
+ switch val.(type) {
+ // this causes types.Bytes to be rendered as a Base64 string this is
+ // because the Go JSON Encoder encodes []bytes this way, see
+ // https://golang.org/pkg/encoding/json/#Marshal
+ //
+ // An alternative might be to return " + val + " for types.Bytes to
+ // simulate the the JSON encoding.
+ case types.String, types.Bytes:
+ raw, err = val.ConvertToNative(structType)
+ if err == nil {
+ b, err = raw.(*structpb.Value).MarshalJSON()
+ }
+ case types.Double, types.Int:
+ raw, err = val.ConvertToNative(structType)
+ if err == nil {
+ b, err = raw.(*structpb.Value).MarshalJSON()
+ }
+ case traits.Lister:
+ raw, err = val.ConvertToNative(listType)
+ if err == nil {
+ s, err := protojson.Marshal(raw.(proto.Message))
+ if err == nil {
+ b = s
+ }
+ }
+ case traits.Mapper:
+ raw, err = val.ConvertToNative(mapType)
+ if err == nil {
+ s, err := protojson.Marshal(raw.(proto.Message))
+ if err == nil {
+ b = s
+ }
+ }
+ case types.Bool:
+ raw, err = val.ConvertToNative(structType)
+ if err == nil {
+ b, err = json.Marshal(raw.(*structpb.Value).GetBoolValue())
+ }
+ default:
+ raw, err = val.ConvertToNative(reflect.TypeOf([]byte{}))
+ if err == nil {
+ b = raw.([]byte)
+ }
+ }
+
+ if err != nil {
+ return interceptors.Failf(codes.Internal, "failed to convert overlay result to type: %v", err)
+ }
+
+ // TODO: For backwards compatibility, consider also merging and returning the body back?
+ if extensions == nil {
+ extensions = []byte("{}")
+ }
+ extensions, err = sjson.SetRawBytes(extensions, u.Key, b)
+ if err != nil {
+ return interceptors.Failf(codes.Internal, "failed to sjson for key '%s' to '%s': %v", u.Key, val, err)
+ }
+ }
+
+ if extensions == nil {
+ return &triggersv1.InterceptorResponse{
+ Continue: true,
+ }
+ }
+
+ extensionsMap := map[string]interface{}{}
+ if err := json.Unmarshal(extensions, &extensionsMap); err != nil {
+ return interceptors.Failf(codes.Internal, "failed to unmarshal extensions into map: %v", err)
+ }
+ return &triggersv1.InterceptorResponse{
+ Continue: true,
+ Extensions: extensionsMap,
+ }
+}
diff --git a/vendor/github.com/tektoncd/triggers/pkg/interceptors/cel/triggers.go b/vendor/github.com/tektoncd/triggers/pkg/interceptors/cel/triggers.go
new file mode 100644
index 000000000..f1d95fd91
--- /dev/null
+++ b/vendor/github.com/tektoncd/triggers/pkg/interceptors/cel/triggers.go
@@ -0,0 +1,365 @@
+/*
+Copyright 2020 The Tekton Authors
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+package cel
+
+import (
+ "context"
+ "crypto/subtle"
+ "encoding/json"
+ "net/http"
+ "net/url"
+ "reflect"
+ "strings"
+
+ "github.com/google/cel-go/cel"
+ "github.com/google/cel-go/common/types"
+ "github.com/google/cel-go/common/types/ref"
+ "github.com/google/cel-go/interpreter/functions"
+ "github.com/tektoncd/triggers/pkg/interceptors"
+ "sigs.k8s.io/yaml"
+
+ triggersv1 "github.com/tektoncd/triggers/pkg/apis/triggers/v1beta1"
+)
+
+// Triggers returns a cel.EnvOption to configure extended functions for
+// Tekton CEL interceptor expressions.
+//
+// match
+//
+// Returns true if the specified provided header matches the provided string
+// key.
+//
+// It is case insensitive; the header is canonicalised using the rules described
+// here https://golang.org/pkg/net/textproto/#CanonicalMIMEHeaderKey
+//
+// .match(, ) ->
+//
+// Examples:
+//
+// header.match('X-Github-Event', 'push')
+//
+// canonical
+//
+// Can only be applied to the `header` key in the CEL expression context.
+//
+// Gets the first value associated with the given key. If there are no values
+// associated with the key, returns "".
+//
+// It is case insensitive; the header is canonicalised using the rules described
+// here https://golang.org/pkg/net/textproto/#CanonicalMIMEHeaderKey
+//
+// .canonical() ->
+//
+// Examples:
+//
+// header.canonical('X-Github-Event') // returns 'push'
+//
+// truncate
+//
+// Returns a truncated copy of the string, at the given position.
+//
+// If the requested length is longer than the actual length, then the string
+// will be returned unchanged.
+//
+// .truncate() ->
+//
+// Examples:
+//
+// body.request.sha.truncate(7) // returns truncated string
+//
+// compareSecret
+//
+// Returns true if the string matches the value from a Kubernetes secret with
+// the provided key, secret-name, namespace combination.
+//
+// .compareSecret(, , ) ->
+//
+// Examples:
+//
+// header.canonical('X-Secret-Token').compareSecret('key', 'secret-name', 'namespace')
+//
+// There is also an alternative compareSecret which accepts two parameters
+//
+// Returns true if the string matches the value from a Kubernetes secret with
+// the provided key, secret-name combination, this default to the namespace the
+// event-listener is in.
+//
+// .compareSecret(, ) ->
+//
+// Examples:
+//
+// header.canonical('X-Secret-Token').compareSecret('key', 'secret-name')
+//
+// parseJSON
+//
+// Parses a string into a map of strings to dynamic values.
+//
+// .parseJSON() -> map
+//
+// Examples:
+//
+// body.field.parseJSON().item
+//
+// parseURL
+//
+// Parses a URL (in the form of a string) into a map with keys representing the
+// elements of the URL.
+//
+// .parseURL() -> map
+//
+// Examples:
+//
+// 'https://example.com/testing'.parseURL().host == 'example.com'
+//
+// parseYAML
+//
+// Parses a YAML string into a map of strings to dynamic values
+//
+// .parseYAML() -> map
+//
+// Examples:
+//
+// body.field.parseYAML().item
+//
+// marshalJSON
+//
+// Returns the JSON encoding of 'jsonObjectOrList'.
+//
+// .marshalJSON() ->
+//
+// Examples:
+//
+// body.jsonObjectOrList.marshalJSON()
+
+// Triggers creates and returns a new cel.Lib with the triggers extensions.
+func Triggers(ctx context.Context, ns string, sg interceptors.SecretGetter) cel.EnvOption {
+ return cel.Lib(triggersLib{ctx: ctx, defaultNS: ns, secretGetter: sg})
+}
+
+type triggersLib struct {
+ ctx context.Context
+ defaultNS string
+ secretGetter interceptors.SecretGetter
+}
+
+func (t triggersLib) CompileOptions() []cel.EnvOption {
+ mapStrDyn := cel.MapType(cel.StringType, cel.DynType)
+ listStrDyn := cel.ListType(cel.DynType)
+ return []cel.EnvOption{
+ cel.Function("match",
+ cel.MemberOverload("match_map_string_string", []*cel.Type{mapStrDyn, cel.StringType, cel.StringType}, cel.BoolType,
+ cel.FunctionBinding(matchHeader))),
+ cel.Function("canonical",
+ cel.MemberOverload("canonical_map_string", []*cel.Type{mapStrDyn, cel.StringType}, cel.StringType,
+ cel.BinaryBinding(canonicalHeader))),
+ cel.Function("truncate",
+ cel.MemberOverload("truncate_string_uint", []*cel.Type{cel.StringType, cel.IntType}, cel.StringType,
+ cel.BinaryBinding(truncateString))),
+ cel.Function("compareSecret",
+ cel.MemberOverload("compareSecret_string_string_string", []*cel.Type{cel.StringType, cel.StringType, cel.StringType, cel.StringType}, cel.BoolType,
+ cel.FunctionBinding(makeCompareSecret(t.ctx, t.defaultNS, t.secretGetter))),
+ cel.MemberOverload("compareSecret_string_string", []*cel.Type{cel.StringType, cel.StringType, cel.StringType}, cel.BoolType,
+ cel.FunctionBinding(makeCompareSecret(t.ctx, t.defaultNS, t.secretGetter)))),
+ cel.Function("parseJSON",
+ cel.MemberOverload("parseJSON_string", []*cel.Type{cel.StringType}, mapStrDyn,
+ cel.UnaryBinding(parseJSONString))),
+ cel.Function("parseYAML",
+ cel.MemberOverload("parseYAML_string", []*cel.Type{cel.StringType}, mapStrDyn,
+ cel.UnaryBinding(parseYAMLString))),
+ cel.Function("parseURL",
+ cel.MemberOverload("parseURL_string", []*cel.Type{cel.StringType}, mapStrDyn,
+ cel.UnaryBinding(parseURLString))),
+ cel.Function("marshalJSON",
+ cel.MemberOverload("marshalJSON_map", []*cel.Type{mapStrDyn}, cel.StringType,
+ cel.UnaryBinding(marshalJSON)),
+ cel.MemberOverload("marshalJSON_list", []*cel.Type{listStrDyn}, cel.StringType,
+ cel.UnaryBinding(marshalJSON))),
+ }
+}
+
+func (t triggersLib) ProgramOptions() []cel.ProgramOption {
+ return []cel.ProgramOption{}
+}
+
+func matchHeader(vals ...ref.Val) ref.Val {
+ h, err := vals[0].ConvertToNative(reflect.TypeOf(http.Header{}))
+ if err != nil {
+ return types.NewErr("failed to convert to http.Header: %w", err)
+ }
+
+ key := vals[1].(types.String)
+ val := vals[2].(types.String)
+ return types.Bool(h.(http.Header).Get(string(key)) == string(val))
+}
+
+func truncateString(lhs, rhs ref.Val) ref.Val {
+ str := lhs.(types.String)
+ n := rhs.(types.Int)
+ return str[:max(n, types.Int(len(str)))]
+}
+
+func canonicalHeader(lhs, rhs ref.Val) ref.Val {
+ h, err := lhs.ConvertToNative(reflect.TypeOf(http.Header{}))
+ if err != nil {
+ return types.NewErr("failed to convert to http.Header: %w", err)
+ }
+
+ key := rhs.(types.String)
+ return types.String(h.(http.Header).Get(string(key)))
+}
+
+// makeCompareSecret creates and returns a functions.FunctionOp that wraps the
+// ns and client in a closure with a function that can compare the string.
+func makeCompareSecret(ctx context.Context, defaultNS string, sg interceptors.SecretGetter) functions.FunctionOp {
+ return func(vals ...ref.Val) ref.Val {
+ var ok bool
+ compareString, ok := vals[0].(types.String)
+ if !ok {
+ return types.ValOrErr(compareString, "unexpected type '%v' passed to compareSecret", vals[0].Type())
+ }
+
+ secretNS := types.String(defaultNS)
+
+ secretName, ok := vals[2].(types.String)
+ if !ok {
+ return types.ValOrErr(secretName, "unexpected type '%v' passed to compareSecret", vals[2].Type())
+ }
+
+ secretKey, ok := vals[1].(types.String)
+ if !ok {
+ return types.ValOrErr(secretKey, "unexpected type '%v' passed to compareSecret", vals[3].Type())
+ }
+
+ secretRef := &triggersv1.SecretRef{
+ SecretKey: string(secretKey),
+ SecretName: string(secretName),
+ }
+ // GetSecretToken uses request as a cache key to cache secret lookup. Since multiple
+ // triggers execute concurrently in separate goroutines, this cache is not very effective
+ // for this use case
+ secretToken, err := sg.Get(ctx, string(secretNS), secretRef)
+ if err != nil {
+ return types.NewErr("failed to find secret '%#v' in compareSecret: %w", *secretRef, err)
+ }
+ return types.Bool(subtle.ConstantTimeCompare(secretToken, []byte(compareString)) == 1)
+ }
+}
+
+func parseJSONString(val ref.Val) ref.Val {
+ str := val.(types.String)
+ decodedVal := map[string]interface{}{}
+ err := json.Unmarshal([]byte(str), &decodedVal)
+ if err != nil {
+ return types.NewErr("failed to decode '%v' in parseJSON: %w", str, err)
+ }
+ r, err := types.NewRegistry()
+ if err != nil {
+ return types.NewErr("failed to create a new registry in parseJSON: %w", err)
+ }
+ return types.NewDynamicMap(r, decodedVal)
+}
+
+func parseYAMLString(val ref.Val) ref.Val {
+ str := val.(types.String)
+ decodedVal := map[string]interface{}{}
+ err := yaml.Unmarshal([]byte(str), &decodedVal)
+ if err != nil {
+ return types.NewErr("failed to decode '%v' in parseYAML: %w", str, err)
+ }
+ r, err := types.NewRegistry()
+ if err != nil {
+ return types.NewErr("failed to create a new registry in parseJSON: %w", err)
+ }
+ return types.NewDynamicMap(r, decodedVal)
+}
+
+func parseURLString(val ref.Val) ref.Val {
+ str := val.(types.String)
+ parsed, err := url.Parse(string(str))
+ if err != nil {
+ return types.NewErr("failed to decode '%v' in parseURL: %w", str, err)
+ }
+ r, err := types.NewRegistry()
+ if err != nil {
+ return types.NewErr("failed to create a new registry in parseJSON: %w", err)
+ }
+ return types.NewDynamicMap(r, urlToMap(parsed))
+}
+
+func marshalJSON(val ref.Val) ref.Val {
+ var typeDesc reflect.Type
+
+ switch val.Type() {
+ case types.MapType:
+ typeDesc = mapType
+ case types.ListType:
+ typeDesc = listType
+ default:
+ return types.ValOrErr(val, "unexpected type '%v' passed to marshalJSON", val.Type())
+ }
+
+ nativeVal, err := val.ConvertToNative(typeDesc)
+ if err != nil {
+ return types.NewErr("failed to convert to native: %w", err)
+ }
+
+ marshaledVal, err := json.Marshal(nativeVal)
+ if err != nil {
+ return types.NewErr("failed to marshal to json: %w", err)
+ }
+
+ return types.String(marshaledVal)
+}
+
+func max(x, y types.Int) types.Int {
+ switch x.Compare(y) {
+ case types.IntNegOne:
+ return x
+ case types.IntOne:
+ return y
+ default:
+ return x
+ }
+}
+
+func urlToMap(u *url.URL) map[string]interface{} {
+ // This doesn't return the RawPath.
+ m := map[string]interface{}{
+ "scheme": u.Scheme,
+ "host": u.Host,
+ "path": u.Path,
+ "rawQuery": u.RawQuery,
+ "fragment": u.Fragment,
+ "queryStrings": u.Query(),
+ "query": flatten(u.Query()),
+ }
+ if u.User != nil {
+ pass, _ := u.User.Password()
+ m["auth"] = map[string]string{
+ "username": u.User.Username(),
+ "password": pass,
+ }
+ }
+ return m
+}
+
+func flatten(uv url.Values) map[string]string {
+ r := map[string]string{}
+ for k, v := range uv {
+ r[k] = strings.Join(v, ",")
+ }
+ return r
+}
diff --git a/vendor/github.com/tektoncd/triggers/pkg/interceptors/interceptors.go b/vendor/github.com/tektoncd/triggers/pkg/interceptors/interceptors.go
new file mode 100644
index 000000000..05cee74aa
--- /dev/null
+++ b/vendor/github.com/tektoncd/triggers/pkg/interceptors/interceptors.go
@@ -0,0 +1,145 @@
+/*
+Copyright 2019 The Tekton Authors
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package interceptors
+
+import (
+ "bytes"
+ "context"
+ "encoding/json"
+ "fmt"
+ "io"
+ "net/http"
+
+ triggersv1alpha1 "github.com/tektoncd/triggers/pkg/apis/triggers/v1alpha1"
+ triggersv1beta1 "github.com/tektoncd/triggers/pkg/apis/triggers/v1beta1"
+ "google.golang.org/grpc/codes"
+ "knative.dev/pkg/apis"
+)
+
+const (
+ CoreInterceptorsHost = "tekton-triggers-core-interceptors"
+)
+
+// Interceptor is the interface that all interceptors implement.
+type Interceptor interface {
+ ExecuteTrigger(req *http.Request) (*http.Response, error)
+}
+
+// GetInterceptorParams returns InterceptorParams for the current interceptors
+func GetInterceptorParams(i *triggersv1beta1.EventInterceptor) map[string]interface{} {
+ ip := map[string]interface{}{}
+ switch {
+ case i.Webhook != nil:
+ // WebHook headers are of type map[string][]string.
+ // Use old style for now. Upgrade later.
+ if i.Webhook != nil {
+ ip["objectRef"] = i.Webhook.ObjectRef
+ ip["header"] = i.Webhook.Header
+ }
+ case i.Params != nil:
+ for _, p := range i.Params {
+ ip[p.Name] = p.Value
+ }
+ }
+ return ip
+}
+
+// Fail constructs a InterceptorResponse that should not continue further processing.
+func Fail(c codes.Code, msg string) *triggersv1beta1.InterceptorResponse {
+ return &triggersv1beta1.InterceptorResponse{
+ Continue: false,
+ Status: triggersv1beta1.Status{
+ Code: c,
+ Message: msg,
+ },
+ }
+}
+
+// Failf constructs a InterceptorResponse that should not continue further processing.
+func Failf(c codes.Code, format string, a ...interface{}) *triggersv1beta1.InterceptorResponse {
+ return Fail(c, fmt.Sprintf(format, a...))
+}
+
+// Canonical updates the map keys to use the Canonical name
+func Canonical(h map[string][]string) http.Header {
+ c := map[string][]string{}
+ for k, v := range h {
+ c[http.CanonicalHeaderKey(k)] = v
+ }
+ return http.Header(c)
+}
+
+// UnmarshalParams unmarshalls the passed in InterceptorParams into the provided param struct
+func UnmarshalParams(ip map[string]interface{}, p interface{}) error {
+ b, err := json.Marshal(ip)
+ if err != nil {
+ return fmt.Errorf("failed to marshal json: %w", err)
+ }
+
+ if err := json.Unmarshal(b, &p); err != nil {
+ // Should never happen since Unmarshall only returns err if json is invalid which we already check above
+ return fmt.Errorf("invalid json: %w", err)
+ }
+ return nil
+}
+
+type InterceptorGetter func(name string) (*triggersv1alpha1.ClusterInterceptor, error)
+
+// ResolveToURL finds an Interceptor's URL.
+func ResolveToURL(getter InterceptorGetter, name string) (*apis.URL, error) {
+ ic, err := getter(name)
+ if err != nil {
+ return nil, fmt.Errorf("url resolution failed for interceptor %s with: %w", name, err)
+ }
+ if addr := ic.Status.Address; addr != nil {
+ if addr.URL != nil {
+ return addr.URL, nil
+ }
+ }
+ // If the status does not have a URL, try to generate it from the Spec.
+ return ic.ResolveAddress()
+}
+
+func Execute(ctx context.Context, client *http.Client, req *triggersv1beta1.InterceptorRequest, url string) (*triggersv1beta1.InterceptorResponse, error) {
+ b, err := json.Marshal(req)
+ if err != nil {
+ return nil, err
+ }
+ // TODO: Seed context with timeouts
+ r, err := http.NewRequestWithContext(ctx, "POST", url, bytes.NewBuffer(b))
+ if err != nil {
+ return nil, err
+ }
+ res, err := client.Do(r)
+ if err != nil {
+ return nil, err
+ }
+ body, err := io.ReadAll(res.Body)
+ defer res.Body.Close()
+ if err != nil {
+ return nil, err
+ }
+ if res.StatusCode != http.StatusOK {
+ // TODO: error type for easier checking. wrap in status.Errorf?
+ return nil, fmt.Errorf("interceptor response was not 200: %v", string(body))
+ }
+ iresp := triggersv1beta1.InterceptorResponse{}
+ if err := json.Unmarshal(body, &iresp); err != nil {
+ return nil, err
+ }
+ return &iresp, nil
+}
diff --git a/vendor/github.com/tektoncd/triggers/pkg/interceptors/interface.go b/vendor/github.com/tektoncd/triggers/pkg/interceptors/interface.go
new file mode 100644
index 000000000..8f46784f1
--- /dev/null
+++ b/vendor/github.com/tektoncd/triggers/pkg/interceptors/interface.go
@@ -0,0 +1 @@
+package interceptors
diff --git a/vendor/github.com/tektoncd/triggers/pkg/interceptors/secret_getter.go b/vendor/github.com/tektoncd/triggers/pkg/interceptors/secret_getter.go
new file mode 100644
index 000000000..c999bc9fd
--- /dev/null
+++ b/vendor/github.com/tektoncd/triggers/pkg/interceptors/secret_getter.go
@@ -0,0 +1,85 @@
+/*
+Copyright 2022 The Tekton Authors
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package interceptors
+
+import (
+ "context"
+ "fmt"
+ "time"
+
+ triggersv1beta1 "github.com/tektoncd/triggers/pkg/apis/triggers/v1beta1"
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ "k8s.io/apimachinery/pkg/util/cache"
+ corev1 "k8s.io/client-go/kubernetes/typed/core/v1"
+)
+
+const (
+ // cacheSize is the size of the LRU secrets cache
+ cacheSize = 1024
+ // ttl is the time to live for a cache entry
+ ttl = 5 * time.Second
+)
+
+type SecretGetter interface {
+ Get(ctx context.Context, triggerNS string, sr *triggersv1beta1.SecretRef) ([]byte, error)
+}
+
+type kubeclientSecretGetter struct {
+ getter corev1.SecretsGetter
+ cache *cache.LRUExpireCache
+ ttl time.Duration
+}
+
+type cacheKey struct {
+ triggerNS string
+ sr triggersv1beta1.SecretRef
+}
+
+func DefaultSecretGetter(getter corev1.SecretsGetter) SecretGetter {
+ return &kubeclientSecretGetter{
+ getter: getter,
+ cache: cache.NewLRUExpireCache(cacheSize),
+ ttl: ttl,
+ }
+}
+
+// Get queries Kubernetes for the given secret reference. We use this function
+// to resolve secret material like GitHub webhook secrets, and call it once for every
+// trigger that references it.
+//
+// As we may have many triggers that all use the same secret, we cache the secret values
+// in the request cache.
+func (g *kubeclientSecretGetter) Get(ctx context.Context, triggerNS string, sr *triggersv1beta1.SecretRef) ([]byte, error) {
+ key := cacheKey{
+ triggerNS: triggerNS,
+ sr: *sr,
+ }
+ val, ok := g.cache.Get(key)
+ if ok {
+ return val.([]byte), nil
+ }
+ secret, err := g.getter.Secrets(triggerNS).Get(ctx, sr.SecretName, metav1.GetOptions{})
+ if err != nil {
+ return nil, err
+ }
+ secretValue, ok := secret.Data[sr.SecretKey]
+ if !ok {
+ return nil, fmt.Errorf("cannot find %s key in secret %s/%s", sr.SecretKey, triggerNS, sr.SecretName)
+ }
+ g.cache.Add(key, secretValue, g.ttl)
+ return secretValue, nil
+}
diff --git a/vendor/github.com/tektoncd/triggers/pkg/reconciler/eventlistener/resources/deployment.go b/vendor/github.com/tektoncd/triggers/pkg/reconciler/eventlistener/resources/deployment.go
index 7bd5294b2..aac8aeafa 100644
--- a/vendor/github.com/tektoncd/triggers/pkg/reconciler/eventlistener/resources/deployment.go
+++ b/vendor/github.com/tektoncd/triggers/pkg/reconciler/eventlistener/resources/deployment.go
@@ -147,6 +147,9 @@ func addDeploymentBits(el *v1beta1.EventListener, c Config) (ContainerOption, er
if len(el.Spec.Resources.KubernetesResource.Template.Spec.Containers) != 0 {
container.Resources = el.Spec.Resources.KubernetesResource.Template.Spec.Containers[0].Resources
container.Env = append(container.Env, el.Spec.Resources.KubernetesResource.Template.Spec.Containers[0].Env...)
+ container.ReadinessProbe = el.Spec.Resources.KubernetesResource.Template.Spec.Containers[0].ReadinessProbe
+ container.LivenessProbe = el.Spec.Resources.KubernetesResource.Template.Spec.Containers[0].LivenessProbe
+ container.StartupProbe = el.Spec.Resources.KubernetesResource.Template.Spec.Containers[0].StartupProbe
}
}
@@ -200,27 +203,31 @@ func addCertsForSecureConnection(c Config) ContainerOption {
} else {
scheme = corev1.URISchemeHTTP
}
- container.LivenessProbe = &corev1.Probe{
- ProbeHandler: corev1.ProbeHandler{
- HTTPGet: &corev1.HTTPGetAction{
- Path: "/live",
- Scheme: scheme,
- Port: intstr.FromInt(eventListenerContainerPort),
+ if container.LivenessProbe == nil {
+ container.LivenessProbe = &corev1.Probe{
+ ProbeHandler: corev1.ProbeHandler{
+ HTTPGet: &corev1.HTTPGetAction{
+ Path: "/live",
+ Scheme: scheme,
+ Port: intstr.FromInt(eventListenerContainerPort),
+ },
},
- },
- PeriodSeconds: int32(*c.PeriodSeconds),
- FailureThreshold: int32(*c.FailureThreshold),
+ PeriodSeconds: int32(*c.PeriodSeconds),
+ FailureThreshold: int32(*c.FailureThreshold),
+ }
}
- container.ReadinessProbe = &corev1.Probe{
- ProbeHandler: corev1.ProbeHandler{
- HTTPGet: &corev1.HTTPGetAction{
- Path: "/live",
- Scheme: scheme,
- Port: intstr.FromInt(eventListenerContainerPort),
+ if container.ReadinessProbe == nil {
+ container.ReadinessProbe = &corev1.Probe{
+ ProbeHandler: corev1.ProbeHandler{
+ HTTPGet: &corev1.HTTPGetAction{
+ Path: "/live",
+ Scheme: scheme,
+ Port: intstr.FromInt(eventListenerContainerPort),
+ },
},
- },
- PeriodSeconds: int32(*c.PeriodSeconds),
- FailureThreshold: int32(*c.FailureThreshold),
+ PeriodSeconds: int32(*c.PeriodSeconds),
+ FailureThreshold: int32(*c.FailureThreshold),
+ }
}
container.Args = append(container.Args, "--tls-cert="+elCert, "--tls-key="+elKey)
}
diff --git a/vendor/github.com/tektoncd/triggers/pkg/reconciler/eventlistener/resources/service.go b/vendor/github.com/tektoncd/triggers/pkg/reconciler/eventlistener/resources/service.go
index ef195d40c..6adffd41c 100644
--- a/vendor/github.com/tektoncd/triggers/pkg/reconciler/eventlistener/resources/service.go
+++ b/vendor/github.com/tektoncd/triggers/pkg/reconciler/eventlistener/resources/service.go
@@ -77,7 +77,7 @@ func ServicePort(el *v1beta1.EventListener, c Config) corev1.ServicePort {
var elCert, elKey string
servicePortName := eventListenerServicePortName
- servicePortPort := *c.Port
+ servicePort := *c.Port
certEnv := map[string]*corev1.EnvVarSource{}
if el.Spec.Resources.KubernetesResource != nil {
@@ -87,6 +87,9 @@ func ServicePort(el *v1beta1.EventListener, c Config) corev1.ServicePort {
el.Spec.Resources.KubernetesResource.Template.Spec.Containers[0].Env[i].ValueFrom
}
}
+ if el.Spec.Resources.KubernetesResource.ServicePort != nil {
+ servicePort = int(*el.Spec.Resources.KubernetesResource.ServicePort)
+ }
}
if v, ok := certEnv["TLS_CERT"]; ok {
@@ -105,14 +108,14 @@ func ServicePort(el *v1beta1.EventListener, c Config) corev1.ServicePort {
if *c.Port == DefaultPort {
// We return port 8443 if TLS is enabled and the default HTTP port is set.
// This effectively makes 8443 the default HTTPS port unless a user explicitly sets a different port.
- servicePortPort = 8443
+ servicePort = 8443
}
}
return corev1.ServicePort{
Name: servicePortName,
Protocol: corev1.ProtocolTCP,
- Port: int32(servicePortPort),
+ Port: int32(servicePort),
TargetPort: intstr.IntOrString{
IntVal: int32(eventListenerContainerPort),
},
diff --git a/vendor/github.com/tektoncd/triggers/test/e2e-tests-examples.sh b/vendor/github.com/tektoncd/triggers/test/e2e-tests-examples.sh
index b3455c9c8..e5e364a75 100644
--- a/vendor/github.com/tektoncd/triggers/test/e2e-tests-examples.sh
+++ b/vendor/github.com/tektoncd/triggers/test/e2e-tests-examples.sh
@@ -39,18 +39,19 @@ err() {
install_knative_serving() {
# Install Knative by referring https://knative.dev/docs/admin/install/serving/install-serving-with-yaml/#install-the-knative-serving-component
- kubectl apply -f https://github.com/knative/serving/releases/download/knative-v1.6.0/serving-crds.yaml
- kubectl apply -f https://github.com/knative/serving/releases/download/knative-v1.6.0/serving-core.yaml
+ kubectl apply -f https://github.com/knative/serving/releases/download/knative-v1.10.2/serving-crds.yaml
+ kubectl apply -f https://github.com/knative/serving/releases/download/knative-v1.10.2/serving-core.yaml
# Wait for pods to be running in the namespaces we are deploying to
wait_until_pods_running knative-serving || fail_test "Knative Serving did not come up"
- kubectl apply -f https://github.com/knative/net-kourier/releases/download/knative-v1.6.0/kourier.yaml
+ kubectl apply -f https://github.com/knative/net-kourier/releases/download/knative-v1.10.0/kourier.yaml
kubectl patch configmap/config-network \
--namespace knative-serving \
--type merge \
- --patch '{"data":{"ingress.class":"kourier.ingress.networking.knative.dev"}}'
+ --patch '{"data":{"ingress-class":"kourier.ingress.networking.knative.dev"}}'
+
# Wait for pods to be running in the namespaces we are deploying to
wait_until_pods_running knative-serving || fail_test "Knative Serving & Kourier did not come up"
diff --git a/vendor/github.com/tektoncd/triggers/test/resources.go b/vendor/github.com/tektoncd/triggers/test/resources.go
index fcacec6f6..efd8ea1ac 100644
--- a/vendor/github.com/tektoncd/triggers/test/resources.go
+++ b/vendor/github.com/tektoncd/triggers/test/resources.go
@@ -65,6 +65,17 @@ func AddTektonResources(clientset *fakekubeclientset.Clientset) {
APIResources: resources,
})
+ clientset.Resources = append(clientset.Resources, &metav1.APIResourceList{
+ GroupVersion: "tekton.dev/v1",
+ APIResources: []metav1.APIResource{{
+ Group: "tekton.dev",
+ Version: "v1",
+ Namespaced: true,
+ Name: "taskruns",
+ Kind: "TaskRun",
+ }},
+ })
+
clientset.Resources = append(clientset.Resources, &metav1.APIResourceList{
GroupVersion: "tekton.dev/v1beta1",
APIResources: []metav1.APIResource{{
@@ -75,4 +86,5 @@ func AddTektonResources(clientset *fakekubeclientset.Clientset) {
Kind: "TaskRun",
}},
})
+
}
diff --git a/vendor/github.com/tidwall/gjson/LICENSE b/vendor/github.com/tidwall/gjson/LICENSE
new file mode 100644
index 000000000..58f5819a4
--- /dev/null
+++ b/vendor/github.com/tidwall/gjson/LICENSE
@@ -0,0 +1,20 @@
+The MIT License (MIT)
+
+Copyright (c) 2016 Josh Baker
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/vendor/github.com/tidwall/gjson/README.md b/vendor/github.com/tidwall/gjson/README.md
new file mode 100644
index 000000000..bb56b3d9b
--- /dev/null
+++ b/vendor/github.com/tidwall/gjson/README.md
@@ -0,0 +1,490 @@
+
+
+
+
+
+
+
+
+
+get json values quickly
+
+GJSON is a Go package that provides a [fast](#performance) and [simple](#get-a-value) way to get values from a json document.
+It has features such as [one line retrieval](#get-a-value), [dot notation paths](#path-syntax), [iteration](#iterate-through-an-object-or-array), and [parsing json lines](#json-lines).
+
+Also check out [SJSON](https://github.com/tidwall/sjson) for modifying json, and the [JJ](https://github.com/tidwall/jj) command line tool.
+
+Getting Started
+===============
+
+## Installing
+
+To start using GJSON, install Go and run `go get`:
+
+```sh
+$ go get -u github.com/tidwall/gjson
+```
+
+This will retrieve the library.
+
+## Get a value
+Get searches json for the specified path. A path is in dot syntax, such as "name.last" or "age". When the value is found it's returned immediately.
+
+```go
+package main
+
+import "github.com/tidwall/gjson"
+
+const json = `{"name":{"first":"Janet","last":"Prichard"},"age":47}`
+
+func main() {
+ value := gjson.Get(json, "name.last")
+ println(value.String())
+}
+```
+
+This will print:
+
+```
+Prichard
+```
+*There's also the [GetMany](#get-multiple-values-at-once) function to get multiple values at once, and [GetBytes](#working-with-bytes) for working with JSON byte slices.*
+
+## Path Syntax
+
+Below is a quick overview of the path syntax, for more complete information please
+check out [GJSON Syntax](SYNTAX.md).
+
+A path is a series of keys separated by a dot.
+A key may contain special wildcard characters '\*' and '?'.
+To access an array value use the index as the key.
+To get the number of elements in an array or to access a child path, use the '#' character.
+The dot and wildcard characters can be escaped with '\\'.
+
+```json
+{
+ "name": {"first": "Tom", "last": "Anderson"},
+ "age":37,
+ "children": ["Sara","Alex","Jack"],
+ "fav.movie": "Deer Hunter",
+ "friends": [
+ {"first": "Dale", "last": "Murphy", "age": 44, "nets": ["ig", "fb", "tw"]},
+ {"first": "Roger", "last": "Craig", "age": 68, "nets": ["fb", "tw"]},
+ {"first": "Jane", "last": "Murphy", "age": 47, "nets": ["ig", "tw"]}
+ ]
+}
+```
+```
+"name.last" >> "Anderson"
+"age" >> 37
+"children" >> ["Sara","Alex","Jack"]
+"children.#" >> 3
+"children.1" >> "Alex"
+"child*.2" >> "Jack"
+"c?ildren.0" >> "Sara"
+"fav\.movie" >> "Deer Hunter"
+"friends.#.first" >> ["Dale","Roger","Jane"]
+"friends.1.last" >> "Craig"
+```
+
+You can also query an array for the first match by using `#(...)`, or find all
+matches with `#(...)#`. Queries support the `==`, `!=`, `<`, `<=`, `>`, `>=`
+comparison operators and the simple pattern matching `%` (like) and `!%`
+(not like) operators.
+
+```
+friends.#(last=="Murphy").first >> "Dale"
+friends.#(last=="Murphy")#.first >> ["Dale","Jane"]
+friends.#(age>45)#.last >> ["Craig","Murphy"]
+friends.#(first%"D*").last >> "Murphy"
+friends.#(first!%"D*").last >> "Craig"
+friends.#(nets.#(=="fb"))#.first >> ["Dale","Roger"]
+```
+
+*Please note that prior to v1.3.0, queries used the `#[...]` brackets. This was
+changed in v1.3.0 as to avoid confusion with the new
+[multipath](SYNTAX.md#multipaths) syntax. For backwards compatibility,
+`#[...]` will continue to work until the next major release.*
+
+## Result Type
+
+GJSON supports the json types `string`, `number`, `bool`, and `null`.
+Arrays and Objects are returned as their raw json types.
+
+The `Result` type holds one of these:
+
+```
+bool, for JSON booleans
+float64, for JSON numbers
+string, for JSON string literals
+nil, for JSON null
+```
+
+To directly access the value:
+
+```go
+result.Type // can be String, Number, True, False, Null, or JSON
+result.Str // holds the string
+result.Num // holds the float64 number
+result.Raw // holds the raw json
+result.Index // index of raw value in original json, zero means index unknown
+result.Indexes // indexes of all the elements that match on a path containing the '#' query character.
+```
+
+There are a variety of handy functions that work on a result:
+
+```go
+result.Exists() bool
+result.Value() interface{}
+result.Int() int64
+result.Uint() uint64
+result.Float() float64
+result.String() string
+result.Bool() bool
+result.Time() time.Time
+result.Array() []gjson.Result
+result.Map() map[string]gjson.Result
+result.Get(path string) Result
+result.ForEach(iterator func(key, value Result) bool)
+result.Less(token Result, caseSensitive bool) bool
+```
+
+The `result.Value()` function returns an `interface{}` which requires type assertion and is one of the following Go types:
+
+```go
+boolean >> bool
+number >> float64
+string >> string
+null >> nil
+array >> []interface{}
+object >> map[string]interface{}
+```
+
+The `result.Array()` function returns back an array of values.
+If the result represents a non-existent value, then an empty array will be returned.
+If the result is not a JSON array, the return value will be an array containing one result.
+
+### 64-bit integers
+
+The `result.Int()` and `result.Uint()` calls are capable of reading all 64 bits, allowing for large JSON integers.
+
+```go
+result.Int() int64 // -9223372036854775808 to 9223372036854775807
+result.Uint() int64 // 0 to 18446744073709551615
+```
+
+## Modifiers and path chaining
+
+New in version 1.2 is support for modifier functions and path chaining.
+
+A modifier is a path component that performs custom processing on the
+json.
+
+Multiple paths can be "chained" together using the pipe character.
+This is useful for getting results from a modified query.
+
+For example, using the built-in `@reverse` modifier on the above json document,
+we'll get `children` array and reverse the order:
+
+```
+"children|@reverse" >> ["Jack","Alex","Sara"]
+"children|@reverse|0" >> "Jack"
+```
+
+There are currently the following built-in modifiers:
+
+- `@reverse`: Reverse an array or the members of an object.
+- `@ugly`: Remove all whitespace from a json document.
+- `@pretty`: Make the json document more human readable.
+- `@this`: Returns the current element. It can be used to retrieve the root element.
+- `@valid`: Ensure the json document is valid.
+- `@flatten`: Flattens an array.
+- `@join`: Joins multiple objects into a single object.
+- `@keys`: Returns an array of keys for an object.
+- `@values`: Returns an array of values for an object.
+
+### Modifier arguments
+
+A modifier may accept an optional argument. The argument can be a valid JSON
+document or just characters.
+
+For example, the `@pretty` modifier takes a json object as its argument.
+
+```
+@pretty:{"sortKeys":true}
+```
+
+Which makes the json pretty and orders all of its keys.
+
+```json
+{
+ "age":37,
+ "children": ["Sara","Alex","Jack"],
+ "fav.movie": "Deer Hunter",
+ "friends": [
+ {"age": 44, "first": "Dale", "last": "Murphy"},
+ {"age": 68, "first": "Roger", "last": "Craig"},
+ {"age": 47, "first": "Jane", "last": "Murphy"}
+ ],
+ "name": {"first": "Tom", "last": "Anderson"}
+}
+```
+
+*The full list of `@pretty` options are `sortKeys`, `indent`, `prefix`, and `width`.
+Please see [Pretty Options](https://github.com/tidwall/pretty#customized-output) for more information.*
+
+### Custom modifiers
+
+You can also add custom modifiers.
+
+For example, here we create a modifier that makes the entire json document upper
+or lower case.
+
+```go
+gjson.AddModifier("case", func(json, arg string) string {
+ if arg == "upper" {
+ return strings.ToUpper(json)
+ }
+ if arg == "lower" {
+ return strings.ToLower(json)
+ }
+ return json
+})
+```
+
+```
+"children|@case:upper" >> ["SARA","ALEX","JACK"]
+"children|@case:lower|@reverse" >> ["jack","alex","sara"]
+```
+
+## JSON Lines
+
+There's support for [JSON Lines](http://jsonlines.org/) using the `..` prefix, which treats a multilined document as an array.
+
+For example:
+
+```
+{"name": "Gilbert", "age": 61}
+{"name": "Alexa", "age": 34}
+{"name": "May", "age": 57}
+{"name": "Deloise", "age": 44}
+```
+
+```
+..# >> 4
+..1 >> {"name": "Alexa", "age": 34}
+..3 >> {"name": "Deloise", "age": 44}
+..#.name >> ["Gilbert","Alexa","May","Deloise"]
+..#(name="May").age >> 57
+```
+
+The `ForEachLines` function will iterate through JSON lines.
+
+```go
+gjson.ForEachLine(json, func(line gjson.Result) bool{
+ println(line.String())
+ return true
+})
+```
+
+## Get nested array values
+
+Suppose you want all the last names from the following json:
+
+```json
+{
+ "programmers": [
+ {
+ "firstName": "Janet",
+ "lastName": "McLaughlin",
+ }, {
+ "firstName": "Elliotte",
+ "lastName": "Hunter",
+ }, {
+ "firstName": "Jason",
+ "lastName": "Harold",
+ }
+ ]
+}
+```
+
+You would use the path "programmers.#.lastName" like such:
+
+```go
+result := gjson.Get(json, "programmers.#.lastName")
+for _, name := range result.Array() {
+ println(name.String())
+}
+```
+
+You can also query an object inside an array:
+
+```go
+name := gjson.Get(json, `programmers.#(lastName="Hunter").firstName`)
+println(name.String()) // prints "Elliotte"
+```
+
+## Iterate through an object or array
+
+The `ForEach` function allows for quickly iterating through an object or array.
+The key and value are passed to the iterator function for objects.
+Only the value is passed for arrays.
+Returning `false` from an iterator will stop iteration.
+
+```go
+result := gjson.Get(json, "programmers")
+result.ForEach(func(key, value gjson.Result) bool {
+ println(value.String())
+ return true // keep iterating
+})
+```
+
+## Simple Parse and Get
+
+There's a `Parse(json)` function that will do a simple parse, and `result.Get(path)` that will search a result.
+
+For example, all of these will return the same result:
+
+```go
+gjson.Parse(json).Get("name").Get("last")
+gjson.Get(json, "name").Get("last")
+gjson.Get(json, "name.last")
+```
+
+## Check for the existence of a value
+
+Sometimes you just want to know if a value exists.
+
+```go
+value := gjson.Get(json, "name.last")
+if !value.Exists() {
+ println("no last name")
+} else {
+ println(value.String())
+}
+
+// Or as one step
+if gjson.Get(json, "name.last").Exists() {
+ println("has a last name")
+}
+```
+
+## Validate JSON
+
+The `Get*` and `Parse*` functions expects that the json is well-formed. Bad json will not panic, but it may return back unexpected results.
+
+If you are consuming JSON from an unpredictable source then you may want to validate prior to using GJSON.
+
+```go
+if !gjson.Valid(json) {
+ return errors.New("invalid json")
+}
+value := gjson.Get(json, "name.last")
+```
+
+## Unmarshal to a map
+
+To unmarshal to a `map[string]interface{}`:
+
+```go
+m, ok := gjson.Parse(json).Value().(map[string]interface{})
+if !ok {
+ // not a map
+}
+```
+
+## Working with Bytes
+
+If your JSON is contained in a `[]byte` slice, there's the [GetBytes](https://godoc.org/github.com/tidwall/gjson#GetBytes) function. This is preferred over `Get(string(data), path)`.
+
+```go
+var json []byte = ...
+result := gjson.GetBytes(json, path)
+```
+
+If you are using the `gjson.GetBytes(json, path)` function and you want to avoid converting `result.Raw` to a `[]byte`, then you can use this pattern:
+
+```go
+var json []byte = ...
+result := gjson.GetBytes(json, path)
+var raw []byte
+if result.Index > 0 {
+ raw = json[result.Index:result.Index+len(result.Raw)]
+} else {
+ raw = []byte(result.Raw)
+}
+```
+
+This is a best-effort no allocation sub slice of the original json. This method utilizes the `result.Index` field, which is the position of the raw data in the original json. It's possible that the value of `result.Index` equals zero, in which case the `result.Raw` is converted to a `[]byte`.
+
+## Get multiple values at once
+
+The `GetMany` function can be used to get multiple values at the same time.
+
+```go
+results := gjson.GetMany(json, "name.first", "name.last", "age")
+```
+
+The return value is a `[]Result`, which will always contain exactly the same number of items as the input paths.
+
+## Performance
+
+Benchmarks of GJSON alongside [encoding/json](https://golang.org/pkg/encoding/json/),
+[ffjson](https://github.com/pquerna/ffjson),
+[EasyJSON](https://github.com/mailru/easyjson),
+[jsonparser](https://github.com/buger/jsonparser),
+and [json-iterator](https://github.com/json-iterator/go)
+
+```
+BenchmarkGJSONGet-16 11644512 311 ns/op 0 B/op 0 allocs/op
+BenchmarkGJSONUnmarshalMap-16 1122678 3094 ns/op 1920 B/op 26 allocs/op
+BenchmarkJSONUnmarshalMap-16 516681 6810 ns/op 2944 B/op 69 allocs/op
+BenchmarkJSONUnmarshalStruct-16 697053 5400 ns/op 928 B/op 13 allocs/op
+BenchmarkJSONDecoder-16 330450 10217 ns/op 3845 B/op 160 allocs/op
+BenchmarkFFJSONLexer-16 1424979 2585 ns/op 880 B/op 8 allocs/op
+BenchmarkEasyJSONLexer-16 3000000 729 ns/op 501 B/op 5 allocs/op
+BenchmarkJSONParserGet-16 3000000 366 ns/op 21 B/op 0 allocs/op
+BenchmarkJSONIterator-16 3000000 869 ns/op 693 B/op 14 allocs/op
+```
+
+JSON document used:
+
+```json
+{
+ "widget": {
+ "debug": "on",
+ "window": {
+ "title": "Sample Konfabulator Widget",
+ "name": "main_window",
+ "width": 500,
+ "height": 500
+ },
+ "image": {
+ "src": "Images/Sun.png",
+ "hOffset": 250,
+ "vOffset": 250,
+ "alignment": "center"
+ },
+ "text": {
+ "data": "Click Here",
+ "size": 36,
+ "style": "bold",
+ "vOffset": 100,
+ "alignment": "center",
+ "onMouseUp": "sun1.opacity = (sun1.opacity / 100) * 90;"
+ }
+ }
+}
+```
+
+Each operation was rotated through one of the following search paths:
+
+```
+widget.window.name
+widget.image.hOffset
+widget.text.onMouseUp
+```
+
+*These benchmarks were run on a MacBook Pro 16" 2.4 GHz Intel Core i9 using Go 1.17 and can be found [here](https://github.com/tidwall/gjson-benchmarks).*
diff --git a/vendor/github.com/tidwall/gjson/SYNTAX.md b/vendor/github.com/tidwall/gjson/SYNTAX.md
new file mode 100644
index 000000000..1b8663469
--- /dev/null
+++ b/vendor/github.com/tidwall/gjson/SYNTAX.md
@@ -0,0 +1,339 @@
+# GJSON Path Syntax
+
+A GJSON Path is a text string syntax that describes a search pattern for quickly retreiving values from a JSON payload.
+
+This document is designed to explain the structure of a GJSON Path through examples.
+
+- [Path structure](#path-structure)
+- [Basic](#basic)
+- [Wildcards](#wildcards)
+- [Escape Character](#escape-character)
+- [Arrays](#arrays)
+- [Queries](#queries)
+- [Dot vs Pipe](#dot-vs-pipe)
+- [Modifiers](#modifiers)
+- [Multipaths](#multipaths)
+- [Literals](#literals)
+
+The definitive implemenation is [github.com/tidwall/gjson](https://github.com/tidwall/gjson).
+Use the [GJSON Playground](https://gjson.dev) to experiment with the syntax online.
+
+## Path structure
+
+A GJSON Path is intended to be easily expressed as a series of components seperated by a `.` character.
+
+Along with `.` character, there are a few more that have special meaning, including `|`, `#`, `@`, `\`, `*`, and `?`.
+
+## Example
+
+Given this JSON
+
+```json
+{
+ "name": {"first": "Tom", "last": "Anderson"},
+ "age":37,
+ "children": ["Sara","Alex","Jack"],
+ "fav.movie": "Deer Hunter",
+ "friends": [
+ {"first": "Dale", "last": "Murphy", "age": 44, "nets": ["ig", "fb", "tw"]},
+ {"first": "Roger", "last": "Craig", "age": 68, "nets": ["fb", "tw"]},
+ {"first": "Jane", "last": "Murphy", "age": 47, "nets": ["ig", "tw"]}
+ ]
+}
+```
+
+The following GJSON Paths evaluate to the accompanying values.
+
+### Basic
+
+In many cases you'll just want to retreive values by object name or array index.
+
+```go
+name.last "Anderson"
+name.first "Tom"
+age 37
+children ["Sara","Alex","Jack"]
+children.0 "Sara"
+children.1 "Alex"
+friends.1 {"first": "Roger", "last": "Craig", "age": 68}
+friends.1.first "Roger"
+```
+
+### Wildcards
+
+A key may contain the special wildcard characters `*` and `?`.
+The `*` will match on any zero+ characters, and `?` matches on any one character.
+
+```go
+child*.2 "Jack"
+c?ildren.0 "Sara"
+```
+
+### Escape character
+
+Special purpose characters, such as `.`, `*`, and `?` can be escaped with `\`.
+
+```go
+fav\.movie "Deer Hunter"
+```
+
+You'll also need to make sure that the `\` character is correctly escaped when hardcoding a path in you source code.
+
+```go
+// Go
+val := gjson.Get(json, "fav\\.movie") // must escape the slash
+val := gjson.Get(json, `fav\.movie`) // no need to escape the slash
+```
+
+```rust
+// Rust
+let val = gjson::get(json, "fav\\.movie") // must escape the slash
+let val = gjson::get(json, r#"fav\.movie"#) // no need to escape the slash
+```
+
+
+### Arrays
+
+The `#` character allows for digging into JSON Arrays.
+
+To get the length of an array you'll just use the `#` all by itself.
+
+```go
+friends.# 3
+friends.#.age [44,68,47]
+```
+
+### Queries
+
+You can also query an array for the first match by using `#(...)`, or find all matches with `#(...)#`.
+Queries support the `==`, `!=`, `<`, `<=`, `>`, `>=` comparison operators,
+and the simple pattern matching `%` (like) and `!%` (not like) operators.
+
+```go
+friends.#(last=="Murphy").first "Dale"
+friends.#(last=="Murphy")#.first ["Dale","Jane"]
+friends.#(age>45)#.last ["Craig","Murphy"]
+friends.#(first%"D*").last "Murphy"
+friends.#(first!%"D*").last "Craig"
+```
+
+To query for a non-object value in an array, you can forgo the string to the right of the operator.
+
+```go
+children.#(!%"*a*") "Alex"
+children.#(%"*a*")# ["Sara","Jack"]
+```
+
+Nested queries are allowed.
+
+```go
+friends.#(nets.#(=="fb"))#.first >> ["Dale","Roger"]
+```
+
+*Please note that prior to v1.3.0, queries used the `#[...]` brackets. This was
+changed in v1.3.0 as to avoid confusion with the new [multipath](#multipaths)
+syntax. For backwards compatibility, `#[...]` will continue to work until the
+next major release.*
+
+The `~` (tilde) operator will convert a value to a boolean before comparison.
+
+For example, using the following JSON:
+
+```json
+{
+ "vals": [
+ { "a": 1, "b": true },
+ { "a": 2, "b": true },
+ { "a": 3, "b": false },
+ { "a": 4, "b": "0" },
+ { "a": 5, "b": 0 },
+ { "a": 6, "b": "1" },
+ { "a": 7, "b": 1 },
+ { "a": 8, "b": "true" },
+ { "a": 9, "b": false },
+ { "a": 10, "b": null },
+ { "a": 11 }
+ ]
+}
+```
+
+You can now query for all true(ish) or false(ish) values:
+
+```
+vals.#(b==~true)#.a >> [1,2,6,7,8]
+vals.#(b==~false)#.a >> [3,4,5,9,10,11]
+```
+
+The last value which was non-existent is treated as `false`
+
+### Dot vs Pipe
+
+The `.` is standard separator, but it's also possible to use a `|`.
+In most cases they both end up returning the same results.
+The cases where`|` differs from `.` is when it's used after the `#` for [Arrays](#arrays) and [Queries](#queries).
+
+Here are some examples
+
+```go
+friends.0.first "Dale"
+friends|0.first "Dale"
+friends.0|first "Dale"
+friends|0|first "Dale"
+friends|# 3
+friends.# 3
+friends.#(last="Murphy")# [{"first": "Dale", "last": "Murphy", "age": 44},{"first": "Jane", "last": "Murphy", "age": 47}]
+friends.#(last="Murphy")#.first ["Dale","Jane"]
+friends.#(last="Murphy")#|first
+friends.#(last="Murphy")#.0 []
+friends.#(last="Murphy")#|0 {"first": "Dale", "last": "Murphy", "age": 44}
+friends.#(last="Murphy")#.# []
+friends.#(last="Murphy")#|# 2
+```
+
+Let's break down a few of these.
+
+The path `friends.#(last="Murphy")#` all by itself results in
+
+```json
+[{"first": "Dale", "last": "Murphy", "age": 44},{"first": "Jane", "last": "Murphy", "age": 47}]
+```
+
+The `.first` suffix will process the `first` path on each array element *before* returning the results. Which becomes
+
+```json
+["Dale","Jane"]
+```
+
+But the `|first` suffix actually processes the `first` path *after* the previous result.
+Since the previous result is an array, not an object, it's not possible to process
+because `first` does not exist.
+
+Yet, `|0` suffix returns
+
+```json
+{"first": "Dale", "last": "Murphy", "age": 44}
+```
+
+Because `0` is the first index of the previous result.
+
+### Modifiers
+
+A modifier is a path component that performs custom processing on the JSON.
+
+For example, using the built-in `@reverse` modifier on the above JSON payload will reverse the `children` array:
+
+```go
+children.@reverse ["Jack","Alex","Sara"]
+children.@reverse.0 "Jack"
+```
+
+There are currently the following built-in modifiers:
+
+- `@reverse`: Reverse an array or the members of an object.
+- `@ugly`: Remove all whitespace from JSON.
+- `@pretty`: Make the JSON more human readable.
+- `@this`: Returns the current element. It can be used to retrieve the root element.
+- `@valid`: Ensure the json document is valid.
+- `@flatten`: Flattens an array.
+- `@join`: Joins multiple objects into a single object.
+- `@keys`: Returns an array of keys for an object.
+- `@values`: Returns an array of values for an object.
+
+#### Modifier arguments
+
+A modifier may accept an optional argument. The argument can be a valid JSON payload or just characters.
+
+For example, the `@pretty` modifier takes a json object as its argument.
+
+```
+@pretty:{"sortKeys":true}
+```
+
+Which makes the json pretty and orders all of its keys.
+
+```json
+{
+ "age":37,
+ "children": ["Sara","Alex","Jack"],
+ "fav.movie": "Deer Hunter",
+ "friends": [
+ {"age": 44, "first": "Dale", "last": "Murphy"},
+ {"age": 68, "first": "Roger", "last": "Craig"},
+ {"age": 47, "first": "Jane", "last": "Murphy"}
+ ],
+ "name": {"first": "Tom", "last": "Anderson"}
+}
+```
+
+*The full list of `@pretty` options are `sortKeys`, `indent`, `prefix`, and `width`.
+Please see [Pretty Options](https://github.com/tidwall/pretty#customized-output) for more information.*
+
+#### Custom modifiers
+
+You can also add custom modifiers.
+
+For example, here we create a modifier which makes the entire JSON payload upper or lower case.
+
+```go
+gjson.AddModifier("case", func(json, arg string) string {
+ if arg == "upper" {
+ return strings.ToUpper(json)
+ }
+ if arg == "lower" {
+ return strings.ToLower(json)
+ }
+ return json
+})
+"children.@case:upper" ["SARA","ALEX","JACK"]
+"children.@case:lower.@reverse" ["jack","alex","sara"]
+```
+
+*Note: Custom modifiers are not yet available in the Rust version*
+
+### Multipaths
+
+Starting with v1.3.0, GJSON added the ability to join multiple paths together
+to form new documents. Wrapping comma-separated paths between `[...]` or
+`{...}` will result in a new array or object, respectively.
+
+For example, using the given multipath:
+
+```
+{name.first,age,"the_murphys":friends.#(last="Murphy")#.first}
+```
+
+Here we selected the first name, age, and the first name for friends with the
+last name "Murphy".
+
+You'll notice that an optional key can be provided, in this case
+"the_murphys", to force assign a key to a value. Otherwise, the name of the
+actual field will be used, in this case "first". If a name cannot be
+determined, then "_" is used.
+
+This results in
+
+```json
+{"first":"Tom","age":37,"the_murphys":["Dale","Jane"]}
+```
+
+### Literals
+
+Starting with v1.12.0, GJSON added support of json literals, which provides a way for constructing static blocks of json. This is can be particularly useful when constructing a new json document using [multipaths](#multipaths).
+
+A json literal begins with the '!' declaration character.
+
+For example, using the given multipath:
+
+```
+{name.first,age,"company":!"Happysoft","employed":!true}
+```
+
+Here we selected the first name and age. Then add two new fields, "company" and "employed".
+
+This results in
+
+```json
+{"first":"Tom","age":37,"company":"Happysoft","employed":true}
+```
+
+*See issue [#249](https://github.com/tidwall/gjson/issues/249) for additional context on JSON Literals.*
diff --git a/vendor/github.com/tidwall/gjson/gjson.go b/vendor/github.com/tidwall/gjson/gjson.go
new file mode 100644
index 000000000..9920c4d2b
--- /dev/null
+++ b/vendor/github.com/tidwall/gjson/gjson.go
@@ -0,0 +1,3214 @@
+// Package gjson provides searching for json strings.
+package gjson
+
+import (
+ "encoding/json"
+ "strconv"
+ "strings"
+ "time"
+ "unicode/utf16"
+ "unicode/utf8"
+ "unsafe"
+
+ "github.com/tidwall/match"
+ "github.com/tidwall/pretty"
+)
+
+// Type is Result type
+type Type int
+
+const (
+ // Null is a null json value
+ Null Type = iota
+ // False is a json false boolean
+ False
+ // Number is json number
+ Number
+ // String is a json string
+ String
+ // True is a json true boolean
+ True
+ // JSON is a raw block of JSON
+ JSON
+)
+
+// String returns a string representation of the type.
+func (t Type) String() string {
+ switch t {
+ default:
+ return ""
+ case Null:
+ return "Null"
+ case False:
+ return "False"
+ case Number:
+ return "Number"
+ case String:
+ return "String"
+ case True:
+ return "True"
+ case JSON:
+ return "JSON"
+ }
+}
+
+// Result represents a json value that is returned from Get().
+type Result struct {
+ // Type is the json type
+ Type Type
+ // Raw is the raw json
+ Raw string
+ // Str is the json string
+ Str string
+ // Num is the json number
+ Num float64
+ // Index of raw value in original json, zero means index unknown
+ Index int
+ // Indexes of all the elements that match on a path containing the '#'
+ // query character.
+ Indexes []int
+}
+
+// String returns a string representation of the value.
+func (t Result) String() string {
+ switch t.Type {
+ default:
+ return ""
+ case False:
+ return "false"
+ case Number:
+ if len(t.Raw) == 0 {
+ // calculated result
+ return strconv.FormatFloat(t.Num, 'f', -1, 64)
+ }
+ var i int
+ if t.Raw[0] == '-' {
+ i++
+ }
+ for ; i < len(t.Raw); i++ {
+ if t.Raw[i] < '0' || t.Raw[i] > '9' {
+ return strconv.FormatFloat(t.Num, 'f', -1, 64)
+ }
+ }
+ return t.Raw
+ case String:
+ return t.Str
+ case JSON:
+ return t.Raw
+ case True:
+ return "true"
+ }
+}
+
+// Bool returns an boolean representation.
+func (t Result) Bool() bool {
+ switch t.Type {
+ default:
+ return false
+ case True:
+ return true
+ case String:
+ b, _ := strconv.ParseBool(strings.ToLower(t.Str))
+ return b
+ case Number:
+ return t.Num != 0
+ }
+}
+
+// Int returns an integer representation.
+func (t Result) Int() int64 {
+ switch t.Type {
+ default:
+ return 0
+ case True:
+ return 1
+ case String:
+ n, _ := parseInt(t.Str)
+ return n
+ case Number:
+ // try to directly convert the float64 to int64
+ i, ok := safeInt(t.Num)
+ if ok {
+ return i
+ }
+ // now try to parse the raw string
+ i, ok = parseInt(t.Raw)
+ if ok {
+ return i
+ }
+ // fallback to a standard conversion
+ return int64(t.Num)
+ }
+}
+
+// Uint returns an unsigned integer representation.
+func (t Result) Uint() uint64 {
+ switch t.Type {
+ default:
+ return 0
+ case True:
+ return 1
+ case String:
+ n, _ := parseUint(t.Str)
+ return n
+ case Number:
+ // try to directly convert the float64 to uint64
+ i, ok := safeInt(t.Num)
+ if ok && i >= 0 {
+ return uint64(i)
+ }
+ // now try to parse the raw string
+ u, ok := parseUint(t.Raw)
+ if ok {
+ return u
+ }
+ // fallback to a standard conversion
+ return uint64(t.Num)
+ }
+}
+
+// Float returns an float64 representation.
+func (t Result) Float() float64 {
+ switch t.Type {
+ default:
+ return 0
+ case True:
+ return 1
+ case String:
+ n, _ := strconv.ParseFloat(t.Str, 64)
+ return n
+ case Number:
+ return t.Num
+ }
+}
+
+// Time returns a time.Time representation.
+func (t Result) Time() time.Time {
+ res, _ := time.Parse(time.RFC3339, t.String())
+ return res
+}
+
+// Array returns back an array of values.
+// If the result represents a null value or is non-existent, then an empty
+// array will be returned.
+// If the result is not a JSON array, the return value will be an
+// array containing one result.
+func (t Result) Array() []Result {
+ if t.Type == Null {
+ return []Result{}
+ }
+ if !t.IsArray() {
+ return []Result{t}
+ }
+ r := t.arrayOrMap('[', false)
+ return r.a
+}
+
+// IsObject returns true if the result value is a JSON object.
+func (t Result) IsObject() bool {
+ return t.Type == JSON && len(t.Raw) > 0 && t.Raw[0] == '{'
+}
+
+// IsArray returns true if the result value is a JSON array.
+func (t Result) IsArray() bool {
+ return t.Type == JSON && len(t.Raw) > 0 && t.Raw[0] == '['
+}
+
+// ForEach iterates through values.
+// If the result represents a non-existent value, then no values will be
+// iterated. If the result is an Object, the iterator will pass the key and
+// value of each item. If the result is an Array, the iterator will only pass
+// the value of each item. If the result is not a JSON array or object, the
+// iterator will pass back one value equal to the result.
+func (t Result) ForEach(iterator func(key, value Result) bool) {
+ if !t.Exists() {
+ return
+ }
+ if t.Type != JSON {
+ iterator(Result{}, t)
+ return
+ }
+ json := t.Raw
+ var obj bool
+ var i int
+ var key, value Result
+ for ; i < len(json); i++ {
+ if json[i] == '{' {
+ i++
+ key.Type = String
+ obj = true
+ break
+ } else if json[i] == '[' {
+ i++
+ key.Type = Number
+ key.Num = -1
+ break
+ }
+ if json[i] > ' ' {
+ return
+ }
+ }
+ var str string
+ var vesc bool
+ var ok bool
+ var idx int
+ for ; i < len(json); i++ {
+ if obj {
+ if json[i] != '"' {
+ continue
+ }
+ s := i
+ i, str, vesc, ok = parseString(json, i+1)
+ if !ok {
+ return
+ }
+ if vesc {
+ key.Str = unescape(str[1 : len(str)-1])
+ } else {
+ key.Str = str[1 : len(str)-1]
+ }
+ key.Raw = str
+ key.Index = s + t.Index
+ } else {
+ key.Num += 1
+ }
+ for ; i < len(json); i++ {
+ if json[i] <= ' ' || json[i] == ',' || json[i] == ':' {
+ continue
+ }
+ break
+ }
+ s := i
+ i, value, ok = parseAny(json, i, true)
+ if !ok {
+ return
+ }
+ if t.Indexes != nil {
+ if idx < len(t.Indexes) {
+ value.Index = t.Indexes[idx]
+ }
+ } else {
+ value.Index = s + t.Index
+ }
+ if !iterator(key, value) {
+ return
+ }
+ idx++
+ }
+}
+
+// Map returns back a map of values. The result should be a JSON object.
+// If the result is not a JSON object, the return value will be an empty map.
+func (t Result) Map() map[string]Result {
+ if t.Type != JSON {
+ return map[string]Result{}
+ }
+ r := t.arrayOrMap('{', false)
+ return r.o
+}
+
+// Get searches result for the specified path.
+// The result should be a JSON array or object.
+func (t Result) Get(path string) Result {
+ r := Get(t.Raw, path)
+ if r.Indexes != nil {
+ for i := 0; i < len(r.Indexes); i++ {
+ r.Indexes[i] += t.Index
+ }
+ } else {
+ r.Index += t.Index
+ }
+ return r
+}
+
+type arrayOrMapResult struct {
+ a []Result
+ ai []interface{}
+ o map[string]Result
+ oi map[string]interface{}
+ vc byte
+}
+
+func (t Result) arrayOrMap(vc byte, valueize bool) (r arrayOrMapResult) {
+ var json = t.Raw
+ var i int
+ var value Result
+ var count int
+ var key Result
+ if vc == 0 {
+ for ; i < len(json); i++ {
+ if json[i] == '{' || json[i] == '[' {
+ r.vc = json[i]
+ i++
+ break
+ }
+ if json[i] > ' ' {
+ goto end
+ }
+ }
+ } else {
+ for ; i < len(json); i++ {
+ if json[i] == vc {
+ i++
+ break
+ }
+ if json[i] > ' ' {
+ goto end
+ }
+ }
+ r.vc = vc
+ }
+ if r.vc == '{' {
+ if valueize {
+ r.oi = make(map[string]interface{})
+ } else {
+ r.o = make(map[string]Result)
+ }
+ } else {
+ if valueize {
+ r.ai = make([]interface{}, 0)
+ } else {
+ r.a = make([]Result, 0)
+ }
+ }
+ for ; i < len(json); i++ {
+ if json[i] <= ' ' {
+ continue
+ }
+ // get next value
+ if json[i] == ']' || json[i] == '}' {
+ break
+ }
+ switch json[i] {
+ default:
+ if (json[i] >= '0' && json[i] <= '9') || json[i] == '-' {
+ value.Type = Number
+ value.Raw, value.Num = tonum(json[i:])
+ value.Str = ""
+ } else {
+ continue
+ }
+ case '{', '[':
+ value.Type = JSON
+ value.Raw = squash(json[i:])
+ value.Str, value.Num = "", 0
+ case 'n':
+ value.Type = Null
+ value.Raw = tolit(json[i:])
+ value.Str, value.Num = "", 0
+ case 't':
+ value.Type = True
+ value.Raw = tolit(json[i:])
+ value.Str, value.Num = "", 0
+ case 'f':
+ value.Type = False
+ value.Raw = tolit(json[i:])
+ value.Str, value.Num = "", 0
+ case '"':
+ value.Type = String
+ value.Raw, value.Str = tostr(json[i:])
+ value.Num = 0
+ }
+ value.Index = i + t.Index
+
+ i += len(value.Raw) - 1
+
+ if r.vc == '{' {
+ if count%2 == 0 {
+ key = value
+ } else {
+ if valueize {
+ if _, ok := r.oi[key.Str]; !ok {
+ r.oi[key.Str] = value.Value()
+ }
+ } else {
+ if _, ok := r.o[key.Str]; !ok {
+ r.o[key.Str] = value
+ }
+ }
+ }
+ count++
+ } else {
+ if valueize {
+ r.ai = append(r.ai, value.Value())
+ } else {
+ r.a = append(r.a, value)
+ }
+ }
+ }
+end:
+ if t.Indexes != nil {
+ if len(t.Indexes) != len(r.a) {
+ for i := 0; i < len(r.a); i++ {
+ r.a[i].Index = 0
+ }
+ } else {
+ for i := 0; i < len(r.a); i++ {
+ r.a[i].Index = t.Indexes[i]
+ }
+ }
+ }
+ return
+}
+
+// Parse parses the json and returns a result.
+//
+// This function expects that the json is well-formed, and does not validate.
+// Invalid json will not panic, but it may return back unexpected results.
+// If you are consuming JSON from an unpredictable source then you may want to
+// use the Valid function first.
+func Parse(json string) Result {
+ var value Result
+ i := 0
+ for ; i < len(json); i++ {
+ if json[i] == '{' || json[i] == '[' {
+ value.Type = JSON
+ value.Raw = json[i:] // just take the entire raw
+ break
+ }
+ if json[i] <= ' ' {
+ continue
+ }
+ switch json[i] {
+ case '+', '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+ 'i', 'I', 'N':
+ value.Type = Number
+ value.Raw, value.Num = tonum(json[i:])
+ case 'n':
+ if i+1 < len(json) && json[i+1] != 'u' {
+ // nan
+ value.Type = Number
+ value.Raw, value.Num = tonum(json[i:])
+ } else {
+ // null
+ value.Type = Null
+ value.Raw = tolit(json[i:])
+ }
+ case 't':
+ value.Type = True
+ value.Raw = tolit(json[i:])
+ case 'f':
+ value.Type = False
+ value.Raw = tolit(json[i:])
+ case '"':
+ value.Type = String
+ value.Raw, value.Str = tostr(json[i:])
+ default:
+ return Result{}
+ }
+ break
+ }
+ if value.Exists() {
+ value.Index = i
+ }
+ return value
+}
+
+// ParseBytes parses the json and returns a result.
+// If working with bytes, this method preferred over Parse(string(data))
+func ParseBytes(json []byte) Result {
+ return Parse(string(json))
+}
+
+func squash(json string) string {
+ // expects that the lead character is a '[' or '{' or '(' or '"'
+ // squash the value, ignoring all nested arrays and objects.
+ var i, depth int
+ if json[0] != '"' {
+ i, depth = 1, 1
+ }
+ for ; i < len(json); i++ {
+ if json[i] >= '"' && json[i] <= '}' {
+ switch json[i] {
+ case '"':
+ i++
+ s2 := i
+ for ; i < len(json); i++ {
+ if json[i] > '\\' {
+ continue
+ }
+ if json[i] == '"' {
+ // look for an escaped slash
+ if json[i-1] == '\\' {
+ n := 0
+ for j := i - 2; j > s2-1; j-- {
+ if json[j] != '\\' {
+ break
+ }
+ n++
+ }
+ if n%2 == 0 {
+ continue
+ }
+ }
+ break
+ }
+ }
+ if depth == 0 {
+ if i >= len(json) {
+ return json
+ }
+ return json[:i+1]
+ }
+ case '{', '[', '(':
+ depth++
+ case '}', ']', ')':
+ depth--
+ if depth == 0 {
+ return json[:i+1]
+ }
+ }
+ }
+ }
+ return json
+}
+
+func tonum(json string) (raw string, num float64) {
+ for i := 1; i < len(json); i++ {
+ // less than dash might have valid characters
+ if json[i] <= '-' {
+ if json[i] <= ' ' || json[i] == ',' {
+ // break on whitespace and comma
+ raw = json[:i]
+ num, _ = strconv.ParseFloat(raw, 64)
+ return
+ }
+ // could be a '+' or '-'. let's assume so.
+ } else if json[i] == ']' || json[i] == '}' {
+ // break on ']' or '}'
+ raw = json[:i]
+ num, _ = strconv.ParseFloat(raw, 64)
+ return
+ }
+ }
+ raw = json
+ num, _ = strconv.ParseFloat(raw, 64)
+ return
+}
+
+func tolit(json string) (raw string) {
+ for i := 1; i < len(json); i++ {
+ if json[i] < 'a' || json[i] > 'z' {
+ return json[:i]
+ }
+ }
+ return json
+}
+
+func tostr(json string) (raw string, str string) {
+ // expects that the lead character is a '"'
+ for i := 1; i < len(json); i++ {
+ if json[i] > '\\' {
+ continue
+ }
+ if json[i] == '"' {
+ return json[:i+1], json[1:i]
+ }
+ if json[i] == '\\' {
+ i++
+ for ; i < len(json); i++ {
+ if json[i] > '\\' {
+ continue
+ }
+ if json[i] == '"' {
+ // look for an escaped slash
+ if json[i-1] == '\\' {
+ n := 0
+ for j := i - 2; j > 0; j-- {
+ if json[j] != '\\' {
+ break
+ }
+ n++
+ }
+ if n%2 == 0 {
+ continue
+ }
+ }
+ return json[:i+1], unescape(json[1:i])
+ }
+ }
+ var ret string
+ if i+1 < len(json) {
+ ret = json[:i+1]
+ } else {
+ ret = json[:i]
+ }
+ return ret, unescape(json[1:i])
+ }
+ }
+ return json, json[1:]
+}
+
+// Exists returns true if value exists.
+//
+// if gjson.Get(json, "name.last").Exists(){
+// println("value exists")
+// }
+func (t Result) Exists() bool {
+ return t.Type != Null || len(t.Raw) != 0
+}
+
+// Value returns one of these types:
+//
+// bool, for JSON booleans
+// float64, for JSON numbers
+// Number, for JSON numbers
+// string, for JSON string literals
+// nil, for JSON null
+// map[string]interface{}, for JSON objects
+// []interface{}, for JSON arrays
+//
+func (t Result) Value() interface{} {
+ if t.Type == String {
+ return t.Str
+ }
+ switch t.Type {
+ default:
+ return nil
+ case False:
+ return false
+ case Number:
+ return t.Num
+ case JSON:
+ r := t.arrayOrMap(0, true)
+ if r.vc == '{' {
+ return r.oi
+ } else if r.vc == '[' {
+ return r.ai
+ }
+ return nil
+ case True:
+ return true
+ }
+}
+
+func parseString(json string, i int) (int, string, bool, bool) {
+ var s = i
+ for ; i < len(json); i++ {
+ if json[i] > '\\' {
+ continue
+ }
+ if json[i] == '"' {
+ return i + 1, json[s-1 : i+1], false, true
+ }
+ if json[i] == '\\' {
+ i++
+ for ; i < len(json); i++ {
+ if json[i] > '\\' {
+ continue
+ }
+ if json[i] == '"' {
+ // look for an escaped slash
+ if json[i-1] == '\\' {
+ n := 0
+ for j := i - 2; j > 0; j-- {
+ if json[j] != '\\' {
+ break
+ }
+ n++
+ }
+ if n%2 == 0 {
+ continue
+ }
+ }
+ return i + 1, json[s-1 : i+1], true, true
+ }
+ }
+ break
+ }
+ }
+ return i, json[s-1:], false, false
+}
+
+func parseNumber(json string, i int) (int, string) {
+ var s = i
+ i++
+ for ; i < len(json); i++ {
+ if json[i] <= ' ' || json[i] == ',' || json[i] == ']' ||
+ json[i] == '}' {
+ return i, json[s:i]
+ }
+ }
+ return i, json[s:]
+}
+
+func parseLiteral(json string, i int) (int, string) {
+ var s = i
+ i++
+ for ; i < len(json); i++ {
+ if json[i] < 'a' || json[i] > 'z' {
+ return i, json[s:i]
+ }
+ }
+ return i, json[s:]
+}
+
+type arrayPathResult struct {
+ part string
+ path string
+ pipe string
+ piped bool
+ more bool
+ alogok bool
+ arrch bool
+ alogkey string
+ query struct {
+ on bool
+ all bool
+ path string
+ op string
+ value string
+ }
+}
+
+func parseArrayPath(path string) (r arrayPathResult) {
+ for i := 0; i < len(path); i++ {
+ if path[i] == '|' {
+ r.part = path[:i]
+ r.pipe = path[i+1:]
+ r.piped = true
+ return
+ }
+ if path[i] == '.' {
+ r.part = path[:i]
+ if !r.arrch && i < len(path)-1 && isDotPiperChar(path[i+1]) {
+ r.pipe = path[i+1:]
+ r.piped = true
+ } else {
+ r.path = path[i+1:]
+ r.more = true
+ }
+ return
+ }
+ if path[i] == '#' {
+ r.arrch = true
+ if i == 0 && len(path) > 1 {
+ if path[1] == '.' {
+ r.alogok = true
+ r.alogkey = path[2:]
+ r.path = path[:1]
+ } else if path[1] == '[' || path[1] == '(' {
+ // query
+ r.query.on = true
+ qpath, op, value, _, fi, vesc, ok :=
+ parseQuery(path[i:])
+ if !ok {
+ // bad query, end now
+ break
+ }
+ if len(value) >= 2 && value[0] == '"' &&
+ value[len(value)-1] == '"' {
+ value = value[1 : len(value)-1]
+ if vesc {
+ value = unescape(value)
+ }
+ }
+ r.query.path = qpath
+ r.query.op = op
+ r.query.value = value
+
+ i = fi - 1
+ if i+1 < len(path) && path[i+1] == '#' {
+ r.query.all = true
+ }
+ }
+ }
+ continue
+ }
+ }
+ r.part = path
+ r.path = ""
+ return
+}
+
+// splitQuery takes a query and splits it into three parts:
+// path, op, middle, and right.
+// So for this query:
+// #(first_name=="Murphy").last
+// Becomes
+// first_name # path
+// =="Murphy" # middle
+// .last # right
+// Or,
+// #(service_roles.#(=="one")).cap
+// Becomes
+// service_roles.#(=="one") # path
+// # middle
+// .cap # right
+func parseQuery(query string) (
+ path, op, value, remain string, i int, vesc, ok bool,
+) {
+ if len(query) < 2 || query[0] != '#' ||
+ (query[1] != '(' && query[1] != '[') {
+ return "", "", "", "", i, false, false
+ }
+ i = 2
+ j := 0 // start of value part
+ depth := 1
+ for ; i < len(query); i++ {
+ if depth == 1 && j == 0 {
+ switch query[i] {
+ case '!', '=', '<', '>', '%':
+ // start of the value part
+ j = i
+ continue
+ }
+ }
+ if query[i] == '\\' {
+ i++
+ } else if query[i] == '[' || query[i] == '(' {
+ depth++
+ } else if query[i] == ']' || query[i] == ')' {
+ depth--
+ if depth == 0 {
+ break
+ }
+ } else if query[i] == '"' {
+ // inside selector string, balance quotes
+ i++
+ for ; i < len(query); i++ {
+ if query[i] == '\\' {
+ vesc = true
+ i++
+ } else if query[i] == '"' {
+ break
+ }
+ }
+ }
+ }
+ if depth > 0 {
+ return "", "", "", "", i, false, false
+ }
+ if j > 0 {
+ path = trim(query[2:j])
+ value = trim(query[j:i])
+ remain = query[i+1:]
+ // parse the compare op from the value
+ var opsz int
+ switch {
+ case len(value) == 1:
+ opsz = 1
+ case value[0] == '!' && value[1] == '=':
+ opsz = 2
+ case value[0] == '!' && value[1] == '%':
+ opsz = 2
+ case value[0] == '<' && value[1] == '=':
+ opsz = 2
+ case value[0] == '>' && value[1] == '=':
+ opsz = 2
+ case value[0] == '=' && value[1] == '=':
+ value = value[1:]
+ opsz = 1
+ case value[0] == '<':
+ opsz = 1
+ case value[0] == '>':
+ opsz = 1
+ case value[0] == '=':
+ opsz = 1
+ case value[0] == '%':
+ opsz = 1
+ }
+ op = value[:opsz]
+ value = trim(value[opsz:])
+ } else {
+ path = trim(query[2:i])
+ remain = query[i+1:]
+ }
+ return path, op, value, remain, i + 1, vesc, true
+}
+
+func trim(s string) string {
+left:
+ if len(s) > 0 && s[0] <= ' ' {
+ s = s[1:]
+ goto left
+ }
+right:
+ if len(s) > 0 && s[len(s)-1] <= ' ' {
+ s = s[:len(s)-1]
+ goto right
+ }
+ return s
+}
+
+// peek at the next byte and see if it's a '@', '[', or '{'.
+func isDotPiperChar(c byte) bool {
+ return !DisableModifiers && (c == '@' || c == '[' || c == '{')
+}
+
+type objectPathResult struct {
+ part string
+ path string
+ pipe string
+ piped bool
+ wild bool
+ more bool
+}
+
+func parseObjectPath(path string) (r objectPathResult) {
+ for i := 0; i < len(path); i++ {
+ if path[i] == '|' {
+ r.part = path[:i]
+ r.pipe = path[i+1:]
+ r.piped = true
+ return
+ }
+ if path[i] == '.' {
+ r.part = path[:i]
+ if i < len(path)-1 && isDotPiperChar(path[i+1]) {
+ r.pipe = path[i+1:]
+ r.piped = true
+ } else {
+ r.path = path[i+1:]
+ r.more = true
+ }
+ return
+ }
+ if path[i] == '*' || path[i] == '?' {
+ r.wild = true
+ continue
+ }
+ if path[i] == '\\' {
+ // go into escape mode. this is a slower path that
+ // strips off the escape character from the part.
+ epart := []byte(path[:i])
+ i++
+ if i < len(path) {
+ epart = append(epart, path[i])
+ i++
+ for ; i < len(path); i++ {
+ if path[i] == '\\' {
+ i++
+ if i < len(path) {
+ epart = append(epart, path[i])
+ }
+ continue
+ } else if path[i] == '.' {
+ r.part = string(epart)
+ if i < len(path)-1 && isDotPiperChar(path[i+1]) {
+ r.pipe = path[i+1:]
+ r.piped = true
+ } else {
+ r.path = path[i+1:]
+ }
+ r.more = true
+ return
+ } else if path[i] == '|' {
+ r.part = string(epart)
+ r.pipe = path[i+1:]
+ r.piped = true
+ return
+ } else if path[i] == '*' || path[i] == '?' {
+ r.wild = true
+ }
+ epart = append(epart, path[i])
+ }
+ }
+ // append the last part
+ r.part = string(epart)
+ return
+ }
+ }
+ r.part = path
+ return
+}
+
+func parseSquash(json string, i int) (int, string) {
+ // expects that the lead character is a '[' or '{' or '('
+ // squash the value, ignoring all nested arrays and objects.
+ // the first '[' or '{' or '(' has already been read
+ s := i
+ i++
+ depth := 1
+ for ; i < len(json); i++ {
+ if json[i] >= '"' && json[i] <= '}' {
+ switch json[i] {
+ case '"':
+ i++
+ s2 := i
+ for ; i < len(json); i++ {
+ if json[i] > '\\' {
+ continue
+ }
+ if json[i] == '"' {
+ // look for an escaped slash
+ if json[i-1] == '\\' {
+ n := 0
+ for j := i - 2; j > s2-1; j-- {
+ if json[j] != '\\' {
+ break
+ }
+ n++
+ }
+ if n%2 == 0 {
+ continue
+ }
+ }
+ break
+ }
+ }
+ case '{', '[', '(':
+ depth++
+ case '}', ']', ')':
+ depth--
+ if depth == 0 {
+ i++
+ return i, json[s:i]
+ }
+ }
+ }
+ }
+ return i, json[s:]
+}
+
+func parseObject(c *parseContext, i int, path string) (int, bool) {
+ var pmatch, kesc, vesc, ok, hit bool
+ var key, val string
+ rp := parseObjectPath(path)
+ if !rp.more && rp.piped {
+ c.pipe = rp.pipe
+ c.piped = true
+ }
+ for i < len(c.json) {
+ for ; i < len(c.json); i++ {
+ if c.json[i] == '"' {
+ // parse_key_string
+ // this is slightly different from getting s string value
+ // because we don't need the outer quotes.
+ i++
+ var s = i
+ for ; i < len(c.json); i++ {
+ if c.json[i] > '\\' {
+ continue
+ }
+ if c.json[i] == '"' {
+ i, key, kesc, ok = i+1, c.json[s:i], false, true
+ goto parse_key_string_done
+ }
+ if c.json[i] == '\\' {
+ i++
+ for ; i < len(c.json); i++ {
+ if c.json[i] > '\\' {
+ continue
+ }
+ if c.json[i] == '"' {
+ // look for an escaped slash
+ if c.json[i-1] == '\\' {
+ n := 0
+ for j := i - 2; j > 0; j-- {
+ if c.json[j] != '\\' {
+ break
+ }
+ n++
+ }
+ if n%2 == 0 {
+ continue
+ }
+ }
+ i, key, kesc, ok = i+1, c.json[s:i], true, true
+ goto parse_key_string_done
+ }
+ }
+ break
+ }
+ }
+ key, kesc, ok = c.json[s:], false, false
+ parse_key_string_done:
+ break
+ }
+ if c.json[i] == '}' {
+ return i + 1, false
+ }
+ }
+ if !ok {
+ return i, false
+ }
+ if rp.wild {
+ if kesc {
+ pmatch = matchLimit(unescape(key), rp.part)
+ } else {
+ pmatch = matchLimit(key, rp.part)
+ }
+ } else {
+ if kesc {
+ pmatch = rp.part == unescape(key)
+ } else {
+ pmatch = rp.part == key
+ }
+ }
+ hit = pmatch && !rp.more
+ for ; i < len(c.json); i++ {
+ var num bool
+ switch c.json[i] {
+ default:
+ continue
+ case '"':
+ i++
+ i, val, vesc, ok = parseString(c.json, i)
+ if !ok {
+ return i, false
+ }
+ if hit {
+ if vesc {
+ c.value.Str = unescape(val[1 : len(val)-1])
+ } else {
+ c.value.Str = val[1 : len(val)-1]
+ }
+ c.value.Raw = val
+ c.value.Type = String
+ return i, true
+ }
+ case '{':
+ if pmatch && !hit {
+ i, hit = parseObject(c, i+1, rp.path)
+ if hit {
+ return i, true
+ }
+ } else {
+ i, val = parseSquash(c.json, i)
+ if hit {
+ c.value.Raw = val
+ c.value.Type = JSON
+ return i, true
+ }
+ }
+ case '[':
+ if pmatch && !hit {
+ i, hit = parseArray(c, i+1, rp.path)
+ if hit {
+ return i, true
+ }
+ } else {
+ i, val = parseSquash(c.json, i)
+ if hit {
+ c.value.Raw = val
+ c.value.Type = JSON
+ return i, true
+ }
+ }
+ case 'n':
+ if i+1 < len(c.json) && c.json[i+1] != 'u' {
+ num = true
+ break
+ }
+ fallthrough
+ case 't', 'f':
+ vc := c.json[i]
+ i, val = parseLiteral(c.json, i)
+ if hit {
+ c.value.Raw = val
+ switch vc {
+ case 't':
+ c.value.Type = True
+ case 'f':
+ c.value.Type = False
+ }
+ return i, true
+ }
+ case '+', '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+ 'i', 'I', 'N':
+ num = true
+ }
+ if num {
+ i, val = parseNumber(c.json, i)
+ if hit {
+ c.value.Raw = val
+ c.value.Type = Number
+ c.value.Num, _ = strconv.ParseFloat(val, 64)
+ return i, true
+ }
+ }
+ break
+ }
+ }
+ return i, false
+}
+
+// matchLimit will limit the complexity of the match operation to avoid ReDos
+// attacks from arbritary inputs.
+// See the github.com/tidwall/match.MatchLimit function for more information.
+func matchLimit(str, pattern string) bool {
+ matched, _ := match.MatchLimit(str, pattern, 10000)
+ return matched
+}
+
+func queryMatches(rp *arrayPathResult, value Result) bool {
+ rpv := rp.query.value
+ if len(rpv) > 0 && rpv[0] == '~' {
+ // convert to bool
+ rpv = rpv[1:]
+ if value.Bool() {
+ value = Result{Type: True}
+ } else {
+ value = Result{Type: False}
+ }
+ }
+ if !value.Exists() {
+ return false
+ }
+ if rp.query.op == "" {
+ // the query is only looking for existence, such as:
+ // friends.#(name)
+ // which makes sure that the array "friends" has an element of
+ // "name" that exists
+ return true
+ }
+ switch value.Type {
+ case String:
+ switch rp.query.op {
+ case "=":
+ return value.Str == rpv
+ case "!=":
+ return value.Str != rpv
+ case "<":
+ return value.Str < rpv
+ case "<=":
+ return value.Str <= rpv
+ case ">":
+ return value.Str > rpv
+ case ">=":
+ return value.Str >= rpv
+ case "%":
+ return matchLimit(value.Str, rpv)
+ case "!%":
+ return !matchLimit(value.Str, rpv)
+ }
+ case Number:
+ rpvn, _ := strconv.ParseFloat(rpv, 64)
+ switch rp.query.op {
+ case "=":
+ return value.Num == rpvn
+ case "!=":
+ return value.Num != rpvn
+ case "<":
+ return value.Num < rpvn
+ case "<=":
+ return value.Num <= rpvn
+ case ">":
+ return value.Num > rpvn
+ case ">=":
+ return value.Num >= rpvn
+ }
+ case True:
+ switch rp.query.op {
+ case "=":
+ return rpv == "true"
+ case "!=":
+ return rpv != "true"
+ case ">":
+ return rpv == "false"
+ case ">=":
+ return true
+ }
+ case False:
+ switch rp.query.op {
+ case "=":
+ return rpv == "false"
+ case "!=":
+ return rpv != "false"
+ case "<":
+ return rpv == "true"
+ case "<=":
+ return true
+ }
+ }
+ return false
+}
+func parseArray(c *parseContext, i int, path string) (int, bool) {
+ var pmatch, vesc, ok, hit bool
+ var val string
+ var h int
+ var alog []int
+ var partidx int
+ var multires []byte
+ var queryIndexes []int
+ rp := parseArrayPath(path)
+ if !rp.arrch {
+ n, ok := parseUint(rp.part)
+ if !ok {
+ partidx = -1
+ } else {
+ partidx = int(n)
+ }
+ }
+ if !rp.more && rp.piped {
+ c.pipe = rp.pipe
+ c.piped = true
+ }
+
+ procQuery := func(qval Result) bool {
+ if rp.query.all {
+ if len(multires) == 0 {
+ multires = append(multires, '[')
+ }
+ }
+ var tmp parseContext
+ tmp.value = qval
+ fillIndex(c.json, &tmp)
+ parentIndex := tmp.value.Index
+ var res Result
+ if qval.Type == JSON {
+ res = qval.Get(rp.query.path)
+ } else {
+ if rp.query.path != "" {
+ return false
+ }
+ res = qval
+ }
+ if queryMatches(&rp, res) {
+ if rp.more {
+ left, right, ok := splitPossiblePipe(rp.path)
+ if ok {
+ rp.path = left
+ c.pipe = right
+ c.piped = true
+ }
+ res = qval.Get(rp.path)
+ } else {
+ res = qval
+ }
+ if rp.query.all {
+ raw := res.Raw
+ if len(raw) == 0 {
+ raw = res.String()
+ }
+ if raw != "" {
+ if len(multires) > 1 {
+ multires = append(multires, ',')
+ }
+ multires = append(multires, raw...)
+ queryIndexes = append(queryIndexes, res.Index+parentIndex)
+ }
+ } else {
+ c.value = res
+ return true
+ }
+ }
+ return false
+ }
+ for i < len(c.json)+1 {
+ if !rp.arrch {
+ pmatch = partidx == h
+ hit = pmatch && !rp.more
+ }
+ h++
+ if rp.alogok {
+ alog = append(alog, i)
+ }
+ for ; ; i++ {
+ var ch byte
+ if i > len(c.json) {
+ break
+ } else if i == len(c.json) {
+ ch = ']'
+ } else {
+ ch = c.json[i]
+ }
+ var num bool
+ switch ch {
+ default:
+ continue
+ case '"':
+ i++
+ i, val, vesc, ok = parseString(c.json, i)
+ if !ok {
+ return i, false
+ }
+ if rp.query.on {
+ var qval Result
+ if vesc {
+ qval.Str = unescape(val[1 : len(val)-1])
+ } else {
+ qval.Str = val[1 : len(val)-1]
+ }
+ qval.Raw = val
+ qval.Type = String
+ if procQuery(qval) {
+ return i, true
+ }
+ } else if hit {
+ if rp.alogok {
+ break
+ }
+ if vesc {
+ c.value.Str = unescape(val[1 : len(val)-1])
+ } else {
+ c.value.Str = val[1 : len(val)-1]
+ }
+ c.value.Raw = val
+ c.value.Type = String
+ return i, true
+ }
+ case '{':
+ if pmatch && !hit {
+ i, hit = parseObject(c, i+1, rp.path)
+ if hit {
+ if rp.alogok {
+ break
+ }
+ return i, true
+ }
+ } else {
+ i, val = parseSquash(c.json, i)
+ if rp.query.on {
+ if procQuery(Result{Raw: val, Type: JSON}) {
+ return i, true
+ }
+ } else if hit {
+ if rp.alogok {
+ break
+ }
+ c.value.Raw = val
+ c.value.Type = JSON
+ return i, true
+ }
+ }
+ case '[':
+ if pmatch && !hit {
+ i, hit = parseArray(c, i+1, rp.path)
+ if hit {
+ if rp.alogok {
+ break
+ }
+ return i, true
+ }
+ } else {
+ i, val = parseSquash(c.json, i)
+ if rp.query.on {
+ if procQuery(Result{Raw: val, Type: JSON}) {
+ return i, true
+ }
+ } else if hit {
+ if rp.alogok {
+ break
+ }
+ c.value.Raw = val
+ c.value.Type = JSON
+ return i, true
+ }
+ }
+ case 'n':
+ if i+1 < len(c.json) && c.json[i+1] != 'u' {
+ num = true
+ break
+ }
+ fallthrough
+ case 't', 'f':
+ vc := c.json[i]
+ i, val = parseLiteral(c.json, i)
+ if rp.query.on {
+ var qval Result
+ qval.Raw = val
+ switch vc {
+ case 't':
+ qval.Type = True
+ case 'f':
+ qval.Type = False
+ }
+ if procQuery(qval) {
+ return i, true
+ }
+ } else if hit {
+ if rp.alogok {
+ break
+ }
+ c.value.Raw = val
+ switch vc {
+ case 't':
+ c.value.Type = True
+ case 'f':
+ c.value.Type = False
+ }
+ return i, true
+ }
+ case '+', '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+ 'i', 'I', 'N':
+ num = true
+ case ']':
+ if rp.arrch && rp.part == "#" {
+ if rp.alogok {
+ left, right, ok := splitPossiblePipe(rp.alogkey)
+ if ok {
+ rp.alogkey = left
+ c.pipe = right
+ c.piped = true
+ }
+ var indexes = make([]int, 0, 64)
+ var jsons = make([]byte, 0, 64)
+ jsons = append(jsons, '[')
+ for j, k := 0, 0; j < len(alog); j++ {
+ idx := alog[j]
+ for idx < len(c.json) {
+ switch c.json[idx] {
+ case ' ', '\t', '\r', '\n':
+ idx++
+ continue
+ }
+ break
+ }
+ if idx < len(c.json) && c.json[idx] != ']' {
+ _, res, ok := parseAny(c.json, idx, true)
+ if ok {
+ res := res.Get(rp.alogkey)
+ if res.Exists() {
+ if k > 0 {
+ jsons = append(jsons, ',')
+ }
+ raw := res.Raw
+ if len(raw) == 0 {
+ raw = res.String()
+ }
+ jsons = append(jsons, []byte(raw)...)
+ indexes = append(indexes, res.Index)
+ k++
+ }
+ }
+ }
+ }
+ jsons = append(jsons, ']')
+ c.value.Type = JSON
+ c.value.Raw = string(jsons)
+ c.value.Indexes = indexes
+ return i + 1, true
+ }
+ if rp.alogok {
+ break
+ }
+
+ c.value.Type = Number
+ c.value.Num = float64(h - 1)
+ c.value.Raw = strconv.Itoa(h - 1)
+ c.calcd = true
+ return i + 1, true
+ }
+ if !c.value.Exists() {
+ if len(multires) > 0 {
+ c.value = Result{
+ Raw: string(append(multires, ']')),
+ Type: JSON,
+ Indexes: queryIndexes,
+ }
+ } else if rp.query.all {
+ c.value = Result{
+ Raw: "[]",
+ Type: JSON,
+ }
+ }
+ }
+ return i + 1, false
+ }
+ if num {
+ i, val = parseNumber(c.json, i)
+ if rp.query.on {
+ var qval Result
+ qval.Raw = val
+ qval.Type = Number
+ qval.Num, _ = strconv.ParseFloat(val, 64)
+ if procQuery(qval) {
+ return i, true
+ }
+ } else if hit {
+ if rp.alogok {
+ break
+ }
+ c.value.Raw = val
+ c.value.Type = Number
+ c.value.Num, _ = strconv.ParseFloat(val, 64)
+ return i, true
+ }
+ }
+ break
+ }
+ }
+ return i, false
+}
+
+func splitPossiblePipe(path string) (left, right string, ok bool) {
+ // take a quick peek for the pipe character. If found we'll split the piped
+ // part of the path into the c.pipe field and shorten the rp.
+ var possible bool
+ for i := 0; i < len(path); i++ {
+ if path[i] == '|' {
+ possible = true
+ break
+ }
+ }
+ if !possible {
+ return
+ }
+
+ if len(path) > 0 && path[0] == '{' {
+ squashed := squash(path[1:])
+ if len(squashed) < len(path)-1 {
+ squashed = path[:len(squashed)+1]
+ remain := path[len(squashed):]
+ if remain[0] == '|' {
+ return squashed, remain[1:], true
+ }
+ }
+ return
+ }
+
+ // split the left and right side of the path with the pipe character as
+ // the delimiter. This is a little tricky because we'll need to basically
+ // parse the entire path.
+ for i := 0; i < len(path); i++ {
+ if path[i] == '\\' {
+ i++
+ } else if path[i] == '.' {
+ if i == len(path)-1 {
+ return
+ }
+ if path[i+1] == '#' {
+ i += 2
+ if i == len(path) {
+ return
+ }
+ if path[i] == '[' || path[i] == '(' {
+ var start, end byte
+ if path[i] == '[' {
+ start, end = '[', ']'
+ } else {
+ start, end = '(', ')'
+ }
+ // inside selector, balance brackets
+ i++
+ depth := 1
+ for ; i < len(path); i++ {
+ if path[i] == '\\' {
+ i++
+ } else if path[i] == start {
+ depth++
+ } else if path[i] == end {
+ depth--
+ if depth == 0 {
+ break
+ }
+ } else if path[i] == '"' {
+ // inside selector string, balance quotes
+ i++
+ for ; i < len(path); i++ {
+ if path[i] == '\\' {
+ i++
+ } else if path[i] == '"' {
+ break
+ }
+ }
+ }
+ }
+ }
+ }
+ } else if path[i] == '|' {
+ return path[:i], path[i+1:], true
+ }
+ }
+ return
+}
+
+// ForEachLine iterates through lines of JSON as specified by the JSON Lines
+// format (http://jsonlines.org/).
+// Each line is returned as a GJSON Result.
+func ForEachLine(json string, iterator func(line Result) bool) {
+ var res Result
+ var i int
+ for {
+ i, res, _ = parseAny(json, i, true)
+ if !res.Exists() {
+ break
+ }
+ if !iterator(res) {
+ return
+ }
+ }
+}
+
+type subSelector struct {
+ name string
+ path string
+}
+
+// parseSubSelectors returns the subselectors belonging to a '[path1,path2]' or
+// '{"field1":path1,"field2":path2}' type subSelection. It's expected that the
+// first character in path is either '[' or '{', and has already been checked
+// prior to calling this function.
+func parseSubSelectors(path string) (sels []subSelector, out string, ok bool) {
+ modifier := 0
+ depth := 1
+ colon := 0
+ start := 1
+ i := 1
+ pushSel := func() {
+ var sel subSelector
+ if colon == 0 {
+ sel.path = path[start:i]
+ } else {
+ sel.name = path[start:colon]
+ sel.path = path[colon+1 : i]
+ }
+ sels = append(sels, sel)
+ colon = 0
+ modifier = 0
+ start = i + 1
+ }
+ for ; i < len(path); i++ {
+ switch path[i] {
+ case '\\':
+ i++
+ case '@':
+ if modifier == 0 && i > 0 && (path[i-1] == '.' || path[i-1] == '|') {
+ modifier = i
+ }
+ case ':':
+ if modifier == 0 && colon == 0 && depth == 1 {
+ colon = i
+ }
+ case ',':
+ if depth == 1 {
+ pushSel()
+ }
+ case '"':
+ i++
+ loop:
+ for ; i < len(path); i++ {
+ switch path[i] {
+ case '\\':
+ i++
+ case '"':
+ break loop
+ }
+ }
+ case '[', '(', '{':
+ depth++
+ case ']', ')', '}':
+ depth--
+ if depth == 0 {
+ pushSel()
+ path = path[i+1:]
+ return sels, path, true
+ }
+ }
+ }
+ return
+}
+
+// nameOfLast returns the name of the last component
+func nameOfLast(path string) string {
+ for i := len(path) - 1; i >= 0; i-- {
+ if path[i] == '|' || path[i] == '.' {
+ if i > 0 {
+ if path[i-1] == '\\' {
+ continue
+ }
+ }
+ return path[i+1:]
+ }
+ }
+ return path
+}
+
+func isSimpleName(component string) bool {
+ for i := 0; i < len(component); i++ {
+ if component[i] < ' ' {
+ return false
+ }
+ switch component[i] {
+ case '[', ']', '{', '}', '(', ')', '#', '|', '!':
+ return false
+ }
+ }
+ return true
+}
+
+func appendJSONString(dst []byte, s string) []byte {
+ for i := 0; i < len(s); i++ {
+ if s[i] < ' ' || s[i] == '\\' || s[i] == '"' || s[i] > 126 {
+ d, _ := json.Marshal(s)
+ return append(dst, string(d)...)
+ }
+ }
+ dst = append(dst, '"')
+ dst = append(dst, s...)
+ dst = append(dst, '"')
+ return dst
+}
+
+type parseContext struct {
+ json string
+ value Result
+ pipe string
+ piped bool
+ calcd bool
+ lines bool
+}
+
+// Get searches json for the specified path.
+// A path is in dot syntax, such as "name.last" or "age".
+// When the value is found it's returned immediately.
+//
+// A path is a series of keys separated by a dot.
+// A key may contain special wildcard characters '*' and '?'.
+// To access an array value use the index as the key.
+// To get the number of elements in an array or to access a child path, use
+// the '#' character.
+// The dot and wildcard character can be escaped with '\'.
+//
+// {
+// "name": {"first": "Tom", "last": "Anderson"},
+// "age":37,
+// "children": ["Sara","Alex","Jack"],
+// "friends": [
+// {"first": "James", "last": "Murphy"},
+// {"first": "Roger", "last": "Craig"}
+// ]
+// }
+// "name.last" >> "Anderson"
+// "age" >> 37
+// "children" >> ["Sara","Alex","Jack"]
+// "children.#" >> 3
+// "children.1" >> "Alex"
+// "child*.2" >> "Jack"
+// "c?ildren.0" >> "Sara"
+// "friends.#.first" >> ["James","Roger"]
+//
+// This function expects that the json is well-formed, and does not validate.
+// Invalid json will not panic, but it may return back unexpected results.
+// If you are consuming JSON from an unpredictable source then you may want to
+// use the Valid function first.
+func Get(json, path string) Result {
+ if len(path) > 1 {
+ if (path[0] == '@' && !DisableModifiers) || path[0] == '!' {
+ // possible modifier
+ var ok bool
+ var npath string
+ var rjson string
+ if path[0] == '@' && !DisableModifiers {
+ npath, rjson, ok = execModifier(json, path)
+ } else if path[0] == '!' {
+ npath, rjson, ok = execStatic(json, path)
+ }
+ if ok {
+ path = npath
+ if len(path) > 0 && (path[0] == '|' || path[0] == '.') {
+ res := Get(rjson, path[1:])
+ res.Index = 0
+ res.Indexes = nil
+ return res
+ }
+ return Parse(rjson)
+ }
+ }
+ if path[0] == '[' || path[0] == '{' {
+ // using a subselector path
+ kind := path[0]
+ var ok bool
+ var subs []subSelector
+ subs, path, ok = parseSubSelectors(path)
+ if ok {
+ if len(path) == 0 || (path[0] == '|' || path[0] == '.') {
+ var b []byte
+ b = append(b, kind)
+ var i int
+ for _, sub := range subs {
+ res := Get(json, sub.path)
+ if res.Exists() {
+ if i > 0 {
+ b = append(b, ',')
+ }
+ if kind == '{' {
+ if len(sub.name) > 0 {
+ if sub.name[0] == '"' && Valid(sub.name) {
+ b = append(b, sub.name...)
+ } else {
+ b = appendJSONString(b, sub.name)
+ }
+ } else {
+ last := nameOfLast(sub.path)
+ if isSimpleName(last) {
+ b = appendJSONString(b, last)
+ } else {
+ b = appendJSONString(b, "_")
+ }
+ }
+ b = append(b, ':')
+ }
+ var raw string
+ if len(res.Raw) == 0 {
+ raw = res.String()
+ if len(raw) == 0 {
+ raw = "null"
+ }
+ } else {
+ raw = res.Raw
+ }
+ b = append(b, raw...)
+ i++
+ }
+ }
+ b = append(b, kind+2)
+ var res Result
+ res.Raw = string(b)
+ res.Type = JSON
+ if len(path) > 0 {
+ res = res.Get(path[1:])
+ }
+ res.Index = 0
+ return res
+ }
+ }
+ }
+ }
+ var i int
+ var c = &parseContext{json: json}
+ if len(path) >= 2 && path[0] == '.' && path[1] == '.' {
+ c.lines = true
+ parseArray(c, 0, path[2:])
+ } else {
+ for ; i < len(c.json); i++ {
+ if c.json[i] == '{' {
+ i++
+ parseObject(c, i, path)
+ break
+ }
+ if c.json[i] == '[' {
+ i++
+ parseArray(c, i, path)
+ break
+ }
+ }
+ }
+ if c.piped {
+ res := c.value.Get(c.pipe)
+ res.Index = 0
+ return res
+ }
+ fillIndex(json, c)
+ return c.value
+}
+
+// GetBytes searches json for the specified path.
+// If working with bytes, this method preferred over Get(string(data), path)
+func GetBytes(json []byte, path string) Result {
+ return getBytes(json, path)
+}
+
+// runeit returns the rune from the the \uXXXX
+func runeit(json string) rune {
+ n, _ := strconv.ParseUint(json[:4], 16, 64)
+ return rune(n)
+}
+
+// unescape unescapes a string
+func unescape(json string) string {
+ var str = make([]byte, 0, len(json))
+ for i := 0; i < len(json); i++ {
+ switch {
+ default:
+ str = append(str, json[i])
+ case json[i] < ' ':
+ return string(str)
+ case json[i] == '\\':
+ i++
+ if i >= len(json) {
+ return string(str)
+ }
+ switch json[i] {
+ default:
+ return string(str)
+ case '\\':
+ str = append(str, '\\')
+ case '/':
+ str = append(str, '/')
+ case 'b':
+ str = append(str, '\b')
+ case 'f':
+ str = append(str, '\f')
+ case 'n':
+ str = append(str, '\n')
+ case 'r':
+ str = append(str, '\r')
+ case 't':
+ str = append(str, '\t')
+ case '"':
+ str = append(str, '"')
+ case 'u':
+ if i+5 > len(json) {
+ return string(str)
+ }
+ r := runeit(json[i+1:])
+ i += 5
+ if utf16.IsSurrogate(r) {
+ // need another code
+ if len(json[i:]) >= 6 && json[i] == '\\' &&
+ json[i+1] == 'u' {
+ // we expect it to be correct so just consume it
+ r = utf16.DecodeRune(r, runeit(json[i+2:]))
+ i += 6
+ }
+ }
+ // provide enough space to encode the largest utf8 possible
+ str = append(str, 0, 0, 0, 0, 0, 0, 0, 0)
+ n := utf8.EncodeRune(str[len(str)-8:], r)
+ str = str[:len(str)-8+n]
+ i-- // backtrack index by one
+ }
+ }
+ }
+ return string(str)
+}
+
+// Less return true if a token is less than another token.
+// The caseSensitive paramater is used when the tokens are Strings.
+// The order when comparing two different type is:
+//
+// Null < False < Number < String < True < JSON
+//
+func (t Result) Less(token Result, caseSensitive bool) bool {
+ if t.Type < token.Type {
+ return true
+ }
+ if t.Type > token.Type {
+ return false
+ }
+ if t.Type == String {
+ if caseSensitive {
+ return t.Str < token.Str
+ }
+ return stringLessInsensitive(t.Str, token.Str)
+ }
+ if t.Type == Number {
+ return t.Num < token.Num
+ }
+ return t.Raw < token.Raw
+}
+
+func stringLessInsensitive(a, b string) bool {
+ for i := 0; i < len(a) && i < len(b); i++ {
+ if a[i] >= 'A' && a[i] <= 'Z' {
+ if b[i] >= 'A' && b[i] <= 'Z' {
+ // both are uppercase, do nothing
+ if a[i] < b[i] {
+ return true
+ } else if a[i] > b[i] {
+ return false
+ }
+ } else {
+ // a is uppercase, convert a to lowercase
+ if a[i]+32 < b[i] {
+ return true
+ } else if a[i]+32 > b[i] {
+ return false
+ }
+ }
+ } else if b[i] >= 'A' && b[i] <= 'Z' {
+ // b is uppercase, convert b to lowercase
+ if a[i] < b[i]+32 {
+ return true
+ } else if a[i] > b[i]+32 {
+ return false
+ }
+ } else {
+ // neither are uppercase
+ if a[i] < b[i] {
+ return true
+ } else if a[i] > b[i] {
+ return false
+ }
+ }
+ }
+ return len(a) < len(b)
+}
+
+// parseAny parses the next value from a json string.
+// A Result is returned when the hit param is set.
+// The return values are (i int, res Result, ok bool)
+func parseAny(json string, i int, hit bool) (int, Result, bool) {
+ var res Result
+ var val string
+ for ; i < len(json); i++ {
+ if json[i] == '{' || json[i] == '[' {
+ i, val = parseSquash(json, i)
+ if hit {
+ res.Raw = val
+ res.Type = JSON
+ }
+ var tmp parseContext
+ tmp.value = res
+ fillIndex(json, &tmp)
+ return i, tmp.value, true
+ }
+ if json[i] <= ' ' {
+ continue
+ }
+ var num bool
+ switch json[i] {
+ case '"':
+ i++
+ var vesc bool
+ var ok bool
+ i, val, vesc, ok = parseString(json, i)
+ if !ok {
+ return i, res, false
+ }
+ if hit {
+ res.Type = String
+ res.Raw = val
+ if vesc {
+ res.Str = unescape(val[1 : len(val)-1])
+ } else {
+ res.Str = val[1 : len(val)-1]
+ }
+ }
+ return i, res, true
+ case 'n':
+ if i+1 < len(json) && json[i+1] != 'u' {
+ num = true
+ break
+ }
+ fallthrough
+ case 't', 'f':
+ vc := json[i]
+ i, val = parseLiteral(json, i)
+ if hit {
+ res.Raw = val
+ switch vc {
+ case 't':
+ res.Type = True
+ case 'f':
+ res.Type = False
+ }
+ return i, res, true
+ }
+ case '+', '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+ 'i', 'I', 'N':
+ num = true
+ }
+ if num {
+ i, val = parseNumber(json, i)
+ if hit {
+ res.Raw = val
+ res.Type = Number
+ res.Num, _ = strconv.ParseFloat(val, 64)
+ }
+ return i, res, true
+ }
+
+ }
+ return i, res, false
+}
+
+// GetMany searches json for the multiple paths.
+// The return value is a Result array where the number of items
+// will be equal to the number of input paths.
+func GetMany(json string, path ...string) []Result {
+ res := make([]Result, len(path))
+ for i, path := range path {
+ res[i] = Get(json, path)
+ }
+ return res
+}
+
+// GetManyBytes searches json for the multiple paths.
+// The return value is a Result array where the number of items
+// will be equal to the number of input paths.
+func GetManyBytes(json []byte, path ...string) []Result {
+ res := make([]Result, len(path))
+ for i, path := range path {
+ res[i] = GetBytes(json, path)
+ }
+ return res
+}
+
+func validpayload(data []byte, i int) (outi int, ok bool) {
+ for ; i < len(data); i++ {
+ switch data[i] {
+ default:
+ i, ok = validany(data, i)
+ if !ok {
+ return i, false
+ }
+ for ; i < len(data); i++ {
+ switch data[i] {
+ default:
+ return i, false
+ case ' ', '\t', '\n', '\r':
+ continue
+ }
+ }
+ return i, true
+ case ' ', '\t', '\n', '\r':
+ continue
+ }
+ }
+ return i, false
+}
+func validany(data []byte, i int) (outi int, ok bool) {
+ for ; i < len(data); i++ {
+ switch data[i] {
+ default:
+ return i, false
+ case ' ', '\t', '\n', '\r':
+ continue
+ case '{':
+ return validobject(data, i+1)
+ case '[':
+ return validarray(data, i+1)
+ case '"':
+ return validstring(data, i+1)
+ case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
+ return validnumber(data, i+1)
+ case 't':
+ return validtrue(data, i+1)
+ case 'f':
+ return validfalse(data, i+1)
+ case 'n':
+ return validnull(data, i+1)
+ }
+ }
+ return i, false
+}
+func validobject(data []byte, i int) (outi int, ok bool) {
+ for ; i < len(data); i++ {
+ switch data[i] {
+ default:
+ return i, false
+ case ' ', '\t', '\n', '\r':
+ continue
+ case '}':
+ return i + 1, true
+ case '"':
+ key:
+ if i, ok = validstring(data, i+1); !ok {
+ return i, false
+ }
+ if i, ok = validcolon(data, i); !ok {
+ return i, false
+ }
+ if i, ok = validany(data, i); !ok {
+ return i, false
+ }
+ if i, ok = validcomma(data, i, '}'); !ok {
+ return i, false
+ }
+ if data[i] == '}' {
+ return i + 1, true
+ }
+ i++
+ for ; i < len(data); i++ {
+ switch data[i] {
+ default:
+ return i, false
+ case ' ', '\t', '\n', '\r':
+ continue
+ case '"':
+ goto key
+ }
+ }
+ return i, false
+ }
+ }
+ return i, false
+}
+func validcolon(data []byte, i int) (outi int, ok bool) {
+ for ; i < len(data); i++ {
+ switch data[i] {
+ default:
+ return i, false
+ case ' ', '\t', '\n', '\r':
+ continue
+ case ':':
+ return i + 1, true
+ }
+ }
+ return i, false
+}
+func validcomma(data []byte, i int, end byte) (outi int, ok bool) {
+ for ; i < len(data); i++ {
+ switch data[i] {
+ default:
+ return i, false
+ case ' ', '\t', '\n', '\r':
+ continue
+ case ',':
+ return i, true
+ case end:
+ return i, true
+ }
+ }
+ return i, false
+}
+func validarray(data []byte, i int) (outi int, ok bool) {
+ for ; i < len(data); i++ {
+ switch data[i] {
+ default:
+ for ; i < len(data); i++ {
+ if i, ok = validany(data, i); !ok {
+ return i, false
+ }
+ if i, ok = validcomma(data, i, ']'); !ok {
+ return i, false
+ }
+ if data[i] == ']' {
+ return i + 1, true
+ }
+ }
+ case ' ', '\t', '\n', '\r':
+ continue
+ case ']':
+ return i + 1, true
+ }
+ }
+ return i, false
+}
+func validstring(data []byte, i int) (outi int, ok bool) {
+ for ; i < len(data); i++ {
+ if data[i] < ' ' {
+ return i, false
+ } else if data[i] == '\\' {
+ i++
+ if i == len(data) {
+ return i, false
+ }
+ switch data[i] {
+ default:
+ return i, false
+ case '"', '\\', '/', 'b', 'f', 'n', 'r', 't':
+ case 'u':
+ for j := 0; j < 4; j++ {
+ i++
+ if i >= len(data) {
+ return i, false
+ }
+ if !((data[i] >= '0' && data[i] <= '9') ||
+ (data[i] >= 'a' && data[i] <= 'f') ||
+ (data[i] >= 'A' && data[i] <= 'F')) {
+ return i, false
+ }
+ }
+ }
+ } else if data[i] == '"' {
+ return i + 1, true
+ }
+ }
+ return i, false
+}
+func validnumber(data []byte, i int) (outi int, ok bool) {
+ i--
+ // sign
+ if data[i] == '-' {
+ i++
+ if i == len(data) {
+ return i, false
+ }
+ if data[i] < '0' || data[i] > '9' {
+ return i, false
+ }
+ }
+ // int
+ if i == len(data) {
+ return i, false
+ }
+ if data[i] == '0' {
+ i++
+ } else {
+ for ; i < len(data); i++ {
+ if data[i] >= '0' && data[i] <= '9' {
+ continue
+ }
+ break
+ }
+ }
+ // frac
+ if i == len(data) {
+ return i, true
+ }
+ if data[i] == '.' {
+ i++
+ if i == len(data) {
+ return i, false
+ }
+ if data[i] < '0' || data[i] > '9' {
+ return i, false
+ }
+ i++
+ for ; i < len(data); i++ {
+ if data[i] >= '0' && data[i] <= '9' {
+ continue
+ }
+ break
+ }
+ }
+ // exp
+ if i == len(data) {
+ return i, true
+ }
+ if data[i] == 'e' || data[i] == 'E' {
+ i++
+ if i == len(data) {
+ return i, false
+ }
+ if data[i] == '+' || data[i] == '-' {
+ i++
+ }
+ if i == len(data) {
+ return i, false
+ }
+ if data[i] < '0' || data[i] > '9' {
+ return i, false
+ }
+ i++
+ for ; i < len(data); i++ {
+ if data[i] >= '0' && data[i] <= '9' {
+ continue
+ }
+ break
+ }
+ }
+ return i, true
+}
+
+func validtrue(data []byte, i int) (outi int, ok bool) {
+ if i+3 <= len(data) && data[i] == 'r' && data[i+1] == 'u' &&
+ data[i+2] == 'e' {
+ return i + 3, true
+ }
+ return i, false
+}
+func validfalse(data []byte, i int) (outi int, ok bool) {
+ if i+4 <= len(data) && data[i] == 'a' && data[i+1] == 'l' &&
+ data[i+2] == 's' && data[i+3] == 'e' {
+ return i + 4, true
+ }
+ return i, false
+}
+func validnull(data []byte, i int) (outi int, ok bool) {
+ if i+3 <= len(data) && data[i] == 'u' && data[i+1] == 'l' &&
+ data[i+2] == 'l' {
+ return i + 3, true
+ }
+ return i, false
+}
+
+// Valid returns true if the input is valid json.
+//
+// if !gjson.Valid(json) {
+// return errors.New("invalid json")
+// }
+// value := gjson.Get(json, "name.last")
+//
+func Valid(json string) bool {
+ _, ok := validpayload(stringBytes(json), 0)
+ return ok
+}
+
+// ValidBytes returns true if the input is valid json.
+//
+// if !gjson.Valid(json) {
+// return errors.New("invalid json")
+// }
+// value := gjson.Get(json, "name.last")
+//
+// If working with bytes, this method preferred over ValidBytes(string(data))
+//
+func ValidBytes(json []byte) bool {
+ _, ok := validpayload(json, 0)
+ return ok
+}
+
+func parseUint(s string) (n uint64, ok bool) {
+ var i int
+ if i == len(s) {
+ return 0, false
+ }
+ for ; i < len(s); i++ {
+ if s[i] >= '0' && s[i] <= '9' {
+ n = n*10 + uint64(s[i]-'0')
+ } else {
+ return 0, false
+ }
+ }
+ return n, true
+}
+
+func parseInt(s string) (n int64, ok bool) {
+ var i int
+ var sign bool
+ if len(s) > 0 && s[0] == '-' {
+ sign = true
+ i++
+ }
+ if i == len(s) {
+ return 0, false
+ }
+ for ; i < len(s); i++ {
+ if s[i] >= '0' && s[i] <= '9' {
+ n = n*10 + int64(s[i]-'0')
+ } else {
+ return 0, false
+ }
+ }
+ if sign {
+ return n * -1, true
+ }
+ return n, true
+}
+
+// safeInt validates a given JSON number
+// ensures it lies within the minimum and maximum representable JSON numbers
+func safeInt(f float64) (n int64, ok bool) {
+ // https://tc39.es/ecma262/#sec-number.min_safe_integer
+ // https://tc39.es/ecma262/#sec-number.max_safe_integer
+ if f < -9007199254740991 || f > 9007199254740991 {
+ return 0, false
+ }
+ return int64(f), true
+}
+
+// execStatic parses the path to find a static value.
+// The input expects that the path already starts with a '!'
+func execStatic(json, path string) (pathOut, res string, ok bool) {
+ name := path[1:]
+ if len(name) > 0 {
+ switch name[0] {
+ case '{', '[', '"', '+', '-', '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9':
+ _, res = parseSquash(name, 0)
+ pathOut = name[len(res):]
+ return pathOut, res, true
+ }
+ }
+ for i := 1; i < len(path); i++ {
+ if path[i] == '|' {
+ pathOut = path[i:]
+ name = path[1:i]
+ break
+ }
+ if path[i] == '.' {
+ pathOut = path[i:]
+ name = path[1:i]
+ break
+ }
+ }
+ switch strings.ToLower(name) {
+ case "true", "false", "null", "nan", "inf":
+ return pathOut, name, true
+ }
+ return pathOut, res, false
+}
+
+// execModifier parses the path to find a matching modifier function.
+// The input expects that the path already starts with a '@'
+func execModifier(json, path string) (pathOut, res string, ok bool) {
+ name := path[1:]
+ var hasArgs bool
+ for i := 1; i < len(path); i++ {
+ if path[i] == ':' {
+ pathOut = path[i+1:]
+ name = path[1:i]
+ hasArgs = len(pathOut) > 0
+ break
+ }
+ if path[i] == '|' {
+ pathOut = path[i:]
+ name = path[1:i]
+ break
+ }
+ if path[i] == '.' {
+ pathOut = path[i:]
+ name = path[1:i]
+ break
+ }
+ }
+ if fn, ok := modifiers[name]; ok {
+ var args string
+ if hasArgs {
+ var parsedArgs bool
+ switch pathOut[0] {
+ case '{', '[', '"':
+ res := Parse(pathOut)
+ if res.Exists() {
+ args = squash(pathOut)
+ pathOut = pathOut[len(args):]
+ parsedArgs = true
+ }
+ }
+ if !parsedArgs {
+ idx := strings.IndexByte(pathOut, '|')
+ if idx == -1 {
+ args = pathOut
+ pathOut = ""
+ } else {
+ args = pathOut[:idx]
+ pathOut = pathOut[idx:]
+ }
+ }
+ }
+ return pathOut, fn(json, args), true
+ }
+ return pathOut, res, false
+}
+
+// unwrap removes the '[]' or '{}' characters around json
+func unwrap(json string) string {
+ json = trim(json)
+ if len(json) >= 2 && (json[0] == '[' || json[0] == '{') {
+ json = json[1 : len(json)-1]
+ }
+ return json
+}
+
+// DisableModifiers will disable the modifier syntax
+var DisableModifiers = false
+
+var modifiers = map[string]func(json, arg string) string{
+ "pretty": modPretty,
+ "ugly": modUgly,
+ "reverse": modReverse,
+ "this": modThis,
+ "flatten": modFlatten,
+ "join": modJoin,
+ "valid": modValid,
+ "keys": modKeys,
+ "values": modValues,
+}
+
+// AddModifier binds a custom modifier command to the GJSON syntax.
+// This operation is not thread safe and should be executed prior to
+// using all other gjson function.
+func AddModifier(name string, fn func(json, arg string) string) {
+ modifiers[name] = fn
+}
+
+// ModifierExists returns true when the specified modifier exists.
+func ModifierExists(name string, fn func(json, arg string) string) bool {
+ _, ok := modifiers[name]
+ return ok
+}
+
+// cleanWS remove any non-whitespace from string
+func cleanWS(s string) string {
+ for i := 0; i < len(s); i++ {
+ switch s[i] {
+ case ' ', '\t', '\n', '\r':
+ continue
+ default:
+ var s2 []byte
+ for i := 0; i < len(s); i++ {
+ switch s[i] {
+ case ' ', '\t', '\n', '\r':
+ s2 = append(s2, s[i])
+ }
+ }
+ return string(s2)
+ }
+ }
+ return s
+}
+
+// @pretty modifier makes the json look nice.
+func modPretty(json, arg string) string {
+ if len(arg) > 0 {
+ opts := *pretty.DefaultOptions
+ Parse(arg).ForEach(func(key, value Result) bool {
+ switch key.String() {
+ case "sortKeys":
+ opts.SortKeys = value.Bool()
+ case "indent":
+ opts.Indent = cleanWS(value.String())
+ case "prefix":
+ opts.Prefix = cleanWS(value.String())
+ case "width":
+ opts.Width = int(value.Int())
+ }
+ return true
+ })
+ return bytesString(pretty.PrettyOptions(stringBytes(json), &opts))
+ }
+ return bytesString(pretty.Pretty(stringBytes(json)))
+}
+
+// @this returns the current element. Can be used to retrieve the root element.
+func modThis(json, arg string) string {
+ return json
+}
+
+// @ugly modifier removes all whitespace.
+func modUgly(json, arg string) string {
+ return bytesString(pretty.Ugly(stringBytes(json)))
+}
+
+// @reverse reverses array elements or root object members.
+func modReverse(json, arg string) string {
+ res := Parse(json)
+ if res.IsArray() {
+ var values []Result
+ res.ForEach(func(_, value Result) bool {
+ values = append(values, value)
+ return true
+ })
+ out := make([]byte, 0, len(json))
+ out = append(out, '[')
+ for i, j := len(values)-1, 0; i >= 0; i, j = i-1, j+1 {
+ if j > 0 {
+ out = append(out, ',')
+ }
+ out = append(out, values[i].Raw...)
+ }
+ out = append(out, ']')
+ return bytesString(out)
+ }
+ if res.IsObject() {
+ var keyValues []Result
+ res.ForEach(func(key, value Result) bool {
+ keyValues = append(keyValues, key, value)
+ return true
+ })
+ out := make([]byte, 0, len(json))
+ out = append(out, '{')
+ for i, j := len(keyValues)-2, 0; i >= 0; i, j = i-2, j+1 {
+ if j > 0 {
+ out = append(out, ',')
+ }
+ out = append(out, keyValues[i+0].Raw...)
+ out = append(out, ':')
+ out = append(out, keyValues[i+1].Raw...)
+ }
+ out = append(out, '}')
+ return bytesString(out)
+ }
+ return json
+}
+
+// @flatten an array with child arrays.
+// [1,[2],[3,4],[5,[6,7]]] -> [1,2,3,4,5,[6,7]]
+// The {"deep":true} arg can be provide for deep flattening.
+// [1,[2],[3,4],[5,[6,7]]] -> [1,2,3,4,5,6,7]
+// The original json is returned when the json is not an array.
+func modFlatten(json, arg string) string {
+ res := Parse(json)
+ if !res.IsArray() {
+ return json
+ }
+ var deep bool
+ if arg != "" {
+ Parse(arg).ForEach(func(key, value Result) bool {
+ if key.String() == "deep" {
+ deep = value.Bool()
+ }
+ return true
+ })
+ }
+ var out []byte
+ out = append(out, '[')
+ var idx int
+ res.ForEach(func(_, value Result) bool {
+ var raw string
+ if value.IsArray() {
+ if deep {
+ raw = unwrap(modFlatten(value.Raw, arg))
+ } else {
+ raw = unwrap(value.Raw)
+ }
+ } else {
+ raw = value.Raw
+ }
+ raw = strings.TrimSpace(raw)
+ if len(raw) > 0 {
+ if idx > 0 {
+ out = append(out, ',')
+ }
+ out = append(out, raw...)
+ idx++
+ }
+ return true
+ })
+ out = append(out, ']')
+ return bytesString(out)
+}
+
+// @keys extracts the keys from an object.
+// {"first":"Tom","last":"Smith"} -> ["first","last"]
+func modKeys(json, arg string) string {
+ v := Parse(json)
+ if !v.Exists() {
+ return "[]"
+ }
+ obj := v.IsObject()
+ var out strings.Builder
+ out.WriteByte('[')
+ var i int
+ v.ForEach(func(key, _ Result) bool {
+ if i > 0 {
+ out.WriteByte(',')
+ }
+ if obj {
+ out.WriteString(key.Raw)
+ } else {
+ out.WriteString("null")
+ }
+ i++
+ return true
+ })
+ out.WriteByte(']')
+ return out.String()
+}
+
+// @values extracts the values from an object.
+// {"first":"Tom","last":"Smith"} -> ["Tom","Smith"]
+func modValues(json, arg string) string {
+ v := Parse(json)
+ if !v.Exists() {
+ return "[]"
+ }
+ if v.IsArray() {
+ return json
+ }
+ var out strings.Builder
+ out.WriteByte('[')
+ var i int
+ v.ForEach(func(_, value Result) bool {
+ if i > 0 {
+ out.WriteByte(',')
+ }
+ out.WriteString(value.Raw)
+ i++
+ return true
+ })
+ out.WriteByte(']')
+ return out.String()
+}
+
+// @join multiple objects into a single object.
+// [{"first":"Tom"},{"last":"Smith"}] -> {"first","Tom","last":"Smith"}
+// The arg can be "true" to specify that duplicate keys should be preserved.
+// [{"first":"Tom","age":37},{"age":41}] -> {"first","Tom","age":37,"age":41}
+// Without preserved keys:
+// [{"first":"Tom","age":37},{"age":41}] -> {"first","Tom","age":41}
+// The original json is returned when the json is not an object.
+func modJoin(json, arg string) string {
+ res := Parse(json)
+ if !res.IsArray() {
+ return json
+ }
+ var preserve bool
+ if arg != "" {
+ Parse(arg).ForEach(func(key, value Result) bool {
+ if key.String() == "preserve" {
+ preserve = value.Bool()
+ }
+ return true
+ })
+ }
+ var out []byte
+ out = append(out, '{')
+ if preserve {
+ // Preserve duplicate keys.
+ var idx int
+ res.ForEach(func(_, value Result) bool {
+ if !value.IsObject() {
+ return true
+ }
+ if idx > 0 {
+ out = append(out, ',')
+ }
+ out = append(out, unwrap(value.Raw)...)
+ idx++
+ return true
+ })
+ } else {
+ // Deduplicate keys and generate an object with stable ordering.
+ var keys []Result
+ kvals := make(map[string]Result)
+ res.ForEach(func(_, value Result) bool {
+ if !value.IsObject() {
+ return true
+ }
+ value.ForEach(func(key, value Result) bool {
+ k := key.String()
+ if _, ok := kvals[k]; !ok {
+ keys = append(keys, key)
+ }
+ kvals[k] = value
+ return true
+ })
+ return true
+ })
+ for i := 0; i < len(keys); i++ {
+ if i > 0 {
+ out = append(out, ',')
+ }
+ out = append(out, keys[i].Raw...)
+ out = append(out, ':')
+ out = append(out, kvals[keys[i].String()].Raw...)
+ }
+ }
+ out = append(out, '}')
+ return bytesString(out)
+}
+
+// @valid ensures that the json is valid before moving on. An empty string is
+// returned when the json is not valid, otherwise it returns the original json.
+func modValid(json, arg string) string {
+ if !Valid(json) {
+ return ""
+ }
+ return json
+}
+
+// stringHeader instead of reflect.StringHeader
+type stringHeader struct {
+ data unsafe.Pointer
+ len int
+}
+
+// sliceHeader instead of reflect.SliceHeader
+type sliceHeader struct {
+ data unsafe.Pointer
+ len int
+ cap int
+}
+
+// getBytes casts the input json bytes to a string and safely returns the
+// results as uniquely allocated data. This operation is intended to minimize
+// copies and allocations for the large json string->[]byte.
+func getBytes(json []byte, path string) Result {
+ var result Result
+ if json != nil {
+ // unsafe cast to string
+ result = Get(*(*string)(unsafe.Pointer(&json)), path)
+ // safely get the string headers
+ rawhi := *(*stringHeader)(unsafe.Pointer(&result.Raw))
+ strhi := *(*stringHeader)(unsafe.Pointer(&result.Str))
+ // create byte slice headers
+ rawh := sliceHeader{data: rawhi.data, len: rawhi.len, cap: rawhi.len}
+ strh := sliceHeader{data: strhi.data, len: strhi.len, cap: rawhi.len}
+ if strh.data == nil {
+ // str is nil
+ if rawh.data == nil {
+ // raw is nil
+ result.Raw = ""
+ } else {
+ // raw has data, safely copy the slice header to a string
+ result.Raw = string(*(*[]byte)(unsafe.Pointer(&rawh)))
+ }
+ result.Str = ""
+ } else if rawh.data == nil {
+ // raw is nil
+ result.Raw = ""
+ // str has data, safely copy the slice header to a string
+ result.Str = string(*(*[]byte)(unsafe.Pointer(&strh)))
+ } else if uintptr(strh.data) >= uintptr(rawh.data) &&
+ uintptr(strh.data)+uintptr(strh.len) <=
+ uintptr(rawh.data)+uintptr(rawh.len) {
+ // Str is a substring of Raw.
+ start := uintptr(strh.data) - uintptr(rawh.data)
+ // safely copy the raw slice header
+ result.Raw = string(*(*[]byte)(unsafe.Pointer(&rawh)))
+ // substring the raw
+ result.Str = result.Raw[start : start+uintptr(strh.len)]
+ } else {
+ // safely copy both the raw and str slice headers to strings
+ result.Raw = string(*(*[]byte)(unsafe.Pointer(&rawh)))
+ result.Str = string(*(*[]byte)(unsafe.Pointer(&strh)))
+ }
+ }
+ return result
+}
+
+// fillIndex finds the position of Raw data and assigns it to the Index field
+// of the resulting value. If the position cannot be found then Index zero is
+// used instead.
+func fillIndex(json string, c *parseContext) {
+ if len(c.value.Raw) > 0 && !c.calcd {
+ jhdr := *(*stringHeader)(unsafe.Pointer(&json))
+ rhdr := *(*stringHeader)(unsafe.Pointer(&(c.value.Raw)))
+ c.value.Index = int(uintptr(rhdr.data) - uintptr(jhdr.data))
+ if c.value.Index < 0 || c.value.Index >= len(json) {
+ c.value.Index = 0
+ }
+ }
+}
+
+func stringBytes(s string) []byte {
+ return *(*[]byte)(unsafe.Pointer(&sliceHeader{
+ data: (*stringHeader)(unsafe.Pointer(&s)).data,
+ len: len(s),
+ cap: len(s),
+ }))
+}
+
+func bytesString(b []byte) string {
+ return *(*string)(unsafe.Pointer(&b))
+}
+
+func revSquash(json string) string {
+ // reverse squash
+ // expects that the tail character is a ']' or '}' or ')' or '"'
+ // squash the value, ignoring all nested arrays and objects.
+ i := len(json) - 1
+ var depth int
+ if json[i] != '"' {
+ depth++
+ }
+ if json[i] == '}' || json[i] == ']' || json[i] == ')' {
+ i--
+ }
+ for ; i >= 0; i-- {
+ switch json[i] {
+ case '"':
+ i--
+ for ; i >= 0; i-- {
+ if json[i] == '"' {
+ esc := 0
+ for i > 0 && json[i-1] == '\\' {
+ i--
+ esc++
+ }
+ if esc%2 == 1 {
+ continue
+ }
+ i += esc
+ break
+ }
+ }
+ if depth == 0 {
+ if i < 0 {
+ i = 0
+ }
+ return json[i:]
+ }
+ case '}', ']', ')':
+ depth++
+ case '{', '[', '(':
+ depth--
+ if depth == 0 {
+ return json[i:]
+ }
+ }
+ }
+ return json
+}
+
+func (t Result) Paths(json string) []string {
+ if t.Indexes == nil {
+ return nil
+ }
+ paths := make([]string, 0, len(t.Indexes))
+ t.ForEach(func(_, value Result) bool {
+ paths = append(paths, value.Path(json))
+ return true
+ })
+ if len(paths) != len(t.Indexes) {
+ return nil
+ }
+ return paths
+}
+
+// Path returns the original GJSON path for Result.
+// The json param must be the original JSON used when calling Get.
+func (t Result) Path(json string) string {
+ var path []byte
+ var comps []string // raw components
+ i := t.Index - 1
+ if t.Index+len(t.Raw) > len(json) {
+ // JSON cannot safely contain Result.
+ goto fail
+ }
+ if !strings.HasPrefix(json[t.Index:], t.Raw) {
+ // Result is not at the JSON index as exepcted.
+ goto fail
+ }
+ for ; i >= 0; i-- {
+ if json[i] <= ' ' {
+ continue
+ }
+ if json[i] == ':' {
+ // inside of object, get the key
+ for ; i >= 0; i-- {
+ if json[i] != '"' {
+ continue
+ }
+ break
+ }
+ raw := revSquash(json[:i+1])
+ i = i - len(raw)
+ comps = append(comps, raw)
+ // key gotten, now squash the rest
+ raw = revSquash(json[:i+1])
+ i = i - len(raw)
+ i++ // increment the index for next loop step
+ } else if json[i] == '{' {
+ // Encountered an open object. The original result was probably an
+ // object key.
+ goto fail
+ } else if json[i] == ',' || json[i] == '[' {
+ // inside of an array, count the position
+ var arrIdx int
+ if json[i] == ',' {
+ arrIdx++
+ i--
+ }
+ for ; i >= 0; i-- {
+ if json[i] == ':' {
+ // Encountered an unexpected colon. The original result was
+ // probably an object key.
+ goto fail
+ } else if json[i] == ',' {
+ arrIdx++
+ } else if json[i] == '[' {
+ comps = append(comps, strconv.Itoa(arrIdx))
+ break
+ } else if json[i] == ']' || json[i] == '}' || json[i] == '"' {
+ raw := revSquash(json[:i+1])
+ i = i - len(raw) + 1
+ }
+ }
+ }
+ }
+ if len(comps) == 0 {
+ if DisableModifiers {
+ goto fail
+ }
+ return "@this"
+ }
+ for i := len(comps) - 1; i >= 0; i-- {
+ rcomp := Parse(comps[i])
+ if !rcomp.Exists() {
+ goto fail
+ }
+ comp := escapeComp(rcomp.String())
+ path = append(path, '.')
+ path = append(path, comp...)
+ }
+ if len(path) > 0 {
+ path = path[1:]
+ }
+ return string(path)
+fail:
+ return ""
+}
+
+// isSafePathKeyChar returns true if the input character is safe for not
+// needing escaping.
+func isSafePathKeyChar(c byte) bool {
+ return c <= ' ' || c > '~' || c == '_' || c == '-' || c == ':' ||
+ (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
+ (c >= '0' && c <= '9')
+}
+
+// escapeComp escaped a path compontent, making it safe for generating a
+// path for later use.
+func escapeComp(comp string) string {
+ for i := 0; i < len(comp); i++ {
+ if !isSafePathKeyChar(comp[i]) {
+ ncomp := []byte(comp[:i])
+ for ; i < len(comp); i++ {
+ if !isSafePathKeyChar(comp[i]) {
+ ncomp = append(ncomp, '\\')
+ }
+ ncomp = append(ncomp, comp[i])
+ }
+ return string(ncomp)
+ }
+ }
+ return comp
+}
diff --git a/vendor/github.com/tidwall/gjson/logo.png b/vendor/github.com/tidwall/gjson/logo.png
new file mode 100644
index 0000000000000000000000000000000000000000..17a8bbe9d651e5d79cbd59a3645a152443440ad6
GIT binary patch
literal 15936
zcmdseRa9I})9xU_0znfrFi3EBcXtB8-Q8tyw?MEE+&u)>;O-g-!QF!n?wrm0ecyln
zi+`Pqb92@@b204MboZ|AuIj4isoIgsic)AO1SlX72u(&>{38ei4_w2jBEbT8g#0}>
zfj{`J5}K~64(6^NM$Tp+5mN_aGq8-Ek%ieuGb2+^ry(I^6HUo1oax$2(u&{u+covw&X$WR|Y3j=W4v9v&Wy9&C&b&K688JUl#1%&bhTtPDU41{Y6zS0f06
zy$kt&Mi4i1F>$tXbhUD@2fvJHWbEMPDnJHE`mZV2IVvdp*TD8J|6V9y$(SHUj!Z0!
z%uIH6FZ24RwTtUVv;Qr||Jd3^&C}70>7$v8gPXGnupj2+|LF{@-T(PPFAV`{c$J*3
zfK4&76?ZUkvoo`Il@S*p1OCHkYGukR$|buuylm3H
z<}7aJY~^ldD(UQC2mWW3d9D5jDR|g;*tw0_nHkJkjZ7HWS$Vh_jJR2u8Q6HtIgQO&
zSd4j$Sjqm~-}Jw&-oLaIxC6|@@jn9bnzJ+W7@M$}GZ-0hn=-JlaPctk7_+f5@NjXm
zahsTP8Jln!kud=xGQB9ye^aFY+yb=o6ILj1BiHWiOsHjwSN(6-S#&IQQX(?!~oRWla6k
zvj3m#lk>9cCv!wc6L6R*c~`T5NT-O!e%&k`LRLWCk5V)xyH@qD}#ba7*ern
zD^KwwL26x@_H9n^_xJEwj%`LF
z2_M&3l{$q7;~URr@StEw0z3u!#j3ZdE5%$S1w0iM^K2@_(3KW1T0xFBPH3#1nB2_f
zvBMJo!z+(+E_6G$0(R-JL<$OXHd^e=iug&_x%->yfVBZnFV3sIHbvZbAFwXaW7AoKsJ9QG
z>$+mQV_~P4&z8jBcSvrf!^$eZC-BSslJQJOm4Sir>t!xQeA0}meB*bk78Ll6JYotw
zFN_tm1+Ok3dz)A2wN_Xinfj#Ee?*6SsMzd_g;n4n@*KNU9c5|uUDdVb5;09jU=BA8
z7Ip^CUs>Q(aGI&ybtyH$7K|L2U(LdFslcD0RJYaHH%xx{O^TZmsdabO$yfZSTX|)r
z=-oR$toP)*A6N)!Ci&fYk#B|NMo}VC;kw_(;DJ=HK8MnXxCRjx
zm+Ele5%M~`%RXZFhRaja
zofW}k`izaw_BnN>(4NODngeC2ev#$a0Za@}FunO>tS9?CYq6*J5?4v-!SCmNEg}($
zsiIfoly7`UXRh?F`!)YcJa>S4yLz&L#;kL&6#~9Ni+?|0z}yLl+KUVh*{UN
zQL82>H7J0_BwzsZbE2-owg@HT^}ncXoZ;dh4@Ag(^&lQPK)^E=LOJs3m1N!Uj9F54V7Fy*9;Hf!S|
z2Vtfjj8{AZ6|UJ&-*wZR;=h8&K-WF?$U44F^rNysF*k#YfwM3ww(UIiz!K$Vl6g^;
zpZSmDI41>YtUMi>*8?muaBUxB;C6#-g+)6l$2v@q$uZDbJ6wES8#l*s2D<1?VzXJ$
zNn3AE*NNnAtmKenlM+7=mM9>ZV6zb+`lI$2@hpIeP1DdcS*Cvz5A~9(XQ5ee8Zy?1
zV$H!Cd=InD(OPcd;^t`I|2d8dNC%ws6z&4#gegDv>rH+oz!8Nz>NP}eD-R;bVvA0S
z5fJb?Ou@|fK(P*e**ICmfISbcs}Y$fZuREW@ZFBDNYmhXW7PA6V7+}jLHzU1y=p!n
z^hyRvQ|hIqYYoin6oO1NuT}m&C#3Y93YZnNA2Tz$8cr96%FkEFIxLhO1c8xa?YS>1
zYfbRvnrv%W@wwZlMg$41zv!F1Uthy~PJ0n;XM;%WG#G1Z(D~^_heW34*YaC}4fwaY
zQ_|5S2@Q6+L&grf$wpF2KXm2n`%skl-*5HsEQC3gz~7nJ8i!$efQc!-p`}FGdT|bp
zjc+K291ok>nAU4-{|as^#|^q`l>3ommlA=!Yk*~f4lIlN?BhIKO<)tnThs?ySx%(Q
zZ{BqMNZOg7QO=}w219Yn;z5ayrjclN12jx{->DqdA?>)@B*M55Z6*>9uOVG^g4+gB$$
z&!XEFAyF0vK@Hi45CHqg@K*IEb;v3e@Qc{QP%M+qSM^o+6flzV`6>&uh)6U4UOl>Y
zUko)LSj?`l;=xRs21!m{!rvOi>)at<`A6r#TDg{HRsnKvk6eoC&S-x#Mq{7vf>j;i
zpoU-IgJbwqGu*^D+T5dUG0a_I-j;HEIj*%e?#p&>hhO%ho;0*k&ga~7^2w21Ks!^N
zJ88HQ;e-ECm0XE^;oQz-+JymauGTlg2o=jQD#D!&eneT>3#Y{`@=}~!gct3epErdK
zU`nI?9GgnOgA%X>7A8>kKcDjv8zn1;!d*!BC&n1*8?K}4xYS*8J-uGJt;RUTVXir%{}C0=q5B02D<=xOiYxcn?4l1}Em4lV07IMeqs8t@G*e)leU
z^LZ&bK;v9xiiAiYvcgAIY^
z{hsN<54t}2vf2`*A~p<)503a+JOop=cS87$R%0Y9b}n%u{HMx2QvUVcnksc$0lfh|
zO+0575+Z)~?&@C8M99dsa?f$2%sd?hq|Ds&;G=9fK537ECE{4uO>1(q_^&|Vlh_Gr>&p4j#CTe1bR2DJ_0}1+G9&6IH~WZ{A=YBXE4q6-nx9bn^kCGD
zKq`a|i1oH?5f(Dp2PUamK}6jL3(BY6_{%!xtDA#drfkJ=#M6{`HRjVF)bpUQq&Ef6
zyRCSNEr>MF%a_m1u9p-Py~pK8D7c5rSo^`&g9y&-@)_~;#h*R~7VEJ@5*>Y+Ig5{*
z{KaPMCB3%XAcWYoc^46OK;ZSTx9HGO-}GxhBWm@2u4qc+2r6b_aBFo$7yfX_H3CEQ
zaAx(~OTHSE^w9jPe|Db0^FFGfRAv|V-o14(YFFLKu2^KV)OYV$MilR}0%8L8mXrX#
z?aXNsv{y&t%MTik%-A};(yQA&Eexy&Tel+t@?5=F>qE*mRdi^0cko1yYtB`K{ocK2
ze?^g1EeKeXFLrFjvhUiy$_GM26OFkX+qLLsXfuf_
zAiE6m$DGN>RDMk}<35n$|sHc(gYzBw5(l8USpk56G_tt5v
zT2RPk>)0{R5nwf2>%09ZBb^t1O4UtbrXz%J=bQ7Aj>{^+T`g!YD&6-HAA&h~?oH{F
z-*(;OvA=)%wE6M!TY|;d-~Kce;ebbI&U$_a!QI&6cp@;QC-Ynh;FOeB9wl}vAGWi_
zI6Eb)y%&;;oN5BIUcqEK(H~zuZ*l#_kGGu+l9nrvvTET;x{?m&Pz
z)6(6l?`Nf+N{at87srvs@R$3YNC|1B5vn8BpnndfCUEtywUobq0}Eh3Y)W$a((OMt
zeVTMUi_J2y7^X9|!b=N>O53xrkSYtG=HIjP+ixUv0p0}H|0JbRs^%hA!Jwk}>L&MM
z80l=$8*p?p5nqzB2flUC+qS5co0cA{{~DgUCuuOfxzg5oVle|X6R|&z9HyjTBz7=W
z6(hQ3!ou1{BT@o3I#0`zwh{7Z9D2aZ8IS0|LDbPB~{a9
zxp|-)J|}zIePx$CI@kZ{&VL_`9mP8HDU)6(_8QG5JF(05;fr7V+K5bA1Etfxgh#5W>6P@@ucg&Jzly%#@3VwSKV{@&j#^M(
zTlz^^ZmfJ%6rHQ3%yEH?9(L!Qb(!Do<{dt5FB1GvxNV4LI{Pjr0R!MUrMb5A4pX>C
zAxvpRy)idQ1E-@e{fUAX=xnu;V!H}&V4CM$%=yv*v=$M;MOYIcj@A-jG
z?Rpip=$Wr@_3CPVC#tvr@>g2)Q4aUQ5cATrcEjnW2##{myh=>MLI$B&y6jSWY!swkxM01Od*SEg
zL*Mh~ni#4$)U3y+i&vQhK|9qf!@Ie%77J-pfjx;IqN%|*VX(lO%{8>t0l{p^gB)j@
zJH57Z00N>gy2Swd*!!iFW0?|!a>O(rOZL2g&I>ppw~Od1Z5(JPKd=Q&^ICR7OvUvu
z?=;QVzQ(dwYT=aA*Bg?3&P}yAThCa2|K}GvR-m-L*_!MseF=o;M
zOc|!hnA_@||7VYZk>zZ=UNBMA*Vtu^yo#aiaXg2+Bh3A_
z*k(u*3VX`)Fpa0tfiD<{pqWjZHrb&h8UI8iP-1;S@Ctq-P$n^!{&NzMp(LvzzPbW5
z&{drM`nf{0E^A*AS;QZ4;qFHOENld#)$;q_vGmq_=O^r}ovg!Le`|uzGHczAnUBcG
z`*F2&g&n(N8{#Biba+rq`+AT}7E##C*+mWAHcl~e8IF*BlD}ptBDDp7inFHgCu%CG
zMQGj9<9umYwTdv9IK}7?I-Az9B4JJeXGNp&Y~9dg6EMByhM;=CJgzMOHPo|HyPwEF
z>AJ~_8b(2SFF>9)iwy@AzPGmoydb?M{G9dKy6!c@N}i|Lt*7q!;Msy>FWlp16n&Oo
zmA=5&{-W||a^yg79H=mpEMh=;B08fpy9ZhoVvt6ohvYk&9Dko*huy|_Vcj-#n-^%Y
zs(?&;92eWq(+`)_??I^-a?v+g0KQKt*?l$Eba3dO7`iLIHz8VPfP?g+cWvw%=+?0$
zw8JC0o-q5rI(C{(+>M|Yd?#NqbO%~Z8MLGynQ3(_s2no9^BqZSUb>Vsq3+-&Z~pLd
z_+I&t*zl@gEawwB70Gx!2LBP^FYe$`QL1{2+{*4>GM~87Lx9~C-tG~*?hRhhc=M|v
zKz`3aEk0yz8Txxs?~Urdp+R0uG5?!T)2G;O-?IC#fm9y}er2kwt<)7;#|LG5_jh)$
z2Sc<@EHgtod#3K*7;KqZ%_)YTiJL+t8o!4XIkwUN@t`E$Yq7=AK*!U9H?3HzBPCK4
z1;{FwV^;P{uD18>%3tX3j%6R_MIMv&@f1V4k%w(DWcZccnI;9GVC^$jwAX_dysW1j
zM`z~{y%DsP60N1h*GBx4LRqvFn|B3AG`4>4XHx@(`6tg$H8rQaVQ_b9%`q`{{4}r2
z=OP;`SSJVDA#p82i#aqb_VL+eJ|9?gaG4go0A~hZ1+MA=FDhbXUeMCtCDcTTP6}
zxtZStJ{EiC|G-Fk6MeJpZ%|$9Rn@xfF(WyQBgyfy#vHNweKWz*P#EpEYl?H6KHpMe
zvf?*tGh4Og7>Gv?^om*Qpu)Eyho@?PDF~@Ea^wN^&DqhE;aD3KU>Xh(01Gsi_yYOZ*mM@2DpdkOw<+vQpws53fo{
z&wajB`u(vzs_9!4?h&i8?CuR2u+G84+26IV*Kn`^r>fu|-veN(1Zn=_`3YN(XcZ|e1tk=THcWJbl
zsYeS(c=;b95uXNv-?n*7v=S{~uMPFRje+fM2G~eIo<0k{7KhLSksr739qkp}2P;MF
z#RHd6+;5fK#zzu#)US{5c4HuGKPuG*;1FXZM{@sop4IH+(rfX}ZIm^whc{X<>-WUx=Qlw6^^~L>&_wbjA%NM-BO-
ziWfJ(=D?Q^MhL3
zhf&VlDz1)-0Zchw2k$O-icKDM^}Uif#Kk9m;R`tpuwOp5cG?~QR}6ZxbSN_q>1prP
zakr4;NOzZ;Y^{A;uGpF=CV3`sPEq~4a=}w;)_$M_5ewbN6EZm-FnM6t)+yo$1Xzo8
zIpW+8HNz7
zlkMVkuwUHCF6C}Aw-E@>xDL3Tfbn_4oq*Rv>wJw&{jvDbvdHt}yMJ0Gb!csez+k{>
zteQ9MH2^!E*)-B03O|-kOhidM>4!7jddvni6e+3Rhgmz{jFUl94}&j}0ME)Fp%mZ0
zXlE;DA$P!z`Ey7={LOdHkNp(zqOd+a5rWUY-&`B1w6#jF;9ooo#D?cdNf9r=4ZwBl
zOS1FBam;Twsy90oaUIT{CrE+w=xr2`$no9-7C=scPgFEzAOBOZ<*$GeQ77bZwMSg@@7fXHj)VSZO3m{PYxnm7QPW=ydOs
z{#chl`}vB`$gV*CX!a!p0D-WAVE#D;v=)%6LUt~fUM3C-2r&%X-h~3n92m=ymRYwXeipL(xBw46A4m}b
zz`ipJfSi^h{{;9`Am@=3^@?4(vH)Plzr`-h3~f>NWL@{d&CLaZiG|xLcAC$!-`noB
z4&_SEZ1pq&)UusTnZ1RoHFypZcN}#Eq#vv|MOIILF6sZa{{;$X363&PR_E3MC1@C^
zx;^*2YnYQiXAqu1qRWO2EB%sab?nau7YG4niID=(CE2JAH3TMJ{gmd4t!{42oMXA5
z=pHOdBnf^{06X{BZ;N29axO0saaETG~y-q@bv})p+406EHxk$8IMo93knK5R6iV?^+?4JEa=@BB{Wr;7$09%)WWpwdSJpc&gy?Xb#y=!13d4
znM6rJyf+X%lZo?o%SI9DF_A11@m+d`!3G!<29W9k_{MPczg;h)nTL@kmCpN_655)+
zV4#=PKa9~L!Z2&Ah&=5fCU1*LOJ_x$W27L$LOfiib%hP1*Z~zUp#+jQq7DbI-U%rP
zk^