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/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
16.4M
absl::Status CheckListElement(const Value& value) {
70
16.4M
  if (auto error_value = value.AsError(); ABSL_PREDICT_FALSE(error_value)) {
71
0
    return error_value->ToStatus();
72
0
  }
73
16.4M
  if (auto unknown_value = value.AsUnknown();
74
16.4M
      ABSL_PREDICT_FALSE(unknown_value)) {
75
0
    return absl::InvalidArgumentError("cannot add unknown value to list");
76
0
  }
77
16.4M
  return absl::OkStatus();
78
16.4M
}
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
368k
    google::protobuf::Message* absl_nonnull json) {
86
368k
  ABSL_DCHECK(descriptor_pool != nullptr);
87
368k
  ABSL_DCHECK(message_factory != nullptr);
88
368k
  ABSL_DCHECK(json != nullptr);
89
368k
  ABSL_DCHECK_EQ(json->GetDescriptor()->well_known_type(),
90
368k
                 google::protobuf::Descriptor::WELLKNOWNTYPE_LISTVALUE);
91
92
368k
  ListValueReflection reflection;
93
368k
  CEL_RETURN_IF_ERROR(reflection.Initialize(json->GetDescriptor()));
94
95
368k
  json->Clear();
96
97
368k
  if (vector.empty()) {
98
0
    return absl::OkStatus();
99
0
  }
100
101
8.92M
  for (const auto& element : vector) {
102
8.92M
    CEL_RETURN_IF_ERROR(element->ConvertToJson(descriptor_pool, message_factory,
103
8.92M
                                               reflection.AddValues(json)));
104
8.92M
  }
105
368k
  return absl::OkStatus();
106
368k
}
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
247k
      : elements_(elements) {}
130
131
60.1k
  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
60.1k
                    Value* absl_nonnull result) override {
137
60.1k
    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
60.1k
    *result = elements_[index_++];
143
60.1k
    return absl::OkStatus();
144
60.1k
  }
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
1.53M
      Value* absl_nonnull key_or_value) override {
151
1.53M
    ABSL_DCHECK(descriptor_pool != nullptr);
152
1.53M
    ABSL_DCHECK(message_factory != nullptr);
153
1.53M
    ABSL_DCHECK(arena != nullptr);
154
1.53M
    ABSL_DCHECK(key_or_value != nullptr);
155
156
1.53M
    if (index_ >= elements_.size()) {
157
187k
      return false;
158
187k
    }
159
1.34M
    *key_or_value = elements_[index_];
160
1.34M
    ++index_;
161
1.34M
    return true;
162
1.53M
  }
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
2.77M
      : arena_(arena) {
206
2.77M
    elements_.Construct(arena);
207
2.77M
  }
208
209
2.77M
  ~ListValueBuilderImpl() override {
210
2.77M
    if (!elements_trivially_destructible_) {
211
0
      elements_.Destruct();
212
0
    }
213
2.77M
  }
214
215
16.4M
  absl::Status Add(Value value) override {
216
16.4M
    CEL_RETURN_IF_ERROR(CheckListElement(value));
217
16.4M
    UnsafeAdd(std::move(value));
218
16.4M
    return absl::OkStatus();
219
16.4M
  }
220
221
16.4M
  void UnsafeAdd(Value value) override {
222
16.4M
    ABSL_DCHECK_OK(CheckListElement(value));
223
16.4M
    elements_->emplace_back(std::move(value));
224
16.4M
    if (elements_trivially_destructible_) {
225
16.1M
      elements_trivially_destructible_ =
226
16.1M
          ArenaTraits<>::trivially_destructible(elements_->back());
227
16.1M
    }
228
16.4M
  }
229
230
0
  size_t Size() const override { return elements_->size(); }
231
232
2.77M
  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
1.64M
      : 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
368k
      google::protobuf::Message* absl_nonnull json) const override {
263
368k
    return ListValueToJsonArray(elements_, descriptor_pool, message_factory,
264
368k
                                json);
265
368k
  }
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
1.15M
  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
363k
      google::protobuf::Arena* absl_nonnull arena) const override {
285
363k
    const size_t size = elements_.size();
286
714k
    for (size_t i = 0; i < size; ++i) {
287
405k
      CEL_ASSIGN_OR_RETURN(auto ok, callback(i, elements_[i]));
288
405k
      if (!ok) {
289
55.0k
        break;
290
55.0k
      }
291
405k
    }
292
363k
    return absl::OkStatus();
293
363k
  }
