Coverage Report

Created: 2026-09-14 06:52

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