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/value_builder.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 <cstddef>
16
#include <cstdint>
17
#include <cstring>
18
#include <memory>
19
#include <new>
20
#include <string>
21
#include <type_traits>
22
#include <utility>
23
#include <vector>
24
25
#include "absl/base/call_once.h"
26
#include "absl/base/casts.h"
27
#include "absl/base/nullability.h"
28
#include "absl/base/optimization.h"
29
#include "absl/container/flat_hash_map.h"
30
#include "absl/hash/hash.h"
31
#include "absl/log/absl_check.h"
32
#include "absl/status/status.h"
33
#include "absl/status/statusor.h"
34
#include "absl/strings/str_cat.h"
35
#include "absl/strings/str_join.h"
36
#include "absl/types/optional.h"
37
#include "absl/types/span.h"
38
#include "common/allocator.h"
39
#include "common/arena.h"
40
#include "common/legacy_value.h"
41
#include "common/native_type.h"
42
#include "common/type.h"
43
#include "common/value.h"
44
#include "common/value_kind.h"
45
#include "common/values/list_value_builder.h"
46
#include "common/values/map_value_builder.h"
47
#include "eval/public/cel_value.h"
48
#include "internal/casts.h"
49
#include "internal/manual.h"
50
#include "internal/status_macros.h"
51
#include "internal/well_known_types.h"
52
#include "google/protobuf/arena.h"
53
#include "google/protobuf/descriptor.h"
54
#include "google/protobuf/message.h"
55
56
namespace cel {
57
58
namespace common_internal {
59
60
namespace {
61
62
using ::cel::well_known_types::ListValueReflection;
63
using ::cel::well_known_types::StructReflection;
64
using ::cel::well_known_types::ValueReflection;
65
using ::google::api::expr::runtime::CelValue;
66
67
using ValueVector = std::vector<Value, ArenaAllocator<Value>>;
68
69
135k
absl::Status CheckListElement(const Value& value) {
70
135k
  if (auto error_value = value.AsError(); ABSL_PREDICT_FALSE(error_value)) {
71
0
    return error_value->ToStatus();
72
0
  }
73
135k
  if (auto unknown_value = value.AsUnknown();
74
135k
      ABSL_PREDICT_FALSE(unknown_value)) {
75
0
    return absl::InvalidArgumentError("cannot add unknown value to list");
76
0
  }
77
135k
  return absl::OkStatus();
78
135k
}
79
80
template <typename Vector>
81
absl::Status ListValueToJsonArray(
82
    const Vector& vector,
83
    const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
84
    google::protobuf::MessageFactory* absl_nonnull message_factory,
85
0
    google::protobuf::Message* absl_nonnull json) {
86
0
  ABSL_DCHECK(descriptor_pool != nullptr);
87
0
  ABSL_DCHECK(message_factory != nullptr);
88
0
  ABSL_DCHECK(json != nullptr);
89
0
  ABSL_DCHECK_EQ(json->GetDescriptor()->well_known_type(),
90
0
                 google::protobuf::Descriptor::WELLKNOWNTYPE_LISTVALUE);
91
92
0
  ListValueReflection reflection;
93
0
  CEL_RETURN_IF_ERROR(reflection.Initialize(json->GetDescriptor()));
94
95
0
  json->Clear();
96
97
0
  if (vector.empty()) {
98
0
    return absl::OkStatus();
99
0
  }
100
101
0
  for (const auto& element : vector) {
102
0
    CEL_RETURN_IF_ERROR(element->ConvertToJson(descriptor_pool, message_factory,
103
0
                                               reflection.AddValues(json)));
104
0
  }
105
0
  return absl::OkStatus();
106
0
}
107
108
template <typename Vector>
109
absl::Status ListValueToJson(
110
    const Vector& vector,
111
    const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
112
    google::protobuf::MessageFactory* absl_nonnull message_factory,
113
    google::protobuf::Message* absl_nonnull json) {
114
  ABSL_DCHECK(descriptor_pool != nullptr);
115
  ABSL_DCHECK(message_factory != nullptr);
116
  ABSL_DCHECK(json != nullptr);
117
  ABSL_DCHECK_EQ(json->GetDescriptor()->well_known_type(),
118
                 google::protobuf::Descriptor::WELLKNOWNTYPE_VALUE);
119
120
  ValueReflection reflection;
121
  CEL_RETURN_IF_ERROR(reflection.Initialize(json->GetDescriptor()));
122
  return ListValueToJsonArray(vector, descriptor_pool, message_factory,
123
                              reflection.MutableListValue(json));
124
}
125
126
class CompatListValueImplIterator final : public ValueIterator {
127
 public:
128
  explicit CompatListValueImplIterator(absl::Span<const Value> elements)
129
84
      : elements_(elements) {}
130
131
84
  bool HasNext() override { return index_ < elements_.size(); }
132
133
  absl::Status Next(const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
134
                    google::protobuf::MessageFactory* absl_nonnull message_factory,
135
                    google::protobuf::Arena* absl_nonnull arena,
136
84
                    Value* absl_nonnull result) override {
137
84
    if (ABSL_PREDICT_FALSE(index_ >= elements_.size())) {
138
0
      return absl::FailedPreconditionError(
139
0
          "ValueManager::Next called after ValueManager::HasNext returned "
140
0
          "false");
141
0
    }
142
84
    *result = elements_[index_++];
143
84
    return absl::OkStatus();
144
84
  }
145
146
  absl::StatusOr<bool> Next1(
147
      const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
148
      google::protobuf::MessageFactory* absl_nonnull message_factory,
149
      google::protobuf::Arena* absl_nonnull arena,
150
0
      Value* absl_nonnull key_or_value) override {
151
0
    ABSL_DCHECK(descriptor_pool != nullptr);
152
0
    ABSL_DCHECK(message_factory != nullptr);
153
0
    ABSL_DCHECK(arena != nullptr);
154
0
    ABSL_DCHECK(key_or_value != nullptr);
155
156
0
    if (index_ >= elements_.size()) {
157
0
      return false;
158
0
    }
159
0
    *key_or_value = elements_[index_];
160
0
    ++index_;
161
0
    return true;
162
0
  }
163
164
  absl::StatusOr<bool> Next2(
165
      const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
166
      google::protobuf::MessageFactory* absl_nonnull message_factory,
167
      google::protobuf::Arena* absl_nonnull arena, Value* absl_nonnull key,
168
0
      Value* absl_nullable value) override {
169
0
    ABSL_DCHECK(descriptor_pool != nullptr);
170
0
    ABSL_DCHECK(message_factory != nullptr);
171
0
    ABSL_DCHECK(arena != nullptr);
172
0
    ABSL_DCHECK(key != nullptr);
173
174
0
    if (index_ >= elements_.size()) {
175
0
      return false;
176
0
    }
177
0
    if (value != nullptr) {
178
0
      *value = elements_[index_];
179
0
    }
180
0
    *key = IntValue(index_++);
181
0
    return true;
182
0
  }
183
184
 private:
185
  const absl::Span<const Value> elements_;
186
  size_t index_ = 0;
187
};
188
189
struct ValueFormatter {
190
  void operator()(std::string* out,
191
0
                  const std::pair<const Value, Value>& value) const {
192
0
    (*this)(out, value.first);
193
0
    out->append(": ");
194
0
    (*this)(out, value.second);
195
0
  }
196
197
0
  void operator()(std::string* out, const Value& value) const {
198
0
    out->append(value.DebugString());
199
0
  }
200
};
201
202
class ListValueBuilderImpl final : public ListValueBuilder {
203
 public:
204
  explicit ListValueBuilderImpl(google::protobuf::Arena* absl_nonnull arena)
205
11.2k
      : arena_(arena) {
206
11.2k
    elements_.Construct(arena);
207
11.2k
  }
208
209
11.2k
  ~ListValueBuilderImpl() override {
210
11.2k
    if (!elements_trivially_destructible_) {
211
0
      elements_.Destruct();
212
0
    }
213
11.2k
  }
214
215
135k
  absl::Status Add(Value value) override {
216
135k
    CEL_RETURN_IF_ERROR(CheckListElement(value));
217
135k
    UnsafeAdd(std::move(value));
218
135k
    return absl::OkStatus();
219
135k
  }
220
221
135k
  void UnsafeAdd(Value value) override {
222
135k
    ABSL_DCHECK_OK(CheckListElement(value));
223
135k
    elements_->emplace_back(std::move(value));
224
135k
    if (elements_trivially_destructible_) {
225
99.9k
      elements_trivially_destructible_ =
226
99.9k
          ArenaTraits<>::trivially_destructible(elements_->back());
227
99.9k
    }
228
135k
  }
229
230
0
  size_t Size() const override { return elements_->size(); }
231
232
11.2k
  void Reserve(size_t capacity) override { elements_->reserve(capacity); }
233
234
  ListValue Build() && override;
235
236
  CustomListValue BuildCustom() &&;
237
238
  const CompatListValue* absl_nonnull BuildCompat() &&;
239
240
  const CompatListValue* absl_nonnull BuildCompatAt(
241
      void* absl_nonnull address) &&;
242
243
 private:
244
  google::protobuf::Arena* absl_nonnull const arena_;
245
  internal::Manual<ValueVector> elements_;
246
  bool elements_trivially_destructible_ = true;
247
};
248
249
class CompatListValueImpl final : public CompatListValue {
250
 public:
251
  explicit CompatListValueImpl(ValueVector&& elements)
252
9.51k
      : elements_(std::move(elements)) {}
253
254
0
  std::string DebugString() const override {
255
0
    return absl::StrCat("[", absl::StrJoin(elements_, ", ", ValueFormatter{}),
256
0
                        "]");
257
0
  }
258
259
  absl::Status ConvertToJsonArray(
260
      const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
261
      google::protobuf::MessageFactory* absl_nonnull message_factory,
262
0
      google::protobuf::Message* absl_nonnull json) const override {
263
0
    return ListValueToJsonArray(elements_, descriptor_pool, message_factory,
264
0
                                json);
265
0
  }
266
267
0
  CustomListValue Clone(google::protobuf::Arena* absl_nonnull arena) const override {
268
0
    ABSL_DCHECK(arena != nullptr);
269
270
0
    ListValueBuilderImpl builder(arena);
271
0
    builder.Reserve(elements_.size());
272
0
    for (const auto& element : elements_) {
273
0
      builder.UnsafeAdd(element.Clone(arena));
274
0
    }
275
0
    return std::move(builder).BuildCustom();
276
0
  }
277
278
6.86k
  size_t Size() const override { return elements_.size(); }
279
280
  absl::Status ForEach(
281
      ForEachWithIndexCallback callback,
282
      const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
283
      google::protobuf::MessageFactory* absl_nonnull message_factory,
284
1.50k
      google::protobuf::Arena* absl_nonnull arena) const override {
285
1.50k
    const size_t size = elements_.size();
286
12.6k
    for (size_t i = 0; i < size; ++i) {
287
11.4k
      CEL_ASSIGN_OR_RETURN(auto ok, callback(i, elements_[i]));
288
11.4k
      if (!ok) {
289
239
        break;
290
239
      }
291
11.4k
    }
292
1.50k
    return absl::OkStatus();
293
1.50k
  }
294
295
84
  absl::StatusOr<absl_nonnull ValueIteratorPtr> NewIterator() const override {
296
84
    return std::make_unique<CompatListValueImplIterator>(
297
84
        absl::MakeConstSpan(elements_));
298
84
  }
299
300
0
  CelValue operator[](int index) const override {
301
0
    return Get(elements_.get_allocator().arena(), index);
302
0
  }
303
304
  // Like `operator[](int)` above, but also accepts an arena. Prefer calling
305
  // this variant if the arena is known.
306
0
  CelValue Get(google::protobuf::Arena* arena, int index) const override {
307
0
    if (arena == nullptr) {
308
0
      arena = elements_.get_allocator().arena();
309
0
    }
310
0
    if (ABSL_PREDICT_FALSE(index < 0 || index >= size())) {
311
0
      return CelValue::CreateError(google::protobuf::Arena::Create<absl::Status>(
312
0
          arena, IndexOutOfBoundsError(index).ToStatus()));
313
0
    }
314
0
    return common_internal::UnsafeLegacyValue(
315
0
        elements_[index],
316
0
        /*stable=*/true,
317
0
        arena != nullptr ? arena : elements_.get_allocator().arena());
318
0
  }
319
320
0
  int size() const override { return static_cast<int>(Size()); }
321
322
 protected:
323
  absl::Status Get(size_t index,
324
                   const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
325
                   google::protobuf::MessageFactory* absl_nonnull message_factory,
326
                   google::protobuf::Arena* absl_nonnull arena,
327
112k
                   Value* absl_nonnull result) const override {
328
112k
    if (index >= elements_.size()) {
329
0
      *result = IndexOutOfBoundsError(index);
330
112k
    } else {
331
112k
      *result = elements_[index];
332
112k
    }
333
112k
    return absl::OkStatus();
334
112k
  }
335
336
 private:
337
  const ValueVector elements_;
338
};
339
340
}  // namespace
341
342
}  // namespace common_internal
343
344
template <>
345
struct ArenaTraits<common_internal::CompatListValueImpl> {
346
  using always_trivially_destructible = std::true_type;
347
};
348
349
namespace common_internal {
350
351
namespace {
352
353
11.2k
ListValue ListValueBuilderImpl::Build() && {
354
11.2k
  if (elements_->empty()) {
355
1.68k
    return ListValue();
356
1.68k
  }
357
9.51k
  return std::move(*this).BuildCustom();
358
11.2k
}
359
360
9.51k
CustomListValue ListValueBuilderImpl::BuildCustom() && {
361
9.51k
  if (elements_->empty()) {
362
0
    return CustomListValue(EmptyCompatListValue(), arena_);
363
0
  }
364
9.51k
  return CustomListValue(std::move(*this).BuildCompat(), arena_);
365
9.51k
}
366
367
9.51k
const CompatListValue* absl_nonnull ListValueBuilderImpl::BuildCompat() && {
368
9.51k
  if (elements_->empty()) {
369
0
    return EmptyCompatListValue();
370
0
  }
371
9.51k
  return std::move(*this).BuildCompatAt(arena_->AllocateAligned(
372
9.51k
      sizeof(CompatListValueImpl), alignof(CompatListValueImpl)));
373
9.51k
}
374
375
const CompatListValue* absl_nonnull ListValueBuilderImpl::BuildCompatAt(
376
9.51k
    void* absl_nonnull address) && {
377
9.51k
  CompatListValueImpl* absl_nonnull impl =
378
9.51k
      ::new (address) CompatListValueImpl(std::move(*elements_));
379
9.51k
  if (!elements_trivially_destructible_) {
380
1.66k
    arena_->OwnDestructor(impl);
381
1.66k
    elements_trivially_destructible_ = true;
382
1.66k
  }
383
9.51k
  return impl;
384
9.51k
}
385
386
class MutableCompatListValueImpl final : public MutableCompatListValue {
387
 public:
388
  explicit MutableCompatListValueImpl(google::protobuf::Arena* absl_nonnull arena)
389
0
      : elements_(arena) {}
390
391
0
  std::string DebugString() const override {
392
0
    return absl::StrCat("[", absl::StrJoin(elements_, ", ", ValueFormatter{}),
393
0
                        "]");
394
0
  }
395
396
  absl::Status ConvertToJsonArray(
397
      const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
398
      google::protobuf::MessageFactory* absl_nonnull message_factory,
399
0
      google::protobuf::Message* absl_nonnull json) const override {
400
0
    return ListValueToJsonArray(elements_, descriptor_pool, message_factory,
401
0
                                json);
402
0
  }
403
404
0
  CustomListValue Clone(google::protobuf::Arena* absl_nonnull arena) const override {
405
0
    ABSL_DCHECK(arena != nullptr);
406
407
0
    ListValueBuilderImpl builder(arena);
408
0
    builder.Reserve(elements_.size());
409
0
    for (const auto& element : elements_) {
410
0
      builder.UnsafeAdd(element.Clone(arena));
411
0
    }
412
0
    return std::move(builder).BuildCustom();
413
0
  }
414
415
0
  size_t Size() const override { return elements_.size(); }
416
417
  absl::Status ForEach(
418
      ForEachWithIndexCallback callback,
419
      const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
420
      google::protobuf::MessageFactory* absl_nonnull message_factory,
421
0
      google::protobuf::Arena* absl_nonnull arena) const override {
422
0
    const size_t size = elements_.size();
423
0
    for (size_t i = 0; i < size; ++i) {
424
0
      CEL_ASSIGN_OR_RETURN(auto ok, callback(i, elements_[i]));
425
0
      if (!ok) {
426
0
        break;
427
0
      }
428
0
    }
429
0
    return absl::OkStatus();
430
0
  }
431
432
0
  absl::StatusOr<absl_nonnull ValueIteratorPtr> NewIterator() const override {
433
0
    return std::make_unique<CompatListValueImplIterator>(
434
0
        absl::MakeConstSpan(elements_));
435
0
  }
436
437
0
  CelValue operator[](int index) const override {
438
0
    return Get(elements_.get_allocator().arena(), index);
439
0
  }
440
441
  // Like `operator[](int)` above, but also accepts an arena. Prefer calling
442
  // this variant if the arena is known.
443
0
  CelValue Get(google::protobuf::Arena* arena, int index) const override {
444
0
    if (arena == nullptr) {
445
0
      arena = elements_.get_allocator().arena();
446
0
    }
447
0
    if (ABSL_PREDICT_FALSE(index < 0 || index >= size())) {
448
0
      return CelValue::CreateError(google::protobuf::Arena::Create<absl::Status>(
449
0
          arena, IndexOutOfBoundsError(index).ToStatus()));
450
0
    }
451
0
    return common_internal::UnsafeLegacyValue(
452
0
        elements_[index], /*stable=*/false,
453
0
        arena != nullptr ? arena : elements_.get_allocator().arena());
454
0
  }
455
456
0
  int size() const override { return static_cast<int>(Size()); }
457
458
0
  absl::Status Append(Value value) const override {
459
0
    CEL_RETURN_IF_ERROR(CheckListElement(value));
460
0
    elements_.emplace_back(std::move(value));
461
0
    if (elements_trivially_destructible_) {
462
0
      elements_trivially_destructible_ =
463
0
          ArenaTraits<>::trivially_destructible(elements_.back());
464
0
      if (!elements_trivially_destructible_) {
465
0
        elements_.get_allocator().arena()->OwnDestructor(
466
0
            const_cast<MutableCompatListValueImpl*>(this));
467
0
      }
468
0
    }
469
0
    return absl::OkStatus();
470
0
  }
471
472
0
  void Reserve(size_t capacity) const override { elements_.reserve(capacity); }
473
474
 protected:
475
  absl::Status Get(size_t index,
476
                   const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
477
                   google::protobuf::MessageFactory* absl_nonnull message_factory,
478
                   google::protobuf::Arena* absl_nonnull arena,
479
0
                   Value* absl_nonnull result) const override {
480
0
    if (index >= elements_.size()) {
481
0
      *result = IndexOutOfBoundsError(index);
482
0
    } else {
483
0
      *result = elements_[index];
484
0
    }
485
0
    return absl::OkStatus();
486
0
  }
487
488
 private:
489
  mutable ValueVector elements_;
490
  mutable bool elements_trivially_destructible_ = true;
491
};
492
493
}  // namespace
494
495
}  // namespace common_internal
496
497
template <>
498
struct ArenaTraits<common_internal::MutableCompatListValueImpl> {
499
  using constructible = std::true_type;
500
501
  using always_trivially_destructible = std::true_type;
502
};
503
504
namespace common_internal {
505
506
namespace {}  // namespace
507
508
absl::StatusOr<const CompatListValue* absl_nonnull> MakeCompatListValue(
509
    const CustomListValue& value,
510
    const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
511
    google::protobuf::MessageFactory* absl_nonnull message_factory,
512
0
    google::protobuf::Arena* absl_nonnull arena) {
513
0
  ListValueBuilderImpl builder(arena);
514
0
  builder.Reserve(value.Size());
515
516
0
  CEL_RETURN_IF_ERROR(value.ForEach(
517
0
      [&](const Value& element) -> absl::StatusOr<bool> {
518
0
        CEL_RETURN_IF_ERROR(builder.Add(element));
519
0
        return true;
520
0
      },
521
0
      descriptor_pool, message_factory, arena));
522
523
0
  return std::move(builder).BuildCompat();
524
0
}
525
526
MutableListValue* absl_nonnull NewMutableListValue(
527
0
    google::protobuf::Arena* absl_nonnull arena) {
528
0
  return ::new (arena->AllocateAligned(sizeof(MutableCompatListValueImpl),
529
0
                                       alignof(MutableCompatListValueImpl)))
530
0
      MutableCompatListValueImpl(arena);
531
0
}
532
533
0
bool IsMutableListValue(const Value& value) {
534
0
  if (auto custom_list_value = value.AsCustomList(); custom_list_value) {
535
0
    NativeTypeId native_type_id = custom_list_value->GetTypeId();
536
0
    if (native_type_id == NativeTypeId::For<MutableListValue>() ||
537
0
        native_type_id == NativeTypeId::For<MutableCompatListValue>()) {
538
0
      return true;
539
0
    }
540
0
  }
541
0
  return false;
542
0
}
543
544
0
bool IsMutableListValue(const ListValue& value) {
545
0
  if (auto custom_list_value = value.AsCustom(); custom_list_value) {
546
0
    NativeTypeId native_type_id = custom_list_value->GetTypeId();
547
0
    if (native_type_id == NativeTypeId::For<MutableListValue>() ||
548
0
        native_type_id == NativeTypeId::For<MutableCompatListValue>()) {
549
0
      return true;
550
0
    }
551
0
  }
552
0
  return false;
553
0
}
554
555
0
const MutableListValue* absl_nullable AsMutableListValue(const Value& value) {
556
0
  if (auto custom_list_value = value.AsCustomList(); custom_list_value) {
557
0
    NativeTypeId native_type_id = custom_list_value->GetTypeId();
558
0
    if (native_type_id == NativeTypeId::For<MutableListValue>()) {
559
0
      return cel::internal::down_cast<const MutableListValue*>(
560
0
          custom_list_value->interface());
561
0
    }
562
0
    if (native_type_id == NativeTypeId::For<MutableCompatListValue>()) {
563
0
      return cel::internal::down_cast<const MutableCompatListValue*>(
564
0
          custom_list_value->interface());
565
0
    }
566
0
  }
567
0
  return nullptr;
568
0
}
569
570
const MutableListValue* absl_nullable AsMutableListValue(
571
0
    const ListValue& value) {
572
0
  if (auto custom_list_value = value.AsCustom(); custom_list_value) {
573
0
    NativeTypeId native_type_id = custom_list_value->GetTypeId();
574
0
    if (native_type_id == NativeTypeId::For<MutableListValue>()) {
575
0
      return cel::internal::down_cast<const MutableListValue*>(
576
0
          custom_list_value->interface());
577
0
    }
578
0
    if (native_type_id == NativeTypeId::For<MutableCompatListValue>()) {
579
0
      return cel::internal::down_cast<const MutableCompatListValue*>(
580
0
          custom_list_value->interface());
581
0
    }
582
0
  }
583
0
  return nullptr;
584
0
}
585
586
0
const MutableListValue& GetMutableListValue(const Value& value) {
587
0
  ABSL_DCHECK(IsMutableListValue(value)) << value;
588
0
  const auto& custom_list_value = value.GetCustomList();
589
0
  NativeTypeId native_type_id = custom_list_value.GetTypeId();
590
0
  if (native_type_id == NativeTypeId::For<MutableListValue>()) {
591
0
    return cel::internal::down_cast<const MutableListValue&>(
592
0
        *custom_list_value.interface());
593
0
  }
594
0
  if (native_type_id == NativeTypeId::For<MutableCompatListValue>()) {
595
0
    return cel::internal::down_cast<const MutableCompatListValue&>(
596
0
        *custom_list_value.interface());
597
0
  }
598
0
  ABSL_UNREACHABLE();
599
0
}
600
601
0
const MutableListValue& GetMutableListValue(const ListValue& value) {
602
0
  ABSL_DCHECK(IsMutableListValue(value)) << value;
603
0
  const auto& custom_list_value = value.GetCustom();
604
0
  NativeTypeId native_type_id = custom_list_value.GetTypeId();
605
0
  if (native_type_id == NativeTypeId::For<MutableListValue>()) {
606
0
    return cel::internal::down_cast<const MutableListValue&>(
607
0
        *custom_list_value.interface());
608
0
  }
609
0
  if (native_type_id == NativeTypeId::For<MutableCompatListValue>()) {
610
0
    return cel::internal::down_cast<const MutableCompatListValue&>(
611
0
        *custom_list_value.interface());
612
0
  }
613
0
  ABSL_UNREACHABLE();
614
0
}
615
616
absl_nonnull cel::ListValueBuilderPtr NewListValueBuilder(
617
11.2k
    google::protobuf::Arena* absl_nonnull arena) {
618
11.2k
  return std::make_unique<ListValueBuilderImpl>(arena);
619
11.2k
}
620
621
}  // namespace common_internal
622
623
}  // namespace cel
624
625
namespace cel {
626
627
namespace common_internal {
628
629
namespace {
630
631
using ::google::api::expr::runtime::CelList;
632
using ::google::api::expr::runtime::CelValue;
633
634
2.86k
absl::Status CheckMapValue(const Value& value) {
635
2.86k
  if (auto error_value = value.AsError(); ABSL_PREDICT_FALSE(error_value)) {
636
0
    return error_value->ToStatus();
637
0
  }
638
2.86k
  if (auto unknown_value = value.AsUnknown();
639
2.86k
      ABSL_PREDICT_FALSE(unknown_value)) {
640
0
    return absl::InvalidArgumentError("cannot add unknown value to list");
641
0
  }
642
2.86k
  return absl::OkStatus();
643
2.86k
}
644
645
3.14k
size_t ValueHash(const Value& value) {
646
3.14k
  switch (value.kind()) {
647
0
    case ValueKind::kBool:
648
0
      return absl::HashOf(value.kind(), value.GetBool());
649
1.59k
    case ValueKind::kInt:
650
1.59k
      return absl::HashOf(ValueKind::kInt,
651
1.59k
                          absl::implicit_cast<int64_t>(value.GetInt()));
652
8
    case ValueKind::kUint:
653
8
      return absl::HashOf(ValueKind::kUint,
654
8
                          absl::implicit_cast<uint64_t>(value.GetUint()));
655
1.54k
    case ValueKind::kString:
656
1.54k
      return absl::HashOf(value.kind(), value.GetString());
657
0
    default:
658
0
      ABSL_UNREACHABLE();
659
3.14k
  }
660
3.14k
}
661
662
0
size_t ValueHash(const CelValue& value) {
663
0
  switch (value.type()) {
664
0
    case CelValue::Type::kBool:
665
0
      return absl::HashOf(ValueKind::kBool, value.BoolOrDie());
666
0
    case CelValue::Type::kInt:
667
0
      return absl::HashOf(ValueKind::kInt, value.Int64OrDie());
668
0
    case CelValue::Type::kUint:
669
0
      return absl::HashOf(ValueKind::kUint, value.Uint64OrDie());
670
0
    case CelValue::Type::kString:
671
0
      return absl::HashOf(ValueKind::kString, value.StringOrDie().value());
672
0
    default:
673
0
      ABSL_UNREACHABLE();
674
0
  }
675
0
}
676
677
463
bool ValueEquals(const Value& lhs, const Value& rhs) {
678
463
  switch (lhs.kind()) {
679
85
    case ValueKind::kBool:
680
85
      switch (rhs.kind()) {
681
1
        case ValueKind::kBool:
682
1
          return lhs.GetBool() == rhs.GetBool();
683
1
        case ValueKind::kInt:
684
1
          return false;
685
1
        case ValueKind::kUint:
686
1
          return false;
687
82
        case ValueKind::kString:
688
82
          return false;
689
0
        default:
690
0
          ABSL_UNREACHABLE();
691
85
      }
692
262
    case ValueKind::kInt:
693
262
      switch (rhs.kind()) {
694
2
        case ValueKind::kBool:
695
2
          return false;
696
132
        case ValueKind::kInt:
697
132
          return lhs.GetInt() == rhs.GetInt();
698
43
        case ValueKind::kUint:
699
43
          return false;
700
85
        case ValueKind::kString:
701
85
          return false;
702
0
        default:
703
0
          ABSL_UNREACHABLE();
704
262
      }
705
67
    case ValueKind::kUint:
706
67
      switch (rhs.kind()) {
707
0
        case ValueKind::kBool:
708
0
          return false;
709
3
        case ValueKind::kInt:
710
3
          return false;
711
3
        case ValueKind::kUint:
712
3
          return lhs.GetUint() == rhs.GetUint();
713
61
        case ValueKind::kString:
714
61
          return false;
715
0
        default:
716
0
          ABSL_UNREACHABLE();
717
67
      }
718
49
    case ValueKind::kString:
719
49
      switch (rhs.kind()) {
720
0
        case ValueKind::kBool:
721
0
          return false;
722
3
        case ValueKind::kInt:
723
3
          return false;
724
4
        case ValueKind::kUint:
725
4
          return false;
726
42
        case ValueKind::kString:
727
42
          return lhs.GetString() == rhs.GetString();
728
0
        default:
729
0
          ABSL_UNREACHABLE();
730
49
      }
731
0
    default:
732
0
      ABSL_UNREACHABLE();
733
463
  }
734
463
}
735
736
0
bool CelValueEquals(const CelValue& lhs, const Value& rhs) {
737
0
  switch (lhs.type()) {
738
0
    case CelValue::Type::kBool:
739
0
      switch (rhs.kind()) {
740
0
        case ValueKind::kBool:
741
0
          return BoolValue(lhs.BoolOrDie()) == rhs.GetBool();
742
0
        case ValueKind::kInt:
743
0
          return false;
744
0
        case ValueKind::kUint:
745
0
          return false;
746
0
        case ValueKind::kString:
747
0
          return false;
748
0
        default:
749
0
          ABSL_UNREACHABLE();
750
0
      }
751
0
    case CelValue::Type::kInt:
752
0
      switch (rhs.kind()) {
753
0
        case ValueKind::kBool:
754
0
          return false;
755
0
        case ValueKind::kInt:
756
0
          return IntValue(lhs.Int64OrDie()) == rhs.GetInt();
757
0
        case ValueKind::kUint:
758
0
          return false;
759
0
        case ValueKind::kString:
760
0
          return false;
761
0
        default:
762
0
          ABSL_UNREACHABLE();
763
0
      }
764
0
    case CelValue::Type::kUint:
765
0
      switch (rhs.kind()) {
766
0
        case ValueKind::kBool:
767
0
          return false;
768
0
        case ValueKind::kInt:
769
0
          return false;
770
0
        case ValueKind::kUint:
771
0
          return UintValue(lhs.Uint64OrDie()) == rhs.GetUint();
772
0
        case ValueKind::kString:
773
0
          return false;
774
0
        default:
775
0
          ABSL_UNREACHABLE();
776
0
      }
777
0
    case CelValue::Type::kString:
778
0
      switch (rhs.kind()) {
779
0
        case ValueKind::kBool:
780
0
          return false;
781
0
        case ValueKind::kInt:
782
0
          return false;
783
0
        case ValueKind::kUint:
784
0
          return false;
785
0
        case ValueKind::kString:
786
0
          return rhs.GetString().Equals(lhs.StringOrDie().value());
787
0
        default:
788
0
          ABSL_UNREACHABLE();
789
0
      }
790
0
    default:
791
0
      ABSL_UNREACHABLE();
792
0
  }
793
0
}
794
795
0
absl::StatusOr<std::string> ValueToJsonString(const Value& value) {
796
0
  switch (value.kind()) {
797
0
    case ValueKind::kString:
798
0
      return value.GetString().NativeString();
799
0
    default:
800
0
      return TypeConversionError(value.GetRuntimeType(), StringType())
801
0
          .ToStatus();
802
0
  }
803
0
}
804
805
template <typename Map>
806
absl::Status MapValueToJsonObject(
807
    const Map& map, const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
808
    google::protobuf::MessageFactory* absl_nonnull message_factory,
809
0
    google::protobuf::Message* absl_nonnull json) {
810
0
  ABSL_DCHECK(descriptor_pool != nullptr);
811
0
  ABSL_DCHECK(message_factory != nullptr);
812
0
  ABSL_DCHECK(json != nullptr);
813
0
  ABSL_DCHECK_EQ(json->GetDescriptor()->well_known_type(),
814
0
                 google::protobuf::Descriptor::WELLKNOWNTYPE_STRUCT);
815
816
0
  StructReflection reflection;
817
0
  CEL_RETURN_IF_ERROR(reflection.Initialize(json->GetDescriptor()));
818
819
0
  json->Clear();
820
821
0
  if (map.empty()) {
822
0
    return absl::OkStatus();
823
0
  }
824
825
0
  for (const auto& entry : map) {
826
0
    CEL_ASSIGN_OR_RETURN(auto key, ValueToJsonString(entry.first));
827
0
    CEL_RETURN_IF_ERROR(entry.second.ConvertToJson(
828
0
        descriptor_pool, message_factory, reflection.InsertField(json, key)));
829
0
  }
830
0
  return absl::OkStatus();
831
0
}
832
833
template <typename Map>
834
absl::Status MapValueToJson(
835
    const Map& map, const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
836
    google::protobuf::MessageFactory* absl_nonnull message_factory,
837
    google::protobuf::Message* absl_nonnull json) {
838
  ABSL_DCHECK(descriptor_pool != nullptr);
839
  ABSL_DCHECK(message_factory != nullptr);
840
  ABSL_DCHECK(json != nullptr);
841
  ABSL_DCHECK_EQ(json->GetDescriptor()->well_known_type(),
842
                 google::protobuf::Descriptor::WELLKNOWNTYPE_VALUE);
843
844
  ValueReflection reflection;
845
  CEL_RETURN_IF_ERROR(reflection.Initialize(json->GetDescriptor()));
846
  return MapValueToJsonObject(map, descriptor_pool, message_factory,
847
                              reflection.MutableStructValue(json));
848
}
849
850
struct ValueHasher {
851
  using is_transparent = void;
852
853
3.14k
  size_t operator()(const Value& value) const { return (ValueHash)(value); }
854
855
0
  size_t operator()(const CelValue& value) const { return (ValueHash)(value); }
856
};
857
858
struct ValueEqualer {
859
  using is_transparent = void;
860
861
0
  bool operator()(const Value& lhs, const CelValue& rhs) const {
862
0
    return (*this)(rhs, lhs);
863
0
  }
864
865
0
  bool operator()(const CelValue& lhs, const Value& rhs) const {
866
0
    return (CelValueEquals)(lhs, rhs);
867
0
  }
868
869
463
  bool operator()(const Value& lhs, const Value& rhs) const {
870
463
    return (ValueEquals)(lhs, rhs);
871
463
  }
872
};
873
874
using ValueFlatHashMapAllocator = ArenaAllocator<std::pair<const Value, Value>>;
875
876
using ValueFlatHashMap =
877
    absl::flat_hash_map<Value, Value, ValueHasher, ValueEqualer,
878
                        ValueFlatHashMapAllocator>;
879
880
class CompatMapValueImplIterator final : public ValueIterator {
881
 public:
882
  explicit CompatMapValueImplIterator(const ValueFlatHashMap* absl_nonnull map)
883
44
      : begin_(map->begin()), end_(map->end()) {}
884
885
49
  bool HasNext() override { return begin_ != end_; }
886
887
  absl::Status Next(const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
888
                    google::protobuf::MessageFactory* absl_nonnull message_factory,
889
                    google::protobuf::Arena* absl_nonnull arena,
890
44
                    Value* absl_nonnull result) override {
891
44
    if (ABSL_PREDICT_FALSE(begin_ == end_)) {
892
0
      return absl::FailedPreconditionError(
893
0
          "ValueManager::Next called after ValueManager::HasNext returned "
894
0
          "false");
895
0
    }
896
44
    *result = begin_->first;
897
44
    ++begin_;
898
44
    return absl::OkStatus();
899
44
  }
900
901
  absl::StatusOr<bool> Next1(
902
      const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
903
      google::protobuf::MessageFactory* absl_nonnull message_factory,
904
      google::protobuf::Arena* absl_nonnull arena,
905
0
      Value* absl_nonnull key_or_value) override {
906
0
    ABSL_DCHECK(descriptor_pool != nullptr);
907
0
    ABSL_DCHECK(message_factory != nullptr);
908
0
    ABSL_DCHECK(arena != nullptr);
909
0
    ABSL_DCHECK(key_or_value != nullptr);
910
911
0
    if (begin_ == end_) {
912
0
      return false;
913
0
    }
914
0
    *key_or_value = begin_->first;
915
0
    ++begin_;
916
0
    return true;
917
0
  }
918
919
  absl::StatusOr<bool> Next2(
920
      const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
921
      google::protobuf::MessageFactory* absl_nonnull message_factory,
922
      google::protobuf::Arena* absl_nonnull arena, Value* absl_nonnull key,
923
0
      Value* absl_nullable value) override {
924
0
    ABSL_DCHECK(descriptor_pool != nullptr);
925
0
    ABSL_DCHECK(message_factory != nullptr);
926
0
    ABSL_DCHECK(arena != nullptr);
927
0
    ABSL_DCHECK(key != nullptr);
928
929
0
    if (begin_ == end_) {
930
0
      return false;
931
0
    }
932
0
    *key = begin_->first;
933
0
    if (value != nullptr) {
934
0
      *value = begin_->second;
935
0
    }
936
0
    ++begin_;
937
0
    return true;
938
0
  }
939
940
 private:
941
  typename ValueFlatHashMap::const_iterator begin_;
942
  const typename ValueFlatHashMap::const_iterator end_;
943
};
944
945
class MapValueBuilderImpl final : public MapValueBuilder {
946
 public:
947
  explicit MapValueBuilderImpl(google::protobuf::Arena* absl_nonnull arena)
948
8.29k
      : arena_(arena) {
949
8.29k
    map_.Construct(arena_);
950
8.29k
  }
951
952
8.29k
  ~MapValueBuilderImpl() override {
953
8.29k
    if (!entries_trivially_destructible_) {
954
33
      map_.Destruct();
955
33
    }
956
8.29k
  }
957
958
2.86k
  absl::Status Put(Value key, Value value) override {
959
2.86k
    CEL_RETURN_IF_ERROR(CheckMapKey(key));
960
2.86k
    CEL_RETURN_IF_ERROR(CheckMapValue(value));
961
2.86k
    if (auto it = map_->find(key); ABSL_PREDICT_FALSE(it != map_->end())) {
962
30
      return DuplicateKeyError().ToStatus();
963
30
    }
964
2.83k
    UnsafePut(std::move(key), std::move(value));
965
2.83k
    return absl::OkStatus();
966
2.86k
  }
967
968
2.83k
  void UnsafePut(Value key, Value value) override {
969
2.83k
    auto insertion = map_->insert({std::move(key), std::move(value)});
970
2.83k
    ABSL_DCHECK(insertion.second);
971
2.83k
    if (entries_trivially_destructible_) {
972
2.57k
      entries_trivially_destructible_ =
973
2.57k
          ArenaTraits<>::trivially_destructible(insertion.first->first) &&
974
2.35k
          ArenaTraits<>::trivially_destructible(insertion.first->second);
975
2.57k
    }
976
2.83k
  }
977
978
0
  size_t Size() const override { return map_->size(); }
979
980
8.29k
  void Reserve(size_t capacity) override { map_->reserve(capacity); }
981
982
  MapValue Build() && override;
983
984
  CustomMapValue BuildCustom() &&;
985
986
  const CompatMapValue* absl_nonnull BuildCompat() &&;
987
988
 private:
989
  google::protobuf::Arena* absl_nonnull const arena_;
990
  internal::Manual<ValueFlatHashMap> map_;
991
  bool entries_trivially_destructible_ = true;
992
};
993
994
class CompatMapValueImpl final : public CompatMapValue {
995
 public:
996
1.97k
  explicit CompatMapValueImpl(ValueFlatHashMap&& map) : map_(std::move(map)) {}
997
998
0
  std::string DebugString() const override {
999
0
    return absl::StrCat("{", absl::StrJoin(map_, ", ", ValueFormatter{}), "}");
1000
0
  }
1001
1002
  absl::Status ConvertToJsonObject(
1003
      const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
1004
      google::protobuf::MessageFactory* absl_nonnull message_factory,
1005
0
      google::protobuf::Message* absl_nonnull json) const override {
1006
0
    return MapValueToJsonObject(map_, descriptor_pool, message_factory, json);
1007
0
  }
1008
1009
0
  CustomMapValue Clone(google::protobuf::Arena* absl_nonnull arena) const override {
1010
0
    ABSL_DCHECK(arena != nullptr);
1011
1012
0
    MapValueBuilderImpl builder(arena);
1013
0
    builder.Reserve(map_.size());
1014
0
    for (const auto& entry : map_) {
1015
0
      builder.UnsafePut(entry.first.Clone(arena), entry.second.Clone(arena));
1016
0
    }
1017
0
    return std::move(builder).BuildCustom();
1018
0
  }
1019
1020
93
  size_t Size() const override { return map_.size(); }
1021
1022
  absl::Status ListKeys(
1023
      const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
1024
      google::protobuf::MessageFactory* absl_nonnull message_factory,
1025
      google::protobuf::Arena* absl_nonnull arena,
1026
0
      ListValue* absl_nonnull result) const override {
1027
0
    *result = CustomListValue(ProjectKeys(), map_.get_allocator().arena());
1028
0
    return absl::OkStatus();
1029
0
  }
1030
1031
  absl::Status ForEach(
1032
      ForEachCallback callback,
1033
      const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
1034
      google::protobuf::MessageFactory* absl_nonnull message_factory,
1035
0
      google::protobuf::Arena* absl_nonnull arena) const override {
1036
0
    for (const auto& entry : map_) {
1037
0
      CEL_ASSIGN_OR_RETURN(auto ok, callback(entry.first, entry.second));
1038
0
      if (!ok) {
1039
0
        break;
1040
0
      }
1041
0
    }
1042
0
    return absl::OkStatus();
1043
0
  }
1044
1045
44
  absl::StatusOr<absl_nonnull ValueIteratorPtr> NewIterator() const override {
1046
44
    return std::make_unique<CompatMapValueImplIterator>(&map_);
1047
44
  }
1048
1049
0
  absl::optional<CelValue> operator[](CelValue key) const override {
1050
0
    return Get(map_.get_allocator().arena(), key);
1051
0
  }
1052
1053
  using CompatMapValue::Get;
1054
  absl::optional<CelValue> Get(google::protobuf::Arena* arena,
1055
0
                               CelValue key) const override {
1056
0
    if (auto status = CelValue::CheckMapKeyType(key); !status.ok()) {
1057
0
      status.IgnoreError();
1058
0
      return absl::nullopt;
1059
0
    }
1060
0
    if (auto it = map_.find(key); it != map_.end()) {
1061
0
      return common_internal::UnsafeLegacyValue(
1062
0
          it->second, /*stable=*/true,
1063
0
          arena != nullptr ? arena : map_.get_allocator().arena());
1064
0
    }
1065
0
    return absl::nullopt;
1066
0
  }
1067
1068
0
  absl::StatusOr<bool> Has(const CelValue& key) const override {
1069
    // This check safeguards against issues with invalid key types such as NaN.
1070
0
    CEL_RETURN_IF_ERROR(CelValue::CheckMapKeyType(key));
1071
0
    return map_.find(key) != map_.end();
1072
0
  }
1073
1074
0
  int size() const override { return static_cast<int>(Size()); }
1075
1076
0
  absl::StatusOr<const CelList*> ListKeys() const override {
1077
0
    return ProjectKeys();
1078
0
  }
1079
1080
0
  absl::StatusOr<const CelList*> ListKeys(google::protobuf::Arena* arena) const override {
1081
0
    return ProjectKeys();
1082
0
  }
1083
1084
 protected:
1085
  absl::StatusOr<bool> Find(
1086
      const Value& key,
1087
      const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
1088
      google::protobuf::MessageFactory* absl_nonnull message_factory,
1089
      google::protobuf::Arena* absl_nonnull arena,
1090
681
      Value* absl_nonnull result) const override {
1091
681
    CEL_RETURN_IF_ERROR(CheckMapKey(key));
1092
681
    if (auto it = map_.find(key); it != map_.end()) {
1093
30
      *result = it->second;
1094
30
      return true;
1095
30
    }
1096
651
    return false;
1097
681
  }
1098
1099
  absl::StatusOr<bool> Has(
1100
      const Value& key,
1101
      const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
1102
      google::protobuf::MessageFactory* absl_nonnull message_factory,
1103
8
      google::protobuf::Arena* absl_nonnull arena) const override {
1104
8
    CEL_RETURN_IF_ERROR(CheckMapKey(key));
1105
8
    return map_.find(key) != map_.end();
1106
8
  }
1107
1108
 private:
1109
0
  const CompatListValue* absl_nonnull ProjectKeys() const {
1110
0
    absl::call_once(keys_once_, [this]() {
1111
0
      ListValueBuilderImpl builder(map_.get_allocator().arena());
1112
0
      builder.Reserve(map_.size());
1113
1114
0
      for (const auto& entry : map_) {
1115
0
        builder.UnsafeAdd(entry.first);
1116
0
      }
1117
1118
0
      std::move(builder).BuildCompatAt(&keys_[0]);
1119
0
    });
1120
0
    return std::launder(
1121
0
        reinterpret_cast<const CompatListValueImpl*>(&keys_[0]));
1122
0
  }
1123
1124
  const ValueFlatHashMap map_;
1125
  mutable absl::once_flag keys_once_;
1126
  alignas(CompatListValueImpl) mutable char keys_[sizeof(CompatListValueImpl)];
1127
};
1128
1129
8.13k
MapValue MapValueBuilderImpl::Build() && {
1130
8.13k
  if (map_->empty()) {
1131
6.15k
    return MapValue();
1132
6.15k
  }
1133
1.97k
  return std::move(*this).BuildCustom();
1134
8.13k
}
1135
1136
1.97k
CustomMapValue MapValueBuilderImpl::BuildCustom() && {
1137
1.97k
  if (map_->empty()) {
1138
0
    return CustomMapValue(EmptyCompatMapValue(), arena_);
1139
0
  }
1140
1.97k
  return CustomMapValue(std::move(*this).BuildCompat(), arena_);
1141
1.97k
}
1142
1143
1.97k
const CompatMapValue* absl_nonnull MapValueBuilderImpl::BuildCompat() && {
1144
1.97k
  if (map_->empty()) {
1145
0
    return EmptyCompatMapValue();
1146
0
  }
1147
1.97k
  CompatMapValueImpl* absl_nonnull impl = ::new (arena_->AllocateAligned(
1148
1.97k
      sizeof(CompatMapValueImpl), alignof(CompatMapValueImpl)))
1149
1.97k
      CompatMapValueImpl(std::move(*map_));
1150
1.97k
  if (!entries_trivially_destructible_) {
1151
283
    arena_->OwnDestructor(impl);
1152
283
    entries_trivially_destructible_ = true;
1153
283
  }
1154
1.97k
  return impl;
1155
1.97k
}
1156
1157
class TrivialMutableMapValueImpl final : public MutableCompatMapValue {
1158
 public:
1159
  explicit TrivialMutableMapValueImpl(google::protobuf::Arena* absl_nonnull arena)
1160
0
      : map_(arena) {}
1161
1162
0
  std::string DebugString() const override {
1163
0
    return absl::StrCat("{", absl::StrJoin(map_, ", ", ValueFormatter{}), "}");
1164
0
  }
1165
1166
  absl::Status ConvertToJsonObject(
1167
      const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
1168
      google::protobuf::MessageFactory* absl_nonnull message_factory,
1169
0
      google::protobuf::Message* absl_nonnull json) const override {
1170
0
    return MapValueToJsonObject(map_, descriptor_pool, message_factory, json);
1171
0
  }
1172
1173
0
  CustomMapValue Clone(google::protobuf::Arena* absl_nonnull arena) const override {
1174
0
    ABSL_DCHECK(arena != nullptr);
1175
1176
0
    MapValueBuilderImpl builder(arena);
1177
0
    builder.Reserve(map_.size());
1178
0
    for (const auto& entry : map_) {
1179
0
      builder.UnsafePut(entry.first.Clone(arena), entry.second.Clone(arena));
1180
0
    }
1181
0
    return std::move(builder).BuildCustom();
1182
0
  }
1183
1184
0
  size_t Size() const override { return map_.size(); }
1185
1186
  absl::Status ListKeys(
1187
      const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
1188
      google::protobuf::MessageFactory* absl_nonnull message_factory,
1189
      google::protobuf::Arena* absl_nonnull arena,
1190
0
      ListValue* absl_nonnull result) const override {
1191
0
    *result = CustomListValue(ProjectKeys(), map_.get_allocator().arena());
1192
0
    return absl::OkStatus();
1193
0
  }
1194
1195
  absl::Status ForEach(
1196
      ForEachCallback callback,
1197
      const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
1198
      google::protobuf::MessageFactory* absl_nonnull message_factory,
1199
0
      google::protobuf::Arena* absl_nonnull arena) const override {
1200
0
    for (const auto& entry : map_) {
1201
0
      CEL_ASSIGN_OR_RETURN(auto ok, callback(entry.first, entry.second));
1202
0
      if (!ok) {
1203
0
        break;
1204
0
      }
1205
0
    }
1206
0
    return absl::OkStatus();
1207
0
  }
1208
1209
0
  absl::StatusOr<absl_nonnull ValueIteratorPtr> NewIterator() const override {
1210
0
    return std::make_unique<CompatMapValueImplIterator>(&map_);
1211
0
  }
1212
1213
0
  absl::optional<CelValue> operator[](CelValue key) const override {
1214
0
    return Get(map_.get_allocator().arena(), key);
1215
0
  }
1216
1217
  using MutableCompatMapValue::Get;
1218
  absl::optional<CelValue> Get(google::protobuf::Arena* arena,
1219
0
                               CelValue key) const override {
1220
0
    if (auto status = CelValue::CheckMapKeyType(key); !status.ok()) {
1221
0
      status.IgnoreError();
1222
0
      return absl::nullopt;
1223
0
    }
1224
0
    if (auto it = map_.find(key); it != map_.end()) {
1225
0
      return common_internal::UnsafeLegacyValue(
1226
0
          it->second, /*stable=*/false,
1227
0
          arena != nullptr ? arena : map_.get_allocator().arena());
1228
0
    }
1229
0
    return absl::nullopt;
1230
0
  }
1231
1232
0
  absl::StatusOr<bool> Has(const CelValue& key) const override {
1233
    // This check safeguards against issues with invalid key types such as NaN.
1234
0
    CEL_RETURN_IF_ERROR(CelValue::CheckMapKeyType(key));
1235
0
    return map_.find(key) != map_.end();
1236
0
  }
1237
1238
0
  int size() const override { return static_cast<int>(Size()); }
1239
1240
0
  absl::StatusOr<const CelList*> ListKeys() const override {
1241
0
    return ProjectKeys();
1242
0
  }
1243
1244
0
  absl::StatusOr<const CelList*> ListKeys(google::protobuf::Arena* arena) const override {
1245
0
    return ProjectKeys();
1246
0
  }
1247
1248
0
  absl::Status Put(Value key, Value value) const override {
1249
0
    CEL_RETURN_IF_ERROR(CheckMapKey(key));
1250
0
    CEL_RETURN_IF_ERROR(CheckMapValue(value));
1251
0
    if (auto it = map_.find(key); ABSL_PREDICT_FALSE(it != map_.end())) {
1252
0
      return DuplicateKeyError().ToStatus();
1253
0
    }
1254
0
    auto insertion = map_.insert({std::move(key), std::move(value)});
1255
0
    ABSL_DCHECK(insertion.second);
1256
0
    if (entries_trivially_destructible_) {
1257
0
      entries_trivially_destructible_ =
1258
0
          ArenaTraits<>::trivially_destructible(insertion.first->first) &&
1259
0
          ArenaTraits<>::trivially_destructible(insertion.first->second);
1260
0
      if (!entries_trivially_destructible_) {
1261
0
        map_.get_allocator().arena()->OwnDestructor(
1262
0
            const_cast<TrivialMutableMapValueImpl*>(this));
1263
0
      }
1264
0
    }
1265
0
    return absl::OkStatus();
1266
0
  }
1267
1268
0
  void Reserve(size_t capacity) const override { map_.reserve(capacity); }
1269
1270
 protected:
1271
  absl::StatusOr<bool> Find(
1272
      const Value& key,
1273
      const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
1274
      google::protobuf::MessageFactory* absl_nonnull message_factory,
1275
      google::protobuf::Arena* absl_nonnull arena,
1276
0
      Value* absl_nonnull result) const override {
1277
0
    CEL_RETURN_IF_ERROR(CheckMapKey(key));
1278
0
    if (auto it = map_.find(key); it != map_.end()) {
1279
0
      *result = it->second;
1280
0
      return true;
1281
0
    }
1282
0
    return false;
1283
0
  }
1284
1285
  absl::StatusOr<bool> Has(
1286
      const Value& key,
1287
      const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
1288
      google::protobuf::MessageFactory* absl_nonnull message_factory,
1289
0
      google::protobuf::Arena* absl_nonnull arena) const override {
1290
0
    CEL_RETURN_IF_ERROR(CheckMapKey(key));
1291
0
    return map_.find(key) != map_.end();
1292
0
  }
1293
1294
 private:
1295
0
  const CompatListValue* absl_nonnull ProjectKeys() const {
1296
0
    absl::call_once(keys_once_, [this]() {
1297
0
      ListValueBuilderImpl builder(map_.get_allocator().arena());
1298
0
      builder.Reserve(map_.size());
1299
1300
0
      for (const auto& entry : map_) {
1301
0
        builder.UnsafeAdd(entry.first);
1302
0
      }
1303
1304
0
      std::move(builder).BuildCompatAt(&keys_[0]);
1305
0
    });
1306
0
    return std::launder(
1307
0
        reinterpret_cast<const CompatListValueImpl*>(&keys_[0]));
1308
0
  }
1309
1310
  mutable ValueFlatHashMap map_;
1311
  mutable bool entries_trivially_destructible_ = true;
1312
  mutable absl::once_flag keys_once_;
1313
  alignas(CompatListValueImpl) mutable char keys_[sizeof(CompatListValueImpl)];
1314
};
1315
1316
}  // namespace
1317
1318
absl::StatusOr<const CompatMapValue* absl_nonnull> MakeCompatMapValue(
1319
    const CustomMapValue& value,
1320
    const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
1321
    google::protobuf::MessageFactory* absl_nonnull message_factory,
1322
0
    google::protobuf::Arena* absl_nonnull arena) {
1323
0
  MapValueBuilderImpl builder(arena);
1324
0
  builder.Reserve(value.Size());
1325
1326
0
  CEL_RETURN_IF_ERROR(value.ForEach(
1327
0
      [&](const Value& key, const Value& value) -> absl::StatusOr<bool> {
1328
0
        CEL_RETURN_IF_ERROR(builder.Put(key, value));
1329
0
        return true;
1330
0
      },
1331
0
      descriptor_pool, message_factory, arena));
1332
1333
0
  return std::move(builder).BuildCompat();
1334
0
}
1335
1336
MutableMapValue* absl_nonnull NewMutableMapValue(
1337
0
    google::protobuf::Arena* absl_nonnull arena) {
1338
0
  return ::new (arena->AllocateAligned(sizeof(TrivialMutableMapValueImpl),
1339
0
                                       alignof(TrivialMutableMapValueImpl)))
1340
0
      TrivialMutableMapValueImpl(arena);
1341
0
}
1342
1343
0
bool IsMutableMapValue(const Value& value) {
1344
0
  if (auto custom_map_value = value.AsCustomMap(); custom_map_value) {
1345
0
    NativeTypeId native_type_id = custom_map_value->GetTypeId();
1346
0
    if (native_type_id == NativeTypeId::For<MutableMapValue>() ||
1347
0
        native_type_id == NativeTypeId::For<MutableCompatMapValue>()) {
1348
0
      return true;
1349
0
    }
1350
0
  }
1351
0
  return false;
1352
0
}
1353
1354
0
bool IsMutableMapValue(const MapValue& value) {
1355
0
  if (auto custom_map_value = value.AsCustom(); custom_map_value) {
1356
0
    NativeTypeId native_type_id = custom_map_value->GetTypeId();
1357
0
    if (native_type_id == NativeTypeId::For<MutableMapValue>() ||
1358
0
        native_type_id == NativeTypeId::For<MutableCompatMapValue>()) {
1359
0
      return true;
1360
0
    }
1361
0
  }
1362
0
  return false;
1363
0
}
1364
1365
0
const MutableMapValue* absl_nullable AsMutableMapValue(const Value& value) {
1366
0
  if (auto custom_map_value = value.AsCustomMap(); custom_map_value) {
1367
0
    NativeTypeId native_type_id = custom_map_value->GetTypeId();
1368
0
    if (native_type_id == NativeTypeId::For<MutableMapValue>()) {
1369
0
      return cel::internal::down_cast<const MutableMapValue*>(
1370
0
          custom_map_value->interface());
1371
0
    }
1372
0
    if (native_type_id == NativeTypeId::For<MutableCompatMapValue>()) {
1373
0
      return cel::internal::down_cast<const MutableCompatMapValue*>(
1374
0
          custom_map_value->interface());
1375
0
    }
1376
0
  }
1377
0
  return nullptr;
1378
0
}
1379
1380
0
const MutableMapValue* absl_nullable AsMutableMapValue(const MapValue& value) {
1381
0
  if (auto custom_map_value = value.AsCustom(); custom_map_value) {
1382
0
    NativeTypeId native_type_id = custom_map_value->GetTypeId();
1383
0
    if (native_type_id == NativeTypeId::For<MutableMapValue>()) {
1384
0
      return cel::internal::down_cast<const MutableMapValue*>(
1385
0
          custom_map_value->interface());
1386
0
    }
1387
0
    if (native_type_id == NativeTypeId::For<MutableCompatMapValue>()) {
1388
0
      return cel::internal::down_cast<const MutableCompatMapValue*>(
1389
0
          custom_map_value->interface());
1390
0
    }
1391
0
  }
1392
0
  return nullptr;
1393
0
}
1394
1395
0
const MutableMapValue& GetMutableMapValue(const Value& value) {
1396
0
  ABSL_DCHECK(IsMutableMapValue(value)) << value;
1397
0
  const auto& custom_map_value = value.GetCustomMap();
1398
0
  NativeTypeId native_type_id = custom_map_value.GetTypeId();
1399
0
  if (native_type_id == NativeTypeId::For<MutableMapValue>()) {
1400
0
    return cel::internal::down_cast<const MutableMapValue&>(
1401
0
        *custom_map_value.interface());
1402
0
  }
1403
0
  if (native_type_id == NativeTypeId::For<MutableCompatMapValue>()) {
1404
0
    return cel::internal::down_cast<const MutableCompatMapValue&>(
1405
0
        *custom_map_value.interface());
1406
0
  }
1407
0
  ABSL_UNREACHABLE();
1408
0
}
1409
1410
0
const MutableMapValue& GetMutableMapValue(const MapValue& value) {
1411
0
  ABSL_DCHECK(IsMutableMapValue(value)) << value;
1412
0
  const auto& custom_map_value = value.GetCustom();
1413
0
  NativeTypeId native_type_id = custom_map_value.GetTypeId();
1414
0
  if (native_type_id == NativeTypeId::For<MutableMapValue>()) {
1415
0
    return cel::internal::down_cast<const MutableMapValue&>(
1416
0
        *custom_map_value.interface());
1417
0
  }
1418
0
  if (native_type_id == NativeTypeId::For<MutableCompatMapValue>()) {
1419
0
    return cel::internal::down_cast<const MutableCompatMapValue&>(
1420
0
        *custom_map_value.interface());
1421
0
  }
1422
0
  ABSL_UNREACHABLE();
1423
0
}
1424
1425
absl_nonnull cel::MapValueBuilderPtr NewMapValueBuilder(
1426
8.29k
    google::protobuf::Arena* absl_nonnull arena) {
1427
8.29k
  return std::make_unique<MapValueBuilderImpl>(arena);
1428
8.29k
}
1429
1430
}  // namespace common_internal
1431
1432
}  // namespace cel