294
295
247k
  absl::StatusOr<absl_nonnull ValueIteratorPtr> NewIterator() const override {
296
247k
    return std::make_unique<CompatListValueImplIterator>(
297
247k
        absl::MakeConstSpan(elements_));
298
247k
  }
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
4.90M
                   Value* absl_nonnull result) const override {
328
4.90M
    if (index >= elements_.size()) {
329
0
      *result = IndexOutOfBoundsError(index);
330
4.90M
    } else {
331
4.90M
      *result = elements_[index];
332
4.90M
    }
333
4.90M
    return absl::OkStatus();
334
4.90M
  }
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
2.77M
ListValue ListValueBuilderImpl::Build() && {
354
2.77M
  if (elements_->empty()) {
355
1.12M
    return ListValue();
356
1.12M
  }
357
1.64M
  return std::move(*this).BuildCustom();
358
2.77M
}
359
360
1.64M
CustomListValue ListValueBuilderImpl::BuildCustom() && {
361
1.64M
  if (elements_->empty()) {
362
0
    return CustomListValue(EmptyCompatListValue(), arena_);
363
0
  }
364
1.64M
  return CustomListValue(std::move(*this).BuildCompat(), arena_);
365
1.64M
}
366
367
1.64M
const CompatListValue* absl_nonnull ListValueBuilderImpl::BuildCompat() && {
368
1.64M
  if (elements_->empty()) {
369
0
    return EmptyCompatListValue();
370
0
  }
371
1.64M
  return std::move(*this).BuildCompatAt(arena_->AllocateAligned(
372
1.64M
      sizeof(CompatListValueImpl), alignof(CompatListValueImpl)));
373
1.64M
}
374
375
const CompatListValue* absl_nonnull ListValueBuilderImpl::BuildCompatAt(
376
1.64M
    void* absl_nonnull address) && {
377
1.64M
  CompatListValueImpl* absl_nonnull impl =
378
1.64M
      ::new (address) CompatListValueImpl(std::move(*elements_));
379
1.64M
  if (!elements_trivially_destructible_) {
380
48.4k
    arena_->OwnDestructor(impl);
381
48.4k
    elements_trivially_destructible_ = true;
382
48.4k
  }
383
1.64M
  return impl;
384
1.64M
}
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
2.77M
    google::protobuf::Arena* absl_nonnull arena) {
618
2.77M
  return std::make_unique<ListValueBuilderImpl>(arena);
619
2.77M
}
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
347k
absl::Status CheckMapValue(const Value& value) {
635
347k
  if (auto error_value = value.AsError(); ABSL_PREDICT_FALSE(error_value)) {
636
0
    return error_value->ToStatus();
637
0
  }
638
347k
  if (auto unknown_value = value.AsUnknown();
639
347k
      ABSL_PREDICT_FALSE(unknown_value)) {
640
0
    return absl::InvalidArgumentError("cannot add unknown value to list");
641
0
  }
642
347k
  return absl::OkStatus();
643
347k
}
644
645
529k
size_t ValueHash(const Value& value) {
646
529k
  switch (value.kind()) {
647
4.59k
    case ValueKind::kBool:
648
4.59k
      return absl::HashOf(value.kind(), value.GetBool());
649
205k
    case ValueKind::kInt:
650
205k
      return absl::HashOf(ValueKind::kInt,
651
205k
                          absl::implicit_cast<int64_t>(value.GetInt()));
652
16.6k
    case ValueKind::kUint:
653
16.6k
      return absl::HashOf(ValueKind::kUint,
654
16.6k
                          absl::implicit_cast<uint64_t>(value.GetUint()));
655
302k
    case ValueKind::kString:
656
302k
      return absl::HashOf(value.kind(), value.GetString());
657
0
    default:
658
0
      ABSL_UNREACHABLE();
659
529k
  }
660
529k
}
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
76.3k
bool ValueEquals(const Value& lhs, const Value& rhs) {
678
76.3k
  switch (lhs.kind()) {
679
768
    case ValueKind::kBool:
680
768
      switch (rhs.kind()) {
681
394
        case ValueKind::kBool:
682
394
          return lhs.GetBool() == rhs.GetBool();
683
13
        case ValueKind::kInt:
684
13
          return false;
685
10
        case ValueKind::kUint:
686
10
          return false;
687
351
        case ValueKind::kString:
688
351
          return false;
689
0
        default:
690
0
          ABSL_UNREACHABLE();
691
768
      }
692
39.0k
    case ValueKind::kInt:
693
39.0k
      switch (rhs.kind()) {
694
84
        case ValueKind::kBool:
695
84
          return false;
696
30.8k
        case ValueKind::kInt:
697
30.8k
          return lhs.GetInt() == rhs.GetInt();
698
8.06k
        case ValueKind::kUint:
699
8.06k
          return false;
700
60
        case ValueKind::kString:
701
60
          return false;
702
0
        default:
703
0
          ABSL_UNREACHABLE();
704
39.0k
      }
705
4.86k
    case ValueKind::kUint:
706
4.86k
      switch (rhs.kind()) {
707
2
        case ValueKind::kBool:
708
2
          return false;
709
1.01k
        case ValueKind::kInt:
710
1.01k
          return false;
711
3.84k
        case ValueKind::kUint:
712
3.84k
          return lhs.GetUint() == rhs.GetUint();
713
0
        case ValueKind::kString:
714
0
          return false;
715
0
        default:
716
0
          ABSL_UNREACHABLE();
717
4.86k
      }
718
31.6k
    case ValueKind::kString:
719
31.6k
      switch (rhs.kind()) {
720
0
        case ValueKind::kBool:
721
0
          return false;
722
73
        case ValueKind::kInt:
723
73
          return false;
724
141
        case ValueKind::kUint:
725
141
          return false;
726
31.4k
        case ValueKind::kString:
727
31.4k
          return lhs.GetString() == rhs.GetString();
728
0
        default:
729
0
          ABSL_UNREACHABLE();
730
31.6k
      }
731
0
    default:
732
0
      ABSL_UNREACHABLE();
733
76.3k
  }
734
76.3k
}
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
54.1k
absl::StatusOr<std::string> ValueToJsonString(const Value& value) {
796
54.1k
  switch (value.kind()) {
797
54.1k
    case ValueKind::kString:
798
54.1k
      return value.GetString().NativeString();
799
13
    default:
800
13
      return TypeConversionError(value.GetRuntimeType(), StringType())
801
13
          .ToStatus();
802
54.1k
  }
803
54.1k
}
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
20.7k
    google::protobuf::Message* absl_nonnull json) {
810
20.7k
  ABSL_DCHECK(descriptor_pool != nullptr);
811
20.7k
  ABSL_DCHECK(message_factory != nullptr);
812
20.7k
  ABSL_DCHECK(json != nullptr);
813
20.7k
  ABSL_DCHECK_EQ(json->GetDescriptor()->well_known_type(),
814
20.7k
                 google::protobuf::Descriptor::WELLKNOWNTYPE_STRUCT);
815
816
20.7k
  StructReflection reflection;
817
20.7k
  CEL_RETURN_IF_ERROR(reflection.Initialize(json->GetDescriptor()));
818
819
20.7k
  json->Clear();
820
821
20.7k
  if (map.empty()) {
822
0
    return absl::OkStatus();
823
0
  }
824
825
54.1k
  for (const auto& entry : map) {
826
54.1k
    CEL_ASSIGN_OR_RETURN(auto key, ValueToJsonString(entry.first));
827
54.1k
    CEL_RETURN_IF_ERROR(entry.second.ConvertToJson(
828
54.1k
        descriptor_pool, message_factory, reflection.InsertField(json, key)));
829
54.1k
  }
830
20.7k
  return absl::OkStatus();
831
20.7k
}
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
529k
  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
