Coverage Report

Created: 2026-05-27 07:00

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
  // The arena will be used to as necessary to allocate values and must outlive
80
  // the returned value, as must this program.
81
  //
82
  //  For consistency, users should use the same arena to create values
83
  //  in the activation and for Program evaluation.
84
  absl::StatusOr<Value> Evaluate(
85
      google::protobuf::Arena* absl_nonnull arena ABSL_ATTRIBUTE_LIFETIME_BOUND,
86
      const ActivationInterface& activation,
87
0
      const EvaluateOptions& options = {}) const ABSL_ATTRIBUTE_LIFETIME_BOUND {
88
0
    return EvaluateImpl(activation, arena, options);
89
0
  }
90
91
  ABSL_DEPRECATED("Use the EvaluateOptions overload instead.")
92
  absl::StatusOr<Value> Evaluate(
93
      google::protobuf::Arena* absl_nonnull arena ABSL_ATTRIBUTE_LIFETIME_BOUND,
94
      google::protobuf::MessageFactory* absl_nullable message_factory
95
          ABSL_ATTRIBUTE_LIFETIME_BOUND,
96
      const ActivationInterface& activation) const
97
0
      ABSL_ATTRIBUTE_LIFETIME_BOUND {
98
0
    return EvaluateImpl(activation, arena, {message_factory});
99
0
  }
100
101
  virtual const TypeProvider& GetTypeProvider() const = 0;
102
103
 protected:
104
  virtual absl::StatusOr<Value> EvaluateImpl(
105
      const ActivationInterface& activation,
106
      google::protobuf::Arena* absl_nonnull arena ABSL_ATTRIBUTE_LIFETIME_BOUND,
107
      const EvaluateOptions& options) const ABSL_ATTRIBUTE_LIFETIME_BOUND = 0;
108
};
109
110
// Representation for a traceable CEL expression.
111
//
112
// Implementations provide an additional Trace method that evaluates the
113
// expression and invokes a callback allowing callers to inspect intermediate
114
// state during evaluation.
115
class TraceableProgram : public Program {
116
 public:
117
  // EvaluationListener may be provided to an EvaluateWithCallback call to
118
  // inspect intermediate values during evaluation.
119
  //
120
  // The callback is called on after every program step that corresponds
121
  // to an AST expression node. The value provided is the top of the value
122
  // stack, corresponding to the result of evaluating the given sub expression.
123
  //
124
  // A returning a non-ok status stops evaluation and forwards the error.
125
  using EvaluationListener = absl::AnyInvocable<absl::Status(
126
      int64_t expr_id, const Value&, const google::protobuf::DescriptorPool* absl_nonnull,
127
      google::protobuf::MessageFactory* absl_nonnull, google::protobuf::Arena* absl_nonnull)>;
128
129
  using Program::Evaluate;
130
131
  // Evaluate the Program plan with a Listener.
132
  //
133
  // The given callback will be invoked after evaluating any program step
134
  // that corresponds to an AST node in the planned CEL expression.
135
  //
136
  // If the callback returns a non-ok status, evaluation stops and the Status
137
  // is forwarded as the result of the EvaluateWithCallback call.
138
  absl::StatusOr<Value> Trace(
139
      google::protobuf::Arena* absl_nonnull arena ABSL_ATTRIBUTE_LIFETIME_BOUND,
140
      const ActivationInterface& activation,
141
      EvaluationListener evaluation_listener,
142
0
      const EvaluateOptions& options = {}) const ABSL_ATTRIBUTE_LIFETIME_BOUND {
143
0
    return TraceImpl(activation, std::move(evaluation_listener), arena,
144
0
                     options);
145
0
  }
146
147
  ABSL_DEPRECATED("Use the EvaluateOptions overload instead.")
148
  absl::StatusOr<Value> Trace(
149
      google::protobuf::Arena* absl_nonnull arena ABSL_ATTRIBUTE_LIFETIME_BOUND,
150
      google::protobuf::MessageFactory* absl_nullable message_factory
151
          ABSL_ATTRIBUTE_LIFETIME_BOUND,
152
      const ActivationInterface& activation,
153
      EvaluationListener evaluation_listener) const
154
0
      ABSL_ATTRIBUTE_LIFETIME_BOUND {
155
0
    return TraceImpl(activation, std::move(evaluation_listener), arena,
156
0
                     {message_factory});
157
0
  }
158
159
 protected:
160
  absl::StatusOr<Value> EvaluateImpl(const ActivationInterface& activation,
161
                                     google::protobuf::Arena* absl_nonnull arena
162
                                         ABSL_ATTRIBUTE_LIFETIME_BOUND,
163
                                     const EvaluateOptions& options) const
164
0
      ABSL_ATTRIBUTE_LIFETIME_BOUND override {
165
0
    return TraceImpl(activation, nullptr, arena, options);
166
0
  }
167
168
  virtual absl::StatusOr<Value> TraceImpl(
169
      const ActivationInterface& activation,
170
      EvaluationListener evaluation_listener,
171
      google::protobuf::Arena* absl_nonnull arena ABSL_ATTRIBUTE_LIFETIME_BOUND,
172
      const EvaluateOptions& options) const ABSL_ATTRIBUTE_LIFETIME_BOUND = 0;
173
};
174
175
// Interface for a CEL runtime.
176
//
177
// Manages the state necessary to generate Programs.
178
//
179
// Runtime instances should be created from a RuntimeBuilder rather than
180
// instantiated directly.
181
//
182
// Implementations provided by CEL will be thread-compatible, but write
183
// operations on the underlying environment (TypeRegistry, FunctionRegistry) or
184
// on the implementation via down casting must be synchronized by the caller and
185
// may invalidate any Programs created from the Runtime.
186
class Runtime {
187
 public:
188
  struct CreateProgramOptions {
189
    // Optional output for collecting issues encountered while planning.
190
    // If non-null, vector is cleared and encountered issues are added.
191
    std::vector<RuntimeIssue>* issues = nullptr;
192
  };
193
194
0
  virtual ~Runtime() = default;
195
196
  absl::StatusOr<std::unique_ptr<Program>> CreateProgram(
197
0
      std::unique_ptr<cel::Ast> ast) const {
198
0
    return CreateProgram(std::move(ast), CreateProgramOptions{});
199
0
  }
200
201
  virtual absl::StatusOr<std::unique_ptr<Program>> CreateProgram(
202
      std::unique_ptr<cel::Ast> ast,
203
      const CreateProgramOptions& options) const = 0;
204
205
  absl::StatusOr<std::unique_ptr<TraceableProgram>> CreateTraceableProgram(
206
0
      std::unique_ptr<cel::Ast> ast) const {
207
0
    return CreateTraceableProgram(std::move(ast), CreateProgramOptions{});
208
0
  }
209
210
  virtual absl::StatusOr<std::unique_ptr<TraceableProgram>>
211
  CreateTraceableProgram(std::unique_ptr<cel::Ast> ast,
212
                         const CreateProgramOptions& options) const = 0;
213
214
  virtual const TypeProvider& GetTypeProvider() const = 0;
215
216
  virtual const google::protobuf::DescriptorPool* absl_nonnull GetDescriptorPool()
217
      const = 0;
218
219
  virtual google::protobuf::MessageFactory* absl_nonnull GetMessageFactory() const = 0;
220
221
 private:
222
  friend class runtime_internal::RuntimeFriendAccess;
223
224
  virtual NativeTypeId GetNativeTypeId() const = 0;
225
};
226
227
}  // namespace cel
228
229
#endif  // THIRD_PARTY_CEL_CPP_RUNTIME_RUNTIME_H_