/proc/self/cwd/common/values/custom_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 | | #ifndef THIRD_PARTY_CEL_CPP_COMMON_VALUES_PARSED_STRUCT_VALUE_H_ |
19 | | #define THIRD_PARTY_CEL_CPP_COMMON_VALUES_PARSED_STRUCT_VALUE_H_ |
20 | | |
21 | | #include <cstdint> |
22 | | #include <ostream> |
23 | | #include <string> |
24 | | #include <utility> |
25 | | |
26 | | #include "absl/base/attributes.h" |
27 | | #include "absl/base/nullability.h" |
28 | | #include "absl/functional/function_ref.h" |
29 | | #include "absl/log/absl_check.h" |
30 | | #include "absl/status/status.h" |
31 | | #include "absl/status/statusor.h" |
32 | | #include "absl/strings/string_view.h" |
33 | | #include "absl/types/span.h" |
34 | | #include "base/attribute.h" |
35 | | #include "common/native_type.h" |
36 | | #include "common/type.h" |
37 | | #include "common/value_kind.h" |
38 | | #include "common/values/custom_value.h" |
39 | | #include "common/values/values.h" |
40 | | #include "runtime/runtime_options.h" |
41 | | #include "google/protobuf/arena.h" |
42 | | #include "google/protobuf/descriptor.h" |
43 | | #include "google/protobuf/io/zero_copy_stream.h" |
44 | | #include "google/protobuf/message.h" |
45 | | |
46 | | namespace cel { |
47 | | |
48 | | class CustomStructValueInterface; |
49 | | class CustomStructValue; |
50 | | class Value; |
51 | | struct CustomStructValueDispatcher; |
52 | | using CustomStructValueContent = CustomValueContent; |
53 | | |
54 | | struct CustomStructValueDispatcher { |
55 | | using GetTypeId = NativeTypeId (*)( |
56 | | const CustomStructValueDispatcher* absl_nonnull dispatcher, |
57 | | CustomStructValueContent content); |
58 | | |
59 | | using GetArena = google::protobuf::Arena* absl_nullable (*)( |
60 | | const CustomStructValueDispatcher* absl_nonnull dispatcher, |
61 | | CustomStructValueContent content); |
62 | | |
63 | | using GetTypeName = absl::string_view (*)( |
64 | | const CustomStructValueDispatcher* absl_nonnull dispatcher, |
65 | | CustomStructValueContent content); |
66 | | |
67 | | using DebugString = std::string (*)( |
68 | | const CustomStructValueDispatcher* absl_nonnull dispatcher, |
69 | | CustomStructValueContent content); |
70 | | |
71 | | using GetRuntimeType = |
72 | | StructType (*)(const CustomStructValueDispatcher* absl_nonnull dispatcher, |
73 | | CustomStructValueContent content); |
74 | | |
75 | | using SerializeTo = absl::Status (*)( |
76 | | const CustomStructValueDispatcher* absl_nonnull dispatcher, |
77 | | CustomStructValueContent content, |
78 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
79 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
80 | | google::protobuf::io::ZeroCopyOutputStream* absl_nonnull output); |
81 | | |
82 | | using ConvertToJsonObject = absl::Status (*)( |
83 | | const CustomStructValueDispatcher* absl_nonnull dispatcher, |
84 | | CustomStructValueContent content, |
85 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
86 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
87 | | google::protobuf::Message* absl_nonnull json); |
88 | | |
89 | | using Equal = absl::Status (*)( |
90 | | const CustomStructValueDispatcher* absl_nonnull dispatcher, |
91 | | CustomStructValueContent content, const StructValue& other, |
92 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
93 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
94 | | google::protobuf::Arena* absl_nonnull arena, Value* absl_nonnull result); |
95 | | |
96 | | using IsZeroValue = |
97 | | bool (*)(const CustomStructValueDispatcher* absl_nonnull dispatcher, |
98 | | CustomStructValueContent content); |
99 | | |
100 | | using GetFieldByName = absl::Status (*)( |
101 | | const CustomStructValueDispatcher* absl_nonnull dispatcher, |
102 | | CustomStructValueContent content, absl::string_view name, |
103 | | ProtoWrapperTypeOptions unboxing_options, |
104 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
105 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
106 | | google::protobuf::Arena* absl_nonnull arena, Value* absl_nonnull result); |
107 | | |
108 | | using GetFieldByNumber = absl::Status (*)( |
109 | | const CustomStructValueDispatcher* absl_nonnull dispatcher, |
110 | | CustomStructValueContent content, int64_t number, |
111 | | ProtoWrapperTypeOptions unboxing_options, |
112 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
113 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
114 | | google::protobuf::Arena* absl_nonnull arena, Value* absl_nonnull result); |
115 | | |
116 | | using HasFieldByName = absl::StatusOr<bool> (*)( |
117 | | const CustomStructValueDispatcher* absl_nonnull dispatcher, |
118 | | CustomStructValueContent content, absl::string_view name); |
119 | | |
120 | | using HasFieldByNumber = absl::StatusOr<bool> (*)( |
121 | | const CustomStructValueDispatcher* absl_nonnull dispatcher, |
122 | | CustomStructValueContent content, int64_t number); |
123 | | |
124 | | using ForEachField = absl::Status (*)( |
125 | | const CustomStructValueDispatcher* absl_nonnull dispatcher, |
126 | | CustomStructValueContent content, |
127 | | absl::FunctionRef<absl::StatusOr<bool>(absl::string_view, const Value&)> |
128 | | callback, |
129 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
130 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
131 | | google::protobuf::Arena* absl_nonnull arena); |
132 | | |
133 | | using Quality = absl::Status (*)( |
134 | | const CustomStructValueDispatcher* absl_nonnull dispatcher, |
135 | | CustomStructValueContent content, |
136 | | absl::Span<const SelectQualifier> qualifiers, bool presence_test, |
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, |
140 | | int* absl_nonnull count); |
141 | | |
142 | | using Clone = CustomStructValue (*)( |
143 | | const CustomStructValueDispatcher* absl_nonnull dispatcher, |
144 | | CustomStructValueContent content, google::protobuf::Arena* absl_nonnull arena); |
145 | | |
146 | | absl_nonnull GetTypeId get_type_id; |
147 | | |
148 | | absl_nonnull GetArena get_arena; |
149 | | |
150 | | absl_nonnull GetTypeName get_type_name; |
151 | | |
152 | | absl_nullable DebugString debug_string = nullptr; |
153 | | |
154 | | absl_nullable GetRuntimeType get_runtime_type = nullptr; |
155 | | |
156 | | absl_nullable SerializeTo serialize_to = nullptr; |
157 | | |
158 | | absl_nullable ConvertToJsonObject convert_to_json_object = nullptr; |
159 | | |
160 | | absl_nullable Equal equal = nullptr; |
161 | | |
162 | | absl_nonnull IsZeroValue is_zero_value; |
163 | | |
164 | | absl_nonnull GetFieldByName get_field_by_name; |
165 | | |
166 | | absl_nullable GetFieldByNumber get_field_by_number = nullptr; |
167 | | |
168 | | absl_nonnull HasFieldByName has_field_by_name; |
169 | | |
170 | | absl_nullable HasFieldByNumber has_field_by_number = nullptr; |
171 | | |
172 | | absl_nonnull ForEachField for_each_field; |
173 | | |
174 | | absl_nullable Quality qualify = nullptr; |
175 | | |
176 | | absl_nonnull Clone clone; |
177 | | }; |
178 | | |
179 | | class CustomStructValueInterface { |
180 | | public: |
181 | | CustomStructValueInterface() = default; |
182 | | CustomStructValueInterface(const CustomStructValueInterface&) = delete; |
183 | | CustomStructValueInterface(CustomStructValueInterface&&) = delete; |
184 | | |
185 | 0 | virtual ~CustomStructValueInterface() = default; |
186 | | |
187 | | CustomStructValueInterface& operator=(const CustomStructValueInterface&) = |
188 | | delete; |
189 | | CustomStructValueInterface& operator=(CustomStructValueInterface&&) = delete; |
190 | | |
191 | | using ForEachFieldCallback = |
192 | | absl::FunctionRef<absl::StatusOr<bool>(absl::string_view, const Value&)>; |
193 | | |
194 | | private: |
195 | | friend class CustomStructValue; |
196 | | friend absl::Status common_internal::StructValueEqual( |
197 | | const CustomStructValueInterface& lhs, const StructValue& rhs, |
198 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
199 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
200 | | google::protobuf::Arena* absl_nonnull arena, Value* absl_nonnull result); |
201 | | |
202 | | virtual std::string DebugString() const = 0; |
203 | | |
204 | | virtual absl::Status SerializeTo( |
205 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
206 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
207 | | google::protobuf::io::ZeroCopyOutputStream* absl_nonnull output) const = 0; |
208 | | |
209 | | virtual absl::Status ConvertToJsonObject( |
210 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
211 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
212 | | google::protobuf::Message* absl_nonnull json) const = 0; |
213 | | |
214 | | virtual absl::string_view GetTypeName() const = 0; |
215 | | |
216 | 0 | virtual StructType GetRuntimeType() const { |
217 | 0 | return common_internal::MakeBasicStructType(GetTypeName()); |
218 | 0 | } |
219 | | |
220 | | virtual absl::Status Equal( |
221 | | const StructValue& other, |
222 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
223 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
224 | | google::protobuf::Arena* absl_nonnull arena, Value* absl_nonnull result) const; |
225 | | |
226 | | virtual bool IsZeroValue() const = 0; |
227 | | |
228 | | virtual absl::Status GetFieldByName( |
229 | | absl::string_view name, ProtoWrapperTypeOptions unboxing_options, |
230 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
231 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
232 | | google::protobuf::Arena* absl_nonnull arena, Value* absl_nonnull result) const = 0; |
233 | | |
234 | | virtual absl::Status GetFieldByNumber( |
235 | | int64_t number, ProtoWrapperTypeOptions unboxing_options, |
236 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
237 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
238 | | google::protobuf::Arena* absl_nonnull arena, Value* absl_nonnull result) const = 0; |
239 | | |
240 | | virtual absl::StatusOr<bool> HasFieldByName(absl::string_view name) const = 0; |
241 | | |
242 | | virtual absl::StatusOr<bool> HasFieldByNumber(int64_t number) const = 0; |
243 | | |
244 | | virtual absl::Status ForEachField( |
245 | | ForEachFieldCallback callback, |
246 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
247 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
248 | | google::protobuf::Arena* absl_nonnull arena) const = 0; |
249 | | |
250 | | virtual absl::Status Qualify( |
251 | | absl::Span<const SelectQualifier> qualifiers, bool presence_test, |
252 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
253 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
254 | | google::protobuf::Arena* absl_nonnull arena, Value* absl_nonnull result, |
255 | | int* absl_nonnull count) const; |
256 | | |
257 | | virtual CustomStructValue Clone(google::protobuf::Arena* absl_nonnull arena) const = 0; |
258 | | |
259 | | virtual NativeTypeId GetNativeTypeId() const = 0; |
260 | | |
261 | | struct Content { |
262 | | const CustomStructValueInterface* absl_nonnull interface; |
263 | | google::protobuf::Arena* absl_nonnull arena; |
264 | | }; |
265 | | }; |
266 | | |
267 | | // Creates a custom struct value from a manual dispatch table `dispatcher` and |
268 | | // opaque data `content` whose format is only know to functions in the manual |
269 | | // dispatch table. The dispatch table should probably be valid for the lifetime |
270 | | // of the process, but at a minimum must outlive all instances of the resulting |
271 | | // value. |
272 | | // |
273 | | // IMPORTANT: This approach to implementing CustomStructValues should only be |
274 | | // used when you know exactly what you are doing. When in doubt, just implement |
275 | | // CustomStructValueInterface. |
276 | | CustomStructValue UnsafeCustomStructValue( |
277 | | const CustomStructValueDispatcher* absl_nonnull dispatcher |
278 | | ABSL_ATTRIBUTE_LIFETIME_BOUND, |
279 | | CustomStructValueContent content); |
280 | | |
281 | | class CustomStructValue final |
282 | | : private common_internal::StructValueMixin<CustomStructValue> { |
283 | | public: |
284 | | static constexpr ValueKind kKind = ValueKind::kStruct; |
285 | | |
286 | | // Constructs a custom struct value from an implementation of |
287 | | // `CustomStructValueInterface` `interface` whose lifetime is tied to that of |
288 | | // the arena `arena`. |
289 | | CustomStructValue(const CustomStructValueInterface* absl_nonnull |
290 | | interface ABSL_ATTRIBUTE_LIFETIME_BOUND, |
291 | | google::protobuf::Arena* absl_nonnull arena |
292 | 0 | ABSL_ATTRIBUTE_LIFETIME_BOUND) { |
293 | 0 | ABSL_DCHECK(interface != nullptr); |
294 | 0 | ABSL_DCHECK(arena != nullptr); |
295 | 0 | content_ = |
296 | 0 | CustomStructValueContent::From(CustomStructValueInterface::Content{ |
297 | 0 | .interface = interface, .arena = arena}); |
298 | 0 | } |
299 | | |
300 | | CustomStructValue() = default; |
301 | | CustomStructValue(const CustomStructValue&) = default; |
302 | | CustomStructValue(CustomStructValue&&) = default; |
303 | | CustomStructValue& operator=(const CustomStructValue&) = default; |
304 | | CustomStructValue& operator=(CustomStructValue&&) = default; |
305 | | |
306 | 0 | static constexpr ValueKind kind() { return kKind; } |
307 | | |
308 | | NativeTypeId GetTypeId() const; |
309 | | |
310 | | StructType GetRuntimeType() const; |
311 | | |
312 | | absl::string_view GetTypeName() const; |
313 | | |
314 | | std::string DebugString() const; |
315 | | |
316 | | // See Value::SerializeTo(). |
317 | | absl::Status SerializeTo( |
318 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
319 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
320 | | google::protobuf::io::ZeroCopyOutputStream* absl_nonnull output) const; |
321 | | |
322 | | // See Value::ConvertToJson(). |
323 | | absl::Status ConvertToJson( |
324 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
325 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
326 | | google::protobuf::Message* absl_nonnull json) const; |
327 | | |
328 | | // See Value::ConvertToJsonObject(). |
329 | | absl::Status ConvertToJsonObject( |
330 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
331 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
332 | | google::protobuf::Message* absl_nonnull json) const; |
333 | | |
334 | | absl::Status Equal(const Value& other, |
335 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
336 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
337 | | google::protobuf::Arena* absl_nonnull arena, |
338 | | Value* absl_nonnull result) const; |
339 | | using StructValueMixin::Equal; |
340 | | |
341 | | bool IsZeroValue() const; |
342 | | |
343 | | CustomStructValue Clone(google::protobuf::Arena* absl_nonnull arena) const; |
344 | | |
345 | | absl::Status GetFieldByName( |
346 | | absl::string_view name, ProtoWrapperTypeOptions unboxing_options, |
347 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
348 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
349 | | google::protobuf::Arena* absl_nonnull arena, Value* absl_nonnull result) const; |
350 | | using StructValueMixin::GetFieldByName; |
351 | | |
352 | | absl::Status GetFieldByNumber( |
353 | | int64_t number, ProtoWrapperTypeOptions unboxing_options, |
354 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
355 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
356 | | google::protobuf::Arena* absl_nonnull arena, Value* absl_nonnull result) const; |
357 | | using StructValueMixin::GetFieldByNumber; |
358 | | |
359 | | absl::StatusOr<bool> HasFieldByName(absl::string_view name) const; |
360 | | |
361 | | absl::StatusOr<bool> HasFieldByNumber(int64_t number) const; |
362 | | |
363 | | using ForEachFieldCallback = CustomStructValueInterface::ForEachFieldCallback; |
364 | | |
365 | | absl::Status ForEachField( |
366 | | ForEachFieldCallback callback, |
367 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
368 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
369 | | google::protobuf::Arena* absl_nonnull arena) const; |
370 | | |
371 | | absl::Status Qualify( |
372 | | absl::Span<const SelectQualifier> qualifiers, bool presence_test, |
373 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
374 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
375 | | google::protobuf::Arena* absl_nonnull arena, Value* absl_nonnull result, |
376 | | int* absl_nonnull count) const; |
377 | | using StructValueMixin::Qualify; |
378 | | |
379 | 0 | const CustomStructValueDispatcher* absl_nullable dispatcher() const { |
380 | 0 | return dispatcher_; |
381 | 0 | } |
382 | | |
383 | 0 | CustomStructValueContent content() const { |
384 | 0 | ABSL_DCHECK(dispatcher_ != nullptr); |
385 | 0 | return content_; |
386 | 0 | } |
387 | | |
388 | 0 | const CustomStructValueInterface* absl_nullable interface() const { |
389 | 0 | if (dispatcher_ == nullptr) { |
390 | 0 | return content_.To<CustomStructValueInterface::Content>().interface; |
391 | 0 | } |
392 | 0 | return nullptr; |
393 | 0 | } |
394 | | |
395 | 0 | explicit operator bool() const { |
396 | 0 | if (dispatcher_ == nullptr) { |
397 | 0 | return content_.To<CustomStructValueInterface::Content>().interface != |
398 | 0 | nullptr; |
399 | 0 | } |
400 | 0 | return true; |
401 | 0 | } |
402 | | |
403 | 0 | friend void swap(CustomStructValue& lhs, CustomStructValue& rhs) noexcept { |
404 | 0 | using std::swap; |
405 | 0 | swap(lhs.dispatcher_, rhs.dispatcher_); |
406 | 0 | swap(lhs.content_, rhs.content_); |
407 | 0 | } |
408 | | |
409 | | private: |
410 | | friend class common_internal::ValueMixin<CustomStructValue>; |
411 | | friend class common_internal::StructValueMixin<CustomStructValue>; |
412 | | friend CustomStructValue UnsafeCustomStructValue( |
413 | | const CustomStructValueDispatcher* absl_nonnull dispatcher |
414 | | ABSL_ATTRIBUTE_LIFETIME_BOUND, |
415 | | CustomStructValueContent content); |
416 | | |
417 | | // Constructs a custom struct value from a dispatcher and content. Only |
418 | | // accessible from `UnsafeCustomStructValue`. |
419 | | CustomStructValue(const CustomStructValueDispatcher* absl_nonnull dispatcher |
420 | | ABSL_ATTRIBUTE_LIFETIME_BOUND, |
421 | | CustomStructValueContent content) |
422 | 0 | : dispatcher_(dispatcher), content_(content) { |
423 | 0 | ABSL_DCHECK(dispatcher != nullptr); |
424 | 0 | ABSL_DCHECK(dispatcher->get_type_id != nullptr); |
425 | 0 | ABSL_DCHECK(dispatcher->get_arena != nullptr); |
426 | 0 | ABSL_DCHECK(dispatcher->get_type_name != nullptr); |
427 | 0 | ABSL_DCHECK(dispatcher->is_zero_value != nullptr); |
428 | 0 | ABSL_DCHECK(dispatcher->get_field_by_name != nullptr); |
429 | 0 | ABSL_DCHECK(dispatcher->has_field_by_name != nullptr); |
430 | 0 | ABSL_DCHECK(dispatcher->for_each_field != nullptr); |
431 | 0 | ABSL_DCHECK(dispatcher->clone != nullptr); |
432 | 0 | } |
433 | | |
434 | | const CustomStructValueDispatcher* absl_nullable dispatcher_ = nullptr; |
435 | | CustomStructValueContent content_ = CustomStructValueContent::Zero(); |
436 | | }; |
437 | | |
438 | | inline std::ostream& operator<<(std::ostream& out, |
439 | 0 | const CustomStructValue& value) { |
440 | 0 | return out << value.DebugString(); |
441 | 0 | } |
442 | | |
443 | | template <> |
444 | | struct NativeTypeTraits<CustomStructValue> final { |
445 | 0 | static NativeTypeId Id(const CustomStructValue& type) { |
446 | 0 | return type.GetTypeId(); |
447 | 0 | } |
448 | | }; |
449 | | |
450 | | inline CustomStructValue UnsafeCustomStructValue( |
451 | | const CustomStructValueDispatcher* absl_nonnull dispatcher |
452 | | ABSL_ATTRIBUTE_LIFETIME_BOUND, |
453 | 0 | CustomStructValueContent content) { |
454 | 0 | return CustomStructValue(dispatcher, content); |
455 | 0 | } |
456 | | |
457 | | } // namespace cel |
458 | | |
459 | | #endif // THIRD_PARTY_CEL_CPP_COMMON_VALUES_PARSED_STRUCT_VALUE_H_ |