76.3k
  bool operator()(const Value& lhs, const Value& rhs) const {
870
76.3k
    return (ValueEquals)(lhs, rhs);
871
76.3k
  }
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
14.2k
      : begin_(map->begin()), end_(map->end()) {}
884
885
13.9k
  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
13.6k
                    Value* absl_nonnull result) override {
891
13.6k
    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
13.6k
    *result = begin_->first;
897
13.6k
    ++begin_;
898
13.6k
    return absl::OkStatus();
899
13.6k
  }
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
6.41k
      Value* absl_nonnull key_or_value) override {
906
6.41k
    ABSL_DCHECK(descriptor_pool != nullptr);
907
6.41k
    ABSL_DCHECK(message_factory != nullptr);
908
6.41k
    ABSL_DCHECK(arena != nullptr);
909
6.41k
    ABSL_DCHECK(key_or_value != nullptr);
910
911
6.41k
    if (begin_ == end_) {
912
1.63k
      return false;
913
1.63k
    }
914
4.78k
    *key_or_value = begin_->first;
915
4.78k
    ++begin_;
916
4.78k
    return true;
917
6.41k
  }
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
823k
      : arena_(arena) {
949
823k
    map_.Construct(arena_);
950
823k
  }
951
952
823k
  ~MapValueBuilderImpl() override {
953
823k
    if (!entries_trivially_destructible_) {
954
727
      map_.Destruct();
955
727
    }
956
823k
  }
