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/error_value.cc
Line
Count
Source
1
// Copyright 2023 Google LLC
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//     https://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
15
#include <cstddef>
16
#include <new>
17
#include <string>
18
#include <utility>
19
20
#include "absl/base/no_destructor.h"
21
#include "absl/base/nullability.h"
22
#include "absl/log/absl_check.h"
23
#include "absl/status/status.h"
24
#include "absl/strings/match.h"
25
#include "absl/strings/str_cat.h"
26
#include "absl/strings/string_view.h"
27
#include "common/type.h"
28
#include "common/value.h"
29
#include "google/protobuf/arena.h"
30
#include "google/protobuf/descriptor.h"
31
#include "google/protobuf/io/zero_copy_stream.h"
32
#include "google/protobuf/message.h"
33
34
namespace cel {
35
36
namespace {
37
38
0
std::string ErrorDebugString(const absl::Status& value) {
39
0
  ABSL_DCHECK(!value.ok()) << "use of moved-from ErrorValue";
40
0
  return value.ToString(absl::StatusToStringMode::kWithEverything);
41
0
}
42
43
0
const absl::Status& DefaultErrorValue() {
44
0
  static const absl::NoDestructor<absl::Status> value(
45
0
      absl::UnknownError("unknown error"));
46
0
  return *value;
47
0
}
48
49
}  // namespace
50
51
0
ErrorValue::ErrorValue() : ErrorValue(DefaultErrorValue()) {}
52
53
0
ErrorValue NoSuchFieldError(absl::string_view field) {
54
0
  return ErrorValue(absl::NotFoundError(
55
0
      absl::StrCat("no_such_field", field.empty() ? "" : " : ", field)));
56
0
}
57
58
426
ErrorValue NoSuchKeyError(absl::string_view key) {
59
426
  return ErrorValue(
60
426
      absl::NotFoundError(absl::StrCat("Key not found in map : ", key)));
61
426
}
62
63
0
ErrorValue NoSuchTypeError(absl::string_view type) {
64
0
  return ErrorValue(
65
0
      absl::NotFoundError(absl::StrCat("type not found: ", type)));
66
0
}
67
68
30
ErrorValue DuplicateKeyError() {
69
30
  return ErrorValue(absl::AlreadyExistsError("duplicate key in map"));
70
30
}
71
72
0
ErrorValue TypeConversionError(absl::string_view from, absl::string_view to) {
73
0
  return ErrorValue(absl::InvalidArgumentError(
74
0
      absl::StrCat("type conversion error from '", from, "' to '", to, "'")));
75
0
}
76
77
0
ErrorValue TypeConversionError(const Type& from, const Type& to) {
78
0
  return TypeConversionError(from.DebugString(), to.DebugString());
79
0
}
80
81
0
ErrorValue IndexOutOfBoundsError(size_t index) {
82
0
  return ErrorValue(
83
0
      absl::InvalidArgumentError(absl::StrCat("index out of bounds: ", index)));
84
0
}
85
86
0
ErrorValue IndexOutOfBoundsError(ptrdiff_t index) {
87
0
  return ErrorValue(
88
0
      absl::InvalidArgumentError(absl::StrCat("index out of bounds: ", index)));
89
0
}
90
91
0
bool IsNoSuchField(const ErrorValue& value) {
92
0
  return absl::IsNotFound(value.NativeValue()) &&
93
0
         absl::StartsWith(value.NativeValue().message(), "no_such_field");
94
0
}
95
96
0
bool IsNoSuchKey(const ErrorValue& value) {
97
0
  return absl::IsNotFound(value.NativeValue()) &&
98
0
         absl::StartsWith(value.NativeValue().message(),
99
0
                          "Key not found in map");
100
0
}
101
102
0
std::string ErrorValue::DebugString() const {
103
0
  return ErrorDebugString(NativeValue());
104
0
}
105
106
absl::Status ErrorValue::SerializeTo(
107
    const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
108
    google::protobuf::MessageFactory* absl_nonnull message_factory,
109
0
    google::protobuf::io::ZeroCopyOutputStream* absl_nonnull output) const {
110
0
  ABSL_DCHECK(descriptor_pool != nullptr);
111
0
  ABSL_DCHECK(message_factory != nullptr);
112
0
  ABSL_DCHECK(output != nullptr);
113
0
  ABSL_DCHECK(*this);
114
115
0
  return absl::FailedPreconditionError(
116
0
      absl::StrCat(GetTypeName(), " is unserializable"));
117
0
}
118
119
absl::Status ErrorValue::ConvertToJson(
120
    const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
121
    google::protobuf::MessageFactory* absl_nonnull message_factory,
122
0
    google::protobuf::Message* absl_nonnull json) const {
123
0
  ABSL_DCHECK(descriptor_pool != nullptr);
124
0
  ABSL_DCHECK(message_factory != nullptr);
125
0
  ABSL_DCHECK(json != nullptr);
126
0
  ABSL_DCHECK_EQ(json->GetDescriptor()->well_known_type(),
127
0
                 google::protobuf::Descriptor::WELLKNOWNTYPE_VALUE);
128
0
  ABSL_DCHECK(*this);
129
130
0
  return absl::FailedPreconditionError(
131
0
      absl::StrCat(GetTypeName(), " is not convertable to JSON"));
132
0
}
133
134
absl::Status ErrorValue::Equal(
135
    const Value& other,
136
    const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
137
    google::protobuf::MessageFactory* absl_nonnull message_factory,
138
0
    google::protobuf::Arena* absl_nonnull arena, Value* absl_nonnull result) const {
139
0
  ABSL_DCHECK(descriptor_pool != nullptr);
140
0
  ABSL_DCHECK(message_factory != nullptr);
141
0
  ABSL_DCHECK(arena != nullptr);
142
0
  ABSL_DCHECK(result != nullptr);
143
0
  ABSL_DCHECK(*this);
144
145
0
  *result = FalseValue();
146
0
  return absl::OkStatus();
147
0
}
148
149
0
ErrorValue ErrorValue::Clone(google::protobuf::Arena* absl_nonnull arena) const {
150
0
  ABSL_DCHECK(arena != nullptr);
151
0
  ABSL_DCHECK(*this);
152
153
0
  if (arena_ == nullptr || arena_ != arena) {
154
0
    return ErrorValue(arena,
155
0
                      google::protobuf::Arena::Create<absl::Status>(arena, ToStatus()));
156
0
  }
157
0
  return *this;
158
0
}
159
160
5.05k
absl::Status ErrorValue::ToStatus() const& {
161
5.05k
  ABSL_DCHECK(*this);
162
163
5.05k
  if (arena_ == nullptr) {
164
5.05k
    return *std::launder(
165
5.05k
        reinterpret_cast<const absl::Status*>(&status_.val[0]));
166
5.05k
  }
167
0
  return *status_.ptr;
168
5.05k
}
169
170
30
absl::Status ErrorValue::ToStatus() && {
171
30
  ABSL_DCHECK(*this);
172
173
30
  if (arena_ == nullptr) {
174
30
    return std::move(
175
30
        *std::launder(reinterpret_cast<absl::Status*>(&status_.val[0])));
176
30
  }
177
0
  return *status_.ptr;
178
30
}
179
180
0
ErrorValue::operator bool() const {
181
0
  if (arena_ == nullptr) {
182
0
    return !std::launder(reinterpret_cast<const absl::Status*>(&status_.val[0]))
183
0
                ->ok();
184
0
  }
185
0
  return status_.ptr != nullptr && !status_.ptr->ok();
186
0
}
187
188
0
void swap(ErrorValue& lhs, ErrorValue& rhs) noexcept {
189
0
  ErrorValue tmp(std::move(lhs));
190
0
  lhs = std::move(rhs);
191
0
  rhs = std::move(tmp);
192
0
}
193
194
}  // namespace cel