Coverage Report

Created: 2026-07-11 06:47

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/proc/self/cwd/common/legacy_value.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/legacy_value.h"
16
17
#include <cstddef>
18
#include <cstdint>
19
#include <memory>
20
#include <string>
21
#include <utility>
22
#include <vector>
23
24
#include "google/protobuf/struct.pb.h"
25
#include "absl/base/attributes.h"
26
#include "absl/base/nullability.h"
27
#include "absl/base/optimization.h"
28
#include "absl/functional/overload.h"
29
#include "absl/log/absl_check.h"
30
#include "absl/status/status.h"
31
#include "absl/status/statusor.h"
32
#include "absl/strings/cord.h"
33
#include "absl/strings/str_cat.h"
34
#include "absl/strings/string_view.h"
35
#include "absl/types/optional.h"
36
#include "absl/types/span.h"
37
#include "absl/types/variant.h"
38
#include "base/attribute.h"
39
#include "common/casting.h"
40
#include "common/kind.h"
41
#include "common/memory.h"
42
#include "common/type.h"
43
#include "common/unknown.h"
44
#include "common/value.h"
45
#include "common/value_kind.h"
46
#include "common/values/list_value_builder.h"
47
#include "common/values/map_value_builder.h"
48
#include "common/values/values.h"
49
#include "eval/internal/cel_value_equal.h"
50
#include "eval/public/cel_value.h"
51
#include "eval/public/containers/field_backed_list_impl.h"
52
#include "eval/public/containers/field_backed_map_impl.h"
53
#include "eval/public/message_wrapper.h"
54
#include "eval/public/structs/cel_proto_wrap_util.h"
55
#include "eval/public/structs/legacy_type_adapter.h"
56
#include "eval/public/structs/legacy_type_info_apis.h"
57
#include "eval/public/structs/proto_message_type_adapter.h"
58
#include "internal/json.h"
59
#include "internal/status_macros.h"
60
#include "internal/well_known_types.h"
61
#include "runtime/runtime_options.h"
62
#include "google/protobuf/arena.h"
63
#include "google/protobuf/descriptor.h"
64
#include "google/protobuf/io/zero_copy_stream.h"
65
#include "google/protobuf/message.h"
66
#include "google/protobuf/message_lite.h"
67
68
// TODO(uncreated-issue/76): improve coverage for JSON/Any handling
69
70
namespace cel {
71
72
namespace {
73
74
using google::api::expr::runtime::CelList;
75
using google::api::expr::runtime::CelMap;
76
using google::api::expr::runtime::CelValue;
77
using google::api::expr::runtime::FieldBackedListImpl;
78
using google::api::expr::runtime::FieldBackedMapImpl;
79
using google::api::expr::runtime::GetGenericProtoTypeInfoInstance;
80
using google::api::expr::runtime::LegacyTypeInfoApis;
81
using google::api::expr::runtime::MessageWrapper;
82
using ::google::api::expr::runtime::internal::MaybeWrapValueToMessage;
83
84
52
absl::Status InvalidMapKeyTypeError(ValueKind kind) {
85
52
  return absl::InvalidArgumentError(
86
52
      absl::StrCat("Invalid map key type: '", ValueKindToString(kind), "'"));
87
52
}
88
89
MessageWrapper AsMessageWrapper(
90
    const google::protobuf::Message* absl_nullability_unknown message_ptr,
91
26.4k
    const LegacyTypeInfoApis* absl_nullability_unknown type_info) {
92
26.4k
  return MessageWrapper(message_ptr, type_info);
93
26.4k
}
94
95
class CelListIterator final : public ValueIterator {
96
 public:
97
  explicit CelListIterator(const CelList* cel_list)
98
0
      : cel_list_(cel_list), size_(cel_list_->size()) {}
99
100
0
  bool HasNext() override { return index_ < size_; }
101
102
  absl::Status Next(const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
103
                    google::protobuf::MessageFactory* absl_nonnull message_factory,
104
                    google::protobuf::Arena* absl_nonnull arena,
105
0
                    Value* absl_nonnull result) override {
106
0
    if (!HasNext()) {
107
0
      return absl::FailedPreconditionError(
108
0
          "ValueIterator::Next() called when ValueIterator::HasNext() returns "
109
0
          "false");
110
0
    }
111
0
    auto cel_value = cel_list_->Get(arena, index_);
112
0
    CEL_RETURN_IF_ERROR(ModernValue(arena, cel_value, *result));
113
0
    ++index_;
114
0
    return absl::OkStatus();
115
0
  }
116
117
  absl::StatusOr<bool> Next1(
118
      const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
119
      google::protobuf::MessageFactory* absl_nonnull message_factory,
120
      google::protobuf::Arena* absl_nonnull arena,
121
0
      Value* absl_nonnull key_or_value) override {
122
0
    ABSL_DCHECK(descriptor_pool != nullptr);
123
0
    ABSL_DCHECK(message_factory != nullptr);
124
0
    ABSL_DCHECK(arena != nullptr);
125
0
    ABSL_DCHECK(key_or_value != nullptr);
126
127
0
    if (index_ >= size_) {
128
0
      return false;
129
0
    }
130
0
    auto cel_value = cel_list_->Get(arena, index_);
131
0
    CEL_RETURN_IF_ERROR(ModernValue(arena, cel_value, *key_or_value));
132
0
    ++index_;
133
0
    return true;
134
0
  }
135
136
  absl::StatusOr<bool> Next2(
137
      const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
138
      google::protobuf::MessageFactory* absl_nonnull message_factory,
139
      google::protobuf::Arena* absl_nonnull arena, Value* absl_nonnull key,
140
0
      Value* absl_nullable value) override {
141
0
    ABSL_DCHECK(descriptor_pool != nullptr);
142
0
    ABSL_DCHECK(message_factory != nullptr);
143
0
    ABSL_DCHECK(arena != nullptr);
144
0
    ABSL_DCHECK(key != nullptr);
145
146
0
    if (index_ >= size_) {
147
0
      return false;
148
0
    }
149
0
    if (value != nullptr) {
150
0
      auto cel_value = cel_list_->Get(arena, index_);
151
0
      CEL_RETURN_IF_ERROR(ModernValue(arena, cel_value, *value));
152
0
    }
153
0
    *key = IntValue(index_);
154
0
    ++index_;
155
0
    return true;
156
0
  }
157
158
 private:
159
  const CelList* const cel_list_;
160
  const int size_;
161
  int index_ = 0;
162
};
163
164
class CelMapIterator final : public ValueIterator {
165
 public:
166
  explicit CelMapIterator(const CelMap* cel_map)
167
200
      : cel_map_(cel_map), size_(cel_map->size()) {}
168
169
0
  bool HasNext() override { return index_ < size_; }
170
171
  absl::Status Next(const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
172
                    google::protobuf::MessageFactory* absl_nonnull message_factory,
173
                    google::protobuf::Arena* absl_nonnull arena,
174
0
                    Value* absl_nonnull result) override {
175
0
    if (!HasNext()) {
176
0
      return absl::FailedPreconditionError(
177
0
          "ValueIterator::Next() called when ValueIterator::HasNext() returns "
178
0
          "false");
179
0
    }
180
0
    CEL_RETURN_IF_ERROR(ProjectKeys(arena));
181
0
    auto cel_value = (*cel_list_)->Get(arena, index_);
182
0
    CEL_RETURN_IF_ERROR(ModernValue(arena, cel_value, *result));
183
0
    ++index_;
184
0
    return absl::OkStatus();
185
0
  }
186
187
  absl::StatusOr<bool> Next1(
188
      const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
189
      google::protobuf::MessageFactory* absl_nonnull message_factory,
190
      google::protobuf::Arena* absl_nonnull arena,
191
199
      Value* absl_nonnull key_or_value) override {
192
199
    ABSL_DCHECK(descriptor_pool != nullptr);
193
199
    ABSL_DCHECK(message_factory != nullptr);
194
199
    ABSL_DCHECK(arena != nullptr);
195
199
    ABSL_DCHECK(key_or_value != nullptr);
196
197
199
    if (index_ >= size_) {
198
199
      return false;
199
199
    }
200
199
    CEL_RETURN_IF_ERROR(ProjectKeys(arena));
201
0
    auto cel_value = (*cel_list_)->Get(arena, index_);
202
0
    CEL_RETURN_IF_ERROR(ModernValue(arena, cel_value, *key_or_value));
203
0
    ++index_;
204
0
    return true;
205
0
  }
206
207
  absl::StatusOr<bool> Next2(
208
      const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
209
      google::protobuf::MessageFactory* absl_nonnull message_factory,
210
      google::protobuf::Arena* absl_nonnull arena, Value* absl_nonnull key,
211
0
      Value* absl_nullable value) override {
212
0
    ABSL_DCHECK(descriptor_pool != nullptr);
213
0
    ABSL_DCHECK(message_factory != nullptr);
214
0
    ABSL_DCHECK(arena != nullptr);
215
0
    ABSL_DCHECK(key != nullptr);
216
217
0
    if (index_ >= size_) {
218
0
      return false;
219
0
    }
220
0
    CEL_RETURN_IF_ERROR(ProjectKeys(arena));
221
0
    auto cel_key = (*cel_list_)->Get(arena, index_);
222
0
    if (value != nullptr) {
223
0
      auto cel_value = cel_map_->Get(arena, cel_key);
224
0
      if (!cel_value) {
225
0
        return absl::DataLossError(
226
0
            "map iterator returned key that was not present in the map");
227
0
      }
228
0
      CEL_RETURN_IF_ERROR(ModernValue(arena, *cel_value, *value));
229
0
    }
230
0
    CEL_RETURN_IF_ERROR(ModernValue(arena, cel_key, *key));
231
0
    ++index_;
232
0
    return true;
233
0
  }
234
235
 private:
236
0
  absl::Status ProjectKeys(google::protobuf::Arena* arena) {
237
0
    if (cel_list_.ok() && *cel_list_ == nullptr) {
238
0
      cel_list_ = cel_map_->ListKeys(arena);
239
0
    }
240
0
    return cel_list_.status();
241
0
  }
242
243
  const CelMap* const cel_map_;
244
  const int size_ = 0;
245
  absl::StatusOr<const CelList*> cel_list_ = nullptr;
246
  int index_ = 0;
247
};
248
249
}  // namespace
250
251
namespace common_internal {
252
253
namespace {
254
255
CelValue LegacyTrivialStructValue(google::protobuf::Arena* absl_nonnull arena,
256
2
                                  const Value& value) {
257
2
  if (auto legacy_struct_value = common_internal::AsLegacyStructValue(value);
258
2
      legacy_struct_value) {
259
2
    return CelValue::CreateMessageWrapper(
260
2
        AsMessageWrapper(legacy_struct_value->message_ptr(),
261
2
                         legacy_struct_value->legacy_type_info()));
262
2
  }
263
0
  if (auto parsed_message_value = value.AsParsedMessage();
264
0
      parsed_message_value) {
265
0
    auto maybe_cloned = parsed_message_value->Clone(arena);
266
0
    return CelValue::CreateMessageWrapper(MessageWrapper(
267
0
        cel::to_address(maybe_cloned), &GetGenericProtoTypeInfoInstance()));
268
0
  }
269
0
  return CelValue::CreateError(google::protobuf::Arena::Create<absl::Status>(
270
0
      arena, absl::InvalidArgumentError(absl::StrCat(
271
0
                 "unsupported conversion from cel::StructValue to CelValue: ",
272
0
                 value.GetRuntimeType().DebugString()))));
273
0
}
274
275
CelValue LegacyTrivialListValue(google::protobuf::Arena* absl_nonnull arena,
276
218
                                const Value& value) {
277
218
  if (auto legacy_list_value = common_internal::AsLegacyListValue(value);
278
218
      legacy_list_value) {
279
218
    return CelValue::CreateList(legacy_list_value->cel_list());
280
218
  }
281
0
  if (auto parsed_repeated_field_value = value.AsParsedRepeatedField();
282
0
      parsed_repeated_field_value) {
283
0
    auto maybe_cloned = parsed_repeated_field_value->Clone(arena);
284
0
    return CelValue::CreateList(google::protobuf::Arena::Create<FieldBackedListImpl>(
285
0
        arena, &maybe_cloned.message(), maybe_cloned.field(), arena));
286
0
  }
287
0
  if (auto parsed_json_list_value = value.AsParsedJsonList();
288
0
      parsed_json_list_value) {
289
0
    auto maybe_cloned = parsed_json_list_value->Clone(arena);
290
0
    return CelValue::CreateList(google::protobuf::Arena::Create<FieldBackedListImpl>(
291
0
        arena, cel::to_address(maybe_cloned),
292
0
        well_known_types::GetListValueReflectionOrDie(
293
0
            maybe_cloned->GetDescriptor())
294
0
            .GetValuesDescriptor(),
295
0
        arena));
296
0
  }
297
0
  if (auto custom_list_value = value.AsCustomList(); custom_list_value) {
298
0
    auto status_or_compat_list = common_internal::MakeCompatListValue(
299
0
        *custom_list_value, google::protobuf::DescriptorPool::generated_pool(),
300
0
        google::protobuf::MessageFactory::generated_factory(), arena);
301
0
    if (!status_or_compat_list.ok()) {
302
0
      return CelValue::CreateError(google::protobuf::Arena::Create<absl::Status>(
303
0
          arena, std::move(status_or_compat_list).status()));
304
0
    }
305
0
    return CelValue::CreateList(*status_or_compat_list);
306
0
  }
307
0
  return CelValue::CreateError(google::protobuf::Arena::Create<absl::Status>(
308
0
      arena, absl::InvalidArgumentError(absl::StrCat(
309
0
                 "unsupported conversion from cel::ListValue to CelValue: ",
310
0
                 value.GetRuntimeType().DebugString()))));
311
0
}
312
313
CelValue LegacyTrivialMapValue(google::protobuf::Arena* absl_nonnull arena,
314
35
                               const Value& value) {
315
35
  if (auto legacy_map_value = common_internal::AsLegacyMapValue(value);
316
35
      legacy_map_value) {
317
35
    return CelValue::CreateMap(legacy_map_value->cel_map());
318
35
  }
319
0
  if (auto parsed_map_field_value = value.AsParsedMapField();
320
0
      parsed_map_field_value) {
321
0
    auto maybe_cloned = parsed_map_field_value->Clone(arena);
322
0
    return CelValue::CreateMap(google::protobuf::Arena::Create<FieldBackedMapImpl>(
323
0
        arena, &maybe_cloned.message(), maybe_cloned.field(), arena));
324
0
  }
325
0
  if (auto parsed_json_map_value = value.AsParsedJsonMap();
326
0
      parsed_json_map_value) {
327
0
    auto maybe_cloned = parsed_json_map_value->Clone(arena);
328
0
    return CelValue::CreateMap(google::protobuf::Arena::Create<FieldBackedMapImpl>(
329
0
        arena, cel::to_address(maybe_cloned),
330
0
        well_known_types::GetStructReflectionOrDie(
331
0
            maybe_cloned->GetDescriptor())
332
0
            .GetFieldsDescriptor(),
333
0
        arena));
334
0
  }
335
0
  if (auto custom_map_value = value.AsCustomMap(); custom_map_value) {
336
0
    auto status_or_compat_map = common_internal::MakeCompatMapValue(
337
0
        *custom_map_value, google::protobuf::DescriptorPool::generated_pool(),
338
0
        google::protobuf::MessageFactory::generated_factory(), arena);
339
0
    if (!status_or_compat_map.ok()) {
340
0
      return CelValue::CreateError(google::protobuf::Arena::Create<absl::Status>(
341
0
          arena, std::move(status_or_compat_map).status()));
342
0
    }
343
0
    return CelValue::CreateMap(*status_or_compat_map);
344
0
  }
345
0
  return CelValue::CreateError(google::protobuf::Arena::Create<absl::Status>(
346
0
      arena, absl::InvalidArgumentError(absl::StrCat(
347
0
                 "unsupported conversion from cel::MapValue to CelValue: ",
348
0
                 value.GetRuntimeType().DebugString()))));
349
0
}
350
351
}  // namespace
352
353
google::api::expr::runtime::CelValue UnsafeLegacyValue(
354
0
    const Value& value, bool stable, google::protobuf::Arena* absl_nonnull arena) {
355
0
  switch (value.kind()) {
356
0
    case ValueKind::kNull:
357
0
      return CelValue::CreateNull();
358
0
    case ValueKind::kBool:
359
0
      return CelValue::CreateBool(value.GetBool());
360
0
    case ValueKind::kInt:
361
0
      return CelValue::CreateInt64(value.GetInt());
362
0
    case ValueKind::kUint:
363
0
      return CelValue::CreateUint64(value.GetUint());
364
0
    case ValueKind::kDouble:
365
0
      return CelValue::CreateDouble(value.GetDouble());
366
0
    case ValueKind::kString:
367
0
      return CelValue::CreateStringView(
368
0
          LegacyStringValue(value.GetString(), stable, arena));
369
0
    case ValueKind::kBytes:
370
0
      return CelValue::CreateBytesView(
371
0
          LegacyBytesValue(value.GetBytes(), stable, arena));
372
0
    case ValueKind::kStruct:
373
0
      return LegacyTrivialStructValue(arena, value);
374
0
    case ValueKind::kDuration:
375
0
      return CelValue::CreateDuration(value.GetDuration().ToDuration());
376
0
    case ValueKind::kTimestamp:
377
0
      return CelValue::CreateTimestamp(value.GetTimestamp().ToTime());
378
0
    case ValueKind::kList:
379
0
      return LegacyTrivialListValue(arena, value);
380
0
    case ValueKind::kMap:
381
0
      return LegacyTrivialMapValue(arena, value);
382
0
    case ValueKind::kType:
383
0
      return CelValue::CreateCelTypeView(value.GetType().name());
384
0
    default:
385
      // Everything else is unsupported.
386
0
      return CelValue::CreateError(google::protobuf::Arena::Create<absl::Status>(
387
0
          arena, absl::InvalidArgumentError(absl::StrCat(
388
0
                     "unsupported conversion from cel::Value to CelValue: ",
389
0
                     value->GetRuntimeType().DebugString()))));
390
0
  }
391
0
}
392
393
}  // namespace common_internal
394
395
namespace common_internal {
396
397
0
std::string LegacyListValue::DebugString() const {
398
0
  return CelValue::CreateList(impl_).DebugString();
399
0
}
400
401
// See `ValueInterface::SerializeTo`.
402
absl::Status LegacyListValue::SerializeTo(
403
    const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
404
    google::protobuf::MessageFactory* absl_nonnull message_factory,
405
0
    google::protobuf::io::ZeroCopyOutputStream* absl_nonnull output) const {
406
0
  ABSL_DCHECK(descriptor_pool != nullptr);
407
0
  ABSL_DCHECK(message_factory != nullptr);
408
0
  ABSL_DCHECK(output != nullptr);
409
410
0
  const google::protobuf::Descriptor* descriptor =
411
0
      descriptor_pool->FindMessageTypeByName("google.protobuf.ListValue");
412
0
  if (descriptor == nullptr) {
413
0
    return absl::InternalError(
414
0
        "unable to locate descriptor for message type: "
415
0
        "google.protobuf.ListValue");
416
0
  }
417
418
0
  google::protobuf::Arena arena;
419
0
  const google::protobuf::Message* wrapped = MaybeWrapValueToMessage(
420
0
      descriptor, message_factory, CelValue::CreateList(impl_), &arena);
421
0
  if (wrapped == nullptr) {
422
0
    return absl::UnknownError("failed to convert legacy map to JSON");
423
0
  }
424
0
  if (!wrapped->SerializePartialToZeroCopyStream(output)) {
425
0
    return absl::UnknownError(
426
0
        absl::StrCat("failed to serialize message: ", wrapped->GetTypeName()));
427
0
  }
428
0
  return absl::OkStatus();
429
0
}
430
431
absl::Status LegacyListValue::ConvertToJson(
432
    const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
433
    google::protobuf::MessageFactory* absl_nonnull message_factory,
434
0
    google::protobuf::Message* absl_nonnull json) const {
435
0
  {
436
0
    ABSL_DCHECK(descriptor_pool != nullptr);
437
0
    ABSL_DCHECK(message_factory != nullptr);
438
0
    ABSL_DCHECK(json != nullptr);
439
0
    ABSL_DCHECK_EQ(json->GetDescriptor()->well_known_type(),
440
0
                   google::protobuf::Descriptor::WELLKNOWNTYPE_VALUE);
441
442
0
    google::protobuf::Arena arena;
443
0
    const google::protobuf::Message* wrapped =
444
0
        MaybeWrapValueToMessage(json->GetDescriptor(), message_factory,
445
0
                                CelValue::CreateList(impl_), &arena);
446
0
    if (wrapped == nullptr) {
447
0
      return absl::UnknownError("failed to convert legacy list to JSON");
448
0
    }
449
450
0
    if (wrapped->GetDescriptor() == json->GetDescriptor()) {
451
      // We can directly use google::protobuf::Message::Copy().
452
0
      json->CopyFrom(*wrapped);
453
0
    } else {
454
      // Equivalent descriptors but not identical. Must serialize and
455
      // deserialize.
456
0
      absl::Cord serialized;
457
0
      if (!wrapped->SerializePartialToString(&serialized)) {
458
0
        return absl::UnknownError(absl::StrCat("failed to serialize message: ",
459
0
                                               wrapped->GetTypeName()));
460
0
      }
461
0
      if (!json->ParsePartialFromString(serialized)) {
462
0
        return absl::UnknownError(
463
0
            absl::StrCat("failed to parsed message: ", json->GetTypeName()));
464
0
      }
465
0
    }
466
0
    return absl::OkStatus();
467
0
  }
468
0
}
469
470
absl::Status LegacyListValue::ConvertToJsonArray(
471
    const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
472
    google::protobuf::MessageFactory* absl_nonnull message_factory,
473
0
    google::protobuf::Message* absl_nonnull json) const {
474
0
  {
475
0
    ABSL_DCHECK(descriptor_pool != nullptr);
476
0
    ABSL_DCHECK(message_factory != nullptr);
477
0
    ABSL_DCHECK(json != nullptr);
478
0
    ABSL_DCHECK_EQ(json->GetDescriptor()->well_known_type(),
479
0
                   google::protobuf::Descriptor::WELLKNOWNTYPE_LISTVALUE);
480
481
0
    google::protobuf::Arena arena;
482
0
    const google::protobuf::Message* wrapped =
483
0
        MaybeWrapValueToMessage(json->GetDescriptor(), message_factory,
484
0
                                CelValue::CreateList(impl_), &arena);
485
0
    if (wrapped == nullptr) {
486
0
      return absl::UnknownError("failed to convert legacy list to JSON");
487
0
    }
488
489
0
    if (wrapped->GetDescriptor() == json->GetDescriptor()) {
490
      // We can directly use google::protobuf::Message::Copy().
491
0
      json->CopyFrom(*wrapped);
492
0
    } else {
493
      // Equivalent descriptors but not identical. Must serialize and
494
      // deserialize.
495
0
      absl::Cord serialized;
496
0
      if (!wrapped->SerializePartialToString(&serialized)) {
497
0
        return absl::UnknownError(absl::StrCat("failed to serialize message: ",
498
0
                                               wrapped->GetTypeName()));
499
0
      }
500
0
      if (!json->ParsePartialFromString(serialized)) {
501
0
        return absl::UnknownError(
502
0
            absl::StrCat("failed to parsed message: ", json->GetTypeName()));
503
0
      }
504
0
    }
505
0
    return absl::OkStatus();
506
0
  }
507
0
}
508
509
0
bool LegacyListValue::IsEmpty() const { return impl_->empty(); }
510
511
1.69k
size_t LegacyListValue::Size() const {
512
1.69k
  return static_cast<size_t>(impl_->size());
513
1.69k
}
514
515
// See LegacyListValueInterface::Get for documentation.
516
absl::Status LegacyListValue::Get(
517
    size_t index, const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
518
    google::protobuf::MessageFactory* absl_nonnull message_factory,
519
0
    google::protobuf::Arena* absl_nonnull arena, Value* absl_nonnull result) const {
520
0
  if (ABSL_PREDICT_FALSE(index < 0 || index >= impl_->size())) {
521
0
    *result = ErrorValue(absl::InvalidArgumentError("index out of bounds"));
522
0
    return absl::OkStatus();
523
0
  }
524
0
  CEL_RETURN_IF_ERROR(
525
0
      ModernValue(arena, impl_->Get(arena, static_cast<int>(index)), *result));
526
0
  return absl::OkStatus();
527
0
}
528
529
absl::Status LegacyListValue::ForEach(
530
    ForEachWithIndexCallback callback,
531
    const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
532
    google::protobuf::MessageFactory* absl_nonnull message_factory,
533
0
    google::protobuf::Arena* absl_nonnull arena) const {
534
0
  const auto size = impl_->size();
535
0
  Value element;
536
0
  for (int index = 0; index < size; ++index) {
537
0
    CEL_RETURN_IF_ERROR(ModernValue(arena, impl_->Get(arena, index), element));
538
0
    CEL_ASSIGN_OR_RETURN(auto ok, callback(index, Value(element)));
539
0
    if (!ok) {
540
0
      break;
541
0
    }
542
0
  }
543
0
  return absl::OkStatus();
544
0
}
545
546
absl::StatusOr<absl_nonnull ValueIteratorPtr> LegacyListValue::NewIterator()
547
0
    const {
548
0
  return std::make_unique<CelListIterator>(impl_);
549
0
}
550
551
absl::Status LegacyListValue::Contains(
552
    const Value& other,
553
    const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
554
    google::protobuf::MessageFactory* absl_nonnull message_factory,
555
0
    google::protobuf::Arena* absl_nonnull arena, Value* absl_nonnull result) const {
556
0
  CEL_ASSIGN_OR_RETURN(auto legacy_other, LegacyValue(arena, other));
557
0
  const auto* cel_list = impl_;
558
0
  for (int i = 0; i < cel_list->size(); ++i) {
559
0
    auto element = cel_list->Get(arena, i);
560
0
    absl::optional<bool> equal =
561
0
        interop_internal::CelValueEqualImpl(element, legacy_other);
562
    // Heterogeneous equality behavior is to just return false if equality
563
    // undefined.
564
0
    if (equal.has_value() && *equal) {
565
0
      *result = TrueValue();
566
0
      return absl::OkStatus();
567
0
    }
568
0
  }
569
0
  *result = FalseValue();
570
0
  return absl::OkStatus();
571
0
}
572
573
0
std::string LegacyMapValue::DebugString() const {
574
0
  return CelValue::CreateMap(impl_).DebugString();
575
0
}
576
577
absl::Status LegacyMapValue::SerializeTo(
578
    const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
579
    google::protobuf::MessageFactory* absl_nonnull message_factory,
580
0
    google::protobuf::io::ZeroCopyOutputStream* absl_nonnull output) const {
581
0
  ABSL_DCHECK(descriptor_pool != nullptr);
582
0
  ABSL_DCHECK(message_factory != nullptr);
583
0
  ABSL_DCHECK(output != nullptr);
584
585
0
  const google::protobuf::Descriptor* descriptor =
586
0
      descriptor_pool->FindMessageTypeByName("google.protobuf.Struct");
587
0
  if (descriptor == nullptr) {
588
0
    return absl::InternalError(
589
0
        "unable to locate descriptor for message type: google.protobuf.Struct");
590
0
  }
591
592
0
  google::protobuf::Arena arena;
593
0
  const google::protobuf::Message* wrapped = MaybeWrapValueToMessage(
594
0
      descriptor, message_factory, CelValue::CreateMap(impl_), &arena);
595
0
  if (wrapped == nullptr) {
596
0
    return absl::UnknownError("failed to convert legacy map to JSON");
597
0
  }
598
0
  if (!wrapped->SerializePartialToZeroCopyStream(output)) {
599
0
    return absl::UnknownError(
600
0
        absl::StrCat("failed to serialize message: ", wrapped->GetTypeName()));
601
0
  }
602
0
  return absl::OkStatus();
603
0
}
604
605
absl::Status LegacyMapValue::ConvertToJson(
606
    const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
607
    google::protobuf::MessageFactory* absl_nonnull message_factory,
608
0
    google::protobuf::Message* absl_nonnull json) const {
609
0
  ABSL_DCHECK(descriptor_pool != nullptr);
610
0
  ABSL_DCHECK(message_factory != nullptr);
611
0
  ABSL_DCHECK(json != nullptr);
612
0
  ABSL_DCHECK_EQ(json->GetDescriptor()->well_known_type(),
613
0
                 google::protobuf::Descriptor::WELLKNOWNTYPE_VALUE);
614
615
0
  google::protobuf::Arena arena;
616
0
  const google::protobuf::Message* wrapped =
617
0
      MaybeWrapValueToMessage(json->GetDescriptor(), message_factory,
618
0
                              CelValue::CreateMap(impl_), &arena);
619
0
  if (wrapped == nullptr) {
620
0
    return absl::UnknownError("failed to convert legacy map to JSON");
621
0
  }
622
623
0
  if (wrapped->GetDescriptor() == json->GetDescriptor()) {
624
    // We can directly use google::protobuf::Message::Copy().
625
0
    json->CopyFrom(*wrapped);
626
0
  } else {
627
    // Equivalent descriptors but not identical. Must serialize and deserialize.
628
0
    absl::Cord serialized;
629
0
    if (!wrapped->SerializePartialToString(&serialized)) {
630
0
      return absl::UnknownError(absl::StrCat("failed to serialize message: ",
631
0
                                             wrapped->GetTypeName()));
632
0
    }
633
0
    if (!json->ParsePartialFromString(serialized)) {
634
0
      return absl::UnknownError(
635
0
          absl::StrCat("failed to parsed message: ", json->GetTypeName()));
636
0
    }
637
0
  }
638
0
  return absl::OkStatus();
639
0
}
640
641
absl::Status LegacyMapValue::ConvertToJsonObject(
642
    const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
643
    google::protobuf::MessageFactory* absl_nonnull message_factory,
644
0
    google::protobuf::Message* absl_nonnull json) const {
645
0
  ABSL_DCHECK(descriptor_pool != nullptr);
646
0
  ABSL_DCHECK(message_factory != nullptr);
647
0
  ABSL_DCHECK(json != nullptr);
648
0
  ABSL_DCHECK_EQ(json->GetDescriptor()->well_known_type(),
649
0
                 google::protobuf::Descriptor::WELLKNOWNTYPE_STRUCT);
650
651
0
  google::protobuf::Arena arena;
652
0
  const google::protobuf::Message* wrapped =
653
0
      MaybeWrapValueToMessage(json->GetDescriptor(), message_factory,
654
0
                              CelValue::CreateMap(impl_), &arena);
655
0
  if (wrapped == nullptr) {
656
0
    return absl::UnknownError("failed to convert legacy map to JSON");
657
0
  }
658
659
0
  if (wrapped->GetDescriptor() == json->GetDescriptor()) {
660
    // We can directly use google::protobuf::Message::Copy().
661
0
    json->CopyFrom(*wrapped);
662
0
  } else {
663
    // Equivalent descriptors but not identical. Must serialize and deserialize.
664
0
    absl::Cord serialized;
665
0
    if (!wrapped->SerializePartialToString(&serialized)) {
666
0
      return absl::UnknownError(absl::StrCat("failed to serialize message: ",
667
0
                                             wrapped->GetTypeName()));
668
0
    }
669
0
    if (!json->ParsePartialFromString(serialized)) {
670
0
      return absl::UnknownError(
671
0
          absl::StrCat("failed to parsed message: ", json->GetTypeName()));
672
0
    }
673
0
  }
674
0
  return absl::OkStatus();
675
0
}
676
677
0
bool LegacyMapValue::IsEmpty() const { return impl_->empty(); }
678
679
3
size_t LegacyMapValue::Size() const {
680
3
  return static_cast<size_t>(impl_->size());
681
3
}
682
683
absl::Status LegacyMapValue::Get(
684
    const Value& key,
685
    const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
686
    google::protobuf::MessageFactory* absl_nonnull message_factory,
687
104k
    google::protobuf::Arena* absl_nonnull arena, Value* absl_nonnull result) const {
688
104k
  switch (key.kind()) {
689
0
    case ValueKind::kError:
690
0
      ABSL_FALLTHROUGH_INTENDED;
691
0
    case ValueKind::kUnknown:
692
0
      *result = Value{key};
693
0
      return absl::OkStatus();
694
252
    case ValueKind::kBool:
695
252
      ABSL_FALLTHROUGH_INTENDED;
696
252
    case ValueKind::kInt:
697
252
      ABSL_FALLTHROUGH_INTENDED;
698
252
    case ValueKind::kUint:
699
252
      ABSL_FALLTHROUGH_INTENDED;
700
104k
    case ValueKind::kString:
701
104k
      break;
702
0
    default:
703
0
      *result = ErrorValue(InvalidMapKeyTypeError(key.kind()));
704
0
      return absl::OkStatus();
705
104k
  }
706
208k
  CEL_ASSIGN_OR_RETURN(auto cel_key, LegacyValue(arena, key));
707
208k
  auto cel_value = impl_->Get(arena, cel_key);
708
208k
  if (!cel_value.has_value()) {
709
104k
    *result = NoSuchKeyError(key.DebugString());
710
104k
    return absl::OkStatus();
711
104k
  }
712
104k
  CEL_RETURN_IF_ERROR(ModernValue(arena, *cel_value, *result));
713
252
  return absl::OkStatus();
714
252
}
715
716
absl::StatusOr<bool> LegacyMapValue::Find(
717
    const Value& key,
718
    const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
719
    google::protobuf::MessageFactory* absl_nonnull message_factory,
720
93.2k
    google::protobuf::Arena* absl_nonnull arena, Value* absl_nonnull result) const {
721
93.2k
  switch (key.kind()) {
722
0
    case ValueKind::kError:
723
0
      ABSL_FALLTHROUGH_INTENDED;
724
0
    case ValueKind::kUnknown:
725
0
      *result = Value{key};
726
0
      return false;
727
0
    case ValueKind::kBool:
728
0
      ABSL_FALLTHROUGH_INTENDED;
729
349
    case ValueKind::kInt:
730
349
      ABSL_FALLTHROUGH_INTENDED;
731
93.2k
    case ValueKind::kUint:
732
93.2k
      ABSL_FALLTHROUGH_INTENDED;
733
93.2k
    case ValueKind::kString:
734
93.2k
      break;
735
0
    default:
736
0
      *result = ErrorValue(InvalidMapKeyTypeError(key.kind()));
737
93.2k
  }
738
186k
  CEL_ASSIGN_OR_RETURN(auto cel_key, LegacyValue(arena, key));
739
186k
  auto cel_value = impl_->Get(arena, cel_key);
740
186k
  if (!cel_value.has_value()) {
741
0
    *result = NullValue{};
742
0
    return false;
743
0
  }
744
93.2k
  CEL_RETURN_IF_ERROR(ModernValue(arena, *cel_value, *result));
745
93.2k
  return true;
746
93.2k
}
747
748
absl::Status LegacyMapValue::Has(
749
    const Value& key,
750
    const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
751
    google::protobuf::MessageFactory* absl_nonnull message_factory,
752
950
    google::protobuf::Arena* absl_nonnull arena, Value* absl_nonnull result) const {
753
950
  switch (key.kind()) {
754
0
    case ValueKind::kError:
755
0
      ABSL_FALLTHROUGH_INTENDED;
756
0
    case ValueKind::kUnknown:
757
0
      *result = Value{key};
758
0
      return absl::OkStatus();
759
135
    case ValueKind::kBool:
760
135
      ABSL_FALLTHROUGH_INTENDED;
761
303
    case ValueKind::kInt:
762
303
      ABSL_FALLTHROUGH_INTENDED;
763
466
    case ValueKind::kUint:
764
466
      ABSL_FALLTHROUGH_INTENDED;
765
898
    case ValueKind::kString:
766
898
      break;
767
52
    default:
768
52
      *result = ErrorValue(InvalidMapKeyTypeError(key.kind()));
769
52
      return absl::OkStatus();
770
950
  }
771
1.79k
  CEL_ASSIGN_OR_RETURN(auto cel_key, LegacyValue(arena, key));
772
1.79k
  absl::StatusOr<bool> has = impl_->Has(cel_key);
773
1.79k
  if (!has.ok()) {
774
466
    *result = ErrorValue(std::move(has).status());
775
466
    return absl::OkStatus();
776
466
  }
777
778
432
  *result = BoolValue(*has);
779
432
  return absl::OkStatus();
780
1.79k
}
781
782
absl::Status LegacyMapValue::ListKeys(
783
    const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
784
    google::protobuf::MessageFactory* absl_nonnull message_factory,
785
0
    google::protobuf::Arena* absl_nonnull arena, ListValue* absl_nonnull result) const {
786
0
  CEL_ASSIGN_OR_RETURN(auto keys, impl_->ListKeys(arena));
787
0
  *result = ListValue{common_internal::LegacyListValue(keys)};
788
0
  return absl::OkStatus();
789
0
}
790
791
absl::Status LegacyMapValue::ForEach(
792
    ForEachCallback callback,
793
    const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
794
    google::protobuf::MessageFactory* absl_nonnull message_factory,
795
0
    google::protobuf::Arena* absl_nonnull arena) const {
796
0
  CEL_ASSIGN_OR_RETURN(auto keys, impl_->ListKeys(arena));
797
0
  const auto size = keys->size();
798
0
  Value key;
799
0
  Value value;
800
0
  for (int index = 0; index < size; ++index) {
801
0
    auto cel_key = keys->Get(arena, index);
802
0
    auto cel_value = *impl_->Get(arena, cel_key);
803
0
    CEL_RETURN_IF_ERROR(ModernValue(arena, cel_key, key));
804
0
    CEL_RETURN_IF_ERROR(ModernValue(arena, cel_value, value));
805
0
    CEL_ASSIGN_OR_RETURN(auto ok, callback(key, value));
806
0
    if (!ok) {
807
0
      break;
808
0
    }
809
0
  }
810
0
  return absl::OkStatus();
811
0
}
812
813
absl::StatusOr<absl_nonnull ValueIteratorPtr> LegacyMapValue::NewIterator()
814
200
    const {
815
200
  return std::make_unique<CelMapIterator>(impl_);
816
200
}
817
818
0
absl::string_view LegacyStructValue::GetTypeName() const {
819
0
  auto message_wrapper = AsMessageWrapper(message_ptr_, legacy_type_info_);
820
0
  return message_wrapper.legacy_type_info()->GetTypename(message_wrapper);
821
0
}
822
823
0
std::string LegacyStructValue::DebugString() const {
824
0
  auto message_wrapper = AsMessageWrapper(message_ptr_, legacy_type_info_);
825
0
  return message_wrapper.legacy_type_info()->DebugString(message_wrapper);
826
0
}
827
828
absl::Status LegacyStructValue::SerializeTo(
829
    const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
830
    google::protobuf::MessageFactory* absl_nonnull message_factory,
831
0
    google::protobuf::io::ZeroCopyOutputStream* absl_nonnull output) const {
832
0
  ABSL_DCHECK(descriptor_pool != nullptr);
833
0
  ABSL_DCHECK(message_factory != nullptr);
834
0
  ABSL_DCHECK(output != nullptr);
835
836
0
  auto message_wrapper = AsMessageWrapper(message_ptr_, legacy_type_info_);
837
0
  if (ABSL_PREDICT_TRUE(
838
0
          message_wrapper.message_ptr()->SerializePartialToZeroCopyStream(
839
0
              output))) {
840
0
    return absl::OkStatus();
841
0
  }
842
0
  return absl::UnknownError("failed to serialize protocol buffer message");
843
0
}
844
845
absl::Status LegacyStructValue::ConvertToJson(
846
    const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
847
    google::protobuf::MessageFactory* absl_nonnull message_factory,
848
0
    google::protobuf::Message* absl_nonnull json) const {
849
0
  ABSL_DCHECK(descriptor_pool != nullptr);
850
0
  ABSL_DCHECK(message_factory != nullptr);
851
0
  ABSL_DCHECK(json != nullptr);
852
0
  ABSL_DCHECK_EQ(json->GetDescriptor()->well_known_type(),
853
0
                 google::protobuf::Descriptor::WELLKNOWNTYPE_VALUE);
854
855
0
  auto message_wrapper = AsMessageWrapper(message_ptr_, legacy_type_info_);
856
857
0
  return internal::MessageToJson(
858
0
      *google::protobuf::DownCastMessage<google::protobuf::Message>(message_wrapper.message_ptr()),
859
0
      descriptor_pool, message_factory, json);
860
0
}
861
862
absl::Status LegacyStructValue::ConvertToJsonObject(
863
    const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
864
    google::protobuf::MessageFactory* absl_nonnull message_factory,
865
0
    google::protobuf::Message* absl_nonnull json) const {
866
0
  ABSL_DCHECK(descriptor_pool != nullptr);
867
0
  ABSL_DCHECK(message_factory != nullptr);
868
0
  ABSL_DCHECK(json != nullptr);
869
0
  ABSL_DCHECK_EQ(json->GetDescriptor()->well_known_type(),
870
0
                 google::protobuf::Descriptor::WELLKNOWNTYPE_STRUCT);
871
872
0
  auto message_wrapper = AsMessageWrapper(message_ptr_, legacy_type_info_);
873
874
0
  return internal::MessageToJson(
875
0
      *google::protobuf::DownCastMessage<google::protobuf::Message>(message_wrapper.message_ptr()),
876
0
      descriptor_pool, message_factory, json);
877
0
}
878
879
absl::Status LegacyStructValue::Equal(
880
    const Value& other,
881
    const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
882
    google::protobuf::MessageFactory* absl_nonnull message_factory,
883
12
    google::protobuf::Arena* absl_nonnull arena, Value* absl_nonnull result) const {
884
12
  if (auto legacy_struct_value = common_internal::AsLegacyStructValue(other);
885
12
      legacy_struct_value.has_value()) {
886
0
    auto message_wrapper = AsMessageWrapper(message_ptr_, legacy_type_info_);
887
0
    const auto* access_apis =
888
0
        message_wrapper.legacy_type_info()->GetAccessApis(message_wrapper);
889
0
    if (ABSL_PREDICT_FALSE(access_apis == nullptr)) {
890
0
      return absl::UnimplementedError(
891
0
          absl::StrCat("legacy access APIs missing for ", GetTypeName()));
892
0
    }
893
0
    auto other_message_wrapper =
894
0
        AsMessageWrapper(legacy_struct_value->message_ptr(),
895
0
                         legacy_struct_value->legacy_type_info());
896
0
    *result = BoolValue{
897
0
        access_apis->IsEqualTo(message_wrapper, other_message_wrapper)};
898
0
    return absl::OkStatus();
899
0
  }
900
12
  if (auto struct_value = other.AsStruct(); struct_value.has_value()) {
901
0
    return common_internal::StructValueEqual(
902
0
        common_internal::LegacyStructValue(message_ptr_, legacy_type_info_),
903
0
        *struct_value, descriptor_pool, message_factory, arena, result);
904
0
  }
905
12
  *result = FalseValue();
906
12
  return absl::OkStatus();
907
12
}
908
909
0
bool LegacyStructValue::IsZeroValue() const {
910
0
  auto message_wrapper = AsMessageWrapper(message_ptr_, legacy_type_info_);
911
0
  const auto* access_apis =
912
0
      message_wrapper.legacy_type_info()->GetAccessApis(message_wrapper);
913
0
  if (ABSL_PREDICT_FALSE(access_apis == nullptr)) {
914
0
    return false;
915
0
  }
916
0
  return access_apis->ListFields(message_wrapper).empty();
917
0
}
918
919
absl::Status LegacyStructValue::GetFieldByName(
920
    absl::string_view name, ProtoWrapperTypeOptions unboxing_options,
921
    const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
922
    google::protobuf::MessageFactory* absl_nonnull message_factory,
923
26.4k
    google::protobuf::Arena* absl_nonnull arena, Value* absl_nonnull result) const {
924
26.4k
  auto message_wrapper = AsMessageWrapper(message_ptr_, legacy_type_info_);
925
26.4k
  const auto* access_apis =
926
26.4k
      message_wrapper.legacy_type_info()->GetAccessApis(message_wrapper);
927
26.4k
  if (ABSL_PREDICT_FALSE(access_apis == nullptr)) {
928
0
    *result = NoSuchFieldError(name);
929
0
    return absl::OkStatus();
930
0
  }
931
52.8k
  CEL_ASSIGN_OR_RETURN(
932
52.8k
      auto cel_value,
933
52.8k
      access_apis->GetField(name, message_wrapper, unboxing_options,
934
52.8k
                            MemoryManagerRef::Pooling(arena)));
935
52.8k
  CEL_RETURN_IF_ERROR(ModernValue(arena, cel_value, *result));
936
26.4k
  return absl::OkStatus();
937
52.8k
}
938
939
absl::Status LegacyStructValue::GetFieldByNumber(
940
    int64_t number, ProtoWrapperTypeOptions unboxing_options,
941
    const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
942
    google::protobuf::MessageFactory* absl_nonnull message_factory,
943
0
    google::protobuf::Arena* absl_nonnull arena, Value* absl_nonnull result) const {
944
0
  return absl::UnimplementedError(
945
0
      "access to fields by numbers is not available for legacy structs");
946
0
}
947
948
absl::StatusOr<bool> LegacyStructValue::HasFieldByName(
949
0
    absl::string_view name) const {
950
0
  auto message_wrapper = AsMessageWrapper(message_ptr_, legacy_type_info_);
951
0
  const auto* access_apis =
952
0
      message_wrapper.legacy_type_info()->GetAccessApis(message_wrapper);
953
0
  if (ABSL_PREDICT_FALSE(access_apis == nullptr)) {
954
0
    return NoSuchFieldError(name).NativeValue();
955
0
  }
956
0
  return access_apis->HasField(name, message_wrapper);
957
0
}
958
959
0
absl::StatusOr<bool> LegacyStructValue::HasFieldByNumber(int64_t number) const {
960
0
  return absl::UnimplementedError(
961
0
      "access to fields by numbers is not available for legacy structs");
962
0
}
963
964
absl::Status LegacyStructValue::ForEachField(
965
    ForEachFieldCallback callback,
966
    const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
967
    google::protobuf::MessageFactory* absl_nonnull message_factory,
968
0
    google::protobuf::Arena* absl_nonnull arena) const {
969
0
  auto message_wrapper = AsMessageWrapper(message_ptr_, legacy_type_info_);
970
0
  const auto* access_apis =
971
0
      message_wrapper.legacy_type_info()->GetAccessApis(message_wrapper);
972
0
  if (ABSL_PREDICT_FALSE(access_apis == nullptr)) {
973
0
    return absl::UnimplementedError(
974
0
        absl::StrCat("legacy access APIs missing for ", GetTypeName()));
975
0
  }
976
0
  auto field_names = access_apis->ListFields(message_wrapper);
977
0
  Value value;
978
0
  for (const auto& field_name : field_names) {
979
0
    CEL_ASSIGN_OR_RETURN(
980
0
        auto cel_value,
981
0
        access_apis->GetField(field_name, message_wrapper,
982
0
                              ProtoWrapperTypeOptions::kUnsetNull,
983
0
                              MemoryManagerRef::Pooling(arena)));
984
0
    CEL_RETURN_IF_ERROR(ModernValue(arena, cel_value, value));
985
0
    CEL_ASSIGN_OR_RETURN(auto ok, callback(field_name, value));
986
0
    if (!ok) {
987
0
      break;
988
0
    }
989
0
  }
990
0
  return absl::OkStatus();
991
0
}
992
993
absl::Status LegacyStructValue::Qualify(
994
    absl::Span<const SelectQualifier> qualifiers, bool presence_test,
995
    const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
996
    google::protobuf::MessageFactory* absl_nonnull message_factory,
997
    google::protobuf::Arena* absl_nonnull arena, Value* absl_nonnull result,
998
0
    int* absl_nonnull count) const {
999
0
  if (ABSL_PREDICT_FALSE(qualifiers.empty())) {
1000
0
    return absl::InvalidArgumentError("invalid select qualifier path.");
1001
0
  }
1002
0
  auto message_wrapper = AsMessageWrapper(message_ptr_, legacy_type_info_);
1003
0
  const auto* access_apis =
1004
0
      message_wrapper.legacy_type_info()->GetAccessApis(message_wrapper);
1005
0
  if (ABSL_PREDICT_FALSE(access_apis == nullptr)) {
1006
0
    absl::string_view field_name = absl::visit(
1007
0
        absl::Overload(
1008
0
            [](const FieldSpecifier& field) -> absl::string_view {
1009
0
              return field.name;
1010
0
            },
1011
0
            [](const AttributeQualifier& field) -> absl::string_view {
1012
0
              return field.GetStringKey().value_or("<invalid field>");
1013
0
            }),
1014
0
        qualifiers.front());
1015
0
    *result = NoSuchFieldError(field_name);
1016
0
    *count = -1;
1017
0
    return absl::OkStatus();
1018
0
  }
1019
0
  CEL_ASSIGN_OR_RETURN(
1020
0
      auto legacy_result,
1021
0
      access_apis->Qualify(qualifiers, message_wrapper, presence_test,
1022
0
                           MemoryManager::Pooling(arena)));
1023
0
  CEL_RETURN_IF_ERROR(ModernValue(arena, legacy_result.value, *result));
1024
0
  *count = legacy_result.qualifier_count;
1025
0
  return absl::OkStatus();
1026
0
}
1027
1028
}  // namespace common_internal
1029
1030
absl::Status ModernValue(google::protobuf::Arena* arena,
1031
                         google::api::expr::runtime::CelValue legacy_value,
1032
370k
                         Value& result) {
1033
370k
  switch (legacy_value.type()) {
1034
183
    case CelValue::Type::kNullType:
1035
183
      result = NullValue{};
1036
183
      return absl::OkStatus();
1037
2
    case CelValue::Type::kBool:
1038
2
      result = BoolValue{legacy_value.BoolOrDie()};
1039
2
      return absl::OkStatus();
1040
47
    case CelValue::Type::kInt64:
1041
47
      result = IntValue{legacy_value.Int64OrDie()};
1042
47
      return absl::OkStatus();
1043
788
    case CelValue::Type::kUint64:
1044
788
      result = UintValue{legacy_value.Uint64OrDie()};
1045
788
      return absl::OkStatus();
1046
131
    case CelValue::Type::kDouble:
1047
131
      result = DoubleValue{legacy_value.DoubleOrDie()};
1048
131
      return absl::OkStatus();
1049
2.95k
    case CelValue::Type::kString:
1050
2.95k
      result = StringValue(Borrower::Arena(arena),
1051
2.95k
                           legacy_value.StringOrDie().value());
1052
2.95k
      return absl::OkStatus();
1053
9.62k
    case CelValue::Type::kBytes:
1054
9.62k
      result =
1055
9.62k
          BytesValue(Borrower::Arena(arena), legacy_value.BytesOrDie().value());
1056
9.62k
      return absl::OkStatus();
1057
26.4k
    case CelValue::Type::kMessage: {
1058
26.4k
      auto message_wrapper = legacy_value.MessageWrapperOrDie();
1059
26.4k
      result = common_internal::LegacyStructValue(
1060
26.4k
          google::protobuf::DownCastMessage<google::protobuf::Message>(
1061
26.4k
              message_wrapper.message_ptr()),
1062
26.4k
          message_wrapper.legacy_type_info());
1063
26.4k
      return absl::OkStatus();
1064
0
    }
1065
15
    case CelValue::Type::kDuration:
1066
15
      result = UnsafeDurationValue(legacy_value.DurationOrDie());
1067
15
      return absl::OkStatus();
1068
386
    case CelValue::Type::kTimestamp:
1069
386
      result = UnsafeTimestampValue(legacy_value.TimestampOrDie());
1070
386
      return absl::OkStatus();
1071
2.27k
    case CelValue::Type::kList:
1072
2.27k
      result =
1073
2.27k
          ListValue(common_internal::LegacyListValue(legacy_value.ListOrDie()));
1074
2.27k
      return absl::OkStatus();
1075
207k
    case CelValue::Type::kMap:
1076
207k
      result =
1077
207k
          MapValue(common_internal::LegacyMapValue(legacy_value.MapOrDie()));
1078
207k
      return absl::OkStatus();
1079
0
    case CelValue::Type::kUnknownSet:
1080
0
      result = UnknownValue{*legacy_value.UnknownSetOrDie()};
1081
0
      return absl::OkStatus();
1082
0
    case CelValue::Type::kCelType: {
1083
0
      auto type_name = legacy_value.CelTypeOrDie().value();
1084
0
      if (type_name.empty()) {
1085
0
        return absl::InvalidArgumentError("empty type name in CelValue");
1086
0
      }
1087
0
      result = TypeValue(common_internal::LegacyRuntimeType(type_name));
1088
0
      return absl::OkStatus();
1089
0
    }
1090
120k
    case CelValue::Type::kError:
1091
120k
      result = ErrorValue{*legacy_value.ErrorOrDie()};
1092
120k
      return absl::OkStatus();
1093
0
    case CelValue::Type::kAny:
1094
0
      return absl::InternalError(absl::StrCat(
1095
0
          "illegal attempt to convert special CelValue type ",
1096
0
          CelValue::TypeName(legacy_value.type()), " to cel::Value"));
1097
0
    default:
1098
0
      break;
1099
370k
  }
1100
0
  return absl::InvalidArgumentError(absl::StrCat(
1101
0
      "cel::Value does not support ", KindToString(legacy_value.type())));
1102
370k
}
1103
1104
absl::StatusOr<google::api::expr::runtime::CelValue> LegacyValue(
1105
198k
    google::protobuf::Arena* arena, const Value& modern_value) {
1106
198k
  switch (modern_value.kind()) {
1107
0
    case ValueKind::kNull:
1108
0
      return CelValue::CreateNull();
1109
387
    case ValueKind::kBool:
1110
387
      return CelValue::CreateBool(Cast<BoolValue>(modern_value).NativeValue());
1111
517
    case ValueKind::kInt:
1112
517
      return CelValue::CreateInt64(Cast<IntValue>(modern_value).NativeValue());
1113
93.0k
    case ValueKind::kUint:
1114
93.0k
      return CelValue::CreateUint64(
1115
93.0k
          Cast<UintValue>(modern_value).NativeValue());
1116
0
    case ValueKind::kDouble:
1117
0
      return CelValue::CreateDouble(
1118
0
          Cast<DoubleValue>(modern_value).NativeValue());
1119
104k
    case ValueKind::kString:
1120
104k
      return CelValue::CreateStringView(common_internal::LegacyStringValue(
1121
104k
          modern_value.GetString(), /*stable=*/false, arena));
1122
0
    case ValueKind::kBytes:
1123
0
      return CelValue::CreateBytesView(common_internal::LegacyBytesValue(
1124
0
          modern_value.GetBytes(), /*stable=*/false, arena));
1125
0
    case ValueKind::kStruct:
1126
0
      return common_internal::LegacyTrivialStructValue(arena, modern_value);
1127
0
    case ValueKind::kDuration:
1128
0
      return CelValue::CreateUncheckedDuration(
1129
0
          modern_value.GetDuration().NativeValue());
1130
0
    case ValueKind::kTimestamp:
1131
0
      return CelValue::CreateTimestamp(
1132
0
          modern_value.GetTimestamp().NativeValue());
1133
0
    case ValueKind::kList:
1134
0
      return common_internal::LegacyTrivialListValue(arena, modern_value);
1135
0
    case ValueKind::kMap:
1136
0
      return common_internal::LegacyTrivialMapValue(arena, modern_value);
1137
0
    case ValueKind::kUnknown:
1138
0
      return CelValue::CreateUnknownSet(google::protobuf::Arena::Create<Unknown>(
1139
0
          arena, Cast<UnknownValue>(modern_value).NativeValue()));
1140
0
    case ValueKind::kType:
1141
0
      return CelValue::CreateCelType(
1142
0
          CelValue::CelTypeHolder(google::protobuf::Arena::Create<std::string>(
1143
0
              arena, Cast<TypeValue>(modern_value).NativeValue().name())));
1144
0
    case ValueKind::kError:
1145
0
      return CelValue::CreateError(google::protobuf::Arena::Create<absl::Status>(
1146
0
          arena, Cast<ErrorValue>(modern_value).NativeValue()));
1147
0
    default:
1148
0
      return absl::InvalidArgumentError(
1149
0
          absl::StrCat("google::api::expr::runtime::CelValue does not support ",
1150
0
                       ValueKindToString(modern_value.kind())));
1151
198k
  }
1152
198k
}
1153
1154
namespace interop_internal {
1155
1156
absl::StatusOr<Value> FromLegacyValue(google::protobuf::Arena* arena,
1157
0
                                      const CelValue& legacy_value, bool) {
1158
0
  switch (legacy_value.type()) {
1159
0
    case CelValue::Type::kNullType:
1160
0
      return NullValue{};
1161
0
    case CelValue::Type::kBool:
1162
0
      return BoolValue(legacy_value.BoolOrDie());
1163
0
    case CelValue::Type::kInt64:
1164
0
      return IntValue(legacy_value.Int64OrDie());
1165
0
    case CelValue::Type::kUint64:
1166
0
      return UintValue(legacy_value.Uint64OrDie());
1167
0
    case CelValue::Type::kDouble:
1168
0
      return DoubleValue(legacy_value.DoubleOrDie());
1169
0
    case CelValue::Type::kString:
1170
0
      return StringValue(Borrower::Arena(arena),
1171
0
                         legacy_value.StringOrDie().value());
1172
0
    case CelValue::Type::kBytes:
1173
0
      return BytesValue(Borrower::Arena(arena),
1174
0
                        legacy_value.BytesOrDie().value());
1175
0
    case CelValue::Type::kMessage: {
1176
0
      auto message_wrapper = legacy_value.MessageWrapperOrDie();
1177
0
      return common_internal::LegacyStructValue(
1178
0
          google::protobuf::DownCastMessage<google::protobuf::Message>(
1179
0
              message_wrapper.message_ptr()),
1180
0
          message_wrapper.legacy_type_info());
1181
0
    }
1182
0
    case CelValue::Type::kDuration:
1183
0
      return UnsafeDurationValue(legacy_value.DurationOrDie());
1184
0
    case CelValue::Type::kTimestamp:
1185
0
      return UnsafeTimestampValue(legacy_value.TimestampOrDie());
1186
0
    case CelValue::Type::kList:
1187
0
      return ListValue(
1188
0
          common_internal::LegacyListValue(legacy_value.ListOrDie()));
1189
0
    case CelValue::Type::kMap:
1190
0
      return MapValue(common_internal::LegacyMapValue(legacy_value.MapOrDie()));
1191
0
    case CelValue::Type::kUnknownSet:
1192
0
      return UnknownValue{*legacy_value.UnknownSetOrDie()};
1193
0
    case CelValue::Type::kCelType:
1194
0
      return CreateTypeValueFromView(arena,
1195
0
                                     legacy_value.CelTypeOrDie().value());
1196
0
    case CelValue::Type::kError:
1197
0
      return ErrorValue(*legacy_value.ErrorOrDie());
1198
0
    case CelValue::Type::kAny:
1199
0
      return absl::InternalError(absl::StrCat(
1200
0
          "illegal attempt to convert special CelValue type ",
1201
0
          CelValue::TypeName(legacy_value.type()), " to cel::Value"));
1202
0
    default:
1203
0
      break;
1204
0
  }
1205
0
  return absl::UnimplementedError(absl::StrCat(
1206
0
      "conversion from CelValue to cel::Value for type ",
1207
0
      CelValue::TypeName(legacy_value.type()), " is not yet implemented"));
1208
0
}
1209
1210
absl::StatusOr<google::api::expr::runtime::CelValue> ToLegacyValue(
1211
10.3k
    google::protobuf::Arena* arena, const Value& value, bool) {
1212
10.3k
  switch (value.kind()) {
1213
2
    case ValueKind::kNull:
1214
2
      return CelValue::CreateNull();
1215
3.39k
    case ValueKind::kBool:
1216
3.39k
      return CelValue::CreateBool(Cast<BoolValue>(value).NativeValue());
1217
393
    case ValueKind::kInt:
1218
393
      return CelValue::CreateInt64(Cast<IntValue>(value).NativeValue());
1219
146
    case ValueKind::kUint:
1220
146
      return CelValue::CreateUint64(Cast<UintValue>(value).NativeValue());
1221
451
    case ValueKind::kDouble:
1222
451
      return CelValue::CreateDouble(Cast<DoubleValue>(value).NativeValue());
1223
240
    case ValueKind::kString:
1224
240
      return CelValue::CreateStringView(common_internal::LegacyStringValue(
1225
240
          value.GetString(), /*stable=*/false, arena));
1226
59
    case ValueKind::kBytes:
1227
59
      return CelValue::CreateBytesView(common_internal::LegacyBytesValue(
1228
59
          value.GetBytes(), /*stable=*/false, arena));
1229
2
    case ValueKind::kStruct:
1230
2
      return common_internal::LegacyTrivialStructValue(arena, value);
1231
65
    case ValueKind::kDuration:
1232
65
      return CelValue::CreateUncheckedDuration(
1233
65
          Cast<DurationValue>(value).NativeValue());
1234
1
    case ValueKind::kTimestamp:
1235
1
      return CelValue::CreateTimestamp(
1236
1
          Cast<TimestampValue>(value).NativeValue());
1237
218
    case ValueKind::kList:
1238
218
      return common_internal::LegacyTrivialListValue(arena, value);
1239
35
    case ValueKind::kMap:
1240
35
      return common_internal::LegacyTrivialMapValue(arena, value);
1241
0
    case ValueKind::kUnknown:
1242
0
      return CelValue::CreateUnknownSet(google::protobuf::Arena::Create<Unknown>(
1243
0
          arena, Cast<UnknownValue>(value).NativeValue()));
1244
15
    case ValueKind::kType:
1245
15
      return CelValue::CreateCelType(
1246
15
          CelValue::CelTypeHolder(google::protobuf::Arena::Create<std::string>(
1247
15
              arena, Cast<TypeValue>(value).NativeValue().name())));
1248
5.28k
    case ValueKind::kError:
1249
5.28k
      return CelValue::CreateError(google::protobuf::Arena::Create<absl::Status>(
1250
5.28k
          arena, Cast<ErrorValue>(value).NativeValue()));
1251
0
    default:
1252
0
      return absl::InvalidArgumentError(
1253
0
          absl::StrCat("google::api::expr::runtime::CelValue does not support ",
1254
0
                       ValueKindToString(value.kind())));
1255
10.3k
  }
1256
10.3k
}
1257
1258
Value LegacyValueToModernValueOrDie(
1259
    google::protobuf::Arena* arena, const google::api::expr::runtime::CelValue& value,
1260
0
    bool unchecked) {
1261
0
  auto status_or_value = FromLegacyValue(arena, value, unchecked);
1262
0
  ABSL_CHECK_OK(status_or_value.status());  // Crash OK
1263
0
  return std::move(*status_or_value);
1264
0
}
1265
1266
std::vector<Value> LegacyValueToModernValueOrDie(
1267
    google::protobuf::Arena* arena,
1268
    absl::Span<const google::api::expr::runtime::CelValue> values,
1269
0
    bool unchecked) {
1270
0
  std::vector<Value> modern_values;
1271
0
  modern_values.reserve(values.size());
1272
0
  for (const auto& value : values) {
1273
0
    modern_values.push_back(
1274
0
        LegacyValueToModernValueOrDie(arena, value, unchecked));
1275
0
  }
1276
0
  return modern_values;
1277
0
}
1278
1279
google::api::expr::runtime::CelValue ModernValueToLegacyValueOrDie(
1280
10.3k
    google::protobuf::Arena* arena, const Value& value, bool unchecked) {
1281
10.3k
  auto status_or_value = ToLegacyValue(arena, value, unchecked);
1282
10.3k
  ABSL_CHECK_OK(status_or_value.status());  // Crash OK
1283
10.3k
  return std::move(*status_or_value);
1284
10.3k
}
1285
1286
TypeValue CreateTypeValueFromView(google::protobuf::Arena* arena,
1287
0
                                  absl::string_view input) {
1288
0
  return TypeValue(common_internal::LegacyRuntimeType(input));
1289
0
}
1290
1291
}  // namespace interop_internal
1292
1293
}  // namespace cel