Coverage Report

Created: 2026-10-09 06:57

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
20.9k
                           cel::expr::Expr* absl_nonnull proto) {
54
20.9k
    Push(expr, proto);
55
20.9k
    Frame frame;
56
3.62M
    while (Pop(frame)) {
57
3.59M
      CEL_RETURN_IF_ERROR(ExprToProtoImpl(*frame.expr, frame.proto));
58
3.59M
    }
59
20.9k
    return absl::OkStatus();
60
20.9k
  }
61
62
 private:
63
  absl::Status ExprToProtoImpl(const Expr& expr,
64
3.59M
                               cel::expr::Expr* absl_nonnull proto) {
65
3.59M
    return absl::visit(
66
3.59M
        absl::Overload(
67
3.59M
            [&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.59M
            [this, &expr, proto](const Constant& const_expr) -> absl::Status {
73
386k
              return ConstExprToProto(expr, const_expr, proto);
74
386k
            },
75
3.59M
            [this, &expr, proto](const IdentExpr& ident_expr) -> absl::Status {
76
1.48M
              return IdentExprToProto(expr, ident_expr, proto);
77
1.48M
            },
78
3.59M
            [this, &expr,
79
3.59M
             proto](const SelectExpr& select_expr) -> absl::Status {
80
19.3k
              return SelectExprToProto(expr, select_expr, proto);
81
19.3k
            },
82
3.59M
            [this, &expr, proto](const CallExpr& call_expr) -> absl::Status {
83
1.61M
              return CallExprToProto(expr, call_expr, proto);
84
1.61M
            },
85
3.59M
            [this, &expr, proto](const ListExpr& list_expr) -> absl::Status {
86
60.9k
              return ListExprToProto(expr, list_expr, proto);
87
60.9k
            },
88
3.59M
            [this, &expr,
89
3.59M
             proto](const StructExpr& struct_expr) -> absl::Status {
90
4.17k
              return StructExprToProto(expr, struct_expr, proto);
91
4.17k
            },
92
3.59M
            [this, &expr, proto](const MapExpr& map_expr) -> absl::Status {
93
7.16k
              return MapExprToProto(expr, map_expr, proto);
94
7.16k
            },
95
3.59M
            [this, &expr, proto](
96
3.59M
                const ComprehensionExpr& comprehension_expr) -> absl::Status {
97
18.5k
              return ComprehensionExprToProto(expr, comprehension_expr, proto);
98
18.5k
            }),
99
3.59M
        expr.kind());
100
3.59M
  }
101
102
  absl::Status ConstExprToProto(const Expr& expr, const Constant& const_expr,
103
386k
                                ExprProto* absl_nonnull proto) {
104
386k
    proto->Clear();
105
386k
    proto->set_id(expr.id());
106
386k
    return ConstantToProto(const_expr, proto->mutable_const_expr());
107
386k
  }
108
109
  absl::Status IdentExprToProto(const Expr& expr, const IdentExpr& ident_expr,
110
1.48M
                                ExprProto* absl_nonnull proto) {
111
1.48M
    proto->Clear();
112
1.48M
    auto* ident_proto = proto->mutable_ident_expr();
113
1.48M
    proto->set_id(expr.id());
114
1.48M
    ident_proto->set_name(ident_expr.name());
115
1.48M
    return absl::OkStatus();
116
1.48M
  }
117
118
  absl::Status SelectExprToProto(const Expr& expr,
119
                                 const SelectExpr& select_expr,
120
19.3k
                                 ExprProto* absl_nonnull proto) {
121
19.3k
    proto->Clear();
122
19.3k
    auto* select_proto = proto->mutable_select_expr();
123
19.3k
    proto->set_id(expr.id());
124
19.3k
    if (select_expr.has_operand()) {
125
19.3k
      Push(select_expr.operand(), select_proto->mutable_operand());
126
19.3k
    }
127
19.3k
    select_proto->set_field(select_expr.field());
128
19.3k
    select_proto->set_test_only(select_expr.test_only());
129
19.3k
    return absl::OkStatus();
130
19.3k
  }
131
132
  absl::Status CallExprToProto(const Expr& expr, const CallExpr& call_expr,
133
1.61M
                               ExprProto* absl_nonnull proto) {
134
1.61M
    proto->Clear();
135
1.61M
    auto* call_proto = proto->mutable_call_expr();
136
1.61M
    proto->set_id(expr.id());
137
1.61M
    if (call_expr.has_target()) {
138
3.48k
      Push(call_expr.target(), call_proto->mutable_target());
139
3.48k
    }
140
1.61M
    call_proto->set_function(call_expr.function());
141
1.61M
    if (!call_expr.args().empty()) {
142
1.61M
      call_proto->mutable_args()->Reserve(
143
1.61M
          static_cast<int>(call_expr.args().size()));
144
3.11M
      for (const auto& argument : call_expr.args()) {
145
3.11M
        Push(argument, call_proto->add_args());
146
3.11M
      }
147
1.61M
    }
148
1.61M
    return absl::OkStatus();
149
1.61M
  }
150
151
  absl::Status ListExprToProto(const Expr& expr, const ListExpr& list_expr,
152
60.9k
                               ExprProto* absl_nonnull proto) {
153
60.9k
    proto->Clear();
154
60.9k
    auto* list_proto = proto->mutable_list_expr();
155
60.9k
    proto->set_id(expr.id());
156
60.9k
    if (!list_expr.elements().empty()) {
157
40.2k
      list_proto->mutable_elements()->Reserve(
158
40.2k
          static_cast<int>(list_expr.elements().size()));
159
160k
      for (size_t i = 0; i < list_expr.elements().size(); ++i) {
160
119k
        const auto& element_expr = list_expr.elements()[i];
161
119k
        auto* element_proto = list_proto->add_elements();
162
119k
        if (element_expr.has_expr()) {
163
119k
          Push(element_expr.expr(), element_proto);
164
119k
        }
165
119k
        if (element_expr.optional()) {
166
0
          list_proto->add_optional_indices(static_cast<int32_t>(i));
167
0
        }
168
119k
      }
169
40.2k
    }
170
60.9k
    return absl::OkStatus();
171
60.9k
  }
172
173
  absl::Status StructExprToProto(const Expr& expr,
174
                                 const StructExpr& struct_expr,
175
4.17k
                                 ExprProto* absl_nonnull proto) {
176
4.17k
    proto->Clear();
177
4.17k
    auto* struct_proto = proto->mutable_struct_expr();
178
4.17k
    proto->set_id(expr.id());
179
4.17k
    struct_proto->set_message_name(struct_expr.name());
180
4.17k
    if (!struct_expr.fields().empty()) {
181
1.51k
      struct_proto->mutable_entries()->Reserve(
182
1.51k
          static_cast<int>(struct_expr.fields().size()));
183
9.61k
      for (const auto& field_expr : struct_expr.fields()) {
184
9.61k
        auto* field_proto = struct_proto->add_entries();
185
9.61k
        field_proto->set_id(field_expr.id());
186
9.61k
        field_proto->set_field_key(field_expr.name());
187
9.61k
        if (field_expr.has_value()) {
188
9.61k
          Push(field_expr.value(), field_proto->mutable_value());
189
9.61k
        }
190
9.61k
        if (field_expr.optional()) {
191
0
          field_proto->set_optional_entry(true);
192
0
        }
193
9.61k
      }
194
1.51k
    }
195
4.17k
    return absl::OkStatus();
196
4.17k
  }
197
198
  absl::Status MapExprToProto(const Expr& expr, const MapExpr& map_expr,
199
7.16k
                              ExprProto* absl_nonnull proto) {
200
7.16k
    proto->Clear();
201
7.16k
    auto* map_proto = proto->mutable_struct_expr();
202
7.16k
    proto->set_id(expr.id());
203
7.16k
    if (!map_expr.entries().empty()) {
204
3.61k
      map_proto->mutable_entries()->Reserve(
205
3.61k
          static_cast<int>(map_expr.entries().size()));
206
107k
      for (const auto& entry_expr : map_expr.entries()) {
207
107k
        auto* entry_proto = map_proto->add_entries();
208
107k
        entry_proto->set_id(entry_expr.id());
209
107k
        if (entry_expr.has_key()) {
210
107k
          Push(entry_expr.key(), entry_proto->mutable_map_key());
211
107k
        }
212
107k
        if (entry_expr.has_value()) {
213
107k
          Push(entry_expr.value(), entry_proto->mutable_value());
214
107k
        }
215
107k
        if (entry_expr.optional()) {
216
0
          entry_proto->set_optional_entry(true);
217
0
        }
218
107k
      }
219
3.61k
    }
220
7.16k
    return absl::OkStatus();
221
7.16k
  }
222
223
  absl::Status ComprehensionExprToProto(
224
      const Expr& expr, const ComprehensionExpr& comprehension_expr,
225
18.5k
      ExprProto* absl_nonnull proto) {
226
18.5k
    proto->Clear();
227
18.5k
    auto* comprehension_proto = proto->mutable_comprehension_expr();
228
18.5k
    proto->set_id(expr.id());
229
18.5k
    comprehension_proto->set_iter_var(comprehension_expr.iter_var());
230
18.5k
    comprehension_proto->set_iter_var2(comprehension_expr.iter_var2());
231
18.5k
    if (comprehension_expr.has_iter_range()) {
232
18.5k
      Push(comprehension_expr.iter_range(),
233
18.5k
           comprehension_proto->mutable_iter_range());
234
18.5k
    }
235
18.5k
    comprehension_proto->set_accu_var(comprehension_expr.accu_var());
236
18.5k
    if (comprehension_expr.has_accu_init()) {
237
18.5k
      Push(comprehension_expr.accu_init(),
238
18.5k
           comprehension_proto->mutable_accu_init());
239
18.5k
    }
240
18.5k
    if (comprehension_expr.has_loop_condition()) {
241
18.5k
      Push(comprehension_expr.loop_condition(),
242
18.5k
           comprehension_proto->mutable_loop_condition());
243
18.5k
    }
244
18.5k
    if (comprehension_expr.has_loop_step()) {
245
18.5k
      Push(comprehension_expr.loop_step(),
246
18.5k
           comprehension_proto->mutable_loop_step());
247
18.5k
    }
248
18.5k
    if (comprehension_expr.has_result()) {
249
18.5k
      Push(comprehension_expr.result(), comprehension_proto->mutable_result());
250
18.5k
    }
251
18.5k
    return absl::OkStatus();
252
18.5k
  }
253
254
3.59M
  void Push(const Expr& expr, ExprProto* absl_nonnull proto) {
255
3.59M
    frames_.push(Frame{&expr, proto});
256
3.59M
  }
257
258
3.62M
  bool Pop(Frame& frame) {
259
3.62M
    if (frames_.empty()) {
260
20.9k
      return false;
261
20.9k
    }
262
3.59M
    frame = frames_.top();
263
3.59M
    frames_.pop();
264
3.59M
    return true;
265
3.62M
  }
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
17.9k
  absl::Status ExprFromProto(const ExprProto& proto, Expr& expr) {
279
17.9k
    Push(proto, expr);
280
17.9k
    Frame frame;
281
502k
    while (Pop(frame)) {
282
484k
      CEL_RETURN_IF_ERROR(ExprFromProtoImpl(*frame.proto, *frame.expr));
283
484k
    }
284
17.9k
    return absl::OkStatus();
285
17.9k
  }
286
287
 private:
288
484k
  absl::Status ExprFromProtoImpl(const ExprProto& proto, Expr& expr) {
289
484k
    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
160k
      case ExprProto::kConstExpr:
295
160k
        return ConstExprFromProto(proto, proto.const_expr(), expr);
296
101k
      case ExprProto::kIdentExpr:
297
101k
        return IdentExprFromProto(proto, proto.ident_expr(), expr);
298
17.1k
      case ExprProto::kSelectExpr:
299
17.1k
        return SelectExprFromProto(proto, proto.select_expr(), expr);
300
124k
      case ExprProto::kCallExpr:
301
124k
        return CallExprFromProto(proto, proto.call_expr(), expr);
302
55.7k
      case ExprProto::kListExpr:
303
55.7k
        return ListExprFromProto(proto, proto.list_expr(), expr);
304
7.99k
      case ExprProto::kStructExpr:
305
7.99k
        if (proto.struct_expr().message_name().empty()) {
306
4.60k
          return MapExprFromProto(proto, proto.struct_expr(), expr);
307
4.60k
        }
308
3.38k
        return StructExprFromProto(proto, proto.struct_expr(), expr);
309
17.6k
      case ExprProto::kComprehensionExpr:
310
17.6k
        return ComprehensionExprFromProto(proto, proto.comprehension_expr(),
311
17.6k
                                          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
484k
    }
317
484k
  }
318
319
  absl::Status ConstExprFromProto(const ExprProto& proto,
320
                                  const ConstantProto& const_proto,
321
160k
                                  Expr& expr) {
322
160k
    expr.Clear();
323
160k
    expr.set_id(proto.id());
324
160k
    return ConstantFromProto(const_proto, expr.mutable_const_expr());
325
160k
  }
326
327
  absl::Status IdentExprFromProto(const ExprProto& proto,
328
                                  const ExprProto::Ident& ident_proto,
329
101k
                                  Expr& expr) {
330
101k
    expr.Clear();
331
101k
    expr.set_id(proto.id());
332
101k
    auto& ident_expr = expr.mutable_ident_expr();
333
101k
    ident_expr.set_name(ident_proto.name());
334
101k
    return absl::OkStatus();
335
101k
  }
336
337
  absl::Status SelectExprFromProto(const ExprProto& proto,
338
                                   const ExprProto::Select& select_proto,
339
17.1k
                                   Expr& expr) {
340
17.1k
    expr.Clear();
341
17.1k
    expr.set_id(proto.id());
342
17.1k
    auto& select_expr = expr.mutable_select_expr();
343
17.1k
    if (select_proto.has_operand()) {
344
17.1k
      Push(select_proto.operand(), select_expr.mutable_operand());
345
17.1k
    }
346
17.1k
    select_expr.set_field(select_proto.field());
347
17.1k
    select_expr.set_test_only(select_proto.test_only());
348
17.1k
    return absl::OkStatus();
349
17.1k
  }
350
351
  absl::Status CallExprFromProto(const ExprProto& proto,
352
                                 const ExprProto::Call& call_proto,
353
124k
                                 Expr& expr) {
354
124k
    expr.Clear();
355
124k
    expr.set_id(proto.id());
356
124k
    auto& call_expr = expr.mutable_call_expr();
357
124k
    call_expr.set_function(call_proto.function());
358
124k
    if (call_proto.has_target()) {
359
1.14k
      Push(call_proto.target(), call_expr.mutable_target());
360
1.14k
    }
361
124k
    call_expr.mutable_args().reserve(
362
124k
        static_cast<size_t>(call_proto.args().size()));
363
236k
    for (const auto& argument_proto : call_proto.args()) {
364
236k
      Push(argument_proto, call_expr.add_args());
365
236k
    }
366
124k
    return absl::OkStatus();
367
124k
  }
368
369
  absl::Status ListExprFromProto(const ExprProto& proto,
370
                                 const ExprProto::CreateList& list_proto,
371
55.7k
                                 Expr& expr) {
372
55.7k
    expr.Clear();
373
55.7k
    expr.set_id(proto.id());
374
55.7k
    auto& list_expr = expr.mutable_list_expr();
375
55.7k
    list_expr.mutable_elements().reserve(
376
55.7k
        static_cast<size_t>(list_proto.elements().size()));
377
166k
    for (int i = 0; i < list_proto.elements().size(); ++i) {
378
110k
      const auto& element_proto = list_proto.elements()[i];
379
110k
      auto& element_expr = list_expr.add_elements();
380
110k
      Push(element_proto, element_expr.mutable_expr());
381
110k
      const auto& optional_indicies_proto = list_proto.optional_indices();
382
110k
      element_expr.set_optional(std::find(optional_indicies_proto.begin(),
383
110k
                                          optional_indicies_proto.end(),
384
110k
                                          i) != optional_indicies_proto.end());
385
110k
    }
386
55.7k
    return absl::OkStatus();
387
55.7k
  }
388
389
  absl::Status StructExprFromProto(const ExprProto& proto,
390
                                   const StructExprProto& struct_proto,
391
3.38k
                                   Expr& expr) {
392
3.38k
    expr.Clear();
393
3.38k
    expr.set_id(proto.id());
394
3.38k
    auto& struct_expr = expr.mutable_struct_expr();
395
3.38k
    struct_expr.set_name(struct_proto.message_name());
396
3.38k
    struct_expr.mutable_fields().reserve(
397
3.38k
        static_cast<size_t>(struct_proto.entries().size()));
398
3.38k
    for (const auto& field_proto : struct_proto.entries()) {
399
3.00k
      switch (field_proto.key_kind_case()) {
400
0
        case StructExprProto::Entry::KEY_KIND_NOT_SET:
401
0
          ABSL_FALLTHROUGH_INTENDED;
402
3.00k
        case StructExprProto::Entry::kFieldKey:
403
3.00k
          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
3.00k
      }
410
3.00k
      auto& field_expr = struct_expr.add_fields();
411
3.00k
      field_expr.set_id(field_proto.id());
412
3.00k
      field_expr.set_name(field_proto.field_key());
413
3.00k
      if (field_proto.has_value()) {
414
3.00k
        Push(field_proto.value(), field_expr.mutable_value());
415
3.00k
      }
416
3.00k
      field_expr.set_optional(field_proto.optional_entry());
417
3.00k
    }
418
3.38k
    return absl::OkStatus();
419
3.38k
  }
420
421
  absl::Status MapExprFromProto(const ExprProto& proto,
422
                                const ExprProto::CreateStruct& map_proto,
423
4.60k
                                Expr& expr) {
424
4.60k
    expr.Clear();
425
4.60k
    expr.set_id(proto.id());
426
4.60k
    auto& map_expr = expr.mutable_map_expr();
427
4.60k
    map_expr.mutable_entries().reserve(
428
4.60k
        static_cast<size_t>(map_proto.entries().size()));
429
5.10k
    for (const auto& entry_proto : map_proto.entries()) {
430
5.10k
      switch (entry_proto.key_kind_case()) {
431
0
        case StructExprProto::Entry::KEY_KIND_NOT_SET:
432
0
          ABSL_FALLTHROUGH_INTENDED;
433
5.10k
        case StructExprProto::Entry::kMapKey:
434
5.10k
          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
5.10k
      }
441
5.10k
      auto& entry_expr = map_expr.add_entries();
442
5.10k
      entry_expr.set_id(entry_proto.id());
443
5.10k
      if (entry_proto.has_map_key()) {
444
5.10k
        Push(entry_proto.map_key(), entry_expr.mutable_key());
445
5.10k
      }
446
5.10k
      if (entry_proto.has_value()) {
447
5.10k
        Push(entry_proto.value(), entry_expr.mutable_value());
448
5.10k
      }
449
5.10k
      entry_expr.set_optional(entry_proto.optional_entry());
450
5.10k
    }
451
4.60k
    return absl::OkStatus();
452
4.60k
  }
453
454
  absl::Status ComprehensionExprFromProto(
455
      const ExprProto& proto,
456
17.6k
      const ExprProto::Comprehension& comprehension_proto, Expr& expr) {
457
17.6k
    expr.Clear();
458
17.6k
    expr.set_id(proto.id());
459
17.6k
    auto& comprehension_expr = expr.mutable_comprehension_expr();
460
17.6k
    comprehension_expr.set_iter_var(comprehension_proto.iter_var());
461
17.6k
    comprehension_expr.set_iter_var2(comprehension_proto.iter_var2());
462
17.6k
    comprehension_expr.set_accu_var(comprehension_proto.accu_var());
463
17.6k
    if (comprehension_proto.has_iter_range()) {
464
17.6k
      Push(comprehension_proto.iter_range(),
465
17.6k
           comprehension_expr.mutable_iter_range());
466
17.6k
    }
467
17.6k
    if (comprehension_proto.has_accu_init()) {
468
17.6k
      Push(comprehension_proto.accu_init(),
469
17.6k
           comprehension_expr.mutable_accu_init());
470
17.6k
    }
471
17.6k
    if (comprehension_proto.has_loop_condition()) {
472
17.6k
      Push(comprehension_proto.loop_condition(),
473
17.6k
           comprehension_expr.mutable_loop_condition());
474
17.6k
    }
475
17.6k
    if (comprehension_proto.has_loop_step()) {
476
17.6k
      Push(comprehension_proto.loop_step(),
477
17.6k
           comprehension_expr.mutable_loop_step());
478
17.6k
    }
479
17.6k
    if (comprehension_proto.has_result()) {
480
17.6k
      Push(comprehension_proto.result(), comprehension_expr.mutable_result());
481
17.6k
    }
482
17.6k
    return absl::OkStatus();
483
17.6k
  }
484
485
484k
  void Push(const ExprProto& proto, Expr& expr) {
486
484k
    frames_.push(Frame{&proto, &expr});
487
484k
  }
488
489
502k
  bool Pop(Frame& frame) {
490
502k
    if (frames_.empty()) {
491
17.9k
      return false;
492
17.9k
    }
493
484k
    frame = frames_.top();
494
484k
    frames_.pop();
495
484k
    return true;
496
502k
  }
497
498
  std::stack<Frame, std::vector<Frame>> frames_;
499
};
500
501
}  // namespace
502
503
absl::Status ExprToProto(const Expr& expr,
504
20.9k
                         cel::expr::Expr* absl_nonnull proto) {
505
20.9k
  ExprToProtoState state;
506
20.9k
  return state.ExprToProto(expr, proto);
507
20.9k
}
508
509
17.9k
absl::Status ExprFromProto(const cel::expr::Expr& proto, Expr& expr) {
510
17.9k
  ExprFromProtoState state;
511
17.9k
  return state.ExprFromProto(proto, expr);
512
17.9k
}
513
514
}  // namespace cel::ast_internal