/proc/self/cwd/runtime/function_registry.h
Line | Count | Source |
1 | | // Copyright 2023 Google LLC |
2 | | // |
3 | | // Licensed under the Apache License, Version 2.0 (the "License"); |
4 | | // you may not use this file except in compliance with the License. |
5 | | // You may obtain a copy of the License at |
6 | | // |
7 | | // https://www.apache.org/licenses/LICENSE-2.0 |
8 | | // |
9 | | // Unless required by applicable law or agreed to in writing, software |
10 | | // distributed under the License is distributed on an "AS IS" BASIS, |
11 | | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 | | // See the License for the specific language governing permissions and |
13 | | // limitations under the License. |
14 | | |
15 | | #ifndef THIRD_PARTY_CEL_CPP_RUNTIME_FUNCTION_REGISTRY_H_ |
16 | | #define THIRD_PARTY_CEL_CPP_RUNTIME_FUNCTION_REGISTRY_H_ |
17 | | |
18 | | #include <cstddef> |
19 | | #include <memory> |
20 | | #include <string> |
21 | | #include <utility> |
22 | | #include <vector> |
23 | | |
24 | | #include "absl/container/flat_hash_map.h" |
25 | | #include "absl/container/node_hash_map.h" |
26 | | #include "absl/status/status.h" |
27 | | #include "absl/strings/string_view.h" |
28 | | #include "absl/types/span.h" |
29 | | #include "common/function_descriptor.h" |
30 | | #include "common/kind.h" |
31 | | #include "runtime/function.h" |
32 | | #include "runtime/function_overload_reference.h" |
33 | | #include "runtime/function_provider.h" |
34 | | |
35 | | namespace cel { |
36 | | |
37 | | // FunctionRegistry manages binding builtin or custom CEL functions to |
38 | | // implementations. |
39 | | // |
40 | | // The registry is consulted during program planning to tie overload candidates |
41 | | // to the CEL function in the AST getting planned. |
42 | | // |
43 | | // The registry takes ownership of the cel::Function objects -- the registry |
44 | | // must outlive any program planned using it. |
45 | | // |
46 | | // This class is move-only. |
47 | | class FunctionRegistry { |
48 | | public: |
49 | | // Represents a single overload for a lazily provided function. |
50 | | struct LazyOverload { |
51 | | const cel::FunctionDescriptor& descriptor; |
52 | | const cel::runtime_internal::FunctionProvider& provider; |
53 | | }; |
54 | | |
55 | 14.5k | FunctionRegistry() = default; |
56 | | |
57 | | // Move-only |
58 | | FunctionRegistry(FunctionRegistry&&) = default; |
59 | | FunctionRegistry& operator=(FunctionRegistry&&) = default; |
60 | | |
61 | | // Register a function implementation for the given descriptor. |
62 | | // Function registration should be performed prior to CelExpression creation. |
63 | | absl::Status Register(const cel::FunctionDescriptor& descriptor, |
64 | | std::unique_ptr<cel::Function> implementation); |
65 | | |
66 | | // Register a lazily provided function. |
67 | | // Internally, the registry binds a FunctionProvider that provides an overload |
68 | | // at evaluation time by resolving against the overloads provided by an |
69 | | // implementation of cel::ActivationInterface. |
70 | | absl::Status RegisterLazyFunction(const cel::FunctionDescriptor& descriptor); |
71 | | |
72 | | // Find subset of cel::Function implementations that match overload conditions |
73 | | // As types may not be available during expression compilation, |
74 | | // further narrowing of this subset will happen at evaluation stage. |
75 | | // |
76 | | // name - the name of CEL function (as distinct from overload ID); |
77 | | // receiver_style - indicates whether function has receiver style; |
78 | | // types - argument types. If type is not known during compilation, |
79 | | // cel::Kind::kAny should be passed. |
80 | | // |
81 | | // Results refer to underlying registry entries by reference. Results are |
82 | | // invalid after the registry is deleted. |
83 | | std::vector<cel::FunctionOverloadReference> FindStaticOverloads( |
84 | | absl::string_view name, bool receiver_style, |
85 | | absl::Span<const cel::Kind> types) const; |
86 | | |
87 | | std::vector<cel::FunctionOverloadReference> FindStaticOverloadsByArity( |
88 | | absl::string_view name, bool receiver_style, size_t arity) const; |
89 | | |
90 | | // Find subset of cel::Function providers that match overload conditions. |
91 | | // As types may not be available during expression compilation, |
92 | | // further narrowing of this subset will happen at evaluation stage. |
93 | | // |
94 | | // name - the name of CEL function (as distinct from overload ID); |
95 | | // receiver_style - indicates whether function has receiver style; |
96 | | // types - argument types. If type is not known during compilation, |
97 | | // cel::Kind::kAny should be passed. |
98 | | // |
99 | | // Results refer to underlying registry entries by reference. Results are |
100 | | // invalid after the registry is deleted. |
101 | | std::vector<LazyOverload> FindLazyOverloads( |
102 | | absl::string_view name, bool receiver_style, |
103 | | absl::Span<const cel::Kind> types) const; |
104 | | |
105 | | std::vector<LazyOverload> FindLazyOverloadsByArity(absl::string_view name, |
106 | | bool receiver_style, |
107 | | size_t arity) const; |
108 | | |
109 | | // Retrieve list of registered function descriptors. This includes both |
110 | | // static and lazy functions. |
111 | | absl::node_hash_map<std::string, std::vector<const cel::FunctionDescriptor*>> |
112 | | ListFunctions() const; |
113 | | |
114 | | private: |
115 | | struct StaticFunctionEntry { |
116 | | StaticFunctionEntry(const cel::FunctionDescriptor& descriptor, |
117 | | std::unique_ptr<cel::Function> impl) |
118 | 2.55M | : descriptor(std::make_unique<cel::FunctionDescriptor>(descriptor)), |
119 | 2.55M | implementation(std::move(impl)) {} |
120 | | |
121 | | // Extra indirection needed to preserve pointer stability for the |
122 | | // descriptors. |
123 | | std::unique_ptr<cel::FunctionDescriptor> descriptor; |
124 | | std::unique_ptr<cel::Function> implementation; |
125 | | }; |
126 | | |
127 | | struct LazyFunctionEntry { |
128 | | LazyFunctionEntry( |
129 | | const cel::FunctionDescriptor& descriptor, |
130 | | std::unique_ptr<cel::runtime_internal::FunctionProvider> provider) |
131 | 0 | : descriptor(std::make_unique<cel::FunctionDescriptor>(descriptor)), |
132 | 0 | function_provider(std::move(provider)) {} |
133 | | |
134 | | // Extra indirection needed to preserve pointer stability for the |
135 | | // descriptors. |
136 | | std::unique_ptr<cel::FunctionDescriptor> descriptor; |
137 | | std::unique_ptr<cel::runtime_internal::FunctionProvider> function_provider; |
138 | | }; |
139 | | |
140 | | struct RegistryEntry { |
141 | | std::vector<StaticFunctionEntry> static_overloads; |
142 | | std::vector<LazyFunctionEntry> lazy_overloads; |
143 | | }; |
144 | | |
145 | | // Returns whether the descriptor is registered either as a lazy function or |
146 | | // as a static function. |
147 | | bool DescriptorRegistered(const cel::FunctionDescriptor& descriptor) const; |
148 | | |
149 | | // Returns true if after adding this function, the rule "a non-strict |
150 | | // function should have only a single overload" will be preserved. |
151 | | bool ValidateNonStrictOverload( |
152 | | const cel::FunctionDescriptor& descriptor) const; |
153 | | |
154 | | // indexed by function name (not type checker overload id). |
155 | | absl::flat_hash_map<std::string, RegistryEntry> functions_; |
156 | | }; |
157 | | |
158 | | } // namespace cel |
159 | | |
160 | | #endif // THIRD_PARTY_CEL_CPP_RUNTIME_FUNCTION_REGISTRY_H_ |