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/message_value.h
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
// IWYU pragma: private, include "common/value.h"
16
// IWYU pragma: friend "common/value.h"
17
18
#ifndef THIRD_PARTY_CEL_CPP_COMMON_VALUES_MESSAGE_VALUE_H_
19
#define THIRD_PARTY_CEL_CPP_COMMON_VALUES_MESSAGE_VALUE_H_
20
21
#include <cstdint>
22
#include <ostream>
23
#include <string>
24
#include <type_traits>
25
#include <utility>
26
27
#include "google/protobuf/any.pb.h"
28
#include "google/protobuf/duration.pb.h"
29
#include "google/protobuf/struct.pb.h"
30
#include "google/protobuf/timestamp.pb.h"
31
#include "google/protobuf/wrappers.pb.h"
32
#include "absl/base/attributes.h"
33
#include "absl/base/nullability.h"
34
#include "absl/status/status.h"
35
#include "absl/status/statusor.h"
36
#include "absl/strings/string_view.h"
37
#include "absl/types/optional.h"
38
#include "absl/types/span.h"
39
#include "absl/types/variant.h"
40
#include "absl/utility/utility.h"
41
#include "base/attribute.h"
42
#include "common/arena.h"
43
#include "common/optional_ref.h"
44
#include "common/type.h"
45
#include "common/value_kind.h"
46
#include "common/values/custom_struct_value.h"
47
#include "common/values/parsed_message_value.h"
48
#include "common/values/values.h"
49
#include "runtime/runtime_options.h"
50
#include "google/protobuf/arena.h"
51
#include "google/protobuf/descriptor.h"
52
#include "google/protobuf/io/zero_copy_stream.h"
53
#include "google/protobuf/message.h"
54
55
namespace cel {
56
57
class Value;
58
class StructValue;
59
60
class MessageValue final
61
    : private common_internal::StructValueMixin<MessageValue> {
62
 public:
63
  static constexpr ValueKind kKind = ValueKind::kStruct;
64
65
  // NOLINTNEXTLINE(google-explicit-constructor)
66
  MessageValue(const ParsedMessageValue& other)
67
0
      : variant_(absl::in_place_type<ParsedMessageValue>, other) {}
68
69
  // NOLINTNEXTLINE(google-explicit-constructor)
70
  MessageValue(ParsedMessageValue&& other)
71
0
      : variant_(absl::in_place_type<ParsedMessageValue>, std::move(other)) {}
72
73
  // Places the `MessageValue` into an unspecified state. Anything except
74
  // assigning to `MessageValue` is undefined behavior.
75
  MessageValue() = default;
76
  MessageValue(const MessageValue&) = default;
77
  MessageValue(MessageValue&&) = default;
78
  MessageValue& operator=(const MessageValue&) = default;
79
  MessageValue& operator=(MessageValue&&) = default;
80
81
0
  static ValueKind kind() { return kKind; }
82
83
0
  absl::string_view GetTypeName() const { return GetDescriptor()->full_name(); }
84
85
0
  MessageType GetRuntimeType() const { return MessageType(GetDescriptor()); }
86
87
  const google::protobuf::Descriptor* absl_nonnull GetDescriptor() const;
88
89
  bool IsZeroValue() const;
90
91
  std::string DebugString() const;
92
93
  // See Value::SerializeTo().
94
  absl::Status SerializeTo(
95
      const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
96
      google::protobuf::MessageFactory* absl_nonnull message_factory,
97
      google::protobuf::io::ZeroCopyOutputStream* absl_nonnull output) const;
98
99
  // See Value::ConvertToJson().
100
  absl::Status ConvertToJson(
101
      const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
102
      google::protobuf::MessageFactory* absl_nonnull message_factory,
103
      google::protobuf::Message* absl_nonnull json) const;
104
105
  // See Value::ConvertToJsonObject().
106
  absl::Status ConvertToJsonObject(
107
      const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
108
      google::protobuf::MessageFactory* absl_nonnull message_factory,
109
      google::protobuf::Message* absl_nonnull json) const;
110
111
  absl::Status Equal(const Value& other,
112
                     const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
113
                     google::protobuf::MessageFactory* absl_nonnull message_factory,
114
                     google::protobuf::Arena* absl_nonnull arena,
115
                     Value* absl_nonnull result) const;
116
  using StructValueMixin::Equal;
117
118
  absl::Status GetFieldByName(
119
      absl::string_view name, ProtoWrapperTypeOptions unboxing_options,
120
      const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
121
      google::protobuf::MessageFactory* absl_nonnull message_factory,
122
      google::protobuf::Arena* absl_nonnull arena, Value* absl_nonnull result) const;
123
  using StructValueMixin::GetFieldByName;
124
125
  absl::Status GetFieldByNumber(
126
      int64_t number, ProtoWrapperTypeOptions unboxing_options,
127
      const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
128
      google::protobuf::MessageFactory* absl_nonnull message_factory,
129
      google::protobuf::Arena* absl_nonnull arena, Value* absl_nonnull result) const;
130
  using StructValueMixin::GetFieldByNumber;
131
132
  absl::StatusOr<bool> HasFieldByName(absl::string_view name) const;
133
134
  absl::StatusOr<bool> HasFieldByNumber(int64_t number) const;
135
136
  using ForEachFieldCallback = CustomStructValueInterface::ForEachFieldCallback;
137
138
  absl::Status ForEachField(
139
      ForEachFieldCallback callback,
140
      const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
141
      google::protobuf::MessageFactory* absl_nonnull message_factory,
142
      google::protobuf::Arena* absl_nonnull arena) const;
143
144
  absl::Status Qualify(
145
      absl::Span<const SelectQualifier> qualifiers, bool presence_test,
146
      const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
147
      google::protobuf::MessageFactory* absl_nonnull message_factory,
148
      google::protobuf::Arena* absl_nonnull arena, Value* absl_nonnull result,
149
      int* absl_nonnull count) const;
150
  using StructValueMixin::Qualify;
151
152
0
  bool IsParsed() const {
153
0
    return absl::holds_alternative<ParsedMessageValue>(variant_);
154
0
  }
155
156
  template <typename T>
157
  std::enable_if_t<std::is_same_v<ParsedMessageValue, T>, bool> Is() const {
158
    return IsParsed();
159
  }
160
161
  cel::optional_ref<const ParsedMessageValue> AsParsed() &
162
0
      ABSL_ATTRIBUTE_LIFETIME_BOUND {
163
0
    return std::as_const(*this).AsParsed();
164
0
  }
165
  cel::optional_ref<const ParsedMessageValue> AsParsed()
166
      const& ABSL_ATTRIBUTE_LIFETIME_BOUND;
167
  absl::optional<ParsedMessageValue> AsParsed() &&;
168
0
  absl::optional<ParsedMessageValue> AsParsed() const&& {
169
0
    return common_internal::AsOptional(AsParsed());
170
0
  }
171
172
  template <typename T>
173
      std::enable_if_t<std::is_same_v<ParsedMessageValue, T>,
174
                       cel::optional_ref<const ParsedMessageValue>>
175
      As() & ABSL_ATTRIBUTE_LIFETIME_BOUND {
176
    return AsParsed();
177
  }
178
  template <typename T>
179
  std::enable_if_t<std::is_same_v<ParsedMessageValue, T>,
180
                   cel::optional_ref<const ParsedMessageValue>>
181
  As() const& ABSL_ATTRIBUTE_LIFETIME_BOUND {
182
    return IsParsed();
183
  }
184
  template <typename T>
185
      std::enable_if_t<std::is_same_v<ParsedMessageValue, T>,
186
                       absl::optional<ParsedMessageValue>>
187
      As() && ABSL_ATTRIBUTE_LIFETIME_BOUND {
188
    return std::move(*this).AsParsed();
189
  }
190
  template <typename T>
191
  std::enable_if_t<std::is_same_v<ParsedMessageValue, T>,
192
                   absl::optional<ParsedMessageValue>>
193
  As() const&& ABSL_ATTRIBUTE_LIFETIME_BOUND {
194
    return std::move(*this).AsParsed();
195
  }
196
197
0
  const ParsedMessageValue& GetParsed() & ABSL_ATTRIBUTE_LIFETIME_BOUND {
198
0
    return std::as_const(*this).GetParsed();
199
0
  }
200
  const ParsedMessageValue& GetParsed() const& ABSL_ATTRIBUTE_LIFETIME_BOUND;
201
  ParsedMessageValue GetParsed() &&;
202
0
  ParsedMessageValue GetParsed() const&& { return GetParsed(); }
203
204
  template <typename T>
205
      std::enable_if_t<std::is_same_v<ParsedMessageValue, T>,
206
                       const ParsedMessageValue&>
207
      Get() & ABSL_ATTRIBUTE_LIFETIME_BOUND {
208
    return GetParsed();
209
  }
210
  template <typename T>
211
  std::enable_if_t<std::is_same_v<ParsedMessageValue, T>,
212
                   const ParsedMessageValue&>
213
  Get() const& ABSL_ATTRIBUTE_LIFETIME_BOUND {
214
    return GetParsed();
215
  }
216
  template <typename T>
217
  std::enable_if_t<std::is_same_v<ParsedMessageValue, T>, ParsedMessageValue>
218
  Get() && {
219
    return std::move(*this).GetParsed();
220
  }
221
  template <typename T>
222
  std::enable_if_t<std::is_same_v<ParsedMessageValue, T>, ParsedMessageValue>
223
  Get() const&& {
224
    return std::move(*this).GetParsed();
225
  }
226
227
0
  explicit operator bool() const {
228
0
    return !absl::holds_alternative<absl::monostate>(variant_);
229
0
  }
230
231
0
  friend void swap(MessageValue& lhs, MessageValue& rhs) noexcept {
232
0
    lhs.variant_.swap(rhs.variant_);
233
0
  }
234
235
 private:
236
  friend class Value;
237
  friend class StructValue;
238
  friend class common_internal::ValueMixin<MessageValue>;
239
  friend class common_internal::StructValueMixin<MessageValue>;
240
  friend struct ArenaTraits<MessageValue>;
241
242
  common_internal::ValueVariant ToValueVariant() const&;
243
  common_internal::ValueVariant ToValueVariant() &&;
244
245
  common_internal::StructValueVariant ToStructValueVariant() const&;
246
  common_internal::StructValueVariant ToStructValueVariant() &&;
247
248
  absl::variant<absl::monostate, ParsedMessageValue> variant_;
249
};
250
251
0
inline std::ostream& operator<<(std::ostream& out, const MessageValue& value) {
252
0
  return out << value.DebugString();
253
0
}
254
255
template <>
256
struct ArenaTraits<MessageValue> {
257
0
  static bool trivially_destructible(const MessageValue& value) {
258
0
    return absl::visit(
259
0
        [](const auto& alternative) -> bool {
260
0
          return ArenaTraits<>::trivially_destructible(alternative);
261
0
        },
262
0
        value.variant_);
263
0
  }
264
};
265
266
}  // namespace cel
267
268
#endif  // THIRD_PARTY_CEL_CPP_COMMON_VALUES_MESSAGE_VALUE_H_