957
958
347k
  absl::Status Put(Value key, Value value) override {
959
347k
    CEL_RETURN_IF_ERROR(CheckMapKey(key));
960
347k
    CEL_RETURN_IF_ERROR(CheckMapValue(value));
961
347k
    if (auto it = map_->find(key); ABSL_PREDICT_FALSE(it != map_->end())) {
962
64
      return DuplicateKeyError().ToStatus();
963
64
    }
964
347k
    UnsafePut(std::move(key), std::move(value));
965
347k
    return absl::OkStatus();
966
347k
  }
967
968
347k
  void UnsafePut(Value key, Value value) override {
969
347k
    auto insertion = map_->insert({std::move(key), std::move(value)});
970
347k
    ABSL_DCHECK(insertion.second);
971
347k
    if (entries_trivially_destructible_) {
972
270k
      entries_trivially_destructible_ =
973
270k
          ArenaTraits<>::trivially_destructible(insertion.first->first) &&
974
183k
          ArenaTraits<>::trivially_destructible(insertion.first->second);
975
270k
    }
976
347k
  }
977
978
0
  size_t Size() const override { return map_->size(); }
979
980
823k
  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
189k
  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
20.7k
      google::protobuf::Message* absl_nonnull json) const override {
1006
20.7k
    return MapValueToJsonObject(map_, descriptor_pool, message_factory, json);
1007
20.7k
  }
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
28.6k
  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
14.2k
  absl::StatusOr<absl_nonnull ValueIteratorPtr> NewIterator() const override {
1046
14.2k
    return std::make_unique<CompatMapValueImplIterator>(&map_);
1047
14.2k
  }
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 std::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 std::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
106k
      Value* absl_nonnull result) const override {
1091
106k
    CEL_RETURN_IF_ERROR(CheckMapKey(key));
1092
106k
    if (auto it = map_.find(key); it != map_.end()) {
1093
32.4k
      *result = it->second;
1094
32.4k
      return true;
1095
32.4k
    }
1096
73.7k
    return false;
1097
106k
  }
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
1.85k
      google::protobuf::Arena* absl_nonnull arena) const override {
1104
1.85k
    CEL_RETURN_IF_ERROR(CheckMapKey(key));
1105
1.85k
    return map_.find(key) != map_.end();
1106
1.85k
  }
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
798k
MapValue MapValueBuilderImpl::Build() && {
1130
798k
  if (map_->empty()) {
1131
608k
    return MapValue();
1132
608k
  }
1133
189k
  return std::move(*this).BuildCustom();
1134
798k
}
1135
1136
189k
CustomMapValue MapValueBuilderImpl::BuildCustom() && {
1137
189k
  if (map_->empty()) {
1138
0
    return CustomMapValue(EmptyCompatMapValue(), arena_);
1139
0
  }
1140
189k
  return CustomMapValue(std::move(*this).BuildCompat(), arena_);
1141
189k
}
1142
1143
189k
const CompatMapValue* absl_nonnull MapValueBuilderImpl::BuildCompat() && {
1144
189k
  if (map_->empty()) {
1145
0
    return EmptyCompatMapValue();
1146
0
  }
1147
189k
  CompatMapValueImpl* absl_nonnull impl = ::new (arena_->AllocateAligned(
1148
189k
      sizeof(CompatMapValueImpl), alignof(CompatMapValueImpl)))
1149
189k
      CompatMapValueImpl(std::move(*map_));
1150
189k
  if (!entries_trivially_destructible_) {
1151
86.8k
    arena_->OwnDestructor(impl);
1152
86.8k
    entries_trivially_destructible_ = true;
1153
86.8k
  }
1154
189k
  return impl;
1155
189k
}
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 std::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 std::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
823k
    google::protobuf::Arena* absl_nonnull arena) {
1427
823k
  return std::make_unique<MapValueBuilderImpl>(arena);
1428
823k
}
1429
1430
}  // namespace common_internal
1431
1432
}  // namespace cel