/proc/self/cwd/common/values/struct_value.h
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 | | // IWYU pragma: private, include "common/value.h" |
16 | | // IWYU pragma: friend "common/value.h" |
17 | | |
18 | | // `StructValue` is the value representation of `StructType`. `StructValue` |
19 | | // itself is a composed type of more specific runtime representations. |
20 | | |
21 | | #ifndef THIRD_PARTY_CEL_CPP_COMMON_VALUES_STRUCT_VALUE_H_ |
22 | | #define THIRD_PARTY_CEL_CPP_COMMON_VALUES_STRUCT_VALUE_H_ |
23 | | |
24 | | #include <cstdint> |
25 | | #include <memory> |
26 | | #include <ostream> |
27 | | #include <string> |
28 | | #include <type_traits> |
29 | | #include <utility> |
30 | | |
31 | | #include "absl/base/attributes.h" |
32 | | #include "absl/base/nullability.h" |
33 | | #include "absl/meta/type_traits.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/utility/utility.h" |
40 | | #include "base/attribute.h" |
41 | | #include "common/native_type.h" |
42 | | #include "common/optional_ref.h" |
43 | | #include "common/type.h" |
44 | | #include "common/value_kind.h" |
45 | | #include "common/values/custom_struct_value.h" |
46 | | #include "common/values/legacy_struct_value.h" |
47 | | #include "common/values/message_value.h" |
48 | | #include "common/values/parsed_message_value.h" |
49 | | #include "common/values/struct_value_variant.h" |
50 | | #include "common/values/values.h" |
51 | | #include "runtime/runtime_options.h" |
52 | | #include "google/protobuf/arena.h" |
53 | | #include "google/protobuf/descriptor.h" |
54 | | #include "google/protobuf/io/zero_copy_stream.h" |
55 | | #include "google/protobuf/message.h" |
56 | | |
57 | | namespace cel { |
58 | | |
59 | | class StructValue; |
60 | | class Value; |
61 | | |
62 | | class StructValue final |
63 | | : private common_internal::StructValueMixin<StructValue> { |
64 | | public: |
65 | | static constexpr ValueKind kKind = ValueKind::kStruct; |
66 | | |
67 | | template < |
68 | | typename T, |
69 | | typename = std::enable_if_t< |
70 | | common_internal::IsStructValueAlternativeV<absl::remove_cvref_t<T>>>> |
71 | | // NOLINTNEXTLINE(google-explicit-constructor) |
72 | | StructValue(T&& value) |
73 | 284 | : variant_(absl::in_place_type<absl::remove_cvref_t<T>>, |
74 | 284 | std::forward<T>(value)) {}Unexecuted instantiation: cel::StructValue::StructValue<cel::ParsedMessageValue const&, void>(cel::ParsedMessageValue const&) Unexecuted instantiation: cel::StructValue::StructValue<cel::CustomStructValue const&, void>(cel::CustomStructValue const&) Unexecuted instantiation: cel::StructValue::StructValue<cel::ParsedMessageValue, void>(cel::ParsedMessageValue&&) Unexecuted instantiation: cel::StructValue::StructValue<cel::common_internal::LegacyStructValue, void>(cel::common_internal::LegacyStructValue&&) cel::StructValue::StructValue<cel::common_internal::LegacyStructValue const&, void>(cel::common_internal::LegacyStructValue const&) Line | Count | Source | 73 | 284 | : variant_(absl::in_place_type<absl::remove_cvref_t<T>>, | 74 | 284 | std::forward<T>(value)) {} |
Unexecuted instantiation: cel::StructValue::StructValue<cel::CustomStructValue, void>(cel::CustomStructValue&&) |
75 | | |
76 | | // NOLINTNEXTLINE(google-explicit-constructor) |
77 | | StructValue(const MessageValue& other) |
78 | 0 | : variant_(other.ToStructValueVariant()) {} |
79 | | |
80 | | // NOLINTNEXTLINE(google-explicit-constructor) |
81 | | StructValue(MessageValue&& other) |
82 | 0 | : variant_(std::move(other).ToStructValueVariant()) {} |
83 | | |
84 | 0 | StructValue() = default; |
85 | | StructValue(const StructValue&) = default; |
86 | | StructValue(StructValue&& other) = default; |
87 | | StructValue& operator=(const StructValue&) = default; |
88 | | StructValue& operator=(StructValue&&) = default; |
89 | | |
90 | 0 | constexpr ValueKind kind() const { return kKind; } |
91 | | |
92 | | StructType GetRuntimeType() const; |
93 | | |
94 | | absl::string_view GetTypeName() const; |
95 | | |
96 | | NativeTypeId GetTypeId() const; |
97 | | |
98 | | std::string DebugString() const; |
99 | | |
100 | | // See Value::SerializeTo(). |
101 | | absl::Status SerializeTo( |
102 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
103 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
104 | | google::protobuf::io::ZeroCopyOutputStream* absl_nonnull output) const; |
105 | | |
106 | | // See Value::ConvertToJson(). |
107 | | absl::Status ConvertToJson( |
108 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
109 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
110 | | google::protobuf::Message* absl_nonnull json) const; |
111 | | |
112 | | // Like ConvertToJson(), except `json` **MUST** be an instance of |
113 | | // `google.protobuf.Struct`. |
114 | | absl::Status ConvertToJsonObject( |
115 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
116 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
117 | | google::protobuf::Message* absl_nonnull json) const; |
118 | | |
119 | | absl::Status Equal(const Value& other, |
120 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
121 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
122 | | google::protobuf::Arena* absl_nonnull arena, |
123 | | Value* absl_nonnull result) const; |
124 | | using StructValueMixin::Equal; |
125 | | |
126 | | bool IsZeroValue() const; |
127 | | |
128 | | absl::Status GetFieldByName( |
129 | | absl::string_view name, ProtoWrapperTypeOptions unboxing_options, |
130 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
131 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
132 | | google::protobuf::Arena* absl_nonnull arena, Value* absl_nonnull result) const; |
133 | | using StructValueMixin::GetFieldByName; |
134 | | |
135 | | absl::Status GetFieldByNumber( |
136 | | int64_t number, ProtoWrapperTypeOptions unboxing_options, |
137 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
138 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
139 | | google::protobuf::Arena* absl_nonnull arena, Value* absl_nonnull result) const; |
140 | | using StructValueMixin::GetFieldByNumber; |
141 | | |
142 | | absl::StatusOr<bool> HasFieldByName(absl::string_view name) const; |
143 | | |
144 | | absl::StatusOr<bool> HasFieldByNumber(int64_t number) const; |
145 | | |
146 | | using ForEachFieldCallback = CustomStructValueInterface::ForEachFieldCallback; |
147 | | |
148 | | absl::Status ForEachField( |
149 | | ForEachFieldCallback callback, |
150 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
151 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
152 | | google::protobuf::Arena* absl_nonnull arena) const; |
153 | | |
154 | | absl::Status Qualify( |
155 | | absl::Span<const SelectQualifier> qualifiers, bool presence_test, |
156 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
157 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
158 | | google::protobuf::Arena* absl_nonnull arena, Value* absl_nonnull result, |
159 | | int* absl_nonnull count) const; |
160 | | using StructValueMixin::Qualify; |
161 | | |
162 | | // Returns `true` if this value is an instance of a message value. If `true` |
163 | | // is returned, it is implied that `IsOpaque()` would also return true. |
164 | 0 | bool IsMessage() const { return IsParsedMessage(); } |
165 | | |
166 | | // Returns `true` if this value is an instance of a parsed message value. If |
167 | | // `true` is returned, it is implied that `IsMessage()` would also return |
168 | | // true. |
169 | 0 | bool IsParsedMessage() const { return variant_.Is<ParsedMessageValue>(); } |
170 | | |
171 | | // Convenience method for use with template metaprogramming. See |
172 | | // `IsMessage()`. |
173 | | template <typename T> |
174 | | std::enable_if_t<std::is_same_v<MessageValue, T>, bool> Is() const { |
175 | | return IsMessage(); |
176 | | } |
177 | | |
178 | | // Convenience method for use with template metaprogramming. See |
179 | | // `IsParsedMessage()`. |
180 | | template <typename T> |
181 | | std::enable_if_t<std::is_same_v<ParsedMessageValue, T>, bool> Is() const { |
182 | | return IsParsedMessage(); |
183 | | } |
184 | | |
185 | | // Performs a checked cast from a value to a message value, |
186 | | // returning a non-empty optional with either a value or reference to the |
187 | | // message value. Otherwise an empty optional is returned. |
188 | 0 | absl::optional<MessageValue> AsMessage() & { |
189 | 0 | return std::as_const(*this).AsMessage(); |
190 | 0 | } |
191 | | absl::optional<MessageValue> AsMessage() const&; |
192 | | absl::optional<MessageValue> AsMessage() &&; |
193 | 0 | absl::optional<MessageValue> AsMessage() const&& { return AsMessage(); } |
194 | | |
195 | | // Performs a checked cast from a value to a parsed message value, |
196 | | // returning a non-empty optional with either a value or reference to the |
197 | | // parsed message value. Otherwise an empty optional is returned. |
198 | | optional_ref<const ParsedMessageValue> AsParsedMessage() & |
199 | 0 | ABSL_ATTRIBUTE_LIFETIME_BOUND { |
200 | 0 | return std::as_const(*this).AsParsedMessage(); |
201 | 0 | } |
202 | | optional_ref<const ParsedMessageValue> AsParsedMessage() |
203 | | const& ABSL_ATTRIBUTE_LIFETIME_BOUND; |
204 | | absl::optional<ParsedMessageValue> AsParsedMessage() &&; |
205 | 0 | absl::optional<ParsedMessageValue> AsParsedMessage() const&& { |
206 | 0 | return common_internal::AsOptional(AsParsedMessage()); |
207 | 0 | } |
208 | | |
209 | | // Convenience method for use with template metaprogramming. See |
210 | | // `AsMessage()`. |
211 | | template <typename T> |
212 | | std::enable_if_t<std::is_same_v<MessageValue, T>, |
213 | | absl::optional<MessageValue>> |
214 | | As() & { |
215 | | return AsMessage(); |
216 | | } |
217 | | template <typename T> |
218 | | std::enable_if_t<std::is_same_v<MessageValue, T>, |
219 | | absl::optional<MessageValue>> |
220 | | As() const& { |
221 | | return AsMessage(); |
222 | | } |
223 | | template <typename T> |
224 | | std::enable_if_t<std::is_same_v<MessageValue, T>, |
225 | | absl::optional<MessageValue>> |
226 | | As() && { |
227 | | return std::move(*this).AsMessage(); |
228 | | } |
229 | | template <typename T> |
230 | | std::enable_if_t<std::is_same_v<MessageValue, T>, |
231 | | absl::optional<MessageValue>> |
232 | | As() const&& { |
233 | | return std::move(*this).AsMessage(); |
234 | | } |
235 | | |
236 | | // Convenience method for use with template metaprogramming. See |
237 | | // `AsParsedMessage()`. |
238 | | template <typename T> |
239 | | std::enable_if_t<std::is_same_v<ParsedMessageValue, T>, |
240 | | optional_ref<const ParsedMessageValue>> |
241 | | As() & ABSL_ATTRIBUTE_LIFETIME_BOUND { |
242 | | return AsParsedMessage(); |
243 | | } |
244 | | template <typename T> |
245 | | std::enable_if_t<std::is_same_v<ParsedMessageValue, T>, |
246 | | optional_ref<const ParsedMessageValue>> |
247 | | As() const& ABSL_ATTRIBUTE_LIFETIME_BOUND { |
248 | | return AsParsedMessage(); |
249 | | } |
250 | | template <typename T> |
251 | | std::enable_if_t<std::is_same_v<ParsedMessageValue, T>, |
252 | | absl::optional<ParsedMessageValue>> |
253 | | As() && { |
254 | | return std::move(*this).AsParsedMessage(); |
255 | | } |
256 | | template <typename T> |
257 | | std::enable_if_t<std::is_same_v<ParsedMessageValue, T>, |
258 | | absl::optional<ParsedMessageValue>> |
259 | | As() const&& { |
260 | | return std::move(*this).AsParsedMessage(); |
261 | | } |
262 | | |
263 | | // Performs an unchecked cast from a value to a message value. In |
264 | | // debug builds a best effort is made to crash. If `IsMessage()` would return |
265 | | // false, calling this method is undefined behavior. |
266 | 0 | MessageValue GetMessage() & { return std::as_const(*this).GetMessage(); } |
267 | | MessageValue GetMessage() const&; |
268 | | MessageValue GetMessage() &&; |
269 | 0 | MessageValue GetMessage() const&& { return GetMessage(); } |
270 | | |
271 | | // Performs an unchecked cast from a value to a parsed message value. In |
272 | | // debug builds a best effort is made to crash. If `IsParsedMessage()` would |
273 | | // return false, calling this method is undefined behavior. |
274 | 0 | const ParsedMessageValue& GetParsedMessage() & ABSL_ATTRIBUTE_LIFETIME_BOUND { |
275 | 0 | return std::as_const(*this).GetParsedMessage(); |
276 | 0 | } |
277 | | const ParsedMessageValue& GetParsedMessage() |
278 | | const& ABSL_ATTRIBUTE_LIFETIME_BOUND; |
279 | | ParsedMessageValue GetParsedMessage() &&; |
280 | 0 | ParsedMessageValue GetParsedMessage() const&& { return GetParsedMessage(); } |
281 | | |
282 | | // Convenience method for use with template metaprogramming. See |
283 | | // `GetMessage()`. |
284 | | template <typename T> |
285 | | std::enable_if_t<std::is_same_v<MessageValue, T>, MessageValue> Get() & { |
286 | | return GetMessage(); |
287 | | } |
288 | | template <typename T> |
289 | | std::enable_if_t<std::is_same_v<MessageValue, T>, MessageValue> Get() const& { |
290 | | return GetMessage(); |
291 | | } |
292 | | template <typename T> |
293 | | std::enable_if_t<std::is_same_v<MessageValue, T>, MessageValue> Get() && { |
294 | | return std::move(*this).GetMessage(); |
295 | | } |
296 | | template <typename T> |
297 | | std::enable_if_t<std::is_same_v<MessageValue, T>, MessageValue> Get() |
298 | | const&& { |
299 | | return std::move(*this).GetMessage(); |
300 | | } |
301 | | |
302 | | // Convenience method for use with template metaprogramming. See |
303 | | // `GetParsedMessage()`. |
304 | | template <typename T> |
305 | | std::enable_if_t<std::is_same_v<ParsedMessageValue, T>, |
306 | | const ParsedMessageValue&> |
307 | | Get() & ABSL_ATTRIBUTE_LIFETIME_BOUND { |
308 | | return GetParsedMessage(); |
309 | | } |
310 | | template <typename T> |
311 | | std::enable_if_t<std::is_same_v<ParsedMessageValue, T>, |
312 | | const ParsedMessageValue&> |
313 | | Get() const& ABSL_ATTRIBUTE_LIFETIME_BOUND { |
314 | | return GetParsedMessage(); |
315 | | } |
316 | | template <typename T> |
317 | | std::enable_if_t<std::is_same_v<ParsedMessageValue, T>, ParsedMessageValue> |
318 | | Get() && { |
319 | | return std::move(*this).GetParsedMessage(); |
320 | | } |
321 | | template <typename T> |
322 | | std::enable_if_t<std::is_same_v<ParsedMessageValue, T>, ParsedMessageValue> |
323 | | Get() const&& { |
324 | | return std::move(*this).GetParsedMessage(); |
325 | | } |
326 | | |
327 | 0 | friend void swap(StructValue& lhs, StructValue& rhs) noexcept { |
328 | 0 | using std::swap; |
329 | 0 | swap(lhs.variant_, rhs.variant_); |
330 | 0 | } |
331 | | |
332 | | private: |
333 | | friend class Value; |
334 | | friend class common_internal::ValueMixin<StructValue>; |
335 | | friend class common_internal::StructValueMixin<StructValue>; |
336 | | |
337 | | common_internal::ValueVariant ToValueVariant() const&; |
338 | | common_internal::ValueVariant ToValueVariant() &&; |
339 | | |
340 | | // Unlike many of the other derived values, `StructValue` is itself a composed |
341 | | // type. This is to avoid making `StructValue` too big and by extension |
342 | | // `Value` too big. Instead we store the derived `StructValue` values in |
343 | | // `Value` and not `StructValue` itself. |
344 | | common_internal::StructValueVariant variant_; |
345 | | }; |
346 | | |
347 | 0 | inline std::ostream& operator<<(std::ostream& out, const StructValue& value) { |
348 | 0 | return out << value.DebugString(); |
349 | 0 | } |
350 | | |
351 | | template <> |
352 | | struct NativeTypeTraits<StructValue> final { |
353 | 0 | static NativeTypeId Id(const StructValue& value) { return value.GetTypeId(); } |
354 | | }; |
355 | | |
356 | | class StructValueBuilder { |
357 | | public: |
358 | 0 | virtual ~StructValueBuilder() = default; |
359 | | |
360 | | virtual absl::StatusOr<absl::optional<ErrorValue>> SetFieldByName( |
361 | | absl::string_view name, Value value) = 0; |
362 | | |
363 | | virtual absl::StatusOr<absl::optional<ErrorValue>> SetFieldByNumber( |
364 | | int64_t number, Value value) = 0; |
365 | | |
366 | | virtual absl::StatusOr<StructValue> Build() && = 0; |
367 | | }; |
368 | | |
369 | | using StructValueBuilderPtr = std::unique_ptr<StructValueBuilder>; |
370 | | |
371 | | } // namespace cel |
372 | | |
373 | | #endif // THIRD_PARTY_CEL_CPP_COMMON_VALUES_STRUCT_VALUE_H_ |