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