Coverage Report

Created: 2026-07-11 06:47

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/proc/self/cwd/common/ast/expr_proto.cc
Line
Count
Source
1
// Copyright 2024 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
#include "common/ast/expr_proto.h"
16
17
#include <algorithm>
18
#include <cstddef>
19
#include <cstdint>
20
#include <stack>
21
#include <vector>
22
23
#include "cel/expr/syntax.pb.h"
24
#include "google/protobuf/struct.pb.h"
25
#include "absl/base/attributes.h"
26
#include "absl/base/nullability.h"
27
#include "absl/functional/overload.h"
28
#include "absl/status/status.h"
29
#include "absl/strings/str_cat.h"
30
#include "absl/types/variant.h"
31
#include "common/ast/constant_proto.h"
32
#include "common/constant.h"
33
#include "common/expr.h"
34
#include "internal/status_macros.h"
35
36
namespace cel::ast_internal {
37
38
namespace {
39
40
using ExprProto = cel::expr::Expr;
41
using ConstantProto = cel::expr::Constant;
42
using StructExprProto = cel::expr::Expr::CreateStruct;
43
44
class ExprToProtoState final {
45
 private:
46
  struct Frame final {
47
    const Expr* absl_nonnull expr;
48
    cel::expr::Expr* absl_nonnull proto;
49
  };
50
51
 public:
52
  absl::Status ExprToProto(const Expr& expr,
53
12.4k
                           cel::expr::Expr* absl_nonnull proto) {
54
12.4k
    Push(expr, proto);
55
12.4k
    Frame frame;
56
3.14M
    while (Pop(frame)) {
57
3.13M
      CEL_RETURN_IF_ERROR(ExprToProtoImpl(*frame.expr, frame.proto));
58
3.13M
    }
59
12.4k
    return absl::OkStatus();
60
12.4k
  }
61
62
 private:
63
  absl::Status ExprToProtoImpl(const Expr& expr,
64
3.13M
                               cel::expr::Expr* absl_nonnull proto) {
65
3.13M
    return absl::visit(
66
3.13M
        absl::Overload(
67
3.13M
            [&expr, proto](const UnspecifiedExpr&) -> absl::Status {
68
0
              proto->Clear();
69
0
              proto->set_id(expr.id());
70
0
              return absl::OkStatus();
71
0
            },
72
3.13M
            [this, &expr, proto](const Constant& const_expr) -> absl::Status {
73
422k
              return ConstExprToProto(expr, const_expr, proto);
74
422k
            },
75
3.13M
            [this, &expr, proto](const IdentExpr& ident_expr) -> absl::Status {
76
1.24M
              return IdentExprToProto(expr, ident_expr, proto);
77
1.24M
            },
78
3.13M
            [this, &expr,
79
3.13M
             proto](const SelectExpr& select_expr) -> absl::Status {
80
14.8k
              return SelectExprToProto(expr, select_expr, proto);
81
14.8k
            },
82
3.13M
            [this, &expr, proto](const CallExpr& call_expr) -> absl::Status {
83
1.40M
              return CallExprToProto(expr, call_expr, proto);
84
1.40M
            },
85
3.13M
            [this, &expr, proto](const ListExpr& list_expr) -> absl::Status {
86
24.5k
              return ListExprToProto(expr, list_expr, proto);
87
24.5k
            },
88
3.13M
            [this, &expr,
89
3.13M
             proto](const StructExpr& struct_expr) -> absl::Status {
90
2.41k
              return StructExprToProto(expr, struct_expr, proto);
91
2.41k
            },
92
3.13M
            [this, &expr, proto](const MapExpr& map_expr) -> absl::Status {
93
8.21k
              return MapExprToProto(expr, map_expr, proto);
94
8.21k
            },
95
3.13M
            [this, &expr, proto](
96
3.13M
                const ComprehensionExpr& comprehension_expr) -> absl::Status {
97
5.44k
              return ComprehensionExprToProto(expr, comprehension_expr, proto);
98
5.44k
            }),
99
3.13M
        expr.kind());
100
3.13M
  }
101
102
  absl::Status ConstExprToProto(const Expr& expr, const Constant& const_expr,
103
422k
                                ExprProto* absl_nonnull proto) {
104
422k
    proto->Clear();
105
422k
    proto->set_id(expr.id());
106
422k
    return ConstantToProto(const_expr, proto->mutable_const_expr());
107
422k
  }
108
109
  absl::Status IdentExprToProto(const Expr& expr, const IdentExpr& ident_expr,
110
1.24M
                                ExprProto* absl_nonnull proto) {
111
1.24M
    proto->Clear();
112
1.24M
    auto* ident_proto = proto->mutable_ident_expr();
113
1.24M
    proto->set_id(expr.id());
114
1.24M
    ident_proto->set_name(ident_expr.name());
115
1.24M
    return absl::OkStatus();
116
1.24M
  }
117
118
  absl::Status SelectExprToProto(const Expr& expr,
119
                                 const SelectExpr& select_expr,
120
14.8k
                                 ExprProto* absl_nonnull proto) {
121
14.8k
    proto->Clear();
122
14.8k
    auto* select_proto = proto->mutable_select_expr();
123
14.8k
    proto->set_id(expr.id());
124
14.8k
    if (select_expr.has_operand()) {
125
14.8k
      Push(select_expr.operand(), select_proto->mutable_operand());
126
14.8k
    }
127
14.8k
    select_proto->set_field(select_expr.field());
128
14.8k
    select_proto->set_test_only(select_expr.test_only());
129
14.8k
    return absl::OkStatus();
130
14.8k
  }
131
132
  absl::Status CallExprToProto(const Expr& expr, const CallExpr& call_expr,
133
1.40M
                               ExprProto* absl_nonnull proto) {
134
1.40M
    proto->Clear();
135
1.40M
    auto* call_proto = proto->mutable_call_expr();
136
1.40M
    proto->set_id(expr.id());
137
1.40M
    if (call_expr.has_target()) {
138
3.09k
      Push(call_expr.target(), call_proto->mutable_target());
139
3.09k
    }
140
1.40M
    call_proto->set_function(call_expr.function());
141
1.40M
    if (!call_expr.args().empty()) {
142
1.40M
      call_proto->mutable_args()->Reserve(
143
1.40M
          static_cast<int>(call_expr.args().size()));
144
2.70M
      for (const auto& argument : call_expr.args()) {
145
2.70M
        Push(argument, call_proto->add_args());
146
2.70M
      }
147
1.40M
    }
148
1.40M
    return absl::OkStatus();
149
1.40M
  }
150
151
  absl::Status ListExprToProto(const Expr& expr, const ListExpr& list_expr,
152
24.5k
                               ExprProto* absl_nonnull proto) {
153
24.5k
    proto->Clear();
154
24.5k
    auto* list_proto = proto->mutable_list_expr();
155
24.5k
    proto->set_id(expr.id());
156
24.5k
    if (!list_expr.elements().empty()) {
157
17.1k
      list_proto->mutable_elements()->Reserve(
158
17.1k
          static_cast<int>(list_expr.elements().size()));
159
95.7k
      for (size_t i = 0; i < list_expr.elements().size(); ++i) {
160
78.5k
        const auto& element_expr = list_expr.elements()[i];
161
78.5k
        auto* element_proto = list_proto->add_elements();
162
78.5k
        if (element_expr.has_expr()) {
163
78.5k
          Push(element_expr.expr(), element_proto);
164
78.5k
        }
165
78.5k
        if (element_expr.optional()) {
166
0
          list_proto->add_optional_indices(static_cast<int32_t>(i));
167
0
        }
168
78.5k
      }
169
17.1k
    }
170
24.5k
    return absl::OkStatus();
171
24.5k
  }
172
173
  absl::Status StructExprToProto(const Expr& expr,
174
                                 const StructExpr& struct_expr,
175
2.41k
                                 ExprProto* absl_nonnull proto) {
176
2.41k
    proto->Clear();
177
2.41k
    auto* struct_proto = proto->mutable_struct_expr();
178
2.41k
    proto->set_id(expr.id());
179
2.41k
    struct_proto->set_message_name(struct_expr.name());
180
2.41k
    if (!struct_expr.fields().empty()) {
181
177
      struct_proto->mutable_entries()->Reserve(
182
177
          static_cast<int>(struct_expr.fields().size()));
183
4.69k
      for (const auto& field_expr : struct_expr.fields()) {
184
4.69k
        auto* field_proto = struct_proto->add_entries();
185
4.69k
        field_proto->set_id(field_expr.id());
186
4.69k
        field_proto->set_field_key(field_expr.name());
187
4.69k
        if (field_expr.has_value()) {
188
4.69k
          Push(field_expr.value(), field_proto->mutable_value());
189
4.69k
        }
190
4.69k
        if (field_expr.optional()) {
191
0
          field_proto->set_optional_entry(true);
192
0
        }
193
4.69k
      }
194
177
    }
195
2.41k
    return absl::OkStatus();
196
2.41k
  }
197
198
  absl::Status MapExprToProto(const Expr& expr, const MapExpr& map_expr,
199
8.21k
                              ExprProto* absl_nonnull proto) {
200
8.21k
    proto->Clear();
201
8.21k
    auto* map_proto = proto->mutable_struct_expr();
202
8.21k
    proto->set_id(expr.id());
203
8.21k
    if (!map_expr.entries().empty()) {
204
3.55k
      map_proto->mutable_entries()->Reserve(
205
3.55k
          static_cast<int>(map_expr.entries().size()));
206
143k
      for (const auto& entry_expr : map_expr.entries()) {
207
143k
        auto* entry_proto = map_proto->add_entries();
208
143k
        entry_proto->set_id(entry_expr.id());
209
143k
        if (entry_expr.has_key()) {
210
143k
          Push(entry_expr.key(), entry_proto->mutable_map_key());
211
143k
        }
212
143k
        if (entry_expr.has_value()) {
213
143k
          Push(entry_expr.value(), entry_proto->mutable_value());
214
143k
        }
215
143k
        if (entry_expr.optional()) {
216
0
          entry_proto->set_optional_entry(true);
217
0
        }
218
143k
      }
219
3.55k
    }
220
8.21k
    return absl::OkStatus();
221
8.21k
  }
222
223
  absl::Status ComprehensionExprToProto(
224
      const Expr& expr, const ComprehensionExpr& comprehension_expr,
225
5.44k
      ExprProto* absl_nonnull proto) {
226
5.44k
    proto->Clear();
227
5.44k
    auto* comprehension_proto = proto->mutable_comprehension_expr();
228
5.44k
    proto->set_id(expr.id());
229
5.44k
    comprehension_proto->set_iter_var(comprehension_expr.iter_var());
230
5.44k
    comprehension_proto->set_iter_var2(comprehension_expr.iter_var2());
231
5.44k
    if (comprehension_expr.has_iter_range()) {
232
5.44k
      Push(comprehension_expr.iter_range(),
233
5.44k
           comprehension_proto->mutable_iter_range());
234
5.44k
    }
235
5.44k
    comprehension_proto->set_accu_var(comprehension_expr.accu_var());
236
5.44k
    if (comprehension_expr.has_accu_init()) {
237
5.44k
      Push(comprehension_expr.accu_init(),
238
5.44k
           comprehension_proto->mutable_accu_init());
239
5.44k
    }
240
5.44k
    if (comprehension_expr.has_loop_condition()) {
241
5.44k
      Push(comprehension_expr.loop_condition(),
242
5.44k
           comprehension_proto->mutable_loop_condition());
243
5.44k
    }
244
5.44k
    if (comprehension_expr.has_loop_step()) {
245
5.44k
      Push(comprehension_expr.loop_step(),
246
5.44k
           comprehension_proto->mutable_loop_step());
247
5.44k
    }
248
5.44k
    if (comprehension_expr.has_result()) {
249
5.44k
      Push(comprehension_expr.result(), comprehension_proto->mutable_result());
250
5.44k
    }
251
5.44k
    return absl::OkStatus();
252
5.44k
  }
253
254
3.13M
  void Push(const Expr& expr, ExprProto* absl_nonnull proto) {
255
3.13M
    frames_.push(Frame{&expr, proto});
256
3.13M
  }
257
258
3.14M
  bool Pop(Frame& frame) {
259
3.14M
    if (frames_.empty()) {
260
12.4k
      return false;
261
12.4k
    }
262
3.13M
    frame = frames_.top();
263
3.13M
    frames_.pop();
264
3.13M
    return true;
265
3.14M
  }
266
267
  std::stack<Frame, std::vector<Frame>> frames_;
268
};
269
270
class ExprFromProtoState final {
271
 private:
272
  struct Frame final {
273
    const ExprProto* absl_nonnull proto;
274
    Expr* absl_nonnull expr;
275
  };
276
277
 public:
278
10.7k
  absl::Status ExprFromProto(const ExprProto& proto, Expr& expr) {
279
10.7k
    Push(proto, expr);
280
10.7k
    Frame frame;
281
361k
    while (Pop(frame)) {
282
350k
      CEL_RETURN_IF_ERROR(ExprFromProtoImpl(*frame.proto, *frame.expr));
283
350k
    }
284
10.7k
    return absl::OkStatus();
285
10.7k
  }
286
287
 private:
288
350k
  absl::Status ExprFromProtoImpl(const ExprProto& proto, Expr& expr) {
289
350k
    switch (proto.expr_kind_case()) {
290
0
      case ExprProto::EXPR_KIND_NOT_SET:
291
0
        expr.Clear();
292
0
        expr.set_id(proto.id());
293
0
        return absl::OkStatus();
294
125k
      case ExprProto::kConstExpr:
295
125k
        return ConstExprFromProto(proto, proto.const_expr(), expr);
296
60.5k
      case ExprProto::kIdentExpr:
297
60.5k
        return IdentExprFromProto(proto, proto.ident_expr(), expr);
298
11.7k
      case ExprProto::kSelectExpr:
299
11.7k
        return SelectExprFromProto(proto, proto.select_expr(), expr);
300
120k
      case ExprProto::kCallExpr:
301
120k
        return CallExprFromProto(proto, proto.call_expr(), expr);
302
20.2k
      case ExprProto::kListExpr:
303
20.2k
        return ListExprFromProto(proto, proto.list_expr(), expr);
304
7.93k
      case ExprProto::kStructExpr:
305
7.93k
        if (proto.struct_expr().message_name().empty()) {
306
6.03k
          return MapExprFromProto(proto, proto.struct_expr(), expr);
307
6.03k
        }
308
1.90k
        return StructExprFromProto(proto, proto.struct_expr(), expr);
309
4.52k
      case ExprProto::kComprehensionExpr:
310
4.52k
        return ComprehensionExprFromProto(proto, proto.comprehension_expr(),
311
4.52k
                                          expr);
312
0
      default:
313
0
        return absl::InvalidArgumentError(
314
0
            absl::StrCat("unexpected ExprKindCase: ",
315
0
                         static_cast<int>(proto.expr_kind_case())));
316
350k
    }
317
350k
  }
318
319
  absl::Status ConstExprFromProto(const ExprProto& proto,
320
                                  const ConstantProto& const_proto,
321
125k
                                  Expr& expr) {
322
125k
    expr.Clear();
323
125k
    expr.set_id(proto.id());
324
125k
    return ConstantFromProto(const_proto, expr.mutable_const_expr());
325
125k
  }
326
327
  absl::Status IdentExprFromProto(const ExprProto& proto,
328
                                  const ExprProto::Ident& ident_proto,
329
60.5k
                                  Expr& expr) {
330
60.5k
    expr.Clear();
331
60.5k
    expr.set_id(proto.id());
332
60.5k
    auto& ident_expr = expr.mutable_ident_expr();
333
60.5k
    ident_expr.set_name(ident_proto.name());
334
60.5k
    return absl::OkStatus();
335
60.5k
  }
336
337
  absl::Status SelectExprFromProto(const ExprProto& proto,
338
                                   const ExprProto::Select& select_proto,
339
11.7k
                                   Expr& expr) {
340
11.7k
    expr.Clear();
341
11.7k
    expr.set_id(proto.id());
342
11.7k
    auto& select_expr = expr.mutable_select_expr();
343
11.7k
    if (select_proto.has_operand()) {
344
11.7k
      Push(select_proto.operand(), select_expr.mutable_operand());
345
11.7k
    }
346
11.7k
    select_expr.set_field(select_proto.field());
347
11.7k
    select_expr.set_test_only(select_proto.test_only());
348
11.7k
    return absl::OkStatus();
349
11.7k
  }
350
351
  absl::Status CallExprFromProto(const ExprProto& proto,
352
                                 const ExprProto::Call& call_proto,
353
120k
                                 Expr& expr) {
354
120k
    expr.Clear();
355
120k
    expr.set_id(proto.id());
356
120k
    auto& call_expr = expr.mutable_call_expr();
357
120k
    call_expr.set_function(call_proto.function());
358
120k
    if (call_proto.has_target()) {
359
962
      Push(call_proto.target(), call_expr.mutable_target());
360
962
    }
361
120k
    call_expr.mutable_args().reserve(
362
120k
        static_cast<size_t>(call_proto.args().size()));
363
226k
    for (const auto& argument_proto : call_proto.args()) {
364
226k
      Push(argument_proto, call_expr.add_args());
365
226k
    }
366
120k
    return absl::OkStatus();
367
120k
  }
368
369
  absl::Status ListExprFromProto(const ExprProto& proto,
370
                                 const ExprProto::CreateList& list_proto,
371
20.2k
                                 Expr& expr) {
372
20.2k
    expr.Clear();
373
20.2k
    expr.set_id(proto.id());
374
20.2k
    auto& list_expr = expr.mutable_list_expr();
375
20.2k
    list_expr.mutable_elements().reserve(
376
20.2k
        static_cast<size_t>(list_proto.elements().size()));
377
88.9k
    for (int i = 0; i < list_proto.elements().size(); ++i) {
378
68.6k
      const auto& element_proto = list_proto.elements()[i];
379
68.6k
      auto& element_expr = list_expr.add_elements();
380
68.6k
      Push(element_proto, element_expr.mutable_expr());
381
68.6k
      const auto& optional_indicies_proto = list_proto.optional_indices();
382
68.6k
      element_expr.set_optional(std::find(optional_indicies_proto.begin(),
383
68.6k
                                          optional_indicies_proto.end(),
384
68.6k
                                          i) != optional_indicies_proto.end());
385
68.6k
    }
386
20.2k
    return absl::OkStatus();
387
20.2k
  }
388
389
  absl::Status StructExprFromProto(const ExprProto& proto,
390
                                   const StructExprProto& struct_proto,
391
1.90k
                                   Expr& expr) {
392
1.90k
    expr.Clear();
393
1.90k
    expr.set_id(proto.id());
394
1.90k
    auto& struct_expr = expr.mutable_struct_expr();
395
1.90k
    struct_expr.set_name(struct_proto.message_name());
396
1.90k
    struct_expr.mutable_fields().reserve(
397
1.90k
        static_cast<size_t>(struct_proto.entries().size()));
398
1.90k
    for (const auto& field_proto : struct_proto.entries()) {
399
695
      switch (field_proto.key_kind_case()) {
400
0
        case StructExprProto::Entry::KEY_KIND_NOT_SET:
401
0
          ABSL_FALLTHROUGH_INTENDED;
402
695
        case StructExprProto::Entry::kFieldKey:
403
695
          break;
404
0
        case StructExprProto::Entry::kMapKey:
405
0
          return absl::InvalidArgumentError("encountered map entry in struct");
406
0
        default:
407
0
          return absl::InvalidArgumentError(absl::StrCat(
408
0
              "unexpected struct field kind: ", field_proto.key_kind_case()));
409
695
      }
410
695
      auto& field_expr = struct_expr.add_fields();
411
695
      field_expr.set_id(field_proto.id());
412
695
      field_expr.set_name(field_proto.field_key());
413
695
      if (field_proto.has_value()) {
414
695
        Push(field_proto.value(), field_expr.mutable_value());
415
695
      }
416
695
      field_expr.set_optional(field_proto.optional_entry());
417
695
    }
418
1.90k
    return absl::OkStatus();
419
1.90k
  }
420
421
  absl::Status MapExprFromProto(const ExprProto& proto,
422
                                const ExprProto::CreateStruct& map_proto,
423
6.03k
                                Expr& expr) {
424
6.03k
    expr.Clear();
425
6.03k
    expr.set_id(proto.id());
426
6.03k
    auto& map_expr = expr.mutable_map_expr();
427
6.03k
    map_expr.mutable_entries().reserve(
428
6.03k
        static_cast<size_t>(map_proto.entries().size()));
429
6.03k
    for (const auto& entry_proto : map_proto.entries()) {
430
4.51k
      switch (entry_proto.key_kind_case()) {
431
0
        case StructExprProto::Entry::KEY_KIND_NOT_SET:
432
0
          ABSL_FALLTHROUGH_INTENDED;
433
4.51k
        case StructExprProto::Entry::kMapKey:
434
4.51k
          break;
435
0
        case StructExprProto::Entry::kFieldKey:
436
0
          return absl::InvalidArgumentError("encountered struct field in map");
437
0
        default:
438
0
          return absl::InvalidArgumentError(absl::StrCat(
439
0
              "unexpected map entry kind: ", entry_proto.key_kind_case()));
440
4.51k
      }
441
4.51k
      auto& entry_expr = map_expr.add_entries();
442
4.51k
      entry_expr.set_id(entry_proto.id());
443
4.51k
      if (entry_proto.has_map_key()) {
444
4.51k
        Push(entry_proto.map_key(), entry_expr.mutable_key());
445
4.51k
      }
446
4.51k
      if (entry_proto.has_value()) {
447
4.51k
        Push(entry_proto.value(), entry_expr.mutable_value());
448
4.51k
      }
449
4.51k
      entry_expr.set_optional(entry_proto.optional_entry());
450
4.51k
    }
451
6.03k
    return absl::OkStatus();
452
6.03k
  }
453
454
  absl::Status ComprehensionExprFromProto(
455
      const ExprProto& proto,
456
4.52k
      const ExprProto::Comprehension& comprehension_proto, Expr& expr) {
457
4.52k
    expr.Clear();
458
4.52k
    expr.set_id(proto.id());
459
4.52k
    auto& comprehension_expr = expr.mutable_comprehension_expr();
460
4.52k
    comprehension_expr.set_iter_var(comprehension_proto.iter_var());
461
4.52k
    comprehension_expr.set_iter_var2(comprehension_proto.iter_var2());
462
4.52k
    comprehension_expr.set_accu_var(comprehension_proto.accu_var());
463
4.52k
    if (comprehension_proto.has_iter_range()) {
464
4.52k
      Push(comprehension_proto.iter_range(),
465
4.52k
           comprehension_expr.mutable_iter_range());
466
4.52k
    }
467
4.52k
    if (comprehension_proto.has_accu_init()) {
468
4.52k
      Push(comprehension_proto.accu_init(),
469
4.52k
           comprehension_expr.mutable_accu_init());
470
4.52k
    }
471
4.52k
    if (comprehension_proto.has_loop_condition()) {
472
4.52k
      Push(comprehension_proto.loop_condition(),
473
4.52k
           comprehension_expr.mutable_loop_condition());
474
4.52k
    }
475
4.52k
    if (comprehension_proto.has_loop_step()) {
476
4.52k
      Push(comprehension_proto.loop_step(),
477
4.52k
           comprehension_expr.mutable_loop_step());
478
4.52k
    }
479
4.52k
    if (comprehension_proto.has_result()) {
480
4.52k
      Push(comprehension_proto.result(), comprehension_expr.mutable_result());
481
4.52k
    }
482
4.52k
    return absl::OkStatus();
483
4.52k
  }
484
485
350k
  void Push(const ExprProto& proto, Expr& expr) {
486
350k
    frames_.push(Frame{&proto, &expr});
487
350k
  }
488
489
361k
  bool Pop(Frame& frame) {
490
361k
    if (frames_.empty()) {
491
10.7k
      return false;
492
10.7k
    }
493
350k
    frame = frames_.top();
494
350k
    frames_.pop();
495
350k
    return true;
496
361k
  }
497
498
  std::stack<Frame, std::vector<Frame>> frames_;
499
};
500
501
}  // namespace
502
503
absl::Status ExprToProto(const Expr& expr,
504
12.4k
                         cel::expr::Expr* absl_nonnull proto) {
505
12.4k
  ExprToProtoState state;
506
12.4k
  return state.ExprToProto(expr, proto);
507
12.4k
}
508
509
10.7k
absl::Status ExprFromProto(const cel::expr::Expr& proto, Expr& expr) {
510
10.7k
  ExprFromProtoState state;
511
10.7k
  return state.ExprFromProto(proto, expr);
512
10.7k
}
513
514
}  // namespace cel::ast_internal