Coverage Report

Created: 2026-09-14 06:52

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