Coverage Report

Created: 2026-09-14 06:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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_