Coverage Report

Created: 2026-10-09 06:57

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/kind.h"
40
#include "common/memory.h"
41
#include "common/type.h"
42
#include "common/unknown.h"
43
#include "common/value.h"
44
#include "common/value_kind.h"
45
#include "common/values/legacy_list_value.h"
46
#include "common/values/legacy_map_value.h"
47
#include "common/values/list_value_builder.h"
48
#include "common/values/map_value_builder.h"
49
#include "common/values/values.h"
50
#include "eval/internal/cel_value_equal.h"
51
#include "eval/public/cel_value.h"
52
#include "eval/public/message_wrapper.h"
53
#include "eval/public/structs/cel_proto_wrap_value_to_message.h"
54
#include "eval/public/structs/legacy_type_info_apis.h"
55
#include "eval/public/structs/proto_message_type_adapter.h"
56
#include "eval/public/structs/trivial_legacy_type_info_internal.h"
57
#include "internal/json.h"
58
#include "internal/status_macros.h"
59
#include "runtime/runtime_options.h"
60
#include "google/protobuf/arena.h"
61
#include "google/protobuf/descriptor.h"
62
#include "google/protobuf/io/zero_copy_stream.h"
63
#include "google/protobuf/message.h"
64
#include "google/protobuf/message_lite.h"
65
66
// TODO(uncreated-issue/76): improve coverage for JSON/Any handling
67
68
namespace cel {
69
70
namespace {
71
72
using ::cel::interop_internal::TrivialTypeInfo;
73
using ::google::api::expr::runtime::CelList;
74
using ::google::api::expr::runtime::CelMap;
75
using ::google::api::expr::runtime::CelValue;
76
using ::google::api::expr::runtime::GetGenericProtoTypeInfoInstance;
77
using ::google::api::expr::runtime::LegacyTypeInfoApis;
78
using ::google::api::expr::runtime::MessageWrapper;
79
using ::google::api::expr::runtime::internal::MaybeWrapValueToMessage;
80
81
0
absl::Status InvalidMapKeyTypeError(ValueKind kind) {
82
0
  return absl::InvalidArgumentError(
83
0
      absl::StrCat("Invalid map key type: '", ValueKindToString(kind), "'"));
84
0
}
85
86
MessageWrapper AsMessageWrapper(
87
    const google::protobuf::Message* absl_nullability_unknown message_ptr,
88
2
    const LegacyTypeInfoApis* absl_nullability_unknown type_info) {
89
2
  return MessageWrapper(message_ptr, type_info);
90
2
}
91
92
class CelListIterator final : public ValueIterator {
93
 public:
94
  explicit CelListIterator(const CelList* cel_list)
95
0
      : cel_list_(cel_list), size_(cel_list_->size()) {}
96
97
0
  bool HasNext() override { return index_ < size_; }
98
99
  absl::Status Next(const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
100
                    google::protobuf::MessageFactory* absl_nonnull message_factory,
101
                    google::protobuf::Arena* absl_nonnull arena,
102
0
                    Value* absl_nonnull result) override {
103
0
    if (!HasNext()) {
104
0
      return absl::FailedPreconditionError(
105
0
          "ValueIterator::Next() called when ValueIterator::HasNext() returns "
106
0
          "false");
107
0
    }
108
0
    auto cel_value = cel_list_->Get(arena, index_);
109
0
    CEL_RETURN_IF_ERROR(ModernValue(arena, cel_value, *result));
110
0
    ++index_;
111
0
    return absl::OkStatus();
112
0
  }
113
114
  absl::StatusOr<bool> Next1(
115
      const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
116
      google::protobuf::MessageFactory* absl_nonnull message_factory,
117
      google::protobuf::Arena* absl_nonnull arena,
118
0
      Value* absl_nonnull key_or_value) override {
119
0
    ABSL_DCHECK(descriptor_pool != nullptr);
120
0
    ABSL_DCHECK(message_factory != nullptr);
121
0
    ABSL_DCHECK(arena != nullptr);
122
0
    ABSL_DCHECK(key_or_value != nullptr);
123
124
0
    if (index_ >= size_) {
125
0
      return false;
126
0
    }
127
0
    auto cel_value = cel_list_->Get(arena, index_);
128
0
    CEL_RETURN_IF_ERROR(ModernValue(arena, cel_value, *key_or_value));
129
0
    ++index_;
130
0
    return true;
131
0
  }
132
133
  absl::StatusOr<bool> Next2(
134
      const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
135
      google::protobuf::MessageFactory* absl_nonnull message_factory,
136
      google::protobuf::Arena* absl_nonnull arena, Value* absl_nonnull key,
137
0
      Value* absl_nullable value) override {
138
0
    ABSL_DCHECK(descriptor_pool != nullptr);
139
0
    ABSL_DCHECK(message_factory != nullptr);
140
0
    ABSL_DCHECK(arena != nullptr);
141
0
    ABSL_DCHECK(key != nullptr);
142
143
0
    if (index_ >= size_) {
144
0
      return false;
145
0
    }
146
0
    if (value != nullptr) {
147
0
      auto cel_value = cel_list_->Get(arena, index_);
148
0
      CEL_RETURN_IF_ERROR(ModernValue(arena, cel_value, *value));
149
0
    }
150
0
    *key = IntValue(index_);
151
0
    ++index_;
152
0
    return true;
153
0
  }
154
155
 private:
156
  const CelList* const cel_list_;
157
  const int size_;
158
  int index_ = 0;
159
};
160
161
class CelMapIterator final : public ValueIterator {
162
 public:
163
  explicit CelMapIterator(const CelMap* cel_map)
164
0
      : cel_map_(cel_map), size_(cel_map->size()) {}
165
166
0
  bool HasNext() override { return index_ < size_; }
167
168
  absl::Status Next(const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
169
                    google::protobuf::MessageFactory* absl_nonnull message_factory,
170
                    google::protobuf::Arena* absl_nonnull arena,
171
0
                    Value* absl_nonnull result) override {
172
0
    if (!HasNext()) {
173
0
      return absl::FailedPreconditionError(
174
0
          "ValueIterator::Next() called when ValueIterator::HasNext() returns "
175
0
          "false");
176
0
    }
177
0
    CEL_RETURN_IF_ERROR(ProjectKeys(arena));
178
0
    auto cel_value = (*cel_list_)->Get(arena, index_);
179
0
    CEL_RETURN_IF_ERROR(ModernValue(arena, cel_value, *result));
180
0
    ++index_;
181
0
    return absl::OkStatus();
182
0
  }
183
184
  absl::StatusOr<bool> Next1(
185
      const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
186
      google::protobuf::MessageFactory* absl_nonnull message_factory,
187
      google::protobuf::Arena* absl_nonnull arena,
188
0
      Value* absl_nonnull key_or_value) override {
189
0
    ABSL_DCHECK(descriptor_pool != nullptr);
190
0
    ABSL_DCHECK(message_factory != nullptr);
191
0
    ABSL_DCHECK(arena != nullptr);
192
0
    ABSL_DCHECK(key_or_value != nullptr);
193
194
0
    if (index_ >= size_) {
195
0
      return false;
196
0
    }
197
0
    CEL_RETURN_IF_ERROR(ProjectKeys(arena));
198
0
    auto cel_value = (*cel_list_)->Get(arena, index_);
199
0
    CEL_RETURN_IF_ERROR(ModernValue(arena, cel_value, *key_or_value));
200
0
    ++index_;
201
0
    return true;
202
0
  }
203
204
  absl::StatusOr<bool> Next2(
205
      const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
206
      google::protobuf::MessageFactory* absl_nonnull message_factory,
207
      google::protobuf::Arena* absl_nonnull arena, Value* absl_nonnull key,
208
0
      Value* absl_nullable value) override {
209
0
    ABSL_DCHECK(descriptor_pool != nullptr);
210
0
    ABSL_DCHECK(message_factory != nullptr);
211
0
    ABSL_DCHECK(arena != nullptr);
212
0
    ABSL_DCHECK(key != nullptr);
213
214
0
    if (index_ >= size_) {
215
0
      return false;
216
0
    }
217
0
    CEL_RETURN_IF_ERROR(ProjectKeys(arena));
218
0
    auto cel_key = (*cel_list_)->Get(arena, index_);
219
0
    if (value != nullptr) {
220
0
      auto cel_value = cel_map_->Get(arena, cel_key);
221
0
      if (!cel_value) {
222
0
        return absl::DataLossError(
223
0
            "map iterator returned key that was not present in the map");
224
0
      }
225
0
      CEL_RETURN_IF_ERROR(ModernValue(arena, *cel_value, *value));
226
0
    }
227
0
    CEL_RETURN_IF_ERROR(ModernValue(arena, cel_key, *key));
228
0
    ++index_;
229
0
    return true;
230
0
  }
231
232
 private:
233
0
  absl::Status ProjectKeys(google::protobuf::Arena* arena) {
234
0
    if (cel_list_.ok() && *cel_list_ == nullptr) {
235
0
      cel_list_ = cel_map_->ListKeys(arena);
236
0
    }
237
0
    return cel_list_.status();
238
0
  }
239
240
  const CelMap* const cel_map_;
241
  const int size_ = 0;
242
  absl::StatusOr<const CelList*> cel_list_ = nullptr;
243
  int index_ = 0;
244
};
245
246
}  // namespace
247
248
namespace common_internal {
249
250
namespace {
251
252
CelValue LegacyTrivialStructValue(google::protobuf::Arena* absl_nonnull arena,
253
467k
                                  const Value& value) {
254
467k
  if (auto legacy_struct_value = common_internal::AsLegacyStructValue(value);
255
467k
      legacy_struct_value) {
256
2
    return CelValue::CreateMessageWrapper(
257
2
        AsMessageWrapper(legacy_struct_value->message_ptr(),
258
2
                         legacy_struct_value->legacy_type_info()));
259
2
  }
260
467k
  if (auto parsed_message_value = value.AsParsedMessage();
261
467k
      parsed_message_value) {
262
467k
    if (interop_internal::IsUnsafeParsedMessageValue(*parsed_message_value)) {
263
0
      return CelValue::CreateMessageWrapper(
264
0
          AsMessageWrapper(cel::to_address(*parsed_message_value),
265
0
                           &GetGenericProtoTypeInfoInstance()));
266
0
    }
267
467k
    auto maybe_cloned = parsed_message_value->Clone(arena);
268
467k
    return CelValue::CreateMessageWrapper(MessageWrapper(
269
467k
        cel::to_address(maybe_cloned), &GetGenericProtoTypeInfoInstance()));
270
467k
  }
271
0
  return CelValue::CreateError(google::protobuf::Arena::Create<absl::Status>(
272
0
      arena, absl::InvalidArgumentError(absl::StrCat(
273
0
                 "unsupported conversion from cel::StructValue to CelValue: ",
274
0
                 value.GetRuntimeType().DebugString()))));
275
467k
}
276
277
CelValue LegacyTrivialListValue(google::protobuf::Arena* absl_nonnull arena,
278
643
                                const Value& value) {
279
643
  if (auto legacy_list_value = common_internal::AsLegacyListValue(value);
280
643
      legacy_list_value) {
281
622
    return CelValue::CreateList(legacy_list_value->cel_list());
282
622
  }
283
21
  if (auto parsed_repeated_field_value = value.AsParsedRepeatedField();
284
21
      parsed_repeated_field_value) {
285
0
    auto wrapped = common_internal::WrapLegacyParsedRepeatedField(
286
0
        *parsed_repeated_field_value, arena);
287
0
    return CelValue::CreateList(
288
0
        common_internal::AsLegacyListValue(wrapped)->cel_list());
289
0
  }
290
21
  if (auto parsed_json_list_value = value.AsParsedJsonList();
291
21
      parsed_json_list_value) {
292
21
    auto wrapped = common_internal::WrapLegacyParsedJsonList(
293
21
        *parsed_json_list_value, arena);
294
21
    return CelValue::CreateList(
295
21
        common_internal::AsLegacyListValue(wrapped)->cel_list());
296
21
  }
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
22
                               const Value& value) {
315
22
  if (auto legacy_map_value = common_internal::AsLegacyMapValue(value);
316
22
      legacy_map_value) {
317
21
    return CelValue::CreateMap(legacy_map_value->cel_map());
318
21
  }
319
1
  if (auto parsed_map_field_value = value.AsParsedMapField();
320
1
      parsed_map_field_value) {
321
0
    auto wrapped = common_internal::WrapLegacyParsedMapField(
322
0
        *parsed_map_field_value, arena);
323
0
    return CelValue::CreateMap(
324
0
        common_internal::AsLegacyMapValue(wrapped)->cel_map());
325
0
  }
326
1
  if (auto parsed_json_map_value = value.AsParsedJsonMap();
327
1
      parsed_json_map_value) {
328
1
    auto wrapped =
329
1
        common_internal::WrapLegacyParsedJsonMap(*parsed_json_map_value, arena);
330
1
    return CelValue::CreateMap(
331
1
        common_internal::AsLegacyMapValue(wrapped)->cel_map());
332
1
  }
333
0
  if (auto custom_map_value = value.AsCustomMap(); custom_map_value) {
334
0
    auto status_or_compat_map = common_internal::MakeCompatMapValue(
335
0
        *custom_map_value, google::protobuf::DescriptorPool::generated_pool(),
336
0
        google::protobuf::MessageFactory::generated_factory(), arena);
337
0
    if (!status_or_compat_map.ok()) {
338
0
      return CelValue::CreateError(google::protobuf::Arena::Create<absl::Status>(
339
0
          arena, std::move(status_or_compat_map).status()));
340
0
    }
341
0
    return CelValue::CreateMap(*status_or_compat_map);
342
0
  }
343
0
  return CelValue::CreateError(google::protobuf::Arena::Create<absl::Status>(
344
0
      arena, absl::InvalidArgumentError(absl::StrCat(
345
0
                 "unsupported conversion from cel::MapValue to CelValue: ",
346
0
                 value.GetRuntimeType().DebugString()))));
347
0
}
348
349
LegacyStructValue ParsedMessageToLegacyStructValue(
350
0
    const ParsedMessageValue& parsed_message) {
351
0
  return LegacyStructValue(cel::to_address(parsed_message),
352
0
                           &GetGenericProtoTypeInfoInstance());
353
0
}
354
355
LegacyStructValue MakeLegacyStructValue(
356
    const google::protobuf::Message* absl_nonnull message,
357
467k
    const LegacyTypeInfoApis* legacy_type_info) {
358
  // Guard against edge cases where a custom implementation of Message
359
  // misbehaves.
360
  // Modern value handles this with DCHECKs on value creation, legacy value
361
  // would allow it and just report an ErrorValue on accesses.
362
467k
  if (message->GetReflection() == nullptr || legacy_type_info == nullptr) {
363
0
    legacy_type_info = TrivialTypeInfo::GetInstance();
364
0
  }
365
467k
  return LegacyStructValue(message, legacy_type_info);
366
467k
}
367
368
}  // namespace
369
370
google::api::expr::runtime::CelValue UnsafeLegacyValue(
371
0
    const Value& value, bool stable, google::protobuf::Arena* absl_nonnull arena) {
372
0
  switch (value.kind()) {
373
0
    case ValueKind::kNull:
374
0
      return CelValue::CreateNull();
375
0
    case ValueKind::kBool:
376
0
      return CelValue::CreateBool(value.GetBool());
377
0
    case ValueKind::kInt:
378
0
      return CelValue::CreateInt64(value.GetInt());
379
0
    case ValueKind::kUint:
380
0
      return CelValue::CreateUint64(value.GetUint());
381
0
    case ValueKind::kDouble:
382
0
      return CelValue::CreateDouble(value.GetDouble());
383
0
    case ValueKind::kString:
384
0
      return CelValue::CreateStringView(
385
0
          LegacyStringValue(value.GetString(), stable, arena));
386
0
    case ValueKind::kBytes:
387
0
      return CelValue::CreateBytesView(
388
0
          LegacyBytesValue(value.GetBytes(), stable, arena));
389
0
    case ValueKind::kStruct:
390
0
      return LegacyTrivialStructValue(arena, value);
391
0
    case ValueKind::kDuration:
392
0
      return CelValue::CreateDuration(value.GetDuration().ToDuration());
393
0
    case ValueKind::kTimestamp:
394
0
      return CelValue::CreateTimestamp(value.GetTimestamp().ToTime());
395
0
    case ValueKind::kList:
396
0
      return LegacyTrivialListValue(arena, value);
397
0
    case ValueKind::kMap:
398
0
      return LegacyTrivialMapValue(arena, value);
399
0
    case ValueKind::kType:
400
0
      return CelValue::CreateCelTypeView(value.GetType().name());
401
0
    default:
402
      // Everything else is unsupported.
403
0
      return CelValue::CreateError(google::protobuf::Arena::Create<absl::Status>(
404
0
          arena, absl::InvalidArgumentError(absl::StrCat(
405
0
                     "unsupported conversion from cel::Value to CelValue: ",
406
0
                     value->GetRuntimeType().DebugString()))));
407
0
  }
408
0
}
409
410
0
std::string LegacyListValue::DebugString() const {
411
0
  return CelValue::CreateList(impl_).DebugString();
412
0
}
413
414
// See `ValueInterface::SerializeTo`.
415
absl::Status LegacyListValue::SerializeTo(
416
    const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
417
    google::protobuf::MessageFactory* absl_nonnull message_factory,
418
0
    google::protobuf::io::ZeroCopyOutputStream* absl_nonnull output) const {
419
0
  ABSL_DCHECK(descriptor_pool != nullptr);
420
0
  ABSL_DCHECK(message_factory != nullptr);
421
0
  ABSL_DCHECK(output != nullptr);
422
423
0
  const google::protobuf::Descriptor* descriptor =
424
0
      descriptor_pool->FindMessageTypeByName("google.protobuf.ListValue");
425
0
  if (descriptor == nullptr) {
426
0
    return absl::InternalError(
427
0
        "unable to locate descriptor for message type: "
428
0
        "google.protobuf.ListValue");
429
0
  }
430
431
0
  google::protobuf::Arena arena;
432
0
  const google::protobuf::Message* wrapped = MaybeWrapValueToMessage(
433
0
      descriptor, message_factory, CelValue::CreateList(impl_), &arena);
434
0
  if (wrapped == nullptr) {
435
0
    return absl::UnknownError("failed to convert legacy map to JSON");
436
0
  }
437
0
  if (!wrapped->SerializePartialToZeroCopyStream(output)) {
438
0
    return absl::UnknownError(
439
0
        absl::StrCat("failed to serialize message: ", wrapped->GetTypeName()));
440
0
  }
441
0
  return absl::OkStatus();
442
0
}
443
444
absl::Status LegacyListValue::ConvertToJson(
445
    const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
446
    google::protobuf::MessageFactory* absl_nonnull message_factory,
447
0
    google::protobuf::Message* absl_nonnull json) const {
448
0
  {
449
0
    ABSL_DCHECK(descriptor_pool != nullptr);
450
0
    ABSL_DCHECK(message_factory != nullptr);
451
0
    ABSL_DCHECK(json != nullptr);
452
0
    ABSL_DCHECK_EQ(json->GetDescriptor()->well_known_type(),
453
0
                   google::protobuf::Descriptor::WELLKNOWNTYPE_VALUE);
454
455
0
    google::protobuf::Arena arena;
456
0
    const google::protobuf::Message* wrapped =
457
0
        MaybeWrapValueToMessage(json->GetDescriptor(), message_factory,
458
0
                                CelValue::CreateList(impl_), &arena);
459
0
    if (wrapped == nullptr) {
460
0
      return absl::UnknownError("failed to convert legacy list to JSON");
461
0
    }
462
463
0
    if (wrapped->GetDescriptor() == json->GetDescriptor()) {
464
      // We can directly use google::protobuf::Message::Copy().
465
0
      json->CopyFrom(*wrapped);
466
0
    } else {
467
      // Equivalent descriptors but not identical. Must serialize and
468
      // deserialize.
469
0
      absl::Cord serialized;
470
0
      if (!wrapped->SerializePartialToString(&serialized)) {
471
0
        return absl::UnknownError(absl::StrCat("failed to serialize message: ",
472
0
                                               wrapped->GetTypeName()));
473
0
      }
474
0
      if (!json->ParsePartialFromString(serialized)) {
475
0
        return absl::UnknownError(
476
0
            absl::StrCat("failed to parsed message: ", json->GetTypeName()));
477
0
      }
478
0
    }
479
0
    return absl::OkStatus();
480
0
  }
481
0
}
482
483
absl::Status LegacyListValue::ConvertToJsonArray(
484
    const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
485
    google::protobuf::MessageFactory* absl_nonnull message_factory,
486
0
    google::protobuf::Message* absl_nonnull json) const {
487
0
  {
488
0
    ABSL_DCHECK(descriptor_pool != nullptr);
489
0
    ABSL_DCHECK(message_factory != nullptr);
490
0
    ABSL_DCHECK(json != nullptr);
491
0
    ABSL_DCHECK_EQ(json->GetDescriptor()->well_known_type(),
492
0
                   google::protobuf::Descriptor::WELLKNOWNTYPE_LISTVALUE);
493
494
0
    google::protobuf::Arena arena;
495
0
    const google::protobuf::Message* wrapped =
496
0
        MaybeWrapValueToMessage(json->GetDescriptor(), message_factory,
497
0
                                CelValue::CreateList(impl_), &arena);
498
0
    if (wrapped == nullptr) {
499
0
      return absl::UnknownError("failed to convert legacy list to JSON");
500
0
    }
501
502
0
    if (wrapped->GetDescriptor() == json->GetDescriptor()) {
503
      // We can directly use google::protobuf::Message::Copy().
504
0
      json->CopyFrom(*wrapped);
505
0
    } else {
506
      // Equivalent descriptors but not identical. Must serialize and
507
      // deserialize.
508
0
      absl::Cord serialized;
509
0
      if (!wrapped->SerializePartialToString(&serialized)) {
510
0
        return absl::UnknownError(absl::StrCat("failed to serialize message: ",
511
0
                                               wrapped->GetTypeName()));
512
0
      }
513
0
      if (!json->ParsePartialFromString(serialized)) {
514
0
        return absl::UnknownError(
515
0
            absl::StrCat("failed to parsed message: ", json->GetTypeName()));
516
0
      }
517
0
    }
518
0
    return absl::OkStatus();
519
0
  }
520
0
}
521
522
0
bool LegacyListValue::IsEmpty() const { return impl_->empty(); }
523
524
0
size_t LegacyListValue::Size() const {
525
0
  return static_cast<size_t>(impl_->size());
526
0
}
527
528
// See LegacyListValueInterface::Get for documentation.
529
absl::Status LegacyListValue::Get(
530
    size_t index, const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
531
    google::protobuf::MessageFactory* absl_nonnull message_factory,
532
0
    google::protobuf::Arena* absl_nonnull arena, Value* absl_nonnull result) const {
533
0
  if (ABSL_PREDICT_FALSE(index < 0 || index >= impl_->size())) {
534
0
    *result = ErrorValue::From(
535
0
        absl::InvalidArgumentError("index out of bounds"), arena);
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::From(InvalidMapKeyTypeError(key.kind()), arena);
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(), arena);
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::From(InvalidMapKeyTypeError(key.kind()), arena);
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::From(InvalidMapKeyTypeError(key.kind()), arena);
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::From(std::move(has).status(), arena);
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
539
    google::protobuf::Message* absl_nonnull json) const {
861
539
  ABSL_DCHECK(message_ptr_ != nullptr);
862
539
  ABSL_DCHECK(descriptor_pool != nullptr);
863
539
  ABSL_DCHECK(message_factory != nullptr);
864
539
  ABSL_DCHECK(json != nullptr);
865
539
  ABSL_DCHECK_EQ(json->GetDescriptor()->well_known_type(),
866
539
                 google::protobuf::Descriptor::WELLKNOWNTYPE_VALUE);
867
868
539
  return internal::MessageToJson(*message_ptr_, descriptor_pool,
869
539
                                 message_factory, json);
870
539
}
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
28.7k
    google::protobuf::Arena* absl_nonnull arena, Value* absl_nonnull result) const {
892
28.7k
  ABSL_DCHECK(message_ptr_ != nullptr);
893
28.7k
  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
28.7k
  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
28.7k
  if (auto other_legacy = common_internal::AsLegacyStructValue(other);
902
28.7k
      other_legacy) {
903
28.5k
    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
28.5k
    auto other_message = UnsafeParsedMessageValue(other_legacy->message_ptr_);
908
28.5k
    return modern_value.Equal(other_message, descriptor_pool, message_factory,
909
28.5k
                              arena, result);
910
28.5k
  }
911
912
222
  return modern_value.Equal(other, descriptor_pool, message_factory, arena,
913
222
                            result);
914
28.7k
}
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
407k
    google::protobuf::Arena* absl_nonnull arena, Value* absl_nonnull result) const {
929
407k
  if (ABSL_PREDICT_FALSE(legacy_type_info_ == TrivialTypeInfo::GetInstance())) {
930
0
    *result = NoSuchFieldError(name, arena);
931
0
    return absl::OkStatus();
932
0
  }
933
934
407k
  ParsedMessageValue parsed_message = UnsafeParsedMessageValue(message_ptr_);
935
407k
  const auto* descriptor = parsed_message.GetDescriptor();
936
407k
  const auto* field = descriptor->FindFieldByName(name);
937
407k
  if (field == nullptr) {
938
407k
    field = descriptor->file()->pool()->FindExtensionByPrintableName(descriptor,
939
407k
                                                                     name);
940
407k
    if (field == nullptr) {
941
407k
      *result = NoSuchFieldError(name, arena);
942
407k
      return absl::OkStatus();
943
407k
    }
944
407k
  }
945
946
0
  return interop_internal::WrapLegacyMessageField(
947
0
      message_ptr_, field, unboxing_options, descriptor_pool, message_factory,
948
0
      arena, result);
949
407k
}
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 common_internal::MakeNoSuchFieldError(name);
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 common_internal::MakeNoSuchFieldError(absl::StrCat(number));
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, arena);
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
467k
                         Value& result) {
1029
467k
  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::Wrap(legacy_value.StringOrDie().value(), nullptr);
1047
0
      return absl::OkStatus();
1048
0
    case CelValue::Type::kBytes:
1049
0
      result = BytesValue::Wrap(legacy_value.BytesOrDie().value(), nullptr);
1050
0
      return absl::OkStatus();
1051
467k
    case CelValue::Type::kMessage: {
1052
467k
      auto message_wrapper = legacy_value.MessageWrapperOrDie();
1053
467k
      result = common_internal::MakeLegacyStructValue(
1054
467k
          google::protobuf::DownCastMessage<google::protobuf::Message>(
1055
467k
              message_wrapper.message_ptr()),
1056
467k
          message_wrapper.legacy_type_info());
1057
467k
      return absl::OkStatus();
1058
0
    }
1059
0
    case CelValue::Type::kDuration:
1060
0
      result = UnsafeDurationValue(legacy_value.DurationOrDie());
1061
0
      return absl::OkStatus();
1062
0
    case CelValue::Type::kTimestamp:
1063
0
      result = UnsafeTimestampValue(legacy_value.TimestampOrDie());
1064
0
      return absl::OkStatus();
1065
0
    case CelValue::Type::kList:
1066
0
      result =
1067
0
          ListValue(common_internal::LegacyListValue(legacy_value.ListOrDie()));
1068
0
      return absl::OkStatus();
1069
0
    case CelValue::Type::kMap:
1070
0
      result =
1071
0
          MapValue(common_internal::LegacyMapValue(legacy_value.MapOrDie()));
1072
0
      return absl::OkStatus();
1073
0
    case CelValue::Type::kUnknownSet:
1074
0
      result =
1075
0
          common_internal::MakeUnknownValue(*legacy_value.UnknownSetOrDie());
1076
0
      return absl::OkStatus();
1077
0
    case CelValue::Type::kCelType: {
1078
0
      auto type_name = legacy_value.CelTypeOrDie().value();
1079
0
      if (type_name.empty()) {
1080
0
        return absl::InvalidArgumentError("empty type name in CelValue");
1081
0
      }
1082
0
      result = TypeValue(common_internal::LegacyRuntimeType(type_name));
1083
0
      return absl::OkStatus();
1084
0
    }
1085
0
    case CelValue::Type::kError:
1086
0
      result = ErrorValue::From(*legacy_value.ErrorOrDie(), arena);
1087
0
      return absl::OkStatus();
1088
0
    case CelValue::Type::kAny:
1089
0
      return absl::InternalError(absl::StrCat(
1090
0
          "illegal attempt to convert special CelValue type ",
1091
0
          CelValue::TypeName(legacy_value.type()), " to cel::Value"));
1092
0
    default:
1093
0
      break;
1094
467k
  }
1095
0
  return absl::InvalidArgumentError(absl::StrCat(
1096
0
      "cel::Value does not support ", KindToString(legacy_value.type())));
1097
467k
}
1098
1099
absl::StatusOr<google::api::expr::runtime::CelValue> LegacyValue(
1100
467k
    google::protobuf::Arena* arena, const Value& modern_value) {
1101
467k
  switch (modern_value.kind()) {
1102
0
    case ValueKind::kNull:
1103
0
      return CelValue::CreateNull();
1104
0
    case ValueKind::kBool:
1105
0
      return CelValue::CreateBool(modern_value.Get<BoolValue>().NativeValue());
1106
0
    case ValueKind::kInt:
1107
0
      return CelValue::CreateInt64(modern_value.Get<IntValue>().NativeValue());
1108
0
    case ValueKind::kUint:
1109
0
      return CelValue::CreateUint64(
1110
0
          modern_value.Get<UintValue>().NativeValue());
1111
0
    case ValueKind::kDouble:
1112
0
      return CelValue::CreateDouble(
1113
0
          modern_value.Get<DoubleValue>().NativeValue());
1114
0
    case ValueKind::kString:
1115
0
      return CelValue::CreateStringView(common_internal::LegacyStringValue(
1116
0
          modern_value.GetString(), /*stable=*/false, arena));
1117
0
    case ValueKind::kBytes:
1118
0
      return CelValue::CreateBytesView(common_internal::LegacyBytesValue(
1119
0
          modern_value.GetBytes(), /*stable=*/false, arena));
1120
467k
    case ValueKind::kStruct:
1121
467k
      return common_internal::LegacyTrivialStructValue(arena, modern_value);
1122
0
    case ValueKind::kDuration:
1123
0
      return CelValue::CreateUncheckedDuration(
1124
0
          modern_value.GetDuration().NativeValue());
1125
0
    case ValueKind::kTimestamp:
1126
0
      return CelValue::CreateTimestamp(
1127
0
          modern_value.GetTimestamp().NativeValue());
1128
0
    case ValueKind::kList:
1129
0
      return common_internal::LegacyTrivialListValue(arena, modern_value);
1130
0
    case ValueKind::kMap:
1131
0
      return common_internal::LegacyTrivialMapValue(arena, modern_value);
1132
0
    case ValueKind::kUnknown:
1133
0
      return CelValue::CreateUnknownSet(google::protobuf::Arena::Create<Unknown>(
1134
0
          arena,
1135
0
          common_internal::GetUnknown(modern_value.Get<UnknownValue>())));
1136
0
    case ValueKind::kType:
1137
0
      return CelValue::CreateCelType(
1138
0
          CelValue::CelTypeHolder(google::protobuf::Arena::Create<std::string>(
1139
0
              arena, modern_value.Get<TypeValue>().NativeValue().name())));
1140
0
    case ValueKind::kError:
1141
0
      return CelValue::CreateError(google::protobuf::Arena::Create<absl::Status>(
1142
0
          arena, modern_value.Get<ErrorValue>().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
467k
  }
1148
467k
}
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::Wrap(legacy_value.StringOrDie().value(), nullptr);
1167
0
    case CelValue::Type::kBytes:
1168
0
      return BytesValue::Wrap(legacy_value.BytesOrDie().value(), nullptr);
1169
0
    case CelValue::Type::kMessage: {
1170
0
      auto message_wrapper = legacy_value.MessageWrapperOrDie();
1171
0
      return common_internal::MakeLegacyStructValue(
1172
0
          google::protobuf::DownCastMessage<google::protobuf::Message>(
1173
0
              message_wrapper.message_ptr()),
1174
0
          message_wrapper.legacy_type_info());
1175
0
    }
1176
0
    case CelValue::Type::kDuration:
1177
0
      return UnsafeDurationValue(legacy_value.DurationOrDie());
1178
0
    case CelValue::Type::kTimestamp:
1179
0
      return UnsafeTimestampValue(legacy_value.TimestampOrDie());
1180
0
    case CelValue::Type::kList:
1181
0
      return ListValue(
1182
0
          common_internal::LegacyListValue(legacy_value.ListOrDie()));
1183
0
    case CelValue::Type::kMap:
1184
0
      return MapValue(common_internal::LegacyMapValue(legacy_value.MapOrDie()));
1185
0
    case CelValue::Type::kUnknownSet:
1186
0
      return common_internal::MakeUnknownValue(*legacy_value.UnknownSetOrDie());
1187
0
    case CelValue::Type::kCelType:
1188
0
      return CreateTypeValueFromView(arena,
1189
0
                                     legacy_value.CelTypeOrDie().value());
1190
0
    case CelValue::Type::kError:
1191
0
      return ErrorValue::From(*legacy_value.ErrorOrDie(), arena);
1192
0
    case CelValue::Type::kAny:
1193
0
      return absl::InternalError(absl::StrCat(
1194
0
          "illegal attempt to convert special CelValue type ",
1195
0
          CelValue::TypeName(legacy_value.type()), " to cel::Value"));
1196
0
    default:
1197
0
      break;
1198
0
  }
1199
0
  return absl::UnimplementedError(absl::StrCat(
1200
0
      "conversion from CelValue to cel::Value for type ",
1201
0
      CelValue::TypeName(legacy_value.type()), " is not yet implemented"));
1202
0
}
1203
1204
absl::StatusOr<google::api::expr::runtime::CelValue> ToLegacyValue(
1205
17.1k
    google::protobuf::Arena* arena, const Value& value, bool) {
1206
17.1k
  switch (value.kind()) {
1207
3
    case ValueKind::kNull:
1208
3
      return CelValue::CreateNull();
1209
4.20k
    case ValueKind::kBool:
1210
4.20k
      return CelValue::CreateBool(value.Get<BoolValue>().NativeValue());
1211
600
    case ValueKind::kInt:
1212
600
      return CelValue::CreateInt64(value.Get<IntValue>().NativeValue());
1213
199
    case ValueKind::kUint:
1214
199
      return CelValue::CreateUint64(value.Get<UintValue>().NativeValue());
1215
765
    case ValueKind::kDouble:
1216
765
      return CelValue::CreateDouble(value.Get<DoubleValue>().NativeValue());
1217
429
    case ValueKind::kString:
1218
429
      return CelValue::CreateStringView(common_internal::LegacyStringValue(
1219
429
          value.GetString(), /*stable=*/false, arena));
1220
73
    case ValueKind::kBytes:
1221
73
      return CelValue::CreateBytesView(common_internal::LegacyBytesValue(
1222
73
          value.GetBytes(), /*stable=*/false, arena));
1223
2
    case ValueKind::kStruct:
1224
2
      return common_internal::LegacyTrivialStructValue(arena, value);
1225
421
    case ValueKind::kDuration:
1226
421
      return CelValue::CreateUncheckedDuration(
1227
421
          value.Get<DurationValue>().NativeValue());
1228
231
    case ValueKind::kTimestamp:
1229
231
      return CelValue::CreateTimestamp(
1230
231
          value.Get<TimestampValue>().NativeValue());
1231
643
    case ValueKind::kList:
1232
643
      return common_internal::LegacyTrivialListValue(arena, value);
1233
22
    case ValueKind::kMap:
1234
22
      return common_internal::LegacyTrivialMapValue(arena, value);
1235
0
    case ValueKind::kUnknown:
1236
0
      return CelValue::CreateUnknownSet(google::protobuf::Arena::Create<Unknown>(
1237
0
          arena, common_internal::GetUnknown(value.Get<UnknownValue>())));
1238
18
    case ValueKind::kType:
1239
18
      return CelValue::CreateCelType(
1240
18
          CelValue::CelTypeHolder(google::protobuf::Arena::Create<std::string>(
1241
18
              arena, value.Get<TypeValue>().NativeValue().name())));
1242
9.49k
    case ValueKind::kError:
1243
9.49k
      return CelValue::CreateError(google::protobuf::Arena::Create<absl::Status>(
1244
9.49k
          arena, value.Get<ErrorValue>().NativeValue()));
1245
0
    default:
1246
0
      return absl::InvalidArgumentError(
1247
0
          absl::StrCat("google::api::expr::runtime::CelValue does not support ",
1248
0
                       ValueKindToString(value.kind())));
1249
17.1k
  }
1250
17.1k
}
1251
1252
Value LegacyValueToModernValueOrDie(
1253
    google::protobuf::Arena* arena, const google::api::expr::runtime::CelValue& value,
1254
0
    bool unchecked) {
1255
0
  auto status_or_value = FromLegacyValue(arena, value, unchecked);
1256
0
  ABSL_CHECK_OK(status_or_value.status());  // Crash OK
1257
0
  return std::move(*status_or_value);
1258
0
}
1259
1260
std::vector<Value> LegacyValueToModernValueOrDie(
1261
    google::protobuf::Arena* arena,
1262
    absl::Span<const google::api::expr::runtime::CelValue> values,
1263
0
    bool unchecked) {
1264
0
  std::vector<Value> modern_values;
1265
0
  modern_values.reserve(values.size());
1266
0
  for (const auto& value : values) {
1267
0
    modern_values.push_back(
1268
0
        LegacyValueToModernValueOrDie(arena, value, unchecked));
1269
0
  }
1270
0
  return modern_values;
1271
0
}
1272
1273
google::api::expr::runtime::CelValue ModernValueToLegacyValueOrDie(
1274
17.1k
    google::protobuf::Arena* arena, const Value& value, bool unchecked) {
1275
17.1k
  auto status_or_value = ToLegacyValue(arena, value, unchecked);
1276
17.1k
  ABSL_CHECK_OK(status_or_value.status());  // Crash OK
1277
17.1k
  return std::move(*status_or_value);
1278
17.1k
}
1279
1280
void WrapLegacyFieldAccessResult(google::protobuf::Arena* absl_nonnull arena,
1281
0
                                 Value* absl_nonnull result) {
1282
0
  if (result->IsParsedMessage()) {
1283
0
    *result = common_internal::ParsedMessageToLegacyStructValue(
1284
0
        result->GetParsedMessage());
1285
0
  } else if (result->IsParsedRepeatedField()) {
1286
0
    *result =
1287
0
        WrapLegacyParsedRepeatedField(result->GetParsedRepeatedField(), arena);
1288
0
  } else if (result->IsParsedJsonList()) {
1289
0
    *result = WrapLegacyParsedJsonList(result->GetParsedJsonList(), arena);
1290
0
  } else if (result->IsParsedMapField()) {
1291
0
    *result = WrapLegacyParsedMapField(result->GetParsedMapField(), arena);
1292
0
  } else if (result->IsParsedJsonMap()) {
1293
0
    *result = WrapLegacyParsedJsonMap(result->GetParsedJsonMap(), arena);
1294
0
  }
1295
0
}
1296
1297
TypeValue CreateTypeValueFromView(google::protobuf::Arena* arena,
1298
0
                                  absl::string_view input) {
1299
0
  return TypeValue(common_internal::LegacyRuntimeType(input));
1300
0
}
1301
1302
0
const google::protobuf::Message* absl_nullable GetLegacyMessage(const Value& value) {
1303
0
  if (!common_internal::IsLegacyStructValue(value)) {
1304
0
    return nullptr;
1305
0
  }
1306
1307
0
  auto legacy = common_internal::GetLegacyStructValue(value);
1308
0
  const auto* legacy_type_info = legacy.legacy_type_info();
1309
0
  if (legacy_type_info == nullptr ||
1310
0
      legacy_type_info == TrivialTypeInfo::GetInstance()) {
1311
0
    return nullptr;
1312
0
  }
1313
  // This should not be possible using the normal public APIs, but possible
1314
  // if someone used the MessageWrapper class directly.
1315
0
  if (IsWellKnownMessageType(legacy.message_ptr()->GetDescriptor())) {
1316
0
    return nullptr;
1317
0
  }
1318
0
  return legacy.message_ptr();
1319
0
}
1320
1321
absl::Status WrapLegacyMessageField(
1322
    const google::protobuf::Message* absl_nonnull message,
1323
    const google::protobuf::FieldDescriptor* absl_nonnull field_descriptor,
1324
    ProtoWrapperTypeOptions unboxing_option,
1325
    const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
1326
    google::protobuf::MessageFactory* absl_nonnull message_factory, google::protobuf::Arena* arena,
1327
0
    Value* absl_nonnull out) {
1328
0
  ParsedMessageValue parsed_message = UnsafeParsedMessageValue(message);
1329
0
  CEL_RETURN_IF_ERROR(parsed_message.GetField(field_descriptor, unboxing_option,
1330
0
                                              descriptor_pool, message_factory,
1331
0
                                              arena, out));
1332
0
  WrapLegacyFieldAccessResult(arena, out);
1333
1334
0
  return absl::OkStatus();
1335
0
}
1336
1337
}  // namespace interop_internal
1338
1339
}  // namespace cel