/proc/self/cwd/runtime/runtime.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 | | // Interfaces for runtime concepts. |
16 | | |
17 | | #ifndef THIRD_PARTY_CEL_CPP_RUNTIME_RUNTIME_H_ |
18 | | #define THIRD_PARTY_CEL_CPP_RUNTIME_RUNTIME_H_ |
19 | | |
20 | | #include <cstdint> |
21 | | #include <memory> |
22 | | #include <utility> |
23 | | #include <vector> |
24 | | |
25 | | #include "absl/base/attributes.h" |
26 | | #include "absl/base/nullability.h" |
27 | | #include "absl/functional/any_invocable.h" |
28 | | #include "absl/status/status.h" |
29 | | #include "absl/status/statusor.h" |
30 | | #include "base/ast.h" |
31 | | #include "base/type_provider.h" |
32 | | #include "common/native_type.h" |
33 | | #include "common/value.h" |
34 | | #include "runtime/activation_interface.h" |
35 | | #include "runtime/runtime_issue.h" |
36 | | #include "google/protobuf/arena.h" |
37 | | #include "google/protobuf/descriptor.h" |
38 | | #include "google/protobuf/message.h" |
39 | | |
40 | | namespace cel { |
41 | | |
42 | | namespace runtime_internal { |
43 | | class RuntimeFriendAccess; |
44 | | } // namespace runtime_internal |
45 | | |
46 | | class EmbedderContext; |
47 | | |
48 | | // Options for the Program::Evaluate call. |
49 | | struct EvaluateOptions { |
50 | | // Optional message factory to use for the duration of the Evaluate call. |
51 | | // If unset, a default message factory will be provided by the runtime. |
52 | | google::protobuf::MessageFactory* absl_nullable message_factory = nullptr; |
53 | | |
54 | | // Optional embedder context to use for the duration of the Evaluate call. |
55 | | // This is used to access custom data in extension functions. |
56 | | // This is only propagated to functions that are marked as context sensitive. |
57 | | const EmbedderContext* absl_nullable embedder_context = nullptr; |
58 | | }; |
59 | | |
60 | | // Representation of an evaluable CEL expression. |
61 | | // |
62 | | // See Runtime below for creating new programs. |
63 | | class Program { |
64 | | public: |
65 | 0 | virtual ~Program() = default; |
66 | | |
67 | | // Evaluate the program. |
68 | | // |
69 | | // Non-recoverable errors (i.e. outside of CEL's notion of an error) are |
70 | | // returned as a non-ok absl::Status. These are propagated immediately and do |
71 | | // not participate in CEL's notion of error handling. |
72 | | // |
73 | | // CEL errors are represented as result with an Ok status and a held |
74 | | // cel::ErrorValue result. |
75 | | // |
76 | | // Activation manages instances of variables available in the cel expression's |
77 | | // environment. |
78 | | // |
79 | | // Notes on lifetimes: |
80 | | // |
81 | | // The provided arena will be used as necessary to allocate complex values |
82 | | // and must outlive any returned value. Values created by the program may |
83 | | // depend on internal state in the runtime. In particular protobuf messages |
84 | | // may depend on the descriptor pool and message factory managed by the |
85 | | // runtime or program. |
86 | | // |
87 | | // Programs implicitly keep shared state in the runtime object alive so it |
88 | | // is sufficient to ensure that any cel::Value result is destroyed before the |
89 | | // cel::Program that created it. |
90 | | // |
91 | | // For consistency, users should use the same arena to create values placed in |
92 | | // the activation for calls to Program::Evaluate. |
93 | | absl::StatusOr<Value> Evaluate( |
94 | | google::protobuf::Arena* absl_nonnull arena ABSL_ATTRIBUTE_LIFETIME_BOUND, |
95 | | const ActivationInterface& activation, |
96 | 0 | const EvaluateOptions& options = {}) const ABSL_ATTRIBUTE_LIFETIME_BOUND { |
97 | 0 | return EvaluateImpl(activation, arena, options); |
98 | 0 | } |
99 | | |
100 | | ABSL_DEPRECATED("Use the EvaluateOptions overload instead.") |
101 | | absl::StatusOr<Value> Evaluate( |
102 | | google::protobuf::Arena* absl_nonnull arena ABSL_ATTRIBUTE_LIFETIME_BOUND, |
103 | | google::protobuf::MessageFactory* absl_nullable message_factory |
104 | | ABSL_ATTRIBUTE_LIFETIME_BOUND, |
105 | | const ActivationInterface& activation) const |
106 | 0 | ABSL_ATTRIBUTE_LIFETIME_BOUND { |
107 | 0 | return EvaluateImpl(activation, arena, {message_factory}); |
108 | 0 | } |
109 | | |
110 | | virtual const TypeProvider& GetTypeProvider() const = 0; |
111 | | |
112 | | protected: |
113 | | virtual absl::StatusOr<Value> EvaluateImpl( |
114 | | const ActivationInterface& activation, |
115 | | google::protobuf::Arena* absl_nonnull arena ABSL_ATTRIBUTE_LIFETIME_BOUND, |
116 | | const EvaluateOptions& options) const ABSL_ATTRIBUTE_LIFETIME_BOUND = 0; |
117 | | }; |
118 | | |
119 | | // Representation for a traceable CEL expression. |
120 | | // |
121 | | // Implementations provide an additional Trace method that evaluates the |
122 | | // expression and invokes a callback allowing callers to inspect intermediate |
123 | | // state during evaluation. |
124 | | class TraceableProgram : public Program { |
125 | | public: |
126 | | // EvaluationListener may be provided to an EvaluateWithCallback call to |
127 | | // inspect intermediate values during evaluation. |
128 | | // |
129 | | // The callback is called on after every program step that corresponds |
130 | | // to an AST expression node. The value provided is the top of the value |
131 | | // stack, corresponding to the result of evaluating the given sub expression. |
132 | | // |
133 | | // A returning a non-ok status stops evaluation and forwards the error. |
134 | | using EvaluationListener = absl::AnyInvocable<absl::Status( |
135 | | int64_t expr_id, const Value&, const google::protobuf::DescriptorPool* absl_nonnull, |
136 | | google::protobuf::MessageFactory* absl_nonnull, google::protobuf::Arena* absl_nonnull)>; |
137 | | |
138 | | using Program::Evaluate; |
139 | | |
140 | | // Evaluate the Program plan with a Listener. |
141 | | // |
142 | | // The given callback will be invoked after evaluating any program step |
143 | | // that corresponds to an AST node in the planned CEL expression. |
144 | | // |
145 | | // If the callback returns a non-ok status, evaluation stops and the Status |
146 | | // is forwarded as the result of the EvaluateWithCallback call. |
147 | | absl::StatusOr<Value> Trace( |
148 | | google::protobuf::Arena* absl_nonnull arena ABSL_ATTRIBUTE_LIFETIME_BOUND, |
149 | | const ActivationInterface& activation, |
150 | | EvaluationListener evaluation_listener, |
151 | 0 | const EvaluateOptions& options = {}) const ABSL_ATTRIBUTE_LIFETIME_BOUND { |
152 | 0 | return TraceImpl(activation, std::move(evaluation_listener), arena, |
153 | 0 | options); |
154 | 0 | } |
155 | | |
156 | | ABSL_DEPRECATED("Use the EvaluateOptions overload instead.") |
157 | | absl::StatusOr<Value> Trace( |
158 | | google::protobuf::Arena* absl_nonnull arena ABSL_ATTRIBUTE_LIFETIME_BOUND, |
159 | | google::protobuf::MessageFactory* absl_nullable message_factory |
160 | | ABSL_ATTRIBUTE_LIFETIME_BOUND, |
161 | | const ActivationInterface& activation, |
162 | | EvaluationListener evaluation_listener) const |
163 | 0 | ABSL_ATTRIBUTE_LIFETIME_BOUND { |
164 | 0 | return TraceImpl(activation, std::move(evaluation_listener), arena, |
165 | 0 | {message_factory}); |
166 | 0 | } |
167 | | |
168 | | protected: |
169 | | absl::StatusOr<Value> EvaluateImpl(const ActivationInterface& activation, |
170 | | google::protobuf::Arena* absl_nonnull arena |
171 | | ABSL_ATTRIBUTE_LIFETIME_BOUND, |
172 | | const EvaluateOptions& options) const |
173 | 0 | ABSL_ATTRIBUTE_LIFETIME_BOUND override { |
174 | 0 | return TraceImpl(activation, nullptr, arena, options); |
175 | 0 | } |
176 | | |
177 | | virtual absl::StatusOr<Value> TraceImpl( |
178 | | const ActivationInterface& activation, |
179 | | EvaluationListener evaluation_listener, |
180 | | google::protobuf::Arena* absl_nonnull arena ABSL_ATTRIBUTE_LIFETIME_BOUND, |
181 | | const EvaluateOptions& options) const ABSL_ATTRIBUTE_LIFETIME_BOUND = 0; |
182 | | }; |
183 | | |
184 | | // Interface for a CEL runtime. |
185 | | // |
186 | | // Manages the state necessary to generate Programs. |
187 | | // |
188 | | // Runtime instances should be created from a RuntimeBuilder rather than |
189 | | // instantiated directly. |
190 | | // |
191 | | // Implementations provided by CEL will be thread-compatible, but write |
192 | | // operations on the underlying environment (TypeRegistry, FunctionRegistry) or |
193 | | // on the implementation via down casting must be synchronized by the caller and |
194 | | // may invalidate any Programs created from the Runtime. |
195 | | class Runtime { |
196 | | public: |
197 | | struct CreateProgramOptions { |
198 | | // Optional output for collecting issues encountered while planning. |
199 | | // If non-null, vector is cleared and encountered issues are added. |
200 | | std::vector<RuntimeIssue>* issues = nullptr; |
201 | | }; |
202 | | |
203 | 0 | virtual ~Runtime() = default; |
204 | | |
205 | | absl::StatusOr<std::unique_ptr<Program>> CreateProgram( |
206 | 0 | std::unique_ptr<cel::Ast> ast) const { |
207 | 0 | return CreateProgram(std::move(ast), CreateProgramOptions{}); |
208 | 0 | } |
209 | | |
210 | | virtual absl::StatusOr<std::unique_ptr<Program>> CreateProgram( |
211 | | std::unique_ptr<cel::Ast> ast, |
212 | | const CreateProgramOptions& options) const = 0; |
213 | | |
214 | | absl::StatusOr<std::unique_ptr<TraceableProgram>> CreateTraceableProgram( |
215 | 0 | std::unique_ptr<cel::Ast> ast) const { |
216 | 0 | return CreateTraceableProgram(std::move(ast), CreateProgramOptions{}); |
217 | 0 | } |
218 | | |
219 | | virtual absl::StatusOr<std::unique_ptr<TraceableProgram>> |
220 | | CreateTraceableProgram(std::unique_ptr<cel::Ast> ast, |
221 | | const CreateProgramOptions& options) const = 0; |
222 | | |
223 | | virtual const TypeProvider& GetTypeProvider() const = 0; |
224 | | |
225 | | virtual const google::protobuf::DescriptorPool* absl_nonnull GetDescriptorPool() |
226 | | const = 0; |
227 | | |
228 | | virtual google::protobuf::MessageFactory* absl_nonnull GetMessageFactory() const = 0; |
229 | | |
230 | | private: |
231 | | friend class runtime_internal::RuntimeFriendAccess; |
232 | | |
233 | | virtual NativeTypeId GetNativeTypeId() const = 0; |
234 | | }; |
235 | | |
236 | | } // namespace cel |
237 | | |
238 | | #endif // THIRD_PARTY_CEL_CPP_RUNTIME_RUNTIME_H_ |