/proc/self/cwd/common/values/custom_struct_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 <cstdint> |
16 | | #include <string> |
17 | | |
18 | | #include "absl/base/nullability.h" |
19 | | #include "absl/base/optimization.h" |
20 | | #include "absl/functional/function_ref.h" |
21 | | #include "absl/log/absl_check.h" |
22 | | #include "absl/status/status.h" |
23 | | #include "absl/status/statusor.h" |
24 | | #include "absl/strings/str_cat.h" |
25 | | #include "absl/strings/string_view.h" |
26 | | #include "absl/types/span.h" |
27 | | #include "base/attribute.h" |
28 | | #include "common/native_type.h" |
29 | | #include "common/type.h" |
30 | | #include "common/value.h" |
31 | | #include "common/values/values.h" |
32 | | #include "internal/status_macros.h" |
33 | | #include "internal/well_known_types.h" |
34 | | #include "runtime/runtime_options.h" |
35 | | #include "google/protobuf/arena.h" |
36 | | #include "google/protobuf/descriptor.h" |
37 | | #include "google/protobuf/io/zero_copy_stream.h" |
38 | | #include "google/protobuf/message.h" |
39 | | |
40 | | namespace cel { |
41 | | |
42 | | namespace { |
43 | | |
44 | | using ::cel::well_known_types::ValueReflection; |
45 | | |
46 | | } // namespace |
47 | | |
48 | | absl::Status CustomStructValueInterface::Equal( |
49 | | const StructValue& other, |
50 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
51 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
52 | 0 | google::protobuf::Arena* absl_nonnull arena, Value* absl_nonnull result) const { |
53 | 0 | return common_internal::StructValueEqual(*this, other, descriptor_pool, |
54 | 0 | message_factory, arena, result); |
55 | 0 | } |
56 | | |
57 | | absl::Status CustomStructValueInterface::Qualify( |
58 | | absl::Span<const SelectQualifier> qualifiers, bool presence_test, |
59 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
60 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
61 | | google::protobuf::Arena* absl_nonnull arena, Value* absl_nonnull result, |
62 | 0 | int* absl_nonnull count) const { |
63 | 0 | return absl::UnimplementedError(absl::StrCat( |
64 | 0 | GetTypeName(), " does not implement field selection optimization")); |
65 | 0 | } |
66 | | |
67 | 0 | NativeTypeId CustomStructValue::GetTypeId() const { |
68 | 0 | if (dispatcher_ == nullptr) { |
69 | 0 | CustomStructValueInterface::Content content = |
70 | 0 | content_.To<CustomStructValueInterface::Content>(); |
71 | 0 | if (content.interface == nullptr) { |
72 | 0 | return NativeTypeId(); |
73 | 0 | } |
74 | 0 | return content.interface->GetNativeTypeId(); |
75 | 0 | } |
76 | 0 | return dispatcher_->get_type_id(dispatcher_, content_); |
77 | 0 | } |
78 | | |
79 | 0 | StructType CustomStructValue::GetRuntimeType() const { |
80 | 0 | ABSL_DCHECK(*this); |
81 | |
|
82 | 0 | if (dispatcher_ == nullptr) { |
83 | 0 | CustomStructValueInterface::Content content = |
84 | 0 | content_.To<CustomStructValueInterface::Content>(); |
85 | 0 | ABSL_DCHECK(content.interface != nullptr); |
86 | 0 | return content.interface->GetRuntimeType(); |
87 | 0 | } |
88 | 0 | if (dispatcher_->get_runtime_type != nullptr) { |
89 | 0 | return dispatcher_->get_runtime_type(dispatcher_, content_); |
90 | 0 | } |
91 | 0 | return common_internal::MakeBasicStructType(GetTypeName()); |
92 | 0 | } |
93 | | |
94 | 0 | absl::string_view CustomStructValue::GetTypeName() const { |
95 | 0 | ABSL_DCHECK(*this); |
96 | |
|
97 | 0 | if (dispatcher_ == nullptr) { |
98 | 0 | CustomStructValueInterface::Content content = |
99 | 0 | content_.To<CustomStructValueInterface::Content>(); |
100 | 0 | ABSL_DCHECK(content.interface != nullptr); |
101 | 0 | return content.interface->GetTypeName(); |
102 | 0 | } |
103 | 0 | return dispatcher_->get_type_name(dispatcher_, content_); |
104 | 0 | } |
105 | | |
106 | 0 | std::string CustomStructValue::DebugString() const { |
107 | 0 | ABSL_DCHECK(*this); |
108 | |
|
109 | 0 | if (dispatcher_ == nullptr) { |
110 | 0 | CustomStructValueInterface::Content content = |
111 | 0 | content_.To<CustomStructValueInterface::Content>(); |
112 | 0 | ABSL_DCHECK(content.interface != nullptr); |
113 | 0 | return content.interface->DebugString(); |
114 | 0 | } |
115 | 0 | if (dispatcher_->debug_string != nullptr) { |
116 | 0 | return dispatcher_->debug_string(dispatcher_, content_); |
117 | 0 | } |
118 | 0 | return std::string(GetTypeName()); |
119 | 0 | } |
120 | | |
121 | | absl::Status CustomStructValue::SerializeTo( |
122 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
123 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
124 | 0 | google::protobuf::io::ZeroCopyOutputStream* absl_nonnull output) const { |
125 | 0 | ABSL_DCHECK(*this); |
126 | |
|
127 | 0 | if (dispatcher_ == nullptr) { |
128 | 0 | CustomStructValueInterface::Content content = |
129 | 0 | content_.To<CustomStructValueInterface::Content>(); |
130 | 0 | ABSL_DCHECK(content.interface != nullptr); |
131 | 0 | return content.interface->SerializeTo(descriptor_pool, message_factory, |
132 | 0 | output); |
133 | 0 | } |
134 | 0 | if (dispatcher_->serialize_to != nullptr) { |
135 | 0 | return dispatcher_->serialize_to(dispatcher_, content_, descriptor_pool, |
136 | 0 | message_factory, output); |
137 | 0 | } |
138 | 0 | return absl::UnimplementedError( |
139 | 0 | absl::StrCat(GetTypeName(), " is unserializable")); |
140 | 0 | } |
141 | | |
142 | | absl::Status CustomStructValue::ConvertToJson( |
143 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
144 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
145 | 0 | google::protobuf::Message* absl_nonnull json) const { |
146 | 0 | ABSL_DCHECK(descriptor_pool != nullptr); |
147 | 0 | ABSL_DCHECK(message_factory != nullptr); |
148 | 0 | ABSL_DCHECK(json != nullptr); |
149 | 0 | ABSL_DCHECK_EQ(json->GetDescriptor()->well_known_type(), |
150 | 0 | google::protobuf::Descriptor::WELLKNOWNTYPE_VALUE); |
151 | 0 | ABSL_DCHECK(*this); |
152 | |
|
153 | 0 | ValueReflection value_reflection; |
154 | 0 | CEL_RETURN_IF_ERROR(value_reflection.Initialize(json->GetDescriptor())); |
155 | 0 | google::protobuf::Message* json_object = value_reflection.MutableStructValue(json); |
156 | |
|
157 | 0 | return ConvertToJsonObject(descriptor_pool, message_factory, json_object); |
158 | 0 | } |
159 | | |
160 | | absl::Status CustomStructValue::ConvertToJsonObject( |
161 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
162 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
163 | 0 | google::protobuf::Message* absl_nonnull json) const { |
164 | 0 | ABSL_DCHECK(descriptor_pool != nullptr); |
165 | 0 | ABSL_DCHECK(message_factory != nullptr); |
166 | 0 | ABSL_DCHECK(json != nullptr); |
167 | 0 | ABSL_DCHECK(*this); |
168 | |
|
169 | 0 | if (dispatcher_ == nullptr) { |
170 | 0 | CustomStructValueInterface::Content content = |
171 | 0 | content_.To<CustomStructValueInterface::Content>(); |
172 | 0 | if (ABSL_PREDICT_FALSE(content.interface == nullptr)) { |
173 | 0 | json->Clear(); |
174 | 0 | return absl::OkStatus(); |
175 | 0 | } |
176 | 0 | return content.interface->ConvertToJsonObject(descriptor_pool, |
177 | 0 | message_factory, json); |
178 | 0 | } |
179 | 0 | if (dispatcher_->convert_to_json_object != nullptr) { |
180 | 0 | return dispatcher_->convert_to_json_object( |
181 | 0 | dispatcher_, content_, descriptor_pool, message_factory, json); |
182 | 0 | } |
183 | 0 | return absl::UnimplementedError( |
184 | 0 | absl::StrCat(GetTypeName(), " is not convertable to JSON")); |
185 | 0 | } |
186 | | |
187 | | absl::Status CustomStructValue::Equal( |
188 | | const Value& other, |
189 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
190 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
191 | 0 | google::protobuf::Arena* absl_nonnull arena, Value* absl_nonnull result) const { |
192 | 0 | ABSL_DCHECK(descriptor_pool != nullptr); |
193 | 0 | ABSL_DCHECK(message_factory != nullptr); |
194 | 0 | ABSL_DCHECK(arena != nullptr); |
195 | 0 | ABSL_DCHECK(result != nullptr); |
196 | 0 | ABSL_DCHECK(*this); |
197 | |
|
198 | 0 | if (auto other_struct_value = other.AsStruct(); other_struct_value) { |
199 | 0 | if (dispatcher_ == nullptr) { |
200 | 0 | CustomStructValueInterface::Content content = |
201 | 0 | content_.To<CustomStructValueInterface::Content>(); |
202 | 0 | ABSL_DCHECK(content.interface != nullptr); |
203 | 0 | return content.interface->Equal(*other_struct_value, descriptor_pool, |
204 | 0 | message_factory, arena, result); |
205 | 0 | } |
206 | 0 | if (dispatcher_->equal != nullptr) { |
207 | 0 | return dispatcher_->equal(dispatcher_, content_, *other_struct_value, |
208 | 0 | descriptor_pool, message_factory, arena, |
209 | 0 | result); |
210 | 0 | } |
211 | 0 | return common_internal::StructValueEqual(*this, *other_struct_value, |
212 | 0 | descriptor_pool, message_factory, |
213 | 0 | arena, result); |
214 | 0 | } |
215 | 0 | *result = FalseValue(); |
216 | 0 | return absl::OkStatus(); |
217 | 0 | } |
218 | | |
219 | 0 | bool CustomStructValue::IsZeroValue() const { |
220 | 0 | ABSL_DCHECK(*this); |
221 | |
|
222 | 0 | if (dispatcher_ == nullptr) { |
223 | 0 | CustomStructValueInterface::Content content = |
224 | 0 | content_.To<CustomStructValueInterface::Content>(); |
225 | 0 | if (content.interface == nullptr) { |
226 | 0 | return true; |
227 | 0 | } |
228 | 0 | return content.interface->IsZeroValue(); |
229 | 0 | } |
230 | 0 | return dispatcher_->is_zero_value(dispatcher_, content_); |
231 | 0 | } |
232 | | |
233 | | CustomStructValue CustomStructValue::Clone( |
234 | 0 | google::protobuf::Arena* absl_nonnull arena) const { |
235 | 0 | ABSL_DCHECK(arena != nullptr); |
236 | 0 | ABSL_DCHECK(*this); |
237 | |
|
238 | 0 | if (dispatcher_ == nullptr) { |
239 | 0 | CustomStructValueInterface::Content content = |
240 | 0 | content_.To<CustomStructValueInterface::Content>(); |
241 | 0 | if (content.interface == nullptr) { |
242 | 0 | return *this; |
243 | 0 | } |
244 | 0 | if (content.arena != arena) { |
245 | 0 | return content.interface->Clone(arena); |
246 | 0 | } |
247 | 0 | return *this; |
248 | 0 | } |
249 | 0 | return dispatcher_->clone(dispatcher_, content_, arena); |
250 | 0 | } |
251 | | |
252 | | absl::Status CustomStructValue::GetFieldByName( |
253 | | absl::string_view name, ProtoWrapperTypeOptions unboxing_options, |
254 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
255 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
256 | 0 | google::protobuf::Arena* absl_nonnull arena, Value* absl_nonnull result) const { |
257 | 0 | ABSL_DCHECK(descriptor_pool != nullptr); |
258 | 0 | ABSL_DCHECK(message_factory != nullptr); |
259 | 0 | ABSL_DCHECK(arena != nullptr); |
260 | 0 | ABSL_DCHECK(result != nullptr); |
261 | 0 | ABSL_DCHECK(*this); |
262 | |
|
263 | 0 | if (dispatcher_ == nullptr) { |
264 | 0 | CustomStructValueInterface::Content content = |
265 | 0 | content_.To<CustomStructValueInterface::Content>(); |
266 | 0 | ABSL_DCHECK(content.interface != nullptr); |
267 | 0 | return content.interface->GetFieldByName(name, unboxing_options, |
268 | 0 | descriptor_pool, message_factory, |
269 | 0 | arena, result); |
270 | 0 | } |
271 | 0 | return dispatcher_->get_field_by_name(dispatcher_, content_, name, |
272 | 0 | unboxing_options, descriptor_pool, |
273 | 0 | message_factory, arena, result); |
274 | 0 | } |
275 | | |
276 | | absl::Status CustomStructValue::GetFieldByNumber( |
277 | | int64_t number, ProtoWrapperTypeOptions unboxing_options, |
278 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
279 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
280 | 0 | google::protobuf::Arena* absl_nonnull arena, Value* absl_nonnull result) const { |
281 | 0 | ABSL_DCHECK(descriptor_pool != nullptr); |
282 | 0 | ABSL_DCHECK(message_factory != nullptr); |
283 | 0 | ABSL_DCHECK(arena != nullptr); |
284 | 0 | ABSL_DCHECK(result != nullptr); |
285 | 0 | ABSL_DCHECK(*this); |
286 | |
|
287 | 0 | if (dispatcher_ == nullptr) { |
288 | 0 | CustomStructValueInterface::Content content = |
289 | 0 | content_.To<CustomStructValueInterface::Content>(); |
290 | 0 | ABSL_DCHECK(content.interface != nullptr); |
291 | 0 | return content.interface->GetFieldByNumber(number, unboxing_options, |
292 | 0 | descriptor_pool, message_factory, |
293 | 0 | arena, result); |
294 | 0 | } |
295 | 0 | if (dispatcher_->get_field_by_number != nullptr) { |
296 | 0 | return dispatcher_->get_field_by_number(dispatcher_, content_, number, |
297 | 0 | unboxing_options, descriptor_pool, |
298 | 0 | message_factory, arena, result); |
299 | 0 | } |
300 | 0 | return absl::UnimplementedError(absl::StrCat( |
301 | 0 | GetTypeName(), " does not implement access by field number")); |
302 | 0 | } |
303 | | |
304 | | absl::StatusOr<bool> CustomStructValue::HasFieldByName( |
305 | 0 | absl::string_view name) const { |
306 | 0 | ABSL_DCHECK(*this); |
307 | |
|
308 | 0 | if (dispatcher_ == nullptr) { |
309 | 0 | CustomStructValueInterface::Content content = |
310 | 0 | content_.To<CustomStructValueInterface::Content>(); |
311 | 0 | ABSL_DCHECK(content.interface != nullptr); |
312 | 0 | return content.interface->HasFieldByName(name); |
313 | 0 | } |
314 | 0 | return dispatcher_->has_field_by_name(dispatcher_, content_, name); |
315 | 0 | } |
316 | | |
317 | 0 | absl::StatusOr<bool> CustomStructValue::HasFieldByNumber(int64_t number) const { |
318 | 0 | ABSL_DCHECK(*this); |
319 | |
|
320 | 0 | if (dispatcher_ == nullptr) { |
321 | 0 | CustomStructValueInterface::Content content = |
322 | 0 | content_.To<CustomStructValueInterface::Content>(); |
323 | 0 | ABSL_DCHECK(content.interface != nullptr); |
324 | 0 | return content.interface->HasFieldByNumber(number); |
325 | 0 | } |
326 | 0 | if (dispatcher_->has_field_by_number != nullptr) { |
327 | 0 | return dispatcher_->has_field_by_number(dispatcher_, content_, number); |
328 | 0 | } |
329 | 0 | return absl::UnimplementedError(absl::StrCat( |
330 | 0 | GetTypeName(), " does not implement access by field number")); |
331 | 0 | } |
332 | | |
333 | | absl::Status CustomStructValue::ForEachField( |
334 | | ForEachFieldCallback callback, |
335 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
336 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
337 | 0 | google::protobuf::Arena* absl_nonnull arena) const { |
338 | 0 | ABSL_DCHECK(descriptor_pool != nullptr); |
339 | 0 | ABSL_DCHECK(message_factory != nullptr); |
340 | 0 | ABSL_DCHECK(arena != nullptr); |
341 | 0 | ABSL_DCHECK(*this); |
342 | |
|
343 | 0 | if (dispatcher_ == nullptr) { |
344 | 0 | CustomStructValueInterface::Content content = |
345 | 0 | content_.To<CustomStructValueInterface::Content>(); |
346 | 0 | ABSL_DCHECK(content.interface != nullptr); |
347 | 0 | return content.interface->ForEachField(callback, descriptor_pool, |
348 | 0 | message_factory, arena); |
349 | 0 | } |
350 | 0 | return dispatcher_->for_each_field(dispatcher_, content_, callback, |
351 | 0 | descriptor_pool, message_factory, arena); |
352 | 0 | } |
353 | | |
354 | | absl::Status CustomStructValue::Qualify( |
355 | | absl::Span<const SelectQualifier> qualifiers, bool presence_test, |
356 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
357 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
358 | | google::protobuf::Arena* absl_nonnull arena, Value* absl_nonnull result, |
359 | 0 | int* absl_nonnull count) const { |
360 | 0 | ABSL_DCHECK_GT(qualifiers.size(), 0); |
361 | 0 | ABSL_DCHECK(descriptor_pool != nullptr); |
362 | 0 | ABSL_DCHECK(message_factory != nullptr); |
363 | 0 | ABSL_DCHECK(arena != nullptr); |
364 | 0 | ABSL_DCHECK(result != nullptr); |
365 | 0 | ABSL_DCHECK(count != nullptr); |
366 | 0 | ABSL_DCHECK(*this); |
367 | |
|
368 | 0 | if (dispatcher_ == nullptr) { |
369 | 0 | CustomStructValueInterface::Content content = |
370 | 0 | content_.To<CustomStructValueInterface::Content>(); |
371 | 0 | ABSL_DCHECK(content.interface != nullptr); |
372 | 0 | return content.interface->Qualify(qualifiers, presence_test, |
373 | 0 | descriptor_pool, message_factory, arena, |
374 | 0 | result, count); |
375 | 0 | } |
376 | 0 | if (dispatcher_->qualify != nullptr) { |
377 | 0 | return dispatcher_->qualify(dispatcher_, content_, qualifiers, |
378 | 0 | presence_test, descriptor_pool, message_factory, |
379 | 0 | arena, result, count); |
380 | 0 | } |
381 | 0 | return absl::UnimplementedError(absl::StrCat( |
382 | 0 | GetTypeName(), " does not implement field selection optimization")); |
383 | 0 | } |
384 | | |
385 | | } // namespace cel |