Coverage Report

Created: 2026-09-03 06:30

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