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_variant.cc
Line
Count
Source
1
// Copyright 2025 Google LLC
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//     https://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
15
#include "common/values/value_variant.h"
16
17
#include <cstddef>
18
#include <cstring>
19
#include <memory>
20
#include <utility>
21
22
#include "absl/base/optimization.h"
23
#include "absl/log/absl_check.h"
24
#include "common/values/bytes_value.h"
25
#include "common/values/error_value.h"
26
#include "common/values/string_value.h"
27
#include "common/values/unknown_value.h"
28
#include "common/values/values.h"
29
30
namespace cel::common_internal {
31
32
100k
void ValueVariant::SlowCopyConstruct(const ValueVariant& other) noexcept {
33
100k
  ABSL_DCHECK((flags_ & ValueFlags::kNonTrivial) == ValueFlags::kNonTrivial);
34
35
100k
  switch (index_) {
36
1.32k
    case ValueIndex::kBytes:
37
1.32k
      ::new (static_cast<void*>(&raw_[0])) BytesValue(*other.At<BytesValue>());
38
1.32k
      break;
39
4.59k
    case ValueIndex::kString:
40
4.59k
      ::new (static_cast<void*>(&raw_[0]))
41
4.59k
          StringValue(*other.At<StringValue>());
42
4.59k
      break;
43
94.8k
    case ValueIndex::kError:
44
94.8k
      ::new (static_cast<void*>(&raw_[0])) ErrorValue(*other.At<ErrorValue>());
45
94.8k
      break;
46
0
    case ValueIndex::kUnknown:
47
0
      ::new (static_cast<void*>(&raw_[0]))
48
0
          UnknownValue(*other.At<UnknownValue>());
49
0
      break;
50
0
    default:
51
0
      ABSL_UNREACHABLE();
52
100k
  }
53
100k
}
54
55
331k
void ValueVariant::SlowMoveConstruct(ValueVariant& other) noexcept {
56
331k
  ABSL_DCHECK((flags_ & ValueFlags::kNonTrivial) == ValueFlags::kNonTrivial);
57
58
331k
  switch (index_) {
59
22.7k
    case ValueIndex::kBytes:
60
22.7k
      ::new (static_cast<void*>(&raw_[0]))
61
22.7k
          BytesValue(std::move(*other.At<BytesValue>()));
62
22.7k
      break;
63
19.4k
    case ValueIndex::kString:
64
19.4k
      ::new (static_cast<void*>(&raw_[0]))
65
19.4k
          StringValue(std::move(*other.At<StringValue>()));
66
19.4k
      break;
67
288k
    case ValueIndex::kError:
68
288k
      ::new (static_cast<void*>(&raw_[0]))
69
288k
          ErrorValue(std::move(*other.At<ErrorValue>()));
70
288k
      break;
71
0
    case ValueIndex::kUnknown:
72
0
      ::new (static_cast<void*>(&raw_[0]))
73
0
          UnknownValue(std::move(*other.At<UnknownValue>()));
74
0
      break;
75
0
    default:
76
0
      ABSL_UNREACHABLE();
77
331k
  }
78
331k
}
79
80
553k
void ValueVariant::SlowDestruct() noexcept {
81
553k
  ABSL_DCHECK((flags_ & ValueFlags::kNonTrivial) == ValueFlags::kNonTrivial);
82
83
553k
  switch (index_) {
84
28.5k
    case ValueIndex::kBytes:
85
28.5k
      At<BytesValue>()->~BytesValue();
86
28.5k
      break;
87
27.0k
    case ValueIndex::kString:
88
27.0k
      At<StringValue>()->~StringValue();
89
27.0k
      break;
90
497k
    case ValueIndex::kError:
91
497k
      At<ErrorValue>()->~ErrorValue();
92
497k
      break;
93
0
    case ValueIndex::kUnknown:
94
0
      At<UnknownValue>()->~UnknownValue();
95
0
      break;
96
0
    default:
97
0
      ABSL_UNREACHABLE();
98
553k
  }
99
553k
}
100
101
void ValueVariant::SlowCopyAssign(const ValueVariant& other, bool trivial,
102
13.7k
                                  bool other_trivial) noexcept {
103
13.7k
  ABSL_DCHECK(!trivial || !other_trivial);
104
105
13.7k
  if (trivial) {
106
13.7k
    switch (other.index_) {
107
3.69k
      case ValueIndex::kBytes:
108
3.69k
        ::new (static_cast<void*>(&raw_[0]))
109
3.69k
            BytesValue(*other.At<BytesValue>());
110
3.69k
        break;
111
941
      case ValueIndex::kString:
112
941
        ::new (static_cast<void*>(&raw_[0]))
113
941
            StringValue(*other.At<StringValue>());
114
941
        break;
115
9.14k
      case ValueIndex::kError:
116
9.14k
        ::new (static_cast<void*>(&raw_[0]))
117
9.14k
            ErrorValue(*other.At<ErrorValue>());
118
9.14k
        break;
119
0
      case ValueIndex::kUnknown:
120
0
        ::new (static_cast<void*>(&raw_[0]))
121
0
            UnknownValue(*other.At<UnknownValue>());
122
0
        break;
123
0
      default:
124
0
        ABSL_UNREACHABLE();
125
13.7k
    }
126
13.7k
    index_ = other.index_;
127
13.7k
    kind_ = other.kind_;
128
13.7k
    flags_ = other.flags_;
129
13.7k
  } else if (other_trivial) {
130
0
    switch (index_) {
131
0
      case ValueIndex::kBytes:
132
0
        At<BytesValue>()->~BytesValue();
133
0
        break;
134
0
      case ValueIndex::kString:
135
0
        At<StringValue>()->~StringValue();
136
0
        break;
137
0
      case ValueIndex::kError:
138
0
        At<ErrorValue>()->~ErrorValue();
139
0
        break;
140
0
      case ValueIndex::kUnknown:
141
0
        At<UnknownValue>()->~UnknownValue();
142
0
        break;
143
0
      default:
144
0
        ABSL_UNREACHABLE();
145
0
    }
146
0
    FastCopyAssign(other);
147
0
  } else {
148
0
    switch (index_) {
149
0
      case ValueIndex::kBytes:
150
0
        switch (other.index_) {
151
0
          case ValueIndex::kBytes:
152
0
            *At<BytesValue>() = *other.At<BytesValue>();
153
0
            break;
154
0
          case ValueIndex::kString:
155
0
            At<BytesValue>()->~BytesValue();
156
0
            ::new (static_cast<void*>(&raw_[0]))
157
0
                StringValue(*other.At<StringValue>());
158
0
            index_ = other.index_;
159
0
            kind_ = other.kind_;
160
0
            break;
161
0
          case ValueIndex::kError:
162
0
            At<BytesValue>()->~BytesValue();
163
0
            ::new (static_cast<void*>(&raw_[0]))
164
0
                ErrorValue(*other.At<ErrorValue>());
165
0
            index_ = other.index_;
166
0
            kind_ = other.kind_;
167
0
            break;
168
0
          case ValueIndex::kUnknown:
169
0
            At<BytesValue>()->~BytesValue();
170
0
            ::new (static_cast<void*>(&raw_[0]))
171
0
                UnknownValue(*other.At<UnknownValue>());
172
0
            index_ = other.index_;
173
0
            kind_ = other.kind_;
174
0
            break;
175
0
          default:
176
0
            ABSL_UNREACHABLE();
177
0
        }
178
0
        break;
179
0
      case ValueIndex::kString:
180
0
        switch (other.index_) {
181
0
          case ValueIndex::kBytes:
182
0
            At<StringValue>()->~StringValue();
183
0
            ::new (static_cast<void*>(&raw_[0]))
184
0
                BytesValue(*other.At<BytesValue>());
185
0
            index_ = other.index_;
186
0
            kind_ = other.kind_;
187
0
            break;
188
0
          case ValueIndex::kString:
189
0
            *At<StringValue>() = *other.At<StringValue>();
190
0
            break;
191
0
          case ValueIndex::kError:
192
0
            At<StringValue>()->~StringValue();
193
0
            ::new (static_cast<void*>(&raw_[0]))
194
0
                ErrorValue(*other.At<ErrorValue>());
195
0
            index_ = other.index_;
196
0
            kind_ = other.kind_;
197
0
            break;
198
0
          case ValueIndex::kUnknown:
199
0
            At<StringValue>()->~StringValue();
200
0
            ::new (static_cast<void*>(&raw_[0]))
201
0
                UnknownValue(*other.At<UnknownValue>());
202
0
            index_ = other.index_;
203
0
            kind_ = other.kind_;
204
0
            break;
205
0
          default:
206
0
            ABSL_UNREACHABLE();
207
0
        }
208
0
        break;
209
0
      case ValueIndex::kError:
210
0
        switch (other.index_) {
211
0
          case ValueIndex::kBytes:
212
0
            At<ErrorValue>()->~ErrorValue();
213
0
            ::new (static_cast<void*>(&raw_[0]))
214
0
                BytesValue(*other.At<BytesValue>());
215
0
            index_ = other.index_;
216
0
            kind_ = other.kind_;
217
0
            break;
218
0
          case ValueIndex::kString:
219
0
            At<ErrorValue>()->~ErrorValue();
220
0
            ::new (static_cast<void*>(&raw_[0]))
221
0
                StringValue(*other.At<StringValue>());
222
0
            index_ = other.index_;
223
0
            kind_ = other.kind_;
224
0
            break;
225
0
          case ValueIndex::kError:
226
0
            *At<ErrorValue>() = *other.At<ErrorValue>();
227
0
            break;
228
0
          case ValueIndex::kUnknown:
229
0
            At<ErrorValue>()->~ErrorValue();
230
0
            ::new (static_cast<void*>(&raw_[0]))
231
0
                UnknownValue(*other.At<UnknownValue>());
232
0
            index_ = other.index_;
233
0
            kind_ = other.kind_;
234
0
            break;
235
0
          default:
236
0
            ABSL_UNREACHABLE();
237
0
        }
238
0
        break;
239
0
      case ValueIndex::kUnknown:
240
0
        switch (other.index_) {
241
0
          case ValueIndex::kBytes:
242
0
            At<UnknownValue>()->~UnknownValue();
243
0
            ::new (static_cast<void*>(&raw_[0]))
244
0
                BytesValue(*other.At<BytesValue>());
245
0
            index_ = other.index_;
246
0
            kind_ = other.kind_;
247
0
            break;
248
0
          case ValueIndex::kString:
249
0
            At<UnknownValue>()->~UnknownValue();
250
0
            ::new (static_cast<void*>(&raw_[0]))
251
0
                StringValue(*other.At<StringValue>());
252
0
            index_ = other.index_;
253
0
            kind_ = other.kind_;
254
0
            break;
255
0
          case ValueIndex::kError:
256
0
            At<UnknownValue>()->~UnknownValue();
257
0
            ::new (static_cast<void*>(&raw_[0]))
258
0
                ErrorValue(*other.At<ErrorValue>());
259
0
            index_ = other.index_;
260
0
            kind_ = other.kind_;
261
0
            break;
262
0
          case ValueIndex::kUnknown:
263
0
            At<UnknownValue>()->~UnknownValue();
264
0
            ::new (static_cast<void*>(&raw_[0]))
265
0
                UnknownValue(*other.At<UnknownValue>());
266
0
            index_ = other.index_;
267
0
            kind_ = other.kind_;
268
0
            break;
269
0
          default:
270
0
            ABSL_UNREACHABLE();
271
0
        }
272
0
        break;
273
0
      default:
274
0
        ABSL_UNREACHABLE();
275
0
    }
276
0
    flags_ = other.flags_;
277
0
  }
278
13.7k
}
279
280
void ValueVariant::SlowMoveAssign(ValueVariant& other, bool trivial,
281
124k
                                  bool other_trivial) noexcept {
282
124k
  ABSL_DCHECK(!trivial || !other_trivial);
283
284
124k
  if (trivial) {
285
28.2k
    switch (other.index_) {
286
53
      case ValueIndex::kBytes:
287
53
        ::new (static_cast<void*>(&raw_[0]))
288
53
            BytesValue(std::move(*other.At<BytesValue>()));
289
53
        break;
290
81
      case ValueIndex::kString:
291
81
        ::new (static_cast<void*>(&raw_[0]))
292
81
            StringValue(std::move(*other.At<StringValue>()));
293
81
        break;
294
28.1k
      case ValueIndex::kError:
295
28.1k
        ::new (static_cast<void*>(&raw_[0]))
296
28.1k
            ErrorValue(std::move(*other.At<ErrorValue>()));
297
28.1k
        break;
298
0
      case ValueIndex::kUnknown:
299
0
        ::new (static_cast<void*>(&raw_[0]))
300
0
            UnknownValue(std::move(*other.At<UnknownValue>()));
301
0
        break;
302
0
      default:
303
0
        ABSL_UNREACHABLE();
304
28.2k
    }
305
28.2k
    index_ = other.index_;
306
28.2k
    kind_ = other.kind_;
307
28.2k
    flags_ = other.flags_;
308
95.9k
  } else if (other_trivial) {
309
1.42k
    switch (index_) {
310
369
      case ValueIndex::kBytes:
311
369
        At<BytesValue>()->~BytesValue();
312
369
        break;
313
662
      case ValueIndex::kString:
314
662
        At<StringValue>()->~StringValue();
315
662
        break;
316
395
      case ValueIndex::kError:
317
395
        At<ErrorValue>()->~ErrorValue();
318
395
        break;
319
0
      case ValueIndex::kUnknown:
320
0
        At<UnknownValue>()->~UnknownValue();
321
0
        break;
322
0
      default:
323
0
        ABSL_UNREACHABLE();
324
1.42k
    }
325
1.42k
    FastMoveAssign(other);
326
94.5k
  } else {
327
94.5k
    switch (index_) {
328
174
      case ValueIndex::kBytes:
329
174
        switch (other.index_) {
330
96
          case ValueIndex::kBytes:
331
96
            *At<BytesValue>() = std::move(*other.At<BytesValue>());
332
96
            break;
333
2
          case ValueIndex::kString:
334
2
            At<BytesValue>()->~BytesValue();
335
2
            ::new (static_cast<void*>(&raw_[0]))
336
2
                StringValue(std::move(*other.At<StringValue>()));
337
2
            index_ = other.index_;
338
2
            kind_ = other.kind_;
339
2
            break;
340
76
          case ValueIndex::kError:
341
76
            At<BytesValue>()->~BytesValue();
342
76
            ::new (static_cast<void*>(&raw_[0]))
343
76
                ErrorValue(std::move(*other.At<ErrorValue>()));
344
76
            index_ = other.index_;
345
76
            kind_ = other.kind_;
346
76
            break;
347
0
          case ValueIndex::kUnknown:
348
0
            At<BytesValue>()->~BytesValue();
349
0
            ::new (static_cast<void*>(&raw_[0]))
350
0
                UnknownValue(std::move(*other.At<UnknownValue>()));
351
0
            index_ = other.index_;
352
0
            kind_ = other.kind_;
353
0
            break;
354
0
          default:
355
0
            ABSL_UNREACHABLE();
356
174
        }
357
174
        break;
358
2.13k
      case ValueIndex::kString:
359
2.13k
        switch (other.index_) {
360
0
          case ValueIndex::kBytes:
361
0
            At<StringValue>()->~StringValue();
362
0
            ::new (static_cast<void*>(&raw_[0]))
363
0
                BytesValue(std::move(*other.At<BytesValue>()));
364
0
            index_ = other.index_;
365
0
            kind_ = other.kind_;
366
0
            break;
367
334
          case ValueIndex::kString:
368
334
            *At<StringValue>() = std::move(*other.At<StringValue>());
369
334
            break;
370
1.79k
          case ValueIndex::kError:
371
1.79k
            At<StringValue>()->~StringValue();
372
1.79k
            ::new (static_cast<void*>(&raw_[0]))
373
1.79k
                ErrorValue(std::move(*other.At<ErrorValue>()));
374
1.79k
            index_ = other.index_;
375
1.79k
            kind_ = other.kind_;
376
1.79k
            break;
377
0
          case ValueIndex::kUnknown:
378
0
            At<StringValue>()->~StringValue();
379
0
            ::new (static_cast<void*>(&raw_[0]))
380
0
                UnknownValue(std::move(*other.At<UnknownValue>()));
381
0
            index_ = other.index_;
382
0
            kind_ = other.kind_;
383
0
            break;
384
0
          default:
385
0
            ABSL_UNREACHABLE();
386
2.13k
        }
387
2.13k
        break;
388
92.2k
      case ValueIndex::kError:
389
92.2k
        switch (other.index_) {
390
0
          case ValueIndex::kBytes:
391
0
            At<ErrorValue>()->~ErrorValue();
392
0
            ::new (static_cast<void*>(&raw_[0]))
393
0
                BytesValue(std::move(*other.At<BytesValue>()));
394
0
            index_ = other.index_;
395
0
            kind_ = other.kind_;
396
0
            break;
397
0
          case ValueIndex::kString:
398
0
            At<ErrorValue>()->~ErrorValue();
399
0
            ::new (static_cast<void*>(&raw_[0]))
400
0
                StringValue(std::move(*other.At<StringValue>()));
401
0
            index_ = other.index_;
402
0
            kind_ = other.kind_;
403
0
            break;
404
92.2k
          case ValueIndex::kError:
405
92.2k
            *At<ErrorValue>() = std::move(*other.At<ErrorValue>());
406
92.2k
            break;
407
0
          case ValueIndex::kUnknown:
408
0
            At<ErrorValue>()->~ErrorValue();
409
0
            ::new (static_cast<void*>(&raw_[0]))
410
0
                UnknownValue(std::move(*other.At<UnknownValue>()));
411
0
            index_ = other.index_;
412
0
            kind_ = other.kind_;
413
0
            break;
414
0
          default:
415
0
            ABSL_UNREACHABLE();
416
92.2k
        }
417
92.2k
        break;
418
92.2k
      case ValueIndex::kUnknown:
419
0
        switch (other.index_) {
420
0
          case ValueIndex::kBytes:
421
0
            At<UnknownValue>()->~UnknownValue();
422
0
            ::new (static_cast<void*>(&raw_[0]))
423
0
                BytesValue(std::move(*other.At<BytesValue>()));
424
0
            index_ = other.index_;
425
0
            kind_ = other.kind_;
426
0
            break;
427
0
          case ValueIndex::kString:
428
0
            At<UnknownValue>()->~UnknownValue();
429
0
            ::new (static_cast<void*>(&raw_[0]))
430
0
                StringValue(std::move(*other.At<StringValue>()));
431
0
            index_ = other.index_;
432
0
            kind_ = other.kind_;
433
0
            break;
434
0
          case ValueIndex::kError:
435
0
            At<UnknownValue>()->~UnknownValue();
436
0
            ::new (static_cast<void*>(&raw_[0]))
437
0
                ErrorValue(std::move(*other.At<ErrorValue>()));
438
0
            index_ = other.index_;
439
0
            kind_ = other.kind_;
440
0
            break;
441
0
          case ValueIndex::kUnknown:
442
0
            *At<UnknownValue>() = std::move(*other.At<UnknownValue>());
443
0
            break;
444
0
          default:
445
0
            ABSL_UNREACHABLE();
446
0
        }
447
0
        break;
448
0
      default:
449
0
        ABSL_UNREACHABLE();
450
94.5k
    }
451
94.5k
    flags_ = other.flags_;
452
94.5k
  }
453
124k
}
454
455
void ValueVariant::SlowSwap(ValueVariant& lhs, ValueVariant& rhs,
456
0
                            bool lhs_trivial, bool rhs_trivial) noexcept {
457
0
  using std::swap;
458
0
  ABSL_DCHECK(!lhs_trivial || !rhs_trivial);
459
460
0
  if (lhs_trivial) {
461
0
    alignas(ValueVariant) std::byte tmp[sizeof(ValueVariant)];
462
    // This is acceptable. We know that both are trivially copyable at runtime.
463
    // NOLINTNEXTLINE(bugprone-undefined-memory-manipulation)
464
0
    std::memcpy(tmp, std::addressof(lhs), sizeof(ValueVariant));
465
0
    switch (rhs.index_) {
466
0
      case ValueIndex::kBytes:
467
0
        ::new (static_cast<void*>(&lhs.raw_[0]))
468
0
            BytesValue(*rhs.At<BytesValue>());
469
0
        rhs.At<BytesValue>()->~BytesValue();
470
0
        break;
471
0
      case ValueIndex::kString:
472
0
        ::new (static_cast<void*>(&lhs.raw_[0]))
473
0
            StringValue(*rhs.At<StringValue>());
474
0
        rhs.At<StringValue>()->~StringValue();
475
0
        break;
476
0
      case ValueIndex::kError:
477
0
        ::new (static_cast<void*>(&lhs.raw_[0]))
478
0
            ErrorValue(*rhs.At<ErrorValue>());
479
0
        rhs.At<ErrorValue>()->~ErrorValue();
480
0
        break;
481
0
      case ValueIndex::kUnknown:
482
0
        ::new (static_cast<void*>(&lhs.raw_[0]))
483
0
            UnknownValue(*rhs.At<UnknownValue>());
484
0
        rhs.At<UnknownValue>()->~UnknownValue();
485
0
        break;
486
0
      default:
487
0
        ABSL_UNREACHABLE();
488
0
    }
489
0
    lhs.index_ = rhs.index_;
490
0
    lhs.kind_ = rhs.kind_;
491
0
    lhs.flags_ = rhs.flags_;
492
    // This is acceptable. We know that both are trivially copyable at runtime.
493
    // NOLINTNEXTLINE(bugprone-undefined-memory-manipulation)
494
0
    std::memcpy(std::addressof(rhs), tmp, sizeof(ValueVariant));
495
0
  } else if (rhs_trivial) {
496
0
    alignas(ValueVariant) std::byte tmp[sizeof(ValueVariant)];
497
    // This is acceptable. We know that both are trivially copyable at runtime.
498
    // NOLINTNEXTLINE(bugprone-undefined-memory-manipulation)
499
0
    std::memcpy(tmp, std::addressof(rhs), sizeof(ValueVariant));
500
0
    switch (lhs.index_) {
501
0
      case ValueIndex::kBytes:
502
0
        ::new (static_cast<void*>(&rhs.raw_[0]))
503
0
            BytesValue(*lhs.At<BytesValue>());
504
0
        lhs.At<BytesValue>()->~BytesValue();
505
0
        break;
506
0
      case ValueIndex::kString:
507
0
        ::new (static_cast<void*>(&rhs.raw_[0]))
508
0
            StringValue(*lhs.At<StringValue>());
509
0
        lhs.At<StringValue>()->~StringValue();
510
0
        break;
511
0
      case ValueIndex::kError:
512
0
        ::new (static_cast<void*>(&rhs.raw_[0]))
513
0
            ErrorValue(*lhs.At<ErrorValue>());
514
0
        lhs.At<ErrorValue>()->~ErrorValue();
515
0
        break;
516
0
      case ValueIndex::kUnknown:
517
0
        ::new (static_cast<void*>(&rhs.raw_[0]))
518
0
            UnknownValue(*lhs.At<UnknownValue>());
519
0
        lhs.At<UnknownValue>()->~UnknownValue();
520
0
        break;
521
0
      default:
522
0
        ABSL_UNREACHABLE();
523
0
    }
524
0
    rhs.index_ = lhs.index_;
525
0
    rhs.kind_ = lhs.kind_;
526
0
    rhs.flags_ = lhs.flags_;
527
    // This is acceptable. We know that both are trivially copyable at runtime.
528
    // NOLINTNEXTLINE(bugprone-undefined-memory-manipulation)
529
0
    std::memcpy(std::addressof(lhs), tmp, sizeof(ValueVariant));
530
0
  } else {
531
0
    ValueVariant tmp = std::move(lhs);
532
0
    lhs = std::move(rhs);
533
0
    rhs = std::move(tmp);
534
0
  }
535
0
}
536
537
}  // namespace cel::common_internal