/proc/self/cwd/common/values/legacy_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 "common/values/legacy_map_value.h" |
16 | | |
17 | | #include <cstddef> |
18 | | #include <cstdint> |
19 | | #include <limits> |
20 | | #include <optional> |
21 | | #include <string> |
22 | | #include <utility> |
23 | | |
24 | | #include "absl/base/nullability.h" |
25 | | #include "absl/log/absl_check.h" |
26 | | #include "absl/status/status.h" |
27 | | #include "absl/strings/str_cat.h" |
28 | | #include "absl/strings/string_view.h" |
29 | | #include "common/legacy_value.h" |
30 | | #include "common/memory.h" |
31 | | #include "common/native_type.h" |
32 | | #include "common/value.h" |
33 | | #include "common/value_kind.h" |
34 | | #include "common/values/legacy_list_value.h" |
35 | | #include "common/values/legacy_struct_value.h" |
36 | | #include "common/values/map_value_builder.h" |
37 | | #include "common/values/values.h" |
38 | | #include "eval/public/cel_value.h" |
39 | | #include "eval/public/structs/proto_message_type_adapter.h" |
40 | | #include "internal/casts.h" |
41 | | #include "internal/status_macros.h" |
42 | | #include "google/protobuf/arena.h" |
43 | | #include "google/protobuf/descriptor.h" |
44 | | #include "google/protobuf/message.h" |
45 | | |
46 | | namespace cel::common_internal { |
47 | | |
48 | | namespace { |
49 | | |
50 | | LegacyStructValue ParsedMessageToLegacyStructValue( |
51 | 0 | const ParsedMessageValue& parsed_message) { |
52 | 0 | return LegacyStructValue( |
53 | 0 | cel::to_address(parsed_message), |
54 | 0 | &google::api::expr::runtime::GetGenericProtoTypeInfoInstance()); |
55 | 0 | } |
56 | | |
57 | | bool MatchesMapKeyType(const google::protobuf::FieldDescriptor* absl_nonnull key_desc, |
58 | 0 | const Value& key) { |
59 | 0 | switch (key_desc->cpp_type()) { |
60 | 0 | case google::protobuf::FieldDescriptor::CPPTYPE_BOOL: |
61 | 0 | return key.IsBool(); |
62 | 0 | case google::protobuf::FieldDescriptor::CPPTYPE_INT32: |
63 | 0 | if (key.IsInt()) { |
64 | 0 | auto val = key.GetInt().NativeValue(); |
65 | 0 | return val >= std::numeric_limits<int32_t>::min() && |
66 | 0 | val <= std::numeric_limits<int32_t>::max(); |
67 | 0 | } |
68 | 0 | return false; |
69 | 0 | case google::protobuf::FieldDescriptor::CPPTYPE_INT64: |
70 | 0 | return key.IsInt(); |
71 | 0 | case google::protobuf::FieldDescriptor::CPPTYPE_UINT32: |
72 | 0 | if (key.IsUint()) { |
73 | 0 | auto val = key.GetUint().NativeValue(); |
74 | 0 | return val <= std::numeric_limits<uint32_t>::max(); |
75 | 0 | } |
76 | 0 | return false; |
77 | 0 | case google::protobuf::FieldDescriptor::CPPTYPE_UINT64: |
78 | 0 | return key.IsUint(); |
79 | 0 | case google::protobuf::FieldDescriptor::CPPTYPE_STRING: |
80 | 0 | return key.IsString(); |
81 | 0 | default: |
82 | 0 | return false; |
83 | 0 | } |
84 | 0 | } |
85 | | |
86 | 0 | absl::Status InvalidMapKeyType(absl::string_view key_type) { |
87 | 0 | return absl::InvalidArgumentError( |
88 | 0 | absl::StrCat("Invalid map key type: '", key_type, "'")); |
89 | 0 | } |
90 | | |
91 | | } // namespace |
92 | | |
93 | | class LegacyParsedMapFieldMapValue final |
94 | | : public CustomMapValueInterface, |
95 | | public google::api::expr::runtime::CelMap { |
96 | | public: |
97 | | // `arena` is expected to be the same arena as the one that the object is |
98 | | // allocated on. |
99 | | explicit LegacyParsedMapFieldMapValue(ParsedMapFieldValue value, |
100 | | google::protobuf::Arena* absl_nonnull arena) |
101 | 0 | : value_(std::move(value)), arena_(arena) { |
102 | 0 | ABSL_DCHECK(arena != nullptr); |
103 | 0 | ABSL_DCHECK(value_.field() != nullptr); |
104 | 0 | } |
105 | | |
106 | 0 | std::string DebugString() const override { return value_.DebugString(); } |
107 | | |
108 | | absl::Status SerializeTo( |
109 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
110 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
111 | 0 | google::protobuf::io::ZeroCopyOutputStream* absl_nonnull output) const override { |
112 | 0 | return value_.SerializeTo(descriptor_pool, message_factory, output); |
113 | 0 | } |
114 | | |
115 | | absl::Status ConvertToJsonObject( |
116 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
117 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
118 | 0 | google::protobuf::Message* absl_nonnull json) const override { |
119 | 0 | return value_.ConvertToJsonObject(descriptor_pool, message_factory, json); |
120 | 0 | } |
121 | | |
122 | | absl::Status Equal(const MapValue& other, |
123 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
124 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
125 | | google::protobuf::Arena* absl_nonnull arena, |
126 | 0 | Value* absl_nonnull result) const override { |
127 | 0 | return value_.Equal(other, descriptor_pool, message_factory, arena, result); |
128 | 0 | } |
129 | | |
130 | 0 | bool IsZeroValue() const override { return value_.IsZeroValue(); } |
131 | | |
132 | 0 | bool IsEmpty() const override { return value_.IsEmpty(); } |
133 | | |
134 | 0 | size_t Size() const override { return value_.Size(); } |
135 | | |
136 | | absl::StatusOr<bool> Find( |
137 | | const Value& key, |
138 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
139 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
140 | | google::protobuf::Arena* absl_nonnull arena, |
141 | 0 | Value* absl_nonnull result) const override { |
142 | | // Mimic the legacy behavior of complaining about unexpected key type. |
143 | 0 | const auto* key_field = value_.field()->message_type()->map_key(); |
144 | 0 | if (!MatchesMapKeyType(key_field, key)) { |
145 | 0 | return InvalidMapKeyType(cel::ValueKindToString(key.kind())); |
146 | 0 | } |
147 | | |
148 | 0 | CEL_ASSIGN_OR_RETURN( |
149 | 0 | auto found, |
150 | 0 | value_.Find(key, descriptor_pool, message_factory, arena, result)); |
151 | 0 | if (found) { |
152 | 0 | interop_internal::WrapLegacyFieldAccessResult(arena, result); |
153 | 0 | } |
154 | 0 | return found; |
155 | 0 | } |
156 | | |
157 | | absl::StatusOr<bool> Has( |
158 | | const Value& key, |
159 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
160 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
161 | 0 | google::protobuf::Arena* absl_nonnull arena) const override { |
162 | 0 | const auto* key_field = value_.field()->message_type()->map_key(); |
163 | 0 | if (!MatchesMapKeyType(key_field, key)) { |
164 | 0 | return InvalidMapKeyType(key_field->cpp_type_name()); |
165 | 0 | } |
166 | 0 | Value result; |
167 | 0 | CEL_RETURN_IF_ERROR( |
168 | 0 | value_.Has(key, descriptor_pool, message_factory, arena, &result)); |
169 | 0 | if (result.IsBool()) { |
170 | 0 | return result.GetBool().NativeValue(); |
171 | 0 | } |
172 | 0 | if (result.IsError()) { |
173 | 0 | return result.GetError().NativeValue(); |
174 | 0 | } |
175 | 0 | return false; |
176 | 0 | } |
177 | | |
178 | | absl::Status ListKeys( |
179 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
180 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
181 | | google::protobuf::Arena* absl_nonnull arena, |
182 | 0 | ListValue* absl_nonnull result) const override { |
183 | 0 | return value_.ListKeys(descriptor_pool, message_factory, arena, result); |
184 | 0 | } |
185 | | |
186 | | absl::Status ForEach( |
187 | | ForEachCallback callback, |
188 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
189 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
190 | 0 | google::protobuf::Arena* absl_nonnull arena) const override { |
191 | 0 | return value_.ForEach(callback, descriptor_pool, message_factory, arena); |
192 | 0 | } |
193 | | |
194 | 0 | absl::StatusOr<absl_nonnull ValueIteratorPtr> NewIterator() const override { |
195 | 0 | return value_.NewIterator(); |
196 | 0 | } |
197 | | |
198 | 0 | CustomMapValue Clone(google::protobuf::Arena* absl_nonnull arena) const override { |
199 | 0 | return CustomMapValue(google::protobuf::Arena::Create<LegacyParsedMapFieldMapValue>( |
200 | 0 | arena, value_.Clone(arena), arena), |
201 | 0 | arena); |
202 | 0 | } |
203 | | |
204 | | // CelMap implementation |
205 | 0 | int size() const override { return static_cast<int>(value_.Size()); } |
206 | | |
207 | 0 | bool empty() const override { return value_.IsEmpty(); } |
208 | | |
209 | | std::optional<google::api::expr::runtime::CelValue> operator[]( |
210 | 0 | google::api::expr::runtime::CelValue key) const override { |
211 | 0 | return Get(arena_, key); |
212 | 0 | } |
213 | | |
214 | | std::optional<google::api::expr::runtime::CelValue> Get( |
215 | | google::protobuf::Arena* arena, |
216 | 0 | google::api::expr::runtime::CelValue key) const override { |
217 | 0 | if (arena == nullptr) { |
218 | 0 | arena = arena_; |
219 | 0 | } |
220 | 0 | Value modern_key; |
221 | 0 | if (!ModernValue(arena, key, modern_key).ok()) { |
222 | | // Legacy to modern should succeed for a valid CelValue. |
223 | 0 | return std::nullopt; |
224 | 0 | } |
225 | 0 | Value modern_val; |
226 | | // Call custom map Find directly. MapValue normally handles wrapping |
227 | | // non-ok result to error value types, so emulate that here. |
228 | | // |
229 | | // Use the descriptor pool and message factory from the value. This is not |
230 | | // totally consistent with modern APIs, but this should behave the same as |
231 | | // the legacy map did. |
232 | 0 | const google::protobuf::Message* msg = value_.message_; |
233 | 0 | ABSL_DCHECK(msg->GetDescriptor() != nullptr); |
234 | 0 | ABSL_DCHECK(msg->GetReflection() != nullptr); |
235 | |
|
236 | 0 | const google::protobuf::DescriptorPool* descriptor_pool = |
237 | 0 | msg->GetDescriptor()->file()->pool(); |
238 | 0 | google::protobuf::MessageFactory* message_factory = |
239 | 0 | msg->GetReflection()->GetMessageFactory(); |
240 | 0 | auto found = |
241 | 0 | Find(modern_key, descriptor_pool, message_factory, arena, &modern_val); |
242 | 0 | if (!found.ok()) { |
243 | 0 | return google::api::expr::runtime::CreateErrorValue(arena, |
244 | 0 | found.status()); |
245 | 0 | } |
246 | 0 | if (!(*found) && !modern_val.IsError()) { |
247 | 0 | return std::nullopt; |
248 | 0 | } |
249 | 0 | return UnsafeLegacyValue(modern_val, /*stable=*/false, arena); |
250 | 0 | } |
251 | | |
252 | | absl::StatusOr<bool> Has( |
253 | 0 | const google::api::expr::runtime::CelValue& key) const override { |
254 | 0 | CEL_RETURN_IF_ERROR( |
255 | 0 | google::api::expr::runtime::CelValue::CheckMapKeyType(key)); |
256 | 0 | google::protobuf::Arena scratch_arena; |
257 | 0 | Value modern_key; |
258 | 0 | CEL_RETURN_IF_ERROR(ModernValue(&scratch_arena, key, modern_key)); |
259 | 0 | return Has(modern_key, google::protobuf::DescriptorPool::generated_pool(), |
260 | 0 | google::protobuf::MessageFactory::generated_factory(), &scratch_arena); |
261 | 0 | } |
262 | | |
263 | | absl::StatusOr<const google::api::expr::runtime::CelList*> ListKeys() |
264 | 0 | const override { |
265 | 0 | return ListKeys(arena_); |
266 | 0 | } |
267 | | |
268 | | absl::StatusOr<const google::api::expr::runtime::CelList*> ListKeys( |
269 | 0 | google::protobuf::Arena* arena) const override { |
270 | 0 | if (arena == nullptr) { |
271 | 0 | arena = arena_; |
272 | 0 | } |
273 | 0 | ListValue keys; |
274 | 0 | CEL_RETURN_IF_ERROR(value_.ListKeys( |
275 | 0 | google::protobuf::DescriptorPool::generated_pool(), |
276 | 0 | google::protobuf::MessageFactory::generated_factory(), arena, &keys)); |
277 | 0 | auto legacy_list = AsLegacyListValue(keys); |
278 | 0 | if (!legacy_list.has_value()) { |
279 | 0 | return absl::InternalError("failed to convert list keys to legacy list"); |
280 | 0 | } |
281 | 0 | return legacy_list->cel_list(); |
282 | 0 | } |
283 | | |
284 | | private: |
285 | 0 | NativeTypeId GetNativeTypeId() const override { |
286 | 0 | return NativeTypeId::For<LegacyParsedMapFieldMapValue>(); |
287 | 0 | } |
288 | | |
289 | | ParsedMapFieldValue value_; |
290 | | google::protobuf::Arena* const arena_; |
291 | | }; |
292 | | |
293 | | class LegacyParsedJsonMapValue final |
294 | | : public CustomMapValueInterface, |
295 | | public google::api::expr::runtime::CelMap { |
296 | | public: |
297 | | // `arena` is expected to be the same arena as the one that the object is |
298 | | // allocated on. |
299 | | explicit LegacyParsedJsonMapValue(ParsedJsonMapValue value, |
300 | | google::protobuf::Arena* absl_nonnull arena) |
301 | 1 | : value_(std::move(value)), arena_(arena) { |
302 | 1 | ABSL_DCHECK(arena != nullptr); |
303 | 1 | } |
304 | | |
305 | 0 | std::string DebugString() const override { return value_.DebugString(); } |
306 | | |
307 | | absl::Status SerializeTo( |
308 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
309 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
310 | 0 | google::protobuf::io::ZeroCopyOutputStream* absl_nonnull output) const override { |
311 | 0 | return value_.SerializeTo(descriptor_pool, message_factory, output); |
312 | 0 | } |
313 | | |
314 | | absl::Status ConvertToJsonObject( |
315 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
316 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
317 | 0 | google::protobuf::Message* absl_nonnull json) const override { |
318 | 0 | return value_.ConvertToJsonObject(descriptor_pool, message_factory, json); |
319 | 0 | } |
320 | | |
321 | | absl::Status Equal(const MapValue& other, |
322 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
323 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
324 | | google::protobuf::Arena* absl_nonnull arena, |
325 | 0 | Value* absl_nonnull result) const override { |
326 | 0 | return value_.Equal(other, descriptor_pool, message_factory, arena, result); |
327 | 0 | } |
328 | | |
329 | 0 | bool IsZeroValue() const override { return value_.IsZeroValue(); } |
330 | | |
331 | 0 | bool IsEmpty() const override { return value_.IsEmpty(); } |
332 | | |
333 | 0 | size_t Size() const override { return value_.Size(); } |
334 | | |
335 | | absl::StatusOr<bool> Find( |
336 | | const Value& key, |
337 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
338 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
339 | | google::protobuf::Arena* absl_nonnull arena, |
340 | 0 | Value* absl_nonnull result) const override { |
341 | 0 | if (!key.IsString()) { |
342 | 0 | return InvalidMapKeyType(cel::ValueKindToString(key.kind())); |
343 | 0 | } |
344 | 0 | CEL_ASSIGN_OR_RETURN( |
345 | 0 | auto found, |
346 | 0 | value_.Find(key, descriptor_pool, message_factory, arena, result)); |
347 | 0 | if (found && result->IsParsedMessage()) { |
348 | 0 | *result = ParsedMessageToLegacyStructValue(result->GetParsedMessage()); |
349 | 0 | } |
350 | 0 | return found; |
351 | 0 | } |
352 | | |
353 | | absl::StatusOr<bool> Has( |
354 | | const Value& key, |
355 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
356 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
357 | 0 | google::protobuf::Arena* absl_nonnull arena) const override { |
358 | 0 | if (!key.IsString()) { |
359 | 0 | return InvalidMapKeyType(cel::ValueKindToString(key.kind())); |
360 | 0 | } |
361 | 0 | Value result; |
362 | 0 | CEL_RETURN_IF_ERROR( |
363 | 0 | value_.Has(key, descriptor_pool, message_factory, arena, &result)); |
364 | 0 | if (result.IsBool()) { |
365 | 0 | return result.GetBool().NativeValue(); |
366 | 0 | } |
367 | 0 | if (result.IsError()) { |
368 | 0 | return result.GetError().NativeValue(); |
369 | 0 | } |
370 | 0 | return false; |
371 | 0 | } |
372 | | |
373 | | absl::Status ListKeys( |
374 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
375 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
376 | | google::protobuf::Arena* absl_nonnull arena, |
377 | 0 | ListValue* absl_nonnull result) const override { |
378 | 0 | return value_.ListKeys(descriptor_pool, message_factory, arena, result); |
379 | 0 | } |
380 | | |
381 | | absl::Status ForEach( |
382 | | ForEachCallback callback, |
383 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
384 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
385 | 0 | google::protobuf::Arena* absl_nonnull arena) const override { |
386 | 0 | return value_.ForEach(callback, descriptor_pool, message_factory, arena); |
387 | 0 | } |
388 | | |
389 | 0 | absl::StatusOr<absl_nonnull ValueIteratorPtr> NewIterator() const override { |
390 | 0 | return value_.NewIterator(); |
391 | 0 | } |
392 | | |
393 | 0 | CustomMapValue Clone(google::protobuf::Arena* absl_nonnull arena) const override { |
394 | 0 | return CustomMapValue(google::protobuf::Arena::Create<LegacyParsedJsonMapValue>( |
395 | 0 | arena, value_.Clone(arena), arena), |
396 | 0 | arena); |
397 | 0 | } |
398 | | |
399 | | // CelMap implementation |
400 | 0 | int size() const override { return static_cast<int>(value_.Size()); } |
401 | | |
402 | 0 | bool empty() const override { return value_.IsEmpty(); } |
403 | | |
404 | | std::optional<google::api::expr::runtime::CelValue> operator[]( |
405 | 0 | google::api::expr::runtime::CelValue key) const override { |
406 | 0 | return Get(arena_, key); |
407 | 0 | } |
408 | | |
409 | | std::optional<google::api::expr::runtime::CelValue> Get( |
410 | | google::protobuf::Arena* arena, |
411 | 0 | google::api::expr::runtime::CelValue key) const override { |
412 | 0 | if (arena == nullptr) { |
413 | 0 | arena = arena_; |
414 | 0 | } |
415 | 0 | Value modern_key; |
416 | 0 | if (!ModernValue(arena, key, modern_key).ok()) { |
417 | | // Legacy to modern should succeed for a valid CelValue. |
418 | 0 | return std::nullopt; |
419 | 0 | } |
420 | 0 | Value modern_val; |
421 | | // Call custom map Find directly. MapValue normally handles wrapping |
422 | | // non-ok result to error value types, so emulate that here. |
423 | | // |
424 | | // We know that the descriptor pool and message factory aren't needed here, |
425 | | // so fine to use generated. |
426 | 0 | auto found = |
427 | 0 | Find(modern_key, google::protobuf::DescriptorPool::generated_pool(), |
428 | 0 | google::protobuf::MessageFactory::generated_factory(), arena, &modern_val); |
429 | 0 | if (!found.ok()) { |
430 | 0 | return google::api::expr::runtime::CreateErrorValue(arena, |
431 | 0 | found.status()); |
432 | 0 | } |
433 | 0 | if (!(*found) && !modern_val.IsError()) { |
434 | 0 | return std::nullopt; |
435 | 0 | } |
436 | 0 | return UnsafeLegacyValue(modern_val, /*stable=*/false, arena); |
437 | 0 | } |
438 | | |
439 | | absl::StatusOr<bool> Has( |
440 | 0 | const google::api::expr::runtime::CelValue& key) const override { |
441 | 0 | CEL_RETURN_IF_ERROR( |
442 | 0 | google::api::expr::runtime::CelValue::CheckMapKeyType(key)); |
443 | 0 | google::protobuf::Arena scratch_arena; |
444 | 0 | Value modern_key; |
445 | 0 | CEL_RETURN_IF_ERROR(ModernValue(&scratch_arena, key, modern_key)); |
446 | 0 | return Has(modern_key, google::protobuf::DescriptorPool::generated_pool(), |
447 | 0 | google::protobuf::MessageFactory::generated_factory(), &scratch_arena); |
448 | 0 | } |
449 | | |
450 | | absl::StatusOr<const google::api::expr::runtime::CelList*> ListKeys() |
451 | 0 | const override { |
452 | 0 | return ListKeys(arena_); |
453 | 0 | } |
454 | | |
455 | | absl::StatusOr<const google::api::expr::runtime::CelList*> ListKeys( |
456 | 0 | google::protobuf::Arena* arena) const override { |
457 | 0 | if (arena == nullptr) { |
458 | 0 | arena = arena_; |
459 | 0 | } |
460 | 0 | ListValue keys; |
461 | 0 | CEL_RETURN_IF_ERROR(value_.ListKeys( |
462 | 0 | google::protobuf::DescriptorPool::generated_pool(), |
463 | 0 | google::protobuf::MessageFactory::generated_factory(), arena, &keys)); |
464 | 0 | auto legacy_list = AsLegacyListValue(keys); |
465 | 0 | if (!legacy_list.has_value()) { |
466 | 0 | return absl::InternalError("failed to convert list keys to legacy list"); |
467 | 0 | } |
468 | 0 | return legacy_list->cel_list(); |
469 | 0 | } |
470 | | |
471 | | private: |
472 | 1 | NativeTypeId GetNativeTypeId() const override { |
473 | 1 | return NativeTypeId::For<LegacyParsedJsonMapValue>(); |
474 | 1 | } |
475 | | |
476 | | ParsedJsonMapValue value_; |
477 | | google::protobuf::Arena* const arena_; |
478 | | }; |
479 | | |
480 | | CustomMapValue WrapLegacyParsedMapField(ParsedMapFieldValue value, |
481 | 0 | google::protobuf::Arena* absl_nonnull arena) { |
482 | 0 | return CustomMapValue(google::protobuf::Arena::Create<LegacyParsedMapFieldMapValue>( |
483 | 0 | arena, std::move(value), arena), |
484 | 0 | arena); |
485 | 0 | } |
486 | | |
487 | | CustomMapValue WrapLegacyParsedJsonMap(ParsedJsonMapValue value, |
488 | 1 | google::protobuf::Arena* absl_nonnull arena) { |
489 | 1 | return CustomMapValue(google::protobuf::Arena::Create<LegacyParsedJsonMapValue>( |
490 | 1 | arena, std::move(value), arena), |
491 | 1 | arena); |
492 | 1 | } |
493 | | |
494 | | absl::Status LegacyMapValue::Equal( |
495 | | const Value& other, |
496 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
497 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
498 | 0 | google::protobuf::Arena* absl_nonnull arena, Value* absl_nonnull result) const { |
499 | 0 | if (auto map_value = other.AsMap(); map_value.has_value()) { |
500 | 0 | return MapValueEqual(*this, *map_value, descriptor_pool, message_factory, |
501 | 0 | arena, result); |
502 | 0 | } |
503 | 0 | *result = FalseValue(); |
504 | 0 | return absl::OkStatus(); |
505 | 0 | } |
506 | | |
507 | 29 | bool IsLegacyMapValue(const Value& value) { |
508 | 29 | return value.variant_.Is<LegacyMapValue>(); |
509 | 29 | } |
510 | | |
511 | 0 | LegacyMapValue GetLegacyMapValue(const Value& value) { |
512 | 0 | ABSL_DCHECK(IsLegacyMapValue(value)); |
513 | 0 | return value.variant_.Get<LegacyMapValue>(); |
514 | 0 | } |
515 | | |
516 | 29 | std::optional<LegacyMapValue> AsLegacyMapValue(const Value& value) { |
517 | 29 | if (IsLegacyMapValue(value)) { |
518 | 0 | return GetLegacyMapValue(value); |
519 | 0 | } |
520 | 29 | if (auto custom_map_value = value.AsCustomMap(); custom_map_value) { |
521 | 28 | NativeTypeId native_type_id = NativeTypeId::Of(*custom_map_value); |
522 | 28 | if (native_type_id == NativeTypeId::For<CompatMapValue>()) { |
523 | 27 | return LegacyMapValue( |
524 | 27 | static_cast<const google::api::expr::runtime::CelMap*>( |
525 | 27 | cel::internal::down_cast<const CompatMapValue*>( |
526 | 27 | custom_map_value->interface()))); |
527 | 27 | } else if (native_type_id == NativeTypeId::For<MutableCompatMapValue>()) { |
528 | 0 | return LegacyMapValue( |
529 | 0 | static_cast<const google::api::expr::runtime::CelMap*>( |
530 | 0 | cel::internal::down_cast<const MutableCompatMapValue*>( |
531 | 0 | custom_map_value->interface()))); |
532 | 1 | } else if (native_type_id == |
533 | 1 | NativeTypeId::For<LegacyParsedMapFieldMapValue>()) { |
534 | 0 | return LegacyMapValue( |
535 | 0 | static_cast<const google::api::expr::runtime::CelMap*>( |
536 | 0 | cel::internal::down_cast<const LegacyParsedMapFieldMapValue*>( |
537 | 0 | custom_map_value->interface()))); |
538 | 1 | } else if (native_type_id == |
539 | 1 | NativeTypeId::For<LegacyParsedJsonMapValue>()) { |
540 | 1 | return LegacyMapValue( |
541 | 1 | static_cast<const google::api::expr::runtime::CelMap*>( |
542 | 1 | cel::internal::down_cast<const LegacyParsedJsonMapValue*>( |
543 | 1 | custom_map_value->interface()))); |
544 | 1 | } |
545 | 28 | } |
546 | 1 | return std::nullopt; |
547 | 29 | } |
548 | | |
549 | | } // namespace cel::common_internal |