Coverage Report

Created: 2026-05-27 07:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/proc/self/cwd/common/values/custom_map_value.cc
Line
Count
Source
1
// Copyright 2023 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 <cstddef>
16
#include <memory>
17
#include <string>
18
19
#include "absl/base/attributes.h"
20
#include "absl/base/no_destructor.h"
21
#include "absl/base/nullability.h"
22
#include "absl/base/optimization.h"
23
#include "absl/log/absl_check.h"
24
#include "absl/status/status.h"
25
#include "absl/status/statusor.h"
26
#include "absl/strings/str_cat.h"
27
#include "absl/strings/string_view.h"
28
#include "absl/types/optional.h"
29
#include "common/native_type.h"
30
#include "common/value.h"
31
#include "common/value_kind.h"
32
#include "common/values/list_value_builder.h"
33
#include "common/values/map_value_builder.h"
34
#include "common/values/values.h"
35
#include "eval/public/cel_value.h"
36
#include "internal/status_macros.h"
37
#include "internal/well_known_types.h"
38
#include "google/protobuf/arena.h"
39
#include "google/protobuf/descriptor.h"
40
#include "google/protobuf/io/zero_copy_stream.h"
41
#include "google/protobuf/message.h"
42
43
namespace cel {
44
45
namespace {
46
47
using ::cel::well_known_types::StructReflection;
48
using ::cel::well_known_types::ValueReflection;
49
using ::google::api::expr::runtime::CelList;
50
using ::google::api::expr::runtime::CelValue;
51
52
1.96k
absl::Status NoSuchKeyError(const Value& key) {
53
1.96k
  return absl::NotFoundError(
54
1.96k
      absl::StrCat("Key not found in map : ", key.DebugString()));
55
1.96k
}
56
57
2
absl::Status InvalidMapKeyTypeError(ValueKind kind) {
58
2
  return absl::InvalidArgumentError(
59
2
      absl::StrCat("Invalid map key type: '", ValueKindToString(kind), "'"));
60
2
}
61
62
class EmptyMapValue final : public common_internal::CompatMapValue {
63
 public:
64
6.15k
  static const EmptyMapValue& Get() {
65
6.15k
    static const absl::NoDestructor<EmptyMapValue> empty;
66
6.15k
    return *empty;
67
6.15k
  }
68
69
1
  EmptyMapValue() = default;
70
71
0
  std::string DebugString() const override { return "{}"; }
72
73
0
  bool IsEmpty() const override { return true; }
74
75
28
  size_t Size() const override { return 0; }
76
77
  absl::Status ListKeys(
78
      const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
79
      google::protobuf::MessageFactory* absl_nonnull message_factory,
80
      google::protobuf::Arena* absl_nonnull arena,
81
0
      ListValue* absl_nonnull result) const override {
82
0
    *result = ListValue();
83
0
    return absl::OkStatus();
84
0
  }
85
86
12
  absl::StatusOr<absl_nonnull ValueIteratorPtr> NewIterator() const override {
87
12
    return NewEmptyValueIterator();
88
12
  }
89
90
  absl::Status ConvertToJsonObject(
91
      const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
92
      google::protobuf::MessageFactory* absl_nonnull message_factory,
93
0
      google::protobuf::Message* absl_nonnull json) const override {
94
0
    ABSL_DCHECK(descriptor_pool != nullptr);
95
0
    ABSL_DCHECK(message_factory != nullptr);
96
0
    ABSL_DCHECK(json != nullptr);
97
0
    ABSL_DCHECK_EQ(json->GetDescriptor()->well_known_type(),
98
0
                   google::protobuf::Descriptor::WELLKNOWNTYPE_STRUCT);
99
100
0
    json->Clear();
101
0
    return absl::OkStatus();
102
0
  }
103
104
0
  CustomMapValue Clone(google::protobuf::Arena* absl_nonnull) const override {
105
0
    return CustomMapValue();
106
0
  }
107
108
0
  absl::optional<CelValue> operator[](CelValue key) const override {
109
0
    return absl::nullopt;
110
0
  }
111
112
  using CompatMapValue::Get;
113
  absl::optional<CelValue> Get(google::protobuf::Arena* arena,
114
0
                               CelValue key) const override {
115
0
    return absl::nullopt;
116
0
  }
117
118
0
  absl::StatusOr<bool> Has(const CelValue& key) const override { return false; }
119
120
0
  int size() const override { return static_cast<int>(Size()); }
121
122
0
  absl::StatusOr<const CelList*> ListKeys() const override {
123
0
    return common_internal::EmptyCompatListValue();
124
0
  }
125
126
0
  absl::StatusOr<const CelList*> ListKeys(google::protobuf::Arena*) const override {
127
0
    return ListKeys();
128
0
  }
129
130
 private:
131
  absl::StatusOr<bool> Find(
132
      const Value& key,
133
      const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
134
      google::protobuf::MessageFactory* absl_nonnull message_factory,
135
      google::protobuf::Arena* absl_nonnull arena,
136
4.68k
      Value* absl_nonnull result) const override {
137
4.68k
    return false;
138
4.68k
  }
139
140
  absl::StatusOr<bool> Has(
141
      const Value& key,
142
      const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
143
      google::protobuf::MessageFactory* absl_nonnull message_factory,
144
425
      google::protobuf::Arena* absl_nonnull arena) const override {
145
425
    return false;
146
425
  }
147
};
148
149
}  // namespace
150
151
namespace common_internal {
152
153
0
const CompatMapValue* absl_nonnull EmptyCompatMapValue() {
154
0
  return &EmptyMapValue::Get();
155
0
}
156
157
}  // namespace common_internal
158
159
class CustomMapValueInterfaceIterator final : public ValueIterator {
160
 public:
161
  explicit CustomMapValueInterfaceIterator(
162
      const CustomMapValueInterface* absl_nonnull interface)
163
0
      : interface_(interface) {}
164
165
0
  bool HasNext() override {
166
0
    if (keys_iterator_ == nullptr) {
167
0
      return !interface_->IsEmpty();
168
0
    }
169
0
    return keys_iterator_->HasNext();
170
0
  }
171
172
  absl::Status Next(const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
173
                    google::protobuf::MessageFactory* absl_nonnull message_factory,
174
                    google::protobuf::Arena* absl_nonnull arena,
175
0
                    Value* absl_nonnull result) override {
176
0
    if (keys_iterator_ == nullptr) {
177
0
      if (interface_->IsEmpty()) {
178
0
        return absl::FailedPreconditionError(
179
0
            "ValueIterator::Next() called when "
180
0
            "ValueIterator::HasNext() returns false");
181
0
      }
182
0
      CEL_RETURN_IF_ERROR(ProjectKeys(descriptor_pool, message_factory, arena));
183
0
    }
184
0
    return keys_iterator_->Next(descriptor_pool, message_factory, arena,
185
0
                                result);
186
0
  }
187
188
  absl::StatusOr<bool> Next1(
189
      const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
190
      google::protobuf::MessageFactory* absl_nonnull message_factory,
191
      google::protobuf::Arena* absl_nonnull arena,
192
0
      Value* absl_nonnull key_or_value) override {
193
0
    ABSL_DCHECK(descriptor_pool != nullptr);
194
0
    ABSL_DCHECK(message_factory != nullptr);
195
0
    ABSL_DCHECK(arena != nullptr);
196
0
    ABSL_DCHECK(key_or_value != nullptr);
197
198
0
    if (keys_iterator_ == nullptr) {
199
0
      if (interface_->IsEmpty()) {
200
0
        return false;
201
0
      }
202
0
      CEL_RETURN_IF_ERROR(ProjectKeys(descriptor_pool, message_factory, arena));
203
0
    }
204
205
0
    return keys_iterator_->Next1(descriptor_pool, message_factory, arena,
206
0
                                 key_or_value);
207
0
  }
208
209
  absl::StatusOr<bool> Next2(
210
      const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
211
      google::protobuf::MessageFactory* absl_nonnull message_factory,
212
      google::protobuf::Arena* absl_nonnull arena, Value* absl_nonnull key,
213
0
      Value* absl_nullable value) override {
214
0
    ABSL_DCHECK(descriptor_pool != nullptr);
215
0
    ABSL_DCHECK(message_factory != nullptr);
216
0
    ABSL_DCHECK(arena != nullptr);
217
0
    ABSL_DCHECK(key != nullptr);
218
219
0
    if (keys_iterator_ == nullptr) {
220
0
      if (interface_->IsEmpty()) {
221
0
        return false;
222
0
      }
223
0
      CEL_RETURN_IF_ERROR(ProjectKeys(descriptor_pool, message_factory, arena));
224
0
    }
225
226
0
    CEL_ASSIGN_OR_RETURN(
227
0
        bool ok,
228
0
        keys_iterator_->Next1(descriptor_pool, message_factory, arena, key));
229
0
    if (!ok) {
230
0
      return false;
231
0
    }
232
0
    if (value != nullptr) {
233
0
      CEL_ASSIGN_OR_RETURN(ok, interface_->Find(*key, descriptor_pool,
234
0
                                                message_factory, arena, value));
235
0
      if (!ok) {
236
0
        return absl::DataLossError(
237
0
            "map iterator returned key that was not present in the map");
238
0
      }
239
0
    }
240
0
    return true;
241
0
  }
242
243
 private:
244
  // Projects the keys from the map, setting `keys_` and `keys_iterator_`. If
245
  // this returns OK it is guaranteed that `keys_iterator_` is not null.
246
  absl::Status ProjectKeys(
247
      const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
248
      google::protobuf::MessageFactory* absl_nonnull message_factory,
249
0
      google::protobuf::Arena* absl_nonnull arena) {
250
0
    ABSL_DCHECK(keys_iterator_ == nullptr);
251
252
0
    CEL_RETURN_IF_ERROR(
253
0
        interface_->ListKeys(descriptor_pool, message_factory, arena, &keys_));
254
0
    CEL_ASSIGN_OR_RETURN(keys_iterator_, keys_.NewIterator());
255
0
    ABSL_CHECK(keys_iterator_->HasNext());  // Crash OK
256
0
    return absl::OkStatus();
257
0
  }
258
259
  const CustomMapValueInterface* absl_nonnull const interface_;
260
  ListValue keys_;
261
  absl_nullable ValueIteratorPtr keys_iterator_;
262
};
263
264
namespace {
265
266
class CustomMapValueDispatcherIterator final : public ValueIterator {
267
 public:
268
  explicit CustomMapValueDispatcherIterator(
269
      const CustomMapValueDispatcher* absl_nonnull dispatcher,
270
      CustomMapValueContent content)
271
0
      : dispatcher_(dispatcher), content_(content) {}
272
273
0
  bool HasNext() override {
274
0
    if (keys_iterator_ == nullptr) {
275
0
      if (dispatcher_->is_empty != nullptr) {
276
0
        return !dispatcher_->is_empty(dispatcher_, content_);
277
0
      }
278
0
      return dispatcher_->size(dispatcher_, content_) != 0;
279
0
    }
280
0
    return keys_iterator_->HasNext();
281
0
  }
282
283
  absl::Status Next(const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
284
                    google::protobuf::MessageFactory* absl_nonnull message_factory,
285
                    google::protobuf::Arena* absl_nonnull arena,
286
0
                    Value* absl_nonnull result) override {
287
0
    if (keys_iterator_ == nullptr) {
288
0
      if (dispatcher_->is_empty != nullptr
289
0
              ? dispatcher_->is_empty(dispatcher_, content_)
290
0
              : dispatcher_->size(dispatcher_, content_) == 0) {
291
0
        return absl::FailedPreconditionError(
292
0
            "ValueIterator::Next() called when "
293
0
            "ValueIterator::HasNext() returns false");
294
0
      }
295
0
      CEL_RETURN_IF_ERROR(ProjectKeys(descriptor_pool, message_factory, arena));
296
0
    }
297
0
    return keys_iterator_->Next(descriptor_pool, message_factory, arena,
298
0
                                result);
299
0
  }
300
301
  absl::StatusOr<bool> Next1(
302
      const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
303
      google::protobuf::MessageFactory* absl_nonnull message_factory,
304
      google::protobuf::Arena* absl_nonnull arena,
305
0
      Value* absl_nonnull key_or_value) override {
306
0
    ABSL_DCHECK(descriptor_pool != nullptr);
307
0
    ABSL_DCHECK(message_factory != nullptr);
308
0
    ABSL_DCHECK(arena != nullptr);
309
0
    ABSL_DCHECK(key_or_value != nullptr);
310
311
0
    if (keys_iterator_ == nullptr) {
312
0
      if (dispatcher_->is_empty != nullptr
313
0
              ? dispatcher_->is_empty(dispatcher_, content_)
314
0
              : dispatcher_->size(dispatcher_, content_) == 0) {
315
0
        return false;
316
0
      }
317
0
      CEL_RETURN_IF_ERROR(ProjectKeys(descriptor_pool, message_factory, arena));
318
0
    }
319
320
0
    return keys_iterator_->Next1(descriptor_pool, message_factory, arena,
321
0
                                 key_or_value);
322
0
  }
323
324
  absl::StatusOr<bool> Next2(
325
      const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
326
      google::protobuf::MessageFactory* absl_nonnull message_factory,
327
      google::protobuf::Arena* absl_nonnull arena, Value* absl_nonnull key,
328
0
      Value* absl_nullable value) override {
329
0
    ABSL_DCHECK(descriptor_pool != nullptr);
330
0
    ABSL_DCHECK(message_factory != nullptr);
331
0
    ABSL_DCHECK(arena != nullptr);
332
0
    ABSL_DCHECK(key != nullptr);
333
0
    ABSL_DCHECK(value != nullptr);
334
335
0
    if (keys_iterator_ == nullptr) {
336
0
      if (dispatcher_->is_empty != nullptr
337
0
              ? dispatcher_->is_empty(dispatcher_, content_)
338
0
              : dispatcher_->size(dispatcher_, content_) == 0) {
339
0
        return false;
340
0
      }
341
0
      CEL_RETURN_IF_ERROR(ProjectKeys(descriptor_pool, message_factory, arena));
342
0
    }
343
344
0
    CEL_ASSIGN_OR_RETURN(
345
0
        bool ok,
346
0
        keys_iterator_->Next1(descriptor_pool, message_factory, arena, key));
347
0
    if (!ok) {
348
0
      return false;
349
0
    }
350
0
    if (value != nullptr) {
351
0
      CEL_ASSIGN_OR_RETURN(
352
0
          ok, dispatcher_->find(dispatcher_, content_, *key, descriptor_pool,
353
0
                                message_factory, arena, value));
354
0
      if (!ok) {
355
0
        return absl::DataLossError(
356
0
            "map iterator returned key that was not present in the map");
357
0
      }
358
0
    }
359
0
    return true;
360
0
  }
361
362
 private:
363
  absl::Status ProjectKeys(
364
      const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
365
      google::protobuf::MessageFactory* absl_nonnull message_factory,
366
0
      google::protobuf::Arena* absl_nonnull arena) {
367
0
    ABSL_DCHECK(keys_iterator_ == nullptr);
368
369
0
    CEL_RETURN_IF_ERROR(dispatcher_->list_keys(dispatcher_, content_,
370
0
                                               descriptor_pool, message_factory,
371
0
                                               arena, &keys_));
372
0
    CEL_ASSIGN_OR_RETURN(keys_iterator_, keys_.NewIterator());
373
0
    ABSL_CHECK(keys_iterator_->HasNext());  // Crash OK
374
0
    return absl::OkStatus();
375
0
  }
376
377
  const CustomMapValueDispatcher* absl_nonnull const dispatcher_;
378
  const CustomMapValueContent content_;
379
  ListValue keys_;
380
  absl_nullable ValueIteratorPtr keys_iterator_;
381
};
382
383
}  // namespace
384
385
absl::Status CustomMapValueInterface::SerializeTo(
386
    const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
387
    google::protobuf::MessageFactory* absl_nonnull message_factory,
388
0
    google::protobuf::io::ZeroCopyOutputStream* absl_nonnull output) const {
389
0
  ABSL_DCHECK(descriptor_pool != nullptr);
390
0
  ABSL_DCHECK(message_factory != nullptr);
391
0
  ABSL_DCHECK(output != nullptr);
392
393
0
  StructReflection reflection;
394
0
  CEL_RETURN_IF_ERROR(reflection.Initialize(descriptor_pool));
395
0
  const google::protobuf::Message* prototype =
396
0
      message_factory->GetPrototype(reflection.GetDescriptor());
397
0
  if (prototype == nullptr) {
398
0
    return absl::UnknownError(
399
0
        absl::StrCat("failed to get message prototype: ",
400
0
                     reflection.GetDescriptor()->full_name()));
401
0
  }
402
0
  google::protobuf::Arena arena;
403
0
  google::protobuf::Message* message = prototype->New(&arena);
404
0
  CEL_RETURN_IF_ERROR(
405
0
      ConvertToJsonObject(descriptor_pool, message_factory, message));
406
0
  if (!message->SerializePartialToZeroCopyStream(output)) {
407
0
    return absl::UnknownError(
408
0
        "failed to serialize message: google.protobuf.Struct");
409
0
  }
410
0
  return absl::OkStatus();
411
0
}
412
413
absl::Status CustomMapValueInterface::ForEach(
414
    ForEachCallback callback,
415
    const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
416
    google::protobuf::MessageFactory* absl_nonnull message_factory,
417
0
    google::protobuf::Arena* absl_nonnull arena) const {
418
0
  CEL_ASSIGN_OR_RETURN(auto iterator, NewIterator());
419
0
  while (iterator->HasNext()) {
420
0
    Value key;
421
0
    Value value;
422
0
    CEL_RETURN_IF_ERROR(
423
0
        iterator->Next(descriptor_pool, message_factory, arena, &key));
424
0
    CEL_ASSIGN_OR_RETURN(
425
0
        bool found, Find(key, descriptor_pool, message_factory, arena, &value));
426
0
    if (!found) {
427
0
      value = ErrorValue(NoSuchKeyError(key));
428
0
    }
429
0
    CEL_ASSIGN_OR_RETURN(auto ok, callback(key, value));
430
0
    if (!ok) {
431
0
      break;
432
0
    }
433
0
  }
434
0
  return absl::OkStatus();
435
0
}
436
437
absl::StatusOr<absl_nonnull ValueIteratorPtr>
438
0
CustomMapValueInterface::NewIterator() const {
439
0
  return std::make_unique<CustomMapValueInterfaceIterator>(this);
440
0
}
441
442
absl::Status CustomMapValueInterface::Equal(
443
    const MapValue& other,
444
    const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
445
    google::protobuf::MessageFactory* absl_nonnull message_factory,
446
11
    google::protobuf::Arena* absl_nonnull arena, Value* absl_nonnull result) const {
447
11
  return MapValueEqual(*this, other, descriptor_pool, message_factory, arena,
448
11
                       result);
449
11
}
450
451
6.15k
CustomMapValue::CustomMapValue() {
452
6.15k
  content_ = CustomMapValueContent::From(CustomMapValueInterface::Content{
453
6.15k
      .interface = &EmptyMapValue::Get(), .arena = nullptr});
454
6.15k
}
455
456
43
NativeTypeId CustomMapValue::GetTypeId() const {
457
43
  if (dispatcher_ == nullptr) {
458
43
    CustomMapValueInterface::Content content =
459
43
        content_.To<CustomMapValueInterface::Content>();
460
43
    ABSL_DCHECK(content.interface != nullptr);
461
43
    return content.interface->GetNativeTypeId();
462
43
  }
463
0
  return dispatcher_->get_type_id(dispatcher_, content_);
464
43
}
465
466
0
absl::string_view CustomMapValue::GetTypeName() const { return "map"; }
467
468
0
std::string CustomMapValue::DebugString() const {
469
0
  if (dispatcher_ == nullptr) {
470
0
    CustomMapValueInterface::Content content =
471
0
        content_.To<CustomMapValueInterface::Content>();
472
0
    ABSL_DCHECK(content.interface != nullptr);
473
0
    return content.interface->DebugString();
474
0
  }
475
0
  if (dispatcher_->debug_string != nullptr) {
476
0
    return dispatcher_->debug_string(dispatcher_, content_);
477
0
  }
478
0
  return "map";
479
0
}
480
481
absl::Status CustomMapValue::SerializeTo(
482
    const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
483
    google::protobuf::MessageFactory* absl_nonnull message_factory,
484
0
    google::protobuf::io::ZeroCopyOutputStream* absl_nonnull output) const {
485
0
  if (dispatcher_ == nullptr) {
486
0
    CustomMapValueInterface::Content content =
487
0
        content_.To<CustomMapValueInterface::Content>();
488
0
    ABSL_DCHECK(content.interface != nullptr);
489
0
    return content.interface->SerializeTo(descriptor_pool, message_factory,
490
0
                                          output);
491
0
  }
492
0
  if (dispatcher_->serialize_to != nullptr) {
493
0
    return dispatcher_->serialize_to(dispatcher_, content_, descriptor_pool,
494
0
                                     message_factory, output);
495
0
  }
496
0
  return absl::UnimplementedError(
497
0
      absl::StrCat(GetTypeName(), " is unserializable"));
498
0
}
499
500
absl::Status CustomMapValue::ConvertToJson(
501
    const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
502
    google::protobuf::MessageFactory* absl_nonnull message_factory,
503
0
    google::protobuf::Message* absl_nonnull json) const {
504
0
  ABSL_DCHECK(descriptor_pool != nullptr);
505
0
  ABSL_DCHECK(message_factory != nullptr);
506
0
  ABSL_DCHECK(json != nullptr);
507
0
  ABSL_DCHECK_EQ(json->GetDescriptor()->well_known_type(),
508
0
                 google::protobuf::Descriptor::WELLKNOWNTYPE_VALUE);
509
510
0
  ValueReflection value_reflection;
511
0
  CEL_RETURN_IF_ERROR(value_reflection.Initialize(json->GetDescriptor()));
512
0
  google::protobuf::Message* json_object = value_reflection.MutableStructValue(json);
513
514
0
  return ConvertToJsonObject(descriptor_pool, message_factory, json_object);
515
0
}
516
517
absl::Status CustomMapValue::ConvertToJsonObject(
518
    const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
519
    google::protobuf::MessageFactory* absl_nonnull message_factory,
520
0
    google::protobuf::Message* absl_nonnull json) const {
521
0
  ABSL_DCHECK(descriptor_pool != nullptr);
522
0
  ABSL_DCHECK(message_factory != nullptr);
523
0
  ABSL_DCHECK(json != nullptr);
524
0
  ABSL_DCHECK_EQ(json->GetDescriptor()->well_known_type(),
525
0
                 google::protobuf::Descriptor::WELLKNOWNTYPE_STRUCT);
526
527
0
  if (dispatcher_ == nullptr) {
528
0
    CustomMapValueInterface::Content content =
529
0
        content_.To<CustomMapValueInterface::Content>();
530
0
    ABSL_DCHECK(content.interface != nullptr);
531
0
    return content.interface->ConvertToJsonObject(descriptor_pool,
532
0
                                                  message_factory, json);
533
0
  }
534
0
  if (dispatcher_->convert_to_json_object != nullptr) {
535
0
    return dispatcher_->convert_to_json_object(
536
0
        dispatcher_, content_, descriptor_pool, message_factory, json);
537
0
  }
538
0
  return absl::UnimplementedError(
539
0
      absl::StrCat(GetTypeName(), " is not convertable to JSON"));
540
0
}
541
542
absl::Status CustomMapValue::Equal(
543
    const Value& other,
544
    const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
545
    google::protobuf::MessageFactory* absl_nonnull message_factory,
546
46
    google::protobuf::Arena* absl_nonnull arena, Value* absl_nonnull result) const {
547
46
  ABSL_DCHECK(descriptor_pool != nullptr);
548
46
  ABSL_DCHECK(message_factory != nullptr);
549
46
  ABSL_DCHECK(arena != nullptr);
550
46
  ABSL_DCHECK(result != nullptr);
551
552
46
  if (auto other_map_value = other.AsMap(); other_map_value) {
553
11
    if (dispatcher_ == nullptr) {
554
11
      CustomMapValueInterface::Content content =
555
11
          content_.To<CustomMapValueInterface::Content>();
556
11
      ABSL_DCHECK(content.interface != nullptr);
557
11
      return content.interface->Equal(*other_map_value, descriptor_pool,
558
11
                                      message_factory, arena, result);
559
11
    }
560
0
    if (dispatcher_->equal != nullptr) {
561
0
      return dispatcher_->equal(dispatcher_, content_, *other_map_value,
562
0
                                descriptor_pool, message_factory, arena,
563
0
                                result);
564
0
    }
565
0
    return common_internal::MapValueEqual(*this, *other_map_value,
566
0
                                          descriptor_pool, message_factory,
567
0
                                          arena, result);
568
0
  }
569
35
  *result = FalseValue();
570
35
  return absl::OkStatus();
571
46
}
572
573
0
bool CustomMapValue::IsZeroValue() const {
574
0
  if (dispatcher_ == nullptr) {
575
0
    CustomMapValueInterface::Content content =
576
0
        content_.To<CustomMapValueInterface::Content>();
577
0
    ABSL_DCHECK(content.interface != nullptr);
578
0
    return content.interface->IsZeroValue();
579
0
  }
580
0
  return dispatcher_->is_zero_value(dispatcher_, content_);
581
0
}
582
583
0
CustomMapValue CustomMapValue::Clone(google::protobuf::Arena* absl_nonnull arena) const {
584
0
  ABSL_DCHECK(arena != nullptr);
585
586
0
  if (dispatcher_ == nullptr) {
587
0
    CustomMapValueInterface::Content content =
588
0
        content_.To<CustomMapValueInterface::Content>();
589
0
    ABSL_DCHECK(content.interface != nullptr);
590
0
    if (content.arena != arena) {
591
0
      return content.interface->Clone(arena);
592
0
    }
593
0
    return *this;
594
0
  }
595
0
  return dispatcher_->clone(dispatcher_, content_, arena);
596
0
}
597
598
0
bool CustomMapValue::IsEmpty() const {
599
0
  if (dispatcher_ == nullptr) {
600
0
    CustomMapValueInterface::Content content =
601
0
        content_.To<CustomMapValueInterface::Content>();
602
0
    ABSL_DCHECK(content.interface != nullptr);
603
0
    return content.interface->IsEmpty();
604
0
  }
605
0
  if (dispatcher_->is_empty != nullptr) {
606
0
    return dispatcher_->is_empty(dispatcher_, content_);
607
0
  }
608
0
  return dispatcher_->size(dispatcher_, content_) == 0;
609
0
}
610
611
110
size_t CustomMapValue::Size() const {
612
110
  if (dispatcher_ == nullptr) {
613
110
    CustomMapValueInterface::Content content =
614
110
        content_.To<CustomMapValueInterface::Content>();
615
110
    ABSL_DCHECK(content.interface != nullptr);
616
110
    return content.interface->Size();
617
110
  }
618
0
  return dispatcher_->size(dispatcher_, content_);
619
110
}
620
621
absl::Status CustomMapValue::Get(
622
    const Value& key,
623
    const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
624
    google::protobuf::MessageFactory* absl_nonnull message_factory,
625
1.98k
    google::protobuf::Arena* absl_nonnull arena, Value* absl_nonnull result) const {
626
1.98k
  ABSL_DCHECK(descriptor_pool != nullptr);
627
1.98k
  ABSL_DCHECK(message_factory != nullptr);
628
1.98k
  ABSL_DCHECK(arena != nullptr);
629
1.98k
  ABSL_DCHECK(result != nullptr);
630
631
3.96k
  CEL_ASSIGN_OR_RETURN(
632
3.96k
      bool ok, Find(key, descriptor_pool, message_factory, arena, result));
633
3.96k
  if (ABSL_PREDICT_FALSE(!ok)) {
634
1.96k
    switch (result->kind()) {
635
0
      case ValueKind::kError:
636
0
        ABSL_FALLTHROUGH_INTENDED;
637
0
      case ValueKind::kUnknown:
638
0
        break;
639
1.96k
      default:
640
1.96k
        *result = ErrorValue(NoSuchKeyError(key));
641
1.96k
        break;
642
1.96k
    }
643
1.96k
  }
644
1.98k
  return absl::OkStatus();
645
3.96k
}
646
647
absl::StatusOr<bool> CustomMapValue::Find(
648
    const Value& key,
649
    const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
650
    google::protobuf::MessageFactory* absl_nonnull message_factory,
651
5.36k
    google::protobuf::Arena* absl_nonnull arena, Value* absl_nonnull result) const {
652
5.36k
  ABSL_DCHECK(descriptor_pool != nullptr);
653
5.36k
  ABSL_DCHECK(message_factory != nullptr);
654
5.36k
  ABSL_DCHECK(arena != nullptr);
655
5.36k
  ABSL_DCHECK(result != nullptr);
656
657
5.36k
  switch (key.kind()) {
658
0
    case ValueKind::kError:
659
0
      ABSL_FALLTHROUGH_INTENDED;
660
0
    case ValueKind::kUnknown:
661
0
      *result = key;
662
0
      return false;
663
93
    case ValueKind::kBool:
664
93
      ABSL_FALLTHROUGH_INTENDED;
665
1.62k
    case ValueKind::kInt:
666
1.62k
      ABSL_FALLTHROUGH_INTENDED;
667
3.48k
    case ValueKind::kUint:
668
3.48k
      ABSL_FALLTHROUGH_INTENDED;
669
5.36k
    case ValueKind::kString:
670
5.36k
      break;
671
0
    default:
672
0
      *result = ErrorValue(InvalidMapKeyTypeError(key.kind()));
673
0
      return false;
674
5.36k
  }
675
676
5.36k
  bool ok;
677
5.36k
  if (dispatcher_ == nullptr) {
678
5.36k
    CustomMapValueInterface::Content content =
679
5.36k
        content_.To<CustomMapValueInterface::Content>();
680
5.36k
    ABSL_DCHECK(content.interface != nullptr);
681
10.7k
    CEL_ASSIGN_OR_RETURN(
682
10.7k
        ok, content.interface->Find(key, descriptor_pool, message_factory,
683
10.7k
                                    arena, result));
684
10.7k
  } else {
685
0
    CEL_ASSIGN_OR_RETURN(
686
0
        ok, dispatcher_->find(dispatcher_, content_, key, descriptor_pool,
687
0
                              message_factory, arena, result));
688
0
  }
689
5.36k
  if (ok) {
690
30
    return true;
691
30
  }
692
5.33k
  *result = NullValue{};
693
5.33k
  return false;
694
5.36k
}
695
696
absl::Status CustomMapValue::Has(
697
    const Value& key,
698
    const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
699
    google::protobuf::MessageFactory* absl_nonnull message_factory,
700
435
    google::protobuf::Arena* absl_nonnull arena, Value* absl_nonnull result) const {
701
435
  ABSL_DCHECK(descriptor_pool != nullptr);
702
435
  ABSL_DCHECK(message_factory != nullptr);
703
435
  ABSL_DCHECK(arena != nullptr);
704
435
  ABSL_DCHECK(result != nullptr);
705
706
435
  switch (key.kind()) {
707
0
    case ValueKind::kError:
708
0
      ABSL_FALLTHROUGH_INTENDED;
709
0
    case ValueKind::kUnknown:
710
0
      *result = key;
711
0
      return absl::OkStatus();
712
308
    case ValueKind::kBool:
713
308
      ABSL_FALLTHROUGH_INTENDED;
714
369
    case ValueKind::kInt:
715
369
      ABSL_FALLTHROUGH_INTENDED;
716
432
    case ValueKind::kUint:
717
432
      ABSL_FALLTHROUGH_INTENDED;
718
433
    case ValueKind::kString:
719
433
      break;
720
2
    default:
721
2
      *result = ErrorValue(InvalidMapKeyTypeError(key.kind()));
722
2
      return absl::OkStatus();
723
435
  }
724
433
  bool has;
725
433
  if (dispatcher_ == nullptr) {
726
433
    CustomMapValueInterface::Content content =
727
433
        content_.To<CustomMapValueInterface::Content>();
728
433
    ABSL_DCHECK(content.interface != nullptr);
729
866
    CEL_ASSIGN_OR_RETURN(has, content.interface->Has(key, descriptor_pool,
730
866
                                                     message_factory, arena));
731
866
  } else {
732
0
    CEL_ASSIGN_OR_RETURN(
733
0
        has, dispatcher_->has(dispatcher_, content_, key, descriptor_pool,
734
0
                              message_factory, arena));
735
0
  }
736
433
  *result = BoolValue(has);
737
433
  return absl::OkStatus();
738
433
}
739
740
absl::Status CustomMapValue::ListKeys(
741
    const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
742
    google::protobuf::MessageFactory* absl_nonnull message_factory,
743
0
    google::protobuf::Arena* absl_nonnull arena, ListValue* absl_nonnull result) const {
744
0
  ABSL_DCHECK(descriptor_pool != nullptr);
745
0
  ABSL_DCHECK(message_factory != nullptr);
746
0
  ABSL_DCHECK(arena != nullptr);
747
0
  ABSL_DCHECK(result != nullptr);
748
749
0
  if (dispatcher_ == nullptr) {
750
0
    CustomMapValueInterface::Content content =
751
0
        content_.To<CustomMapValueInterface::Content>();
752
0
    ABSL_DCHECK(content.interface != nullptr);
753
0
    return content.interface->ListKeys(descriptor_pool, message_factory, arena,
754
0
                                       result);
755
0
  }
756
0
  return dispatcher_->list_keys(dispatcher_, content_, descriptor_pool,
757
0
                                message_factory, arena, result);
758
0
}
759
760
absl::Status CustomMapValue::ForEach(
761
    ForEachCallback callback,
762
    const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
763
    google::protobuf::MessageFactory* absl_nonnull message_factory,
764
0
    google::protobuf::Arena* absl_nonnull arena) const {
765
0
  ABSL_DCHECK(descriptor_pool != nullptr);
766
0
  ABSL_DCHECK(message_factory != nullptr);
767
0
  ABSL_DCHECK(arena != nullptr);
768
769
0
  if (dispatcher_ == nullptr) {
770
0
    CustomMapValueInterface::Content content =
771
0
        content_.To<CustomMapValueInterface::Content>();
772
0
    ABSL_DCHECK(content.interface != nullptr);
773
0
    return content.interface->ForEach(callback, descriptor_pool,
774
0
                                      message_factory, arena);
775
0
  }
776
0
  if (dispatcher_->for_each != nullptr) {
777
0
    return dispatcher_->for_each(dispatcher_, content_, callback,
778
0
                                 descriptor_pool, message_factory, arena);
779
0
  }
780
0
  absl_nonnull ValueIteratorPtr iterator;
781
0
  if (dispatcher_->new_iterator != nullptr) {
782
0
    CEL_ASSIGN_OR_RETURN(iterator,
783
0
                         dispatcher_->new_iterator(dispatcher_, content_));
784
0
  } else {
785
0
    iterator = std::make_unique<CustomMapValueDispatcherIterator>(dispatcher_,
786
0
                                                                  content_);
787
0
  }
788
0
  while (iterator->HasNext()) {
789
0
    Value key;
790
0
    Value value;
791
0
    CEL_RETURN_IF_ERROR(
792
0
        iterator->Next(descriptor_pool, message_factory, arena, &key));
793
0
    CEL_ASSIGN_OR_RETURN(
794
0
        bool found,
795
0
        dispatcher_->find(dispatcher_, content_, key, descriptor_pool,
796
0
                          message_factory, arena, &value));
797
0
    if (!found) {
798
0
      value = ErrorValue(NoSuchKeyError(key));
799
0
    }
800
0
    CEL_ASSIGN_OR_RETURN(auto ok, callback(key, value));
801
0
    if (!ok) {
802
0
      break;
803
0
    }
804
0
  }
805
0
  return absl::OkStatus();
806
0
}
807
808
absl::StatusOr<absl_nonnull ValueIteratorPtr> CustomMapValue::NewIterator()
809
45
    const {
810
45
  if (dispatcher_ == nullptr) {
811
45
    CustomMapValueInterface::Content content =
812
45
        content_.To<CustomMapValueInterface::Content>();
813
45
    ABSL_DCHECK(content.interface != nullptr);
814
45
    return content.interface->NewIterator();
815
45
  }
816
0
  if (dispatcher_->new_iterator != nullptr) {
817
0
    return dispatcher_->new_iterator(dispatcher_, content_);
818
0
  }
819
0
  return std::make_unique<CustomMapValueDispatcherIterator>(dispatcher_,
820
0
                                                            content_);
821
0
}
822
823
}  // namespace cel