Coverage Report

Created: 2026-05-27 07:00

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
28
absl::Status InvalidMapKeyTypeError(ValueKind kind) {
85
28
  return absl::InvalidArgumentError(
86
28
      absl::StrCat("Invalid map key type: '", ValueKindToString(kind), "'"));
87
28
}
88
89
MessageWrapper AsMessageWrapper(
90
    const google::protobuf::Message* absl_nullability_unknown message_ptr,
91
285
    const LegacyTypeInfoApis* absl_nullability_unknown type_info) {
92
285
  return MessageWrapper(message_ptr, type_info);
93
285
}
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
0
      : 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
0
      Value* absl_nonnull key_or_value) override {
192
0
    ABSL_DCHECK(descriptor_pool != nullptr);
193
0
    ABSL_DCHECK(message_factory != nullptr);
194
0
    ABSL_DCHECK(arena != nullptr);
195
0
    ABSL_DCHECK(key_or_value != nullptr);
196
197
0
    if (index_ >= size_) {
198
0
      return false;
199
0
    }
200
0
    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
1
                                  const Value& value) {
257
1
  if (auto legacy_struct_value = common_internal::AsLegacyStructValue(value);
258
1
      legacy_struct_value) {
259
1
    return CelValue::CreateMessageWrapper(
260
1
        AsMessageWrapper(legacy_struct_value->message_ptr(),
261
1
                         legacy_struct_value->legacy_type_info()));
262
1
  }
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
274
                                const Value& value) {
277
274
  if (auto legacy_list_value = common_internal::AsLegacyListValue(value);
278
274
      legacy_list_value) {
279
274
    return CelValue::CreateList(legacy_list_value->cel_list());
280
274
  }
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
44
                               const Value& value) {
315
44
  if (auto legacy_map_value = common_internal::AsLegacyMapValue(value);
316
44
      legacy_map_value) {
317
44
    return CelValue::CreateMap(legacy_map_value->cel_map());
318
44
  }
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
16
size_t LegacyListValue::Size() const {
512
16
  return static_cast<size_t>(impl_->size());
513
16
}
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
1
size_t LegacyMapValue::Size() const {
680
1
  return static_cast<size_t>(impl_->size());
681
1
}
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
433
    google::protobuf::Arena* absl_nonnull arena, Value* absl_nonnull result) const {
688
433
  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
7
    case ValueKind::kBool:
695
7
      ABSL_FALLTHROUGH_INTENDED;
696
7
    case ValueKind::kInt:
697
7
      ABSL_FALLTHROUGH_INTENDED;
698
7
    case ValueKind::kUint:
699
7
      ABSL_FALLTHROUGH_INTENDED;
700
433
    case ValueKind::kString:
701
433
      break;
702
0
    default:
703
0
      *result = ErrorValue(InvalidMapKeyTypeError(key.kind()));
704
0
      return absl::OkStatus();
705
433
  }
706
866
  CEL_ASSIGN_OR_RETURN(auto cel_key, LegacyValue(arena, key));
707
866
  auto cel_value = impl_->Get(arena, cel_key);
708
866
  if (!cel_value.has_value()) {
709
426
    *result = NoSuchKeyError(key.DebugString());
710
426
    return absl::OkStatus();
711
426
  }
712
433
  CEL_RETURN_IF_ERROR(ModernValue(arena, *cel_value, *result));
713
7
  return absl::OkStatus();
714
7
}
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
158
    google::protobuf::Arena* absl_nonnull arena, Value* absl_nonnull result) const {
721
158
  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
100
    case ValueKind::kInt:
730
100
      ABSL_FALLTHROUGH_INTENDED;
731
158
    case ValueKind::kUint:
732
158
      ABSL_FALLTHROUGH_INTENDED;
733
158
    case ValueKind::kString:
734
158
      break;
735
0
    default:
736
0
      *result = ErrorValue(InvalidMapKeyTypeError(key.kind()));
737
158
  }
738
316
  CEL_ASSIGN_OR_RETURN(auto cel_key, LegacyValue(arena, key));
739
316
  auto cel_value = impl_->Get(arena, cel_key);
740
316
  if (!cel_value.has_value()) {
741
0
    *result = NullValue{};
742
0
    return false;
743
0
  }
744
158
  CEL_RETURN_IF_ERROR(ModernValue(arena, *cel_value, *result));
745
158
  return true;
746
158
}
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
148
    google::protobuf::Arena* absl_nonnull arena, Value* absl_nonnull result) const {
753
148
  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
6
    case ValueKind::kBool:
760
6
      ABSL_FALLTHROUGH_INTENDED;
761
52
    case ValueKind::kInt:
762
52
      ABSL_FALLTHROUGH_INTENDED;
763
98
    case ValueKind::kUint:
764
98
      ABSL_FALLTHROUGH_INTENDED;
765
120
    case ValueKind::kString:
766
120
      break;
767
28
    default:
768
28
      *result = ErrorValue(InvalidMapKeyTypeError(key.kind()));
769
28
      return absl::OkStatus();
770
148
  }
771
240
  CEL_ASSIGN_OR_RETURN(auto cel_key, LegacyValue(arena, key));
772
240
  absl::StatusOr<bool> has = impl_->Has(cel_key);
773
240
  if (!has.ok()) {
774
98
    *result = ErrorValue(std::move(has).status());
775
98
    return absl::OkStatus();
776
98
  }
777
778
22
  *result = BoolValue(*has);
779
22
  return absl::OkStatus();
780
240
}
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
0
    const {
815
0
  return std::make_unique<CelMapIterator>(impl_);
816
0
}
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
1
    google::protobuf::Arena* absl_nonnull arena, Value* absl_nonnull result) const {
884
1
  if (auto legacy_struct_value = common_internal::AsLegacyStructValue(other);
885
1
      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
1
  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
1
  *result = FalseValue();
906
1
  return absl::OkStatus();
907
1
}
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
284
    google::protobuf::Arena* absl_nonnull arena, Value* absl_nonnull result) const {
924
284
  auto message_wrapper = AsMessageWrapper(message_ptr_, legacy_type_info_);
925
284
  const auto* access_apis =
926
284
      message_wrapper.legacy_type_info()->GetAccessApis(message_wrapper);
927
284
  if (ABSL_PREDICT_FALSE(access_apis == nullptr)) {
928
0
    *result = NoSuchFieldError(name);
929
0
    return absl::OkStatus();
930
0
  }
931
568
  CEL_ASSIGN_OR_RETURN(
932
568
      auto cel_value,
933
568
      access_apis->GetField(name, message_wrapper, unboxing_options,
934
568
                            MemoryManagerRef::Pooling(arena)));
935
568
  CEL_RETURN_IF_ERROR(ModernValue(arena, cel_value, *result));
936
284
  return absl::OkStatus();
937
568
}
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
2.10k
                         Value& result) {
1033
2.10k
  switch (legacy_value.type()) {
1034
42
    case CelValue::Type::kNullType:
1035
42
      result = NullValue{};
1036
42
      return absl::OkStatus();
1037
1
    case CelValue::Type::kBool:
1038
1
      result = BoolValue{legacy_value.BoolOrDie()};
1039
1
      return absl::OkStatus();
1040
76
    case CelValue::Type::kInt64:
1041
76
      result = IntValue{legacy_value.Int64OrDie()};
1042
76
      return absl::OkStatus();
1043
104
    case CelValue::Type::kUint64:
1044
104
      result = UintValue{legacy_value.Uint64OrDie()};
1045
104
      return absl::OkStatus();
1046
117
    case CelValue::Type::kDouble:
1047
117
      result = DoubleValue{legacy_value.DoubleOrDie()};
1048
117
      return absl::OkStatus();
1049
26
    case CelValue::Type::kString:
1050
26
      result = StringValue(Borrower::Arena(arena),
1051
26
                           legacy_value.StringOrDie().value());
1052
26
      return absl::OkStatus();
1053
102
    case CelValue::Type::kBytes:
1054
102
      result =
1055
102
          BytesValue(Borrower::Arena(arena), legacy_value.BytesOrDie().value());
1056
102
      return absl::OkStatus();
1057
289
    case CelValue::Type::kMessage: {
1058
289
      auto message_wrapper = legacy_value.MessageWrapperOrDie();
1059
289
      result = common_internal::LegacyStructValue(
1060
289
          google::protobuf::DownCastMessage<google::protobuf::Message>(
1061
289
              message_wrapper.message_ptr()),
1062
289
          message_wrapper.legacy_type_info());
1063
289
      return absl::OkStatus();
1064
0
    }
1065
6
    case CelValue::Type::kDuration:
1066
6
      result = UnsafeDurationValue(legacy_value.DurationOrDie());
1067
6
      return absl::OkStatus();
1068
48
    case CelValue::Type::kTimestamp:
1069
48
      result = UnsafeTimestampValue(legacy_value.TimestampOrDie());
1070
48
      return absl::OkStatus();
1071
87
    case CelValue::Type::kList:
1072
87
      result =
1073
87
          ListValue(common_internal::LegacyListValue(legacy_value.ListOrDie()));
1074
87
      return absl::OkStatus();
1075
677
    case CelValue::Type::kMap:
1076
677
      result =
1077
677
          MapValue(common_internal::LegacyMapValue(legacy_value.MapOrDie()));
1078
677
      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
528
    case CelValue::Type::kError:
1091
528
      result = ErrorValue{*legacy_value.ErrorOrDie()};
1092
528
      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
2.10k
  }
1100
0
  return absl::InvalidArgumentError(absl::StrCat(
1101
0
      "cel::Value does not support ", KindToString(legacy_value.type())));
1102
2.10k
}
1103
1104
absl::StatusOr<google::api::expr::runtime::CelValue> LegacyValue(
1105
711
    google::protobuf::Arena* arena, const Value& modern_value) {
1106
711
  switch (modern_value.kind()) {
1107
0
    case ValueKind::kNull:
1108
0
      return CelValue::CreateNull();
1109
13
    case ValueKind::kBool:
1110
13
      return CelValue::CreateBool(Cast<BoolValue>(modern_value).NativeValue());
1111
146
    case ValueKind::kInt:
1112
146
      return CelValue::CreateInt64(Cast<IntValue>(modern_value).NativeValue());
1113
104
    case ValueKind::kUint:
1114
104
      return CelValue::CreateUint64(
1115
104
          Cast<UintValue>(modern_value).NativeValue());
1116
0
    case ValueKind::kDouble:
1117
0
      return CelValue::CreateDouble(
1118
0
          Cast<DoubleValue>(modern_value).NativeValue());
1119
448
    case ValueKind::kString:
1120
448
      return CelValue::CreateStringView(common_internal::LegacyStringValue(
1121
448
          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
711
  }
1152
711
}
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
9.89k
    google::protobuf::Arena* arena, const Value& value, bool) {
1212
9.89k
  switch (value.kind()) {
1213
2
    case ValueKind::kNull:
1214
2
      return CelValue::CreateNull();
1215
3.34k
    case ValueKind::kBool:
1216
3.34k
      return CelValue::CreateBool(Cast<BoolValue>(value).NativeValue());
1217
421
    case ValueKind::kInt:
1218
421
      return CelValue::CreateInt64(Cast<IntValue>(value).NativeValue());
1219
143
    case ValueKind::kUint:
1220
143
      return CelValue::CreateUint64(Cast<UintValue>(value).NativeValue());
1221
329
    case ValueKind::kDouble:
1222
329
      return CelValue::CreateDouble(Cast<DoubleValue>(value).NativeValue());
1223
203
    case ValueKind::kString:
1224
203
      return CelValue::CreateStringView(common_internal::LegacyStringValue(
1225
203
          value.GetString(), /*stable=*/false, arena));
1226
67
    case ValueKind::kBytes:
1227
67
      return CelValue::CreateBytesView(common_internal::LegacyBytesValue(
1228
67
          value.GetBytes(), /*stable=*/false, arena));
1229
1
    case ValueKind::kStruct:
1230
1
      return common_internal::LegacyTrivialStructValue(arena, value);
1231
1
    case ValueKind::kDuration:
1232
1
      return CelValue::CreateUncheckedDuration(
1233
1
          Cast<DurationValue>(value).NativeValue());
1234
1
    case ValueKind::kTimestamp:
1235
1
      return CelValue::CreateTimestamp(
1236
1
          Cast<TimestampValue>(value).NativeValue());
1237
274
    case ValueKind::kList:
1238
274
      return common_internal::LegacyTrivialListValue(arena, value);
1239
44
    case ValueKind::kMap:
1240
44
      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
12
    case ValueKind::kType:
1245
12
      return CelValue::CreateCelType(
1246
12
          CelValue::CelTypeHolder(google::protobuf::Arena::Create<std::string>(
1247
12
              arena, Cast<TypeValue>(value).NativeValue().name())));
1248
5.05k
    case ValueKind::kError:
1249
5.05k
      return CelValue::CreateError(google::protobuf::Arena::Create<absl::Status>(
1250
5.05k
          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
9.89k
  }
1256
9.89k
}
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
9.89k
    google::protobuf::Arena* arena, const Value& value, bool unchecked) {
1281
9.89k
  auto status_or_value = ToLegacyValue(arena, value, unchecked);
1282
9.89k
  ABSL_CHECK_OK(status_or_value.status());  // Crash OK
1283
9.89k
  return std::move(*status_or_value);
1284
9.89k
}
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