/proc/self/cwd/common/values/custom_map_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 <memory> |
17 | | #include <string> |
18 | | |
19 | | #include "absl/base/attributes.h" |
20 | | #include "absl/base/no_destructor.h" |
21 | | #include "absl/base/nullability.h" |
22 | | #include "absl/base/optimization.h" |
23 | | #include "absl/log/absl_check.h" |
24 | | #include "absl/status/status.h" |
25 | | #include "absl/status/statusor.h" |
26 | | #include "absl/strings/str_cat.h" |
27 | | #include "absl/strings/string_view.h" |
28 | | #include "absl/types/optional.h" |
29 | | #include "common/native_type.h" |
30 | | #include "common/value.h" |
31 | | #include "common/value_kind.h" |
32 | | #include "common/values/list_value_builder.h" |
33 | | #include "common/values/map_value_builder.h" |
34 | | #include "common/values/values.h" |
35 | | #include "eval/public/cel_value.h" |
36 | | #include "internal/status_macros.h" |
37 | | #include "internal/well_known_types.h" |
38 | | #include "google/protobuf/arena.h" |
39 | | #include "google/protobuf/descriptor.h" |
40 | | #include "google/protobuf/io/zero_copy_stream.h" |
41 | | #include "google/protobuf/message.h" |
42 | | |
43 | | namespace cel { |
44 | | |
45 | | namespace { |
46 | | |
47 | | using ::cel::well_known_types::StructReflection; |
48 | | using ::cel::well_known_types::ValueReflection; |
49 | | using ::google::api::expr::runtime::CelList; |
50 | | using ::google::api::expr::runtime::CelValue; |
51 | | |
52 | 1.96k | absl::Status NoSuchKeyError(const Value& key) { |
53 | 1.96k | return absl::NotFoundError( |
54 | 1.96k | absl::StrCat("Key not found in map : ", key.DebugString())); |
55 | 1.96k | } |
56 | | |
57 | 2 | absl::Status InvalidMapKeyTypeError(ValueKind kind) { |
58 | 2 | return absl::InvalidArgumentError( |
59 | 2 | absl::StrCat("Invalid map key type: '", ValueKindToString(kind), "'")); |
60 | 2 | } |
61 | | |
62 | | class EmptyMapValue final : public common_internal::CompatMapValue { |
63 | | public: |
64 | 6.15k | static const EmptyMapValue& Get() { |
65 | 6.15k | static const absl::NoDestructor<EmptyMapValue> empty; |
66 | 6.15k | return *empty; |
67 | 6.15k | } |
68 | | |
69 | 1 | EmptyMapValue() = default; |
70 | | |
71 | 0 | std::string DebugString() const override { return "{}"; } |
72 | | |
73 | 0 | bool IsEmpty() const override { return true; } |
74 | | |
75 | 28 | size_t Size() const override { return 0; } |
76 | | |
77 | | absl::Status ListKeys( |
78 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
79 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
80 | | google::protobuf::Arena* absl_nonnull arena, |
81 | 0 | ListValue* absl_nonnull result) const override { |
82 | 0 | *result = ListValue(); |
83 | 0 | return absl::OkStatus(); |
84 | 0 | } |
85 | | |
86 | 12 | absl::StatusOr<absl_nonnull ValueIteratorPtr> NewIterator() const override { |
87 | 12 | return NewEmptyValueIterator(); |
88 | 12 | } |
89 | | |
90 | | absl::Status ConvertToJsonObject( |
91 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
92 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
93 | 0 | google::protobuf::Message* absl_nonnull json) const override { |
94 | 0 | ABSL_DCHECK(descriptor_pool != nullptr); |
95 | 0 | ABSL_DCHECK(message_factory != nullptr); |
96 | 0 | ABSL_DCHECK(json != nullptr); |
97 | 0 | ABSL_DCHECK_EQ(json->GetDescriptor()->well_known_type(), |
98 | 0 | google::protobuf::Descriptor::WELLKNOWNTYPE_STRUCT); |
99 | |
|
100 | 0 | json->Clear(); |
101 | 0 | return absl::OkStatus(); |
102 | 0 | } |
103 | | |
104 | 0 | CustomMapValue Clone(google::protobuf::Arena* absl_nonnull) const override { |
105 | 0 | return CustomMapValue(); |
106 | 0 | } |
107 | | |
108 | 0 | absl::optional<CelValue> operator[](CelValue key) const override { |
109 | 0 | return absl::nullopt; |
110 | 0 | } |
111 | | |
112 | | using CompatMapValue::Get; |
113 | | absl::optional<CelValue> Get(google::protobuf::Arena* arena, |
114 | 0 | CelValue key) const override { |
115 | 0 | return absl::nullopt; |
116 | 0 | } |
117 | | |
118 | 0 | absl::StatusOr<bool> Has(const CelValue& key) const override { return false; } |
119 | | |
120 | 0 | int size() const override { return static_cast<int>(Size()); } |
121 | | |
122 | 0 | absl::StatusOr<const CelList*> ListKeys() const override { |
123 | 0 | return common_internal::EmptyCompatListValue(); |
124 | 0 | } |
125 | | |
126 | 0 | absl::StatusOr<const CelList*> ListKeys(google::protobuf::Arena*) const override { |
127 | 0 | return ListKeys(); |
128 | 0 | } |
129 | | |
130 | | private: |
131 | | absl::StatusOr<bool> Find( |
132 | | const Value& key, |
133 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
134 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
135 | | google::protobuf::Arena* absl_nonnull arena, |
136 | 4.68k | Value* absl_nonnull result) const override { |
137 | 4.68k | return false; |
138 | 4.68k | } |
139 | | |
140 | | absl::StatusOr<bool> Has( |
141 | | const Value& key, |
142 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
143 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
144 | 425 | google::protobuf::Arena* absl_nonnull arena) const override { |
145 | 425 | return false; |
146 | 425 | } |
147 | | }; |
148 | | |
149 | | } // namespace |
150 | | |
151 | | namespace common_internal { |
152 | | |
153 | 0 | const CompatMapValue* absl_nonnull EmptyCompatMapValue() { |
154 | 0 | return &EmptyMapValue::Get(); |
155 | 0 | } |
156 | | |
157 | | } // namespace common_internal |
158 | | |
159 | | class CustomMapValueInterfaceIterator final : public ValueIterator { |
160 | | public: |
161 | | explicit CustomMapValueInterfaceIterator( |
162 | | const CustomMapValueInterface* absl_nonnull interface) |
163 | 0 | : interface_(interface) {} |
164 | | |
165 | 0 | bool HasNext() override { |
166 | 0 | if (keys_iterator_ == nullptr) { |
167 | 0 | return !interface_->IsEmpty(); |
168 | 0 | } |
169 | 0 | return keys_iterator_->HasNext(); |
170 | 0 | } |
171 | | |
172 | | absl::Status Next(const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
173 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
174 | | google::protobuf::Arena* absl_nonnull arena, |
175 | 0 | Value* absl_nonnull result) override { |
176 | 0 | if (keys_iterator_ == nullptr) { |
177 | 0 | if (interface_->IsEmpty()) { |
178 | 0 | return absl::FailedPreconditionError( |
179 | 0 | "ValueIterator::Next() called when " |
180 | 0 | "ValueIterator::HasNext() returns false"); |
181 | 0 | } |
182 | 0 | CEL_RETURN_IF_ERROR(ProjectKeys(descriptor_pool, message_factory, arena)); |
183 | 0 | } |
184 | 0 | return keys_iterator_->Next(descriptor_pool, message_factory, arena, |
185 | 0 | result); |
186 | 0 | } |
187 | | |
188 | | absl::StatusOr<bool> Next1( |
189 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
190 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
191 | | google::protobuf::Arena* absl_nonnull arena, |
192 | 0 | Value* absl_nonnull key_or_value) override { |
193 | 0 | ABSL_DCHECK(descriptor_pool != nullptr); |
194 | 0 | ABSL_DCHECK(message_factory != nullptr); |
195 | 0 | ABSL_DCHECK(arena != nullptr); |
196 | 0 | ABSL_DCHECK(key_or_value != nullptr); |
197 | |
|
198 | 0 | if (keys_iterator_ == nullptr) { |
199 | 0 | if (interface_->IsEmpty()) { |
200 | 0 | return false; |
201 | 0 | } |
202 | 0 | CEL_RETURN_IF_ERROR(ProjectKeys(descriptor_pool, message_factory, arena)); |
203 | 0 | } |
204 | | |
205 | 0 | return keys_iterator_->Next1(descriptor_pool, message_factory, arena, |
206 | 0 | key_or_value); |
207 | 0 | } |
208 | | |
209 | | absl::StatusOr<bool> Next2( |
210 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
211 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
212 | | google::protobuf::Arena* absl_nonnull arena, Value* absl_nonnull key, |
213 | 0 | Value* absl_nullable value) override { |
214 | 0 | ABSL_DCHECK(descriptor_pool != nullptr); |
215 | 0 | ABSL_DCHECK(message_factory != nullptr); |
216 | 0 | ABSL_DCHECK(arena != nullptr); |
217 | 0 | ABSL_DCHECK(key != nullptr); |
218 | |
|
219 | 0 | if (keys_iterator_ == nullptr) { |
220 | 0 | if (interface_->IsEmpty()) { |
221 | 0 | return false; |
222 | 0 | } |
223 | 0 | CEL_RETURN_IF_ERROR(ProjectKeys(descriptor_pool, message_factory, arena)); |
224 | 0 | } |
225 | | |
226 | 0 | CEL_ASSIGN_OR_RETURN( |
227 | 0 | bool ok, |
228 | 0 | keys_iterator_->Next1(descriptor_pool, message_factory, arena, key)); |
229 | 0 | if (!ok) { |
230 | 0 | return false; |
231 | 0 | } |
232 | 0 | if (value != nullptr) { |
233 | 0 | CEL_ASSIGN_OR_RETURN(ok, interface_->Find(*key, descriptor_pool, |
234 | 0 | message_factory, arena, value)); |
235 | 0 | if (!ok) { |
236 | 0 | return absl::DataLossError( |
237 | 0 | "map iterator returned key that was not present in the map"); |
238 | 0 | } |
239 | 0 | } |
240 | 0 | return true; |
241 | 0 | } |
242 | | |
243 | | private: |
244 | | // Projects the keys from the map, setting `keys_` and `keys_iterator_`. If |
245 | | // this returns OK it is guaranteed that `keys_iterator_` is not null. |
246 | | absl::Status ProjectKeys( |
247 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
248 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
249 | 0 | google::protobuf::Arena* absl_nonnull arena) { |
250 | 0 | ABSL_DCHECK(keys_iterator_ == nullptr); |
251 | |
|
252 | 0 | CEL_RETURN_IF_ERROR( |
253 | 0 | interface_->ListKeys(descriptor_pool, message_factory, arena, &keys_)); |
254 | 0 | CEL_ASSIGN_OR_RETURN(keys_iterator_, keys_.NewIterator()); |
255 | 0 | ABSL_CHECK(keys_iterator_->HasNext()); // Crash OK |
256 | 0 | return absl::OkStatus(); |
257 | 0 | } |
258 | | |
259 | | const CustomMapValueInterface* absl_nonnull const interface_; |
260 | | ListValue keys_; |
261 | | absl_nullable ValueIteratorPtr keys_iterator_; |
262 | | }; |
263 | | |
264 | | namespace { |
265 | | |
266 | | class CustomMapValueDispatcherIterator final : public ValueIterator { |
267 | | public: |
268 | | explicit CustomMapValueDispatcherIterator( |
269 | | const CustomMapValueDispatcher* absl_nonnull dispatcher, |
270 | | CustomMapValueContent content) |
271 | 0 | : dispatcher_(dispatcher), content_(content) {} |
272 | | |
273 | 0 | bool HasNext() override { |
274 | 0 | if (keys_iterator_ == nullptr) { |
275 | 0 | if (dispatcher_->is_empty != nullptr) { |
276 | 0 | return !dispatcher_->is_empty(dispatcher_, content_); |
277 | 0 | } |
278 | 0 | return dispatcher_->size(dispatcher_, content_) != 0; |
279 | 0 | } |
280 | 0 | return keys_iterator_->HasNext(); |
281 | 0 | } |
282 | | |
283 | | absl::Status Next(const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
284 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
285 | | google::protobuf::Arena* absl_nonnull arena, |
286 | 0 | Value* absl_nonnull result) override { |
287 | 0 | if (keys_iterator_ == nullptr) { |
288 | 0 | if (dispatcher_->is_empty != nullptr |
289 | 0 | ? dispatcher_->is_empty(dispatcher_, content_) |
290 | 0 | : dispatcher_->size(dispatcher_, content_) == 0) { |
291 | 0 | return absl::FailedPreconditionError( |
292 | 0 | "ValueIterator::Next() called when " |
293 | 0 | "ValueIterator::HasNext() returns false"); |
294 | 0 | } |
295 | 0 | CEL_RETURN_IF_ERROR(ProjectKeys(descriptor_pool, message_factory, arena)); |
296 | 0 | } |
297 | 0 | return keys_iterator_->Next(descriptor_pool, message_factory, arena, |
298 | 0 | result); |
299 | 0 | } |
300 | | |
301 | | absl::StatusOr<bool> Next1( |
302 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
303 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
304 | | google::protobuf::Arena* absl_nonnull arena, |
305 | 0 | Value* absl_nonnull key_or_value) override { |
306 | 0 | ABSL_DCHECK(descriptor_pool != nullptr); |
307 | 0 | ABSL_DCHECK(message_factory != nullptr); |
308 | 0 | ABSL_DCHECK(arena != nullptr); |
309 | 0 | ABSL_DCHECK(key_or_value != nullptr); |
310 | |
|
311 | 0 | if (keys_iterator_ == nullptr) { |
312 | 0 | if (dispatcher_->is_empty != nullptr |
313 | 0 | ? dispatcher_->is_empty(dispatcher_, content_) |
314 | 0 | : dispatcher_->size(dispatcher_, content_) == 0) { |
315 | 0 | return false; |
316 | 0 | } |
317 | 0 | CEL_RETURN_IF_ERROR(ProjectKeys(descriptor_pool, message_factory, arena)); |
318 | 0 | } |
319 | | |
320 | 0 | return keys_iterator_->Next1(descriptor_pool, message_factory, arena, |
321 | 0 | key_or_value); |
322 | 0 | } |
323 | | |
324 | | absl::StatusOr<bool> Next2( |
325 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
326 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
327 | | google::protobuf::Arena* absl_nonnull arena, Value* absl_nonnull key, |
328 | 0 | Value* absl_nullable value) override { |
329 | 0 | ABSL_DCHECK(descriptor_pool != nullptr); |
330 | 0 | ABSL_DCHECK(message_factory != nullptr); |
331 | 0 | ABSL_DCHECK(arena != nullptr); |
332 | 0 | ABSL_DCHECK(key != nullptr); |
333 | 0 | ABSL_DCHECK(value != nullptr); |
334 | |
|
335 | 0 | if (keys_iterator_ == nullptr) { |
336 | 0 | if (dispatcher_->is_empty != nullptr |
337 | 0 | ? dispatcher_->is_empty(dispatcher_, content_) |
338 | 0 | : dispatcher_->size(dispatcher_, content_) == 0) { |
339 | 0 | return false; |
340 | 0 | } |
341 | 0 | CEL_RETURN_IF_ERROR(ProjectKeys(descriptor_pool, message_factory, arena)); |
342 | 0 | } |
343 | | |
344 | 0 | CEL_ASSIGN_OR_RETURN( |
345 | 0 | bool ok, |
346 | 0 | keys_iterator_->Next1(descriptor_pool, message_factory, arena, key)); |
347 | 0 | if (!ok) { |
348 | 0 | return false; |
349 | 0 | } |
350 | 0 | if (value != nullptr) { |
351 | 0 | CEL_ASSIGN_OR_RETURN( |
352 | 0 | ok, dispatcher_->find(dispatcher_, content_, *key, descriptor_pool, |
353 | 0 | message_factory, arena, value)); |
354 | 0 | if (!ok) { |
355 | 0 | return absl::DataLossError( |
356 | 0 | "map iterator returned key that was not present in the map"); |
357 | 0 | } |
358 | 0 | } |
359 | 0 | return true; |
360 | 0 | } |
361 | | |
362 | | private: |
363 | | absl::Status ProjectKeys( |
364 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
365 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
366 | 0 | google::protobuf::Arena* absl_nonnull arena) { |
367 | 0 | ABSL_DCHECK(keys_iterator_ == nullptr); |
368 | |
|
369 | 0 | CEL_RETURN_IF_ERROR(dispatcher_->list_keys(dispatcher_, content_, |
370 | 0 | descriptor_pool, message_factory, |
371 | 0 | arena, &keys_)); |
372 | 0 | CEL_ASSIGN_OR_RETURN(keys_iterator_, keys_.NewIterator()); |
373 | 0 | ABSL_CHECK(keys_iterator_->HasNext()); // Crash OK |
374 | 0 | return absl::OkStatus(); |
375 | 0 | } |
376 | | |
377 | | const CustomMapValueDispatcher* absl_nonnull const dispatcher_; |
378 | | const CustomMapValueContent content_; |
379 | | ListValue keys_; |
380 | | absl_nullable ValueIteratorPtr keys_iterator_; |
381 | | }; |
382 | | |
383 | | } // namespace |
384 | | |
385 | | absl::Status CustomMapValueInterface::SerializeTo( |
386 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
387 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
388 | 0 | google::protobuf::io::ZeroCopyOutputStream* absl_nonnull output) const { |
389 | 0 | ABSL_DCHECK(descriptor_pool != nullptr); |
390 | 0 | ABSL_DCHECK(message_factory != nullptr); |
391 | 0 | ABSL_DCHECK(output != nullptr); |
392 | |
|
393 | 0 | StructReflection reflection; |
394 | 0 | CEL_RETURN_IF_ERROR(reflection.Initialize(descriptor_pool)); |
395 | 0 | const google::protobuf::Message* prototype = |
396 | 0 | message_factory->GetPrototype(reflection.GetDescriptor()); |
397 | 0 | if (prototype == nullptr) { |
398 | 0 | return absl::UnknownError( |
399 | 0 | absl::StrCat("failed to get message prototype: ", |
400 | 0 | reflection.GetDescriptor()->full_name())); |
401 | 0 | } |
402 | 0 | google::protobuf::Arena arena; |
403 | 0 | google::protobuf::Message* message = prototype->New(&arena); |
404 | 0 | CEL_RETURN_IF_ERROR( |
405 | 0 | ConvertToJsonObject(descriptor_pool, message_factory, message)); |
406 | 0 | if (!message->SerializePartialToZeroCopyStream(output)) { |
407 | 0 | return absl::UnknownError( |
408 | 0 | "failed to serialize message: google.protobuf.Struct"); |
409 | 0 | } |
410 | 0 | return absl::OkStatus(); |
411 | 0 | } |
412 | | |
413 | | absl::Status CustomMapValueInterface::ForEach( |
414 | | ForEachCallback callback, |
415 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
416 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
417 | 0 | google::protobuf::Arena* absl_nonnull arena) const { |
418 | 0 | CEL_ASSIGN_OR_RETURN(auto iterator, NewIterator()); |
419 | 0 | while (iterator->HasNext()) { |
420 | 0 | Value key; |
421 | 0 | Value value; |
422 | 0 | CEL_RETURN_IF_ERROR( |
423 | 0 | iterator->Next(descriptor_pool, message_factory, arena, &key)); |
424 | 0 | CEL_ASSIGN_OR_RETURN( |
425 | 0 | bool found, Find(key, descriptor_pool, message_factory, arena, &value)); |
426 | 0 | if (!found) { |
427 | 0 | value = ErrorValue(NoSuchKeyError(key)); |
428 | 0 | } |
429 | 0 | CEL_ASSIGN_OR_RETURN(auto ok, callback(key, value)); |
430 | 0 | if (!ok) { |
431 | 0 | break; |
432 | 0 | } |
433 | 0 | } |
434 | 0 | return absl::OkStatus(); |
435 | 0 | } |
436 | | |
437 | | absl::StatusOr<absl_nonnull ValueIteratorPtr> |
438 | 0 | CustomMapValueInterface::NewIterator() const { |
439 | 0 | return std::make_unique<CustomMapValueInterfaceIterator>(this); |
440 | 0 | } |
441 | | |
442 | | absl::Status CustomMapValueInterface::Equal( |
443 | | const MapValue& other, |
444 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
445 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
446 | 11 | google::protobuf::Arena* absl_nonnull arena, Value* absl_nonnull result) const { |
447 | 11 | return MapValueEqual(*this, other, descriptor_pool, message_factory, arena, |
448 | 11 | result); |
449 | 11 | } |
450 | | |
451 | 6.15k | CustomMapValue::CustomMapValue() { |
452 | 6.15k | content_ = CustomMapValueContent::From(CustomMapValueInterface::Content{ |
453 | 6.15k | .interface = &EmptyMapValue::Get(), .arena = nullptr}); |
454 | 6.15k | } |
455 | | |
456 | 43 | NativeTypeId CustomMapValue::GetTypeId() const { |
457 | 43 | if (dispatcher_ == nullptr) { |
458 | 43 | CustomMapValueInterface::Content content = |
459 | 43 | content_.To<CustomMapValueInterface::Content>(); |
460 | 43 | ABSL_DCHECK(content.interface != nullptr); |
461 | 43 | return content.interface->GetNativeTypeId(); |
462 | 43 | } |
463 | 0 | return dispatcher_->get_type_id(dispatcher_, content_); |
464 | 43 | } |
465 | | |
466 | 0 | absl::string_view CustomMapValue::GetTypeName() const { return "map"; } |
467 | | |
468 | 0 | std::string CustomMapValue::DebugString() const { |
469 | 0 | if (dispatcher_ == nullptr) { |
470 | 0 | CustomMapValueInterface::Content content = |
471 | 0 | content_.To<CustomMapValueInterface::Content>(); |
472 | 0 | ABSL_DCHECK(content.interface != nullptr); |
473 | 0 | return content.interface->DebugString(); |
474 | 0 | } |
475 | 0 | if (dispatcher_->debug_string != nullptr) { |
476 | 0 | return dispatcher_->debug_string(dispatcher_, content_); |
477 | 0 | } |
478 | 0 | return "map"; |
479 | 0 | } |
480 | | |
481 | | absl::Status CustomMapValue::SerializeTo( |
482 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
483 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
484 | 0 | google::protobuf::io::ZeroCopyOutputStream* absl_nonnull output) const { |
485 | 0 | if (dispatcher_ == nullptr) { |
486 | 0 | CustomMapValueInterface::Content content = |
487 | 0 | content_.To<CustomMapValueInterface::Content>(); |
488 | 0 | ABSL_DCHECK(content.interface != nullptr); |
489 | 0 | return content.interface->SerializeTo(descriptor_pool, message_factory, |
490 | 0 | output); |
491 | 0 | } |
492 | 0 | if (dispatcher_->serialize_to != nullptr) { |
493 | 0 | return dispatcher_->serialize_to(dispatcher_, content_, descriptor_pool, |
494 | 0 | message_factory, output); |
495 | 0 | } |
496 | 0 | return absl::UnimplementedError( |
497 | 0 | absl::StrCat(GetTypeName(), " is unserializable")); |
498 | 0 | } |
499 | | |
500 | | absl::Status CustomMapValue::ConvertToJson( |
501 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
502 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
503 | 0 | google::protobuf::Message* absl_nonnull json) const { |
504 | 0 | ABSL_DCHECK(descriptor_pool != nullptr); |
505 | 0 | ABSL_DCHECK(message_factory != nullptr); |
506 | 0 | ABSL_DCHECK(json != nullptr); |
507 | 0 | ABSL_DCHECK_EQ(json->GetDescriptor()->well_known_type(), |
508 | 0 | google::protobuf::Descriptor::WELLKNOWNTYPE_VALUE); |
509 | |
|
510 | 0 | ValueReflection value_reflection; |
511 | 0 | CEL_RETURN_IF_ERROR(value_reflection.Initialize(json->GetDescriptor())); |
512 | 0 | google::protobuf::Message* json_object = value_reflection.MutableStructValue(json); |
513 | |
|
514 | 0 | return ConvertToJsonObject(descriptor_pool, message_factory, json_object); |
515 | 0 | } |
516 | | |
517 | | absl::Status CustomMapValue::ConvertToJsonObject( |
518 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
519 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
520 | 0 | google::protobuf::Message* absl_nonnull json) const { |
521 | 0 | ABSL_DCHECK(descriptor_pool != nullptr); |
522 | 0 | ABSL_DCHECK(message_factory != nullptr); |
523 | 0 | ABSL_DCHECK(json != nullptr); |
524 | 0 | ABSL_DCHECK_EQ(json->GetDescriptor()->well_known_type(), |
525 | 0 | google::protobuf::Descriptor::WELLKNOWNTYPE_STRUCT); |
526 | |
|
527 | 0 | if (dispatcher_ == nullptr) { |
528 | 0 | CustomMapValueInterface::Content content = |
529 | 0 | content_.To<CustomMapValueInterface::Content>(); |
530 | 0 | ABSL_DCHECK(content.interface != nullptr); |
531 | 0 | return content.interface->ConvertToJsonObject(descriptor_pool, |
532 | 0 | message_factory, json); |
533 | 0 | } |
534 | 0 | if (dispatcher_->convert_to_json_object != nullptr) { |
535 | 0 | return dispatcher_->convert_to_json_object( |
536 | 0 | dispatcher_, content_, descriptor_pool, message_factory, json); |
537 | 0 | } |
538 | 0 | return absl::UnimplementedError( |
539 | 0 | absl::StrCat(GetTypeName(), " is not convertable to JSON")); |
540 | 0 | } |
541 | | |
542 | | absl::Status CustomMapValue::Equal( |
543 | | const Value& other, |
544 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
545 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
546 | 46 | google::protobuf::Arena* absl_nonnull arena, Value* absl_nonnull result) const { |
547 | 46 | ABSL_DCHECK(descriptor_pool != nullptr); |
548 | 46 | ABSL_DCHECK(message_factory != nullptr); |
549 | 46 | ABSL_DCHECK(arena != nullptr); |
550 | 46 | ABSL_DCHECK(result != nullptr); |
551 | | |
552 | 46 | if (auto other_map_value = other.AsMap(); other_map_value) { |
553 | 11 | if (dispatcher_ == nullptr) { |
554 | 11 | CustomMapValueInterface::Content content = |
555 | 11 | content_.To<CustomMapValueInterface::Content>(); |
556 | 11 | ABSL_DCHECK(content.interface != nullptr); |
557 | 11 | return content.interface->Equal(*other_map_value, descriptor_pool, |
558 | 11 | message_factory, arena, result); |
559 | 11 | } |
560 | 0 | if (dispatcher_->equal != nullptr) { |
561 | 0 | return dispatcher_->equal(dispatcher_, content_, *other_map_value, |
562 | 0 | descriptor_pool, message_factory, arena, |
563 | 0 | result); |
564 | 0 | } |
565 | 0 | return common_internal::MapValueEqual(*this, *other_map_value, |
566 | 0 | descriptor_pool, message_factory, |
567 | 0 | arena, result); |
568 | 0 | } |
569 | 35 | *result = FalseValue(); |
570 | 35 | return absl::OkStatus(); |
571 | 46 | } |
572 | | |
573 | 0 | bool CustomMapValue::IsZeroValue() const { |
574 | 0 | if (dispatcher_ == nullptr) { |
575 | 0 | CustomMapValueInterface::Content content = |
576 | 0 | content_.To<CustomMapValueInterface::Content>(); |
577 | 0 | ABSL_DCHECK(content.interface != nullptr); |
578 | 0 | return content.interface->IsZeroValue(); |
579 | 0 | } |
580 | 0 | return dispatcher_->is_zero_value(dispatcher_, content_); |
581 | 0 | } |
582 | | |
583 | 0 | CustomMapValue CustomMapValue::Clone(google::protobuf::Arena* absl_nonnull arena) const { |
584 | 0 | ABSL_DCHECK(arena != nullptr); |
585 | |
|
586 | 0 | if (dispatcher_ == nullptr) { |
587 | 0 | CustomMapValueInterface::Content content = |
588 | 0 | content_.To<CustomMapValueInterface::Content>(); |
589 | 0 | ABSL_DCHECK(content.interface != nullptr); |
590 | 0 | if (content.arena != arena) { |
591 | 0 | return content.interface->Clone(arena); |
592 | 0 | } |
593 | 0 | return *this; |
594 | 0 | } |
595 | 0 | return dispatcher_->clone(dispatcher_, content_, arena); |
596 | 0 | } |
597 | | |
598 | 0 | bool CustomMapValue::IsEmpty() const { |
599 | 0 | if (dispatcher_ == nullptr) { |
600 | 0 | CustomMapValueInterface::Content content = |
601 | 0 | content_.To<CustomMapValueInterface::Content>(); |
602 | 0 | ABSL_DCHECK(content.interface != nullptr); |
603 | 0 | return content.interface->IsEmpty(); |
604 | 0 | } |
605 | 0 | if (dispatcher_->is_empty != nullptr) { |
606 | 0 | return dispatcher_->is_empty(dispatcher_, content_); |
607 | 0 | } |
608 | 0 | return dispatcher_->size(dispatcher_, content_) == 0; |
609 | 0 | } |
610 | | |
611 | 110 | size_t CustomMapValue::Size() const { |
612 | 110 | if (dispatcher_ == nullptr) { |
613 | 110 | CustomMapValueInterface::Content content = |
614 | 110 | content_.To<CustomMapValueInterface::Content>(); |
615 | 110 | ABSL_DCHECK(content.interface != nullptr); |
616 | 110 | return content.interface->Size(); |
617 | 110 | } |
618 | 0 | return dispatcher_->size(dispatcher_, content_); |
619 | 110 | } |
620 | | |
621 | | absl::Status CustomMapValue::Get( |
622 | | const Value& key, |
623 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
624 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
625 | 1.98k | google::protobuf::Arena* absl_nonnull arena, Value* absl_nonnull result) const { |
626 | 1.98k | ABSL_DCHECK(descriptor_pool != nullptr); |
627 | 1.98k | ABSL_DCHECK(message_factory != nullptr); |
628 | 1.98k | ABSL_DCHECK(arena != nullptr); |
629 | 1.98k | ABSL_DCHECK(result != nullptr); |
630 | | |
631 | 3.96k | CEL_ASSIGN_OR_RETURN( |
632 | 3.96k | bool ok, Find(key, descriptor_pool, message_factory, arena, result)); |
633 | 3.96k | if (ABSL_PREDICT_FALSE(!ok)) { |
634 | 1.96k | switch (result->kind()) { |
635 | 0 | case ValueKind::kError: |
636 | 0 | ABSL_FALLTHROUGH_INTENDED; |
637 | 0 | case ValueKind::kUnknown: |
638 | 0 | break; |
639 | 1.96k | default: |
640 | 1.96k | *result = ErrorValue(NoSuchKeyError(key)); |
641 | 1.96k | break; |
642 | 1.96k | } |
643 | 1.96k | } |
644 | 1.98k | return absl::OkStatus(); |
645 | 3.96k | } |
646 | | |
647 | | absl::StatusOr<bool> CustomMapValue::Find( |
648 | | const Value& key, |
649 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
650 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
651 | 5.36k | google::protobuf::Arena* absl_nonnull arena, Value* absl_nonnull result) const { |
652 | 5.36k | ABSL_DCHECK(descriptor_pool != nullptr); |
653 | 5.36k | ABSL_DCHECK(message_factory != nullptr); |
654 | 5.36k | ABSL_DCHECK(arena != nullptr); |
655 | 5.36k | ABSL_DCHECK(result != nullptr); |
656 | | |
657 | 5.36k | switch (key.kind()) { |
658 | 0 | case ValueKind::kError: |
659 | 0 | ABSL_FALLTHROUGH_INTENDED; |
660 | 0 | case ValueKind::kUnknown: |
661 | 0 | *result = key; |
662 | 0 | return false; |
663 | 93 | case ValueKind::kBool: |
664 | 93 | ABSL_FALLTHROUGH_INTENDED; |
665 | 1.62k | case ValueKind::kInt: |
666 | 1.62k | ABSL_FALLTHROUGH_INTENDED; |
667 | 3.48k | case ValueKind::kUint: |
668 | 3.48k | ABSL_FALLTHROUGH_INTENDED; |
669 | 5.36k | case ValueKind::kString: |
670 | 5.36k | break; |
671 | 0 | default: |
672 | 0 | *result = ErrorValue(InvalidMapKeyTypeError(key.kind())); |
673 | 0 | return false; |
674 | 5.36k | } |
675 | | |
676 | 5.36k | bool ok; |
677 | 5.36k | if (dispatcher_ == nullptr) { |
678 | 5.36k | CustomMapValueInterface::Content content = |
679 | 5.36k | content_.To<CustomMapValueInterface::Content>(); |
680 | 5.36k | ABSL_DCHECK(content.interface != nullptr); |
681 | 10.7k | CEL_ASSIGN_OR_RETURN( |
682 | 10.7k | ok, content.interface->Find(key, descriptor_pool, message_factory, |
683 | 10.7k | arena, result)); |
684 | 10.7k | } else { |
685 | 0 | CEL_ASSIGN_OR_RETURN( |
686 | 0 | ok, dispatcher_->find(dispatcher_, content_, key, descriptor_pool, |
687 | 0 | message_factory, arena, result)); |
688 | 0 | } |
689 | 5.36k | if (ok) { |
690 | 30 | return true; |
691 | 30 | } |
692 | 5.33k | *result = NullValue{}; |
693 | 5.33k | return false; |
694 | 5.36k | } |
695 | | |
696 | | absl::Status CustomMapValue::Has( |
697 | | const Value& key, |
698 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
699 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
700 | 435 | google::protobuf::Arena* absl_nonnull arena, Value* absl_nonnull result) const { |
701 | 435 | ABSL_DCHECK(descriptor_pool != nullptr); |
702 | 435 | ABSL_DCHECK(message_factory != nullptr); |
703 | 435 | ABSL_DCHECK(arena != nullptr); |
704 | 435 | ABSL_DCHECK(result != nullptr); |
705 | | |
706 | 435 | switch (key.kind()) { |
707 | 0 | case ValueKind::kError: |
708 | 0 | ABSL_FALLTHROUGH_INTENDED; |
709 | 0 | case ValueKind::kUnknown: |
710 | 0 | *result = key; |
711 | 0 | return absl::OkStatus(); |
712 | 308 | case ValueKind::kBool: |
713 | 308 | ABSL_FALLTHROUGH_INTENDED; |
714 | 369 | case ValueKind::kInt: |
715 | 369 | ABSL_FALLTHROUGH_INTENDED; |
716 | 432 | case ValueKind::kUint: |
717 | 432 | ABSL_FALLTHROUGH_INTENDED; |
718 | 433 | case ValueKind::kString: |
719 | 433 | break; |
720 | 2 | default: |
721 | 2 | *result = ErrorValue(InvalidMapKeyTypeError(key.kind())); |
722 | 2 | return absl::OkStatus(); |
723 | 435 | } |
724 | 433 | bool has; |
725 | 433 | if (dispatcher_ == nullptr) { |
726 | 433 | CustomMapValueInterface::Content content = |
727 | 433 | content_.To<CustomMapValueInterface::Content>(); |
728 | 433 | ABSL_DCHECK(content.interface != nullptr); |
729 | 866 | CEL_ASSIGN_OR_RETURN(has, content.interface->Has(key, descriptor_pool, |
730 | 866 | message_factory, arena)); |
731 | 866 | } else { |
732 | 0 | CEL_ASSIGN_OR_RETURN( |
733 | 0 | has, dispatcher_->has(dispatcher_, content_, key, descriptor_pool, |
734 | 0 | message_factory, arena)); |
735 | 0 | } |
736 | 433 | *result = BoolValue(has); |
737 | 433 | return absl::OkStatus(); |
738 | 433 | } |
739 | | |
740 | | absl::Status CustomMapValue::ListKeys( |
741 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
742 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
743 | 0 | google::protobuf::Arena* absl_nonnull arena, ListValue* absl_nonnull result) const { |
744 | 0 | ABSL_DCHECK(descriptor_pool != nullptr); |
745 | 0 | ABSL_DCHECK(message_factory != nullptr); |
746 | 0 | ABSL_DCHECK(arena != nullptr); |
747 | 0 | ABSL_DCHECK(result != nullptr); |
748 | |
|
749 | 0 | if (dispatcher_ == nullptr) { |
750 | 0 | CustomMapValueInterface::Content content = |
751 | 0 | content_.To<CustomMapValueInterface::Content>(); |
752 | 0 | ABSL_DCHECK(content.interface != nullptr); |
753 | 0 | return content.interface->ListKeys(descriptor_pool, message_factory, arena, |
754 | 0 | result); |
755 | 0 | } |
756 | 0 | return dispatcher_->list_keys(dispatcher_, content_, descriptor_pool, |
757 | 0 | message_factory, arena, result); |
758 | 0 | } |
759 | | |
760 | | absl::Status CustomMapValue::ForEach( |
761 | | ForEachCallback callback, |
762 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
763 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
764 | 0 | google::protobuf::Arena* absl_nonnull arena) const { |
765 | 0 | ABSL_DCHECK(descriptor_pool != nullptr); |
766 | 0 | ABSL_DCHECK(message_factory != nullptr); |
767 | 0 | ABSL_DCHECK(arena != nullptr); |
768 | |
|
769 | 0 | if (dispatcher_ == nullptr) { |
770 | 0 | CustomMapValueInterface::Content content = |
771 | 0 | content_.To<CustomMapValueInterface::Content>(); |
772 | 0 | ABSL_DCHECK(content.interface != nullptr); |
773 | 0 | return content.interface->ForEach(callback, descriptor_pool, |
774 | 0 | message_factory, arena); |
775 | 0 | } |
776 | 0 | if (dispatcher_->for_each != nullptr) { |
777 | 0 | return dispatcher_->for_each(dispatcher_, content_, callback, |
778 | 0 | descriptor_pool, message_factory, arena); |
779 | 0 | } |
780 | 0 | absl_nonnull ValueIteratorPtr iterator; |
781 | 0 | if (dispatcher_->new_iterator != nullptr) { |
782 | 0 | CEL_ASSIGN_OR_RETURN(iterator, |
783 | 0 | dispatcher_->new_iterator(dispatcher_, content_)); |
784 | 0 | } else { |
785 | 0 | iterator = std::make_unique<CustomMapValueDispatcherIterator>(dispatcher_, |
786 | 0 | content_); |
787 | 0 | } |
788 | 0 | while (iterator->HasNext()) { |
789 | 0 | Value key; |
790 | 0 | Value value; |
791 | 0 | CEL_RETURN_IF_ERROR( |
792 | 0 | iterator->Next(descriptor_pool, message_factory, arena, &key)); |
793 | 0 | CEL_ASSIGN_OR_RETURN( |
794 | 0 | bool found, |
795 | 0 | dispatcher_->find(dispatcher_, content_, key, descriptor_pool, |
796 | 0 | message_factory, arena, &value)); |
797 | 0 | if (!found) { |
798 | 0 | value = ErrorValue(NoSuchKeyError(key)); |
799 | 0 | } |
800 | 0 | CEL_ASSIGN_OR_RETURN(auto ok, callback(key, value)); |
801 | 0 | if (!ok) { |
802 | 0 | break; |
803 | 0 | } |
804 | 0 | } |
805 | 0 | return absl::OkStatus(); |
806 | 0 | } |
807 | | |
808 | | absl::StatusOr<absl_nonnull ValueIteratorPtr> CustomMapValue::NewIterator() |
809 | 45 | const { |
810 | 45 | if (dispatcher_ == nullptr) { |
811 | 45 | CustomMapValueInterface::Content content = |
812 | 45 | content_.To<CustomMapValueInterface::Content>(); |
813 | 45 | ABSL_DCHECK(content.interface != nullptr); |
814 | 45 | return content.interface->NewIterator(); |
815 | 45 | } |
816 | 0 | if (dispatcher_->new_iterator != nullptr) { |
817 | 0 | return dispatcher_->new_iterator(dispatcher_, content_); |
818 | 0 | } |
819 | 0 | return std::make_unique<CustomMapValueDispatcherIterator>(dispatcher_, |
820 | 0 | content_); |
821 | 0 | } |
822 | | |
823 | | } // namespace cel |