/proc/self/cwd/common/values/custom_map_value.h
Line | Count | Source |
1 | | // Copyright 2023 Google LLC |
2 | | // |
3 | | // Licensed under the Apache License, Version 2.0 (the "License"); |
4 | | // you may not use this file except in compliance with the License. |
5 | | // You may obtain a copy of the License at |
6 | | // |
7 | | // https://www.apache.org/licenses/LICENSE-2.0 |
8 | | // |
9 | | // Unless required by applicable law or agreed to in writing, software |
10 | | // distributed under the License is distributed on an "AS IS" BASIS, |
11 | | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 | | // See the License for the specific language governing permissions and |
13 | | // limitations under the License. |
14 | | |
15 | | // IWYU pragma: private, include "common/value.h" |
16 | | // IWYU pragma: friend "common/value.h" |
17 | | |
18 | | // `CustomMapValue` represents values of the primitive `map` type. |
19 | | // `CustomMapValueView` is a non-owning view of `CustomMapValue`. |
20 | | // `CustomMapValueInterface` is the abstract base class of implementations. |
21 | | // `CustomMapValue` and `CustomMapValueView` act as smart pointers to |
22 | | // `CustomMapValueInterface`. |
23 | | |
24 | | #ifndef THIRD_PARTY_CEL_CPP_COMMON_VALUES_PARSED_MAP_VALUE_H_ |
25 | | #define THIRD_PARTY_CEL_CPP_COMMON_VALUES_PARSED_MAP_VALUE_H_ |
26 | | |
27 | | #include <cstddef> |
28 | | #include <ostream> |
29 | | #include <string> |
30 | | #include <utility> |
31 | | |
32 | | #include "absl/base/attributes.h" |
33 | | #include "absl/base/nullability.h" |
34 | | #include "absl/functional/function_ref.h" |
35 | | #include "absl/log/absl_check.h" |
36 | | #include "absl/status/status.h" |
37 | | #include "absl/status/statusor.h" |
38 | | #include "absl/strings/string_view.h" |
39 | | #include "common/native_type.h" |
40 | | #include "common/value_kind.h" |
41 | | #include "common/values/custom_value.h" |
42 | | #include "common/values/values.h" |
43 | | #include "google/protobuf/arena.h" |
44 | | #include "google/protobuf/descriptor.h" |
45 | | #include "google/protobuf/io/zero_copy_stream.h" |
46 | | #include "google/protobuf/message.h" |
47 | | |
48 | | namespace cel { |
49 | | |
50 | | class Value; |
51 | | class ListValue; |
52 | | class CustomMapValueInterface; |
53 | | class CustomMapValueInterfaceKeysIterator; |
54 | | class CustomMapValue; |
55 | | using CustomMapValueContent = CustomValueContent; |
56 | | |
57 | | // Dispatch table for `CustomMapValue`. |
58 | | // |
59 | | // See the documentation for `CustomMapValueInterface` for more details on |
60 | | // composite functions. |
61 | | // |
62 | | // See documentation for `UnsafeCustomMapValue` on how to use this class. |
63 | | struct CustomMapValueDispatcher { |
64 | | using GetTypeId = |
65 | | NativeTypeId (*)(const CustomMapValueDispatcher* absl_nonnull dispatcher, |
66 | | CustomMapValueContent content); |
67 | | |
68 | | using GetArena = google::protobuf::Arena* absl_nullable (*)( |
69 | | const CustomMapValueDispatcher* absl_nonnull dispatcher, |
70 | | CustomMapValueContent content); |
71 | | |
72 | | using DebugString = |
73 | | std::string (*)(const CustomMapValueDispatcher* absl_nonnull dispatcher, |
74 | | CustomMapValueContent content); |
75 | | |
76 | | using SerializeTo = absl::Status (*)( |
77 | | const CustomMapValueDispatcher* absl_nonnull dispatcher, |
78 | | CustomMapValueContent content, |
79 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
80 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
81 | | google::protobuf::io::ZeroCopyOutputStream* absl_nonnull output); |
82 | | |
83 | | using ConvertToJsonObject = absl::Status (*)( |
84 | | const CustomMapValueDispatcher* absl_nonnull dispatcher, |
85 | | CustomMapValueContent content, |
86 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
87 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
88 | | google::protobuf::Message* absl_nonnull json); |
89 | | |
90 | | using Equal = absl::Status (*)( |
91 | | const CustomMapValueDispatcher* absl_nonnull dispatcher, |
92 | | CustomMapValueContent content, const MapValue& other, |
93 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
94 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
95 | | google::protobuf::Arena* absl_nonnull arena, Value* absl_nonnull result); |
96 | | |
97 | | using IsZeroValue = |
98 | | bool (*)(const CustomMapValueDispatcher* absl_nonnull dispatcher, |
99 | | CustomMapValueContent content); |
100 | | |
101 | | using IsEmpty = |
102 | | bool (*)(const CustomMapValueDispatcher* absl_nonnull dispatcher, |
103 | | CustomMapValueContent content); |
104 | | |
105 | | using Size = |
106 | | size_t (*)(const CustomMapValueDispatcher* absl_nonnull dispatcher, |
107 | | CustomMapValueContent content); |
108 | | |
109 | | using Find = absl::StatusOr<bool> (*)( |
110 | | const CustomMapValueDispatcher* absl_nonnull dispatcher, |
111 | | CustomMapValueContent content, const Value& key, |
112 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
113 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
114 | | google::protobuf::Arena* absl_nonnull arena, Value* absl_nonnull result); |
115 | | |
116 | | using Has = absl::StatusOr<bool> (*)( |
117 | | const CustomMapValueDispatcher* absl_nonnull dispatcher, |
118 | | CustomMapValueContent content, const Value& key, |
119 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
120 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
121 | | google::protobuf::Arena* absl_nonnull arena); |
122 | | |
123 | | using ListKeys = absl::Status (*)( |
124 | | const CustomMapValueDispatcher* absl_nonnull dispatcher, |
125 | | CustomMapValueContent content, |
126 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
127 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
128 | | google::protobuf::Arena* absl_nonnull arena, ListValue* absl_nonnull result); |
129 | | |
130 | | using ForEach = absl::Status (*)( |
131 | | const CustomMapValueDispatcher* absl_nonnull dispatcher, |
132 | | CustomMapValueContent content, |
133 | | absl::FunctionRef<absl::StatusOr<bool>(const Value&, const Value&)> |
134 | | callback, |
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 | | |
139 | | using NewIterator = absl::StatusOr<absl_nonnull ValueIteratorPtr> (*)( |
140 | | const CustomMapValueDispatcher* absl_nonnull dispatcher, |
141 | | CustomMapValueContent content); |
142 | | |
143 | | using Clone = CustomMapValue (*)( |
144 | | const CustomMapValueDispatcher* absl_nonnull dispatcher, |
145 | | CustomMapValueContent content, google::protobuf::Arena* absl_nonnull arena); |
146 | | |
147 | | absl_nonnull GetTypeId get_type_id; |
148 | | |
149 | | absl_nonnull GetArena get_arena; |
150 | | |
151 | | // If null, simply returns "map". |
152 | | absl_nullable DebugString debug_string = nullptr; |
153 | | |
154 | | // If null, attempts to serialize results in an UNIMPLEMENTED error. |
155 | | absl_nullable SerializeTo serialize_to = nullptr; |
156 | | |
157 | | // If null, attempts to convert to JSON results in an UNIMPLEMENTED error. |
158 | | absl_nullable ConvertToJsonObject convert_to_json_object = nullptr; |
159 | | |
160 | | // If null, an nonoptimal fallback implementation for equality is used. |
161 | | absl_nullable Equal equal = nullptr; |
162 | | |
163 | | absl_nonnull IsZeroValue is_zero_value; |
164 | | |
165 | | // If null, `size(...) == 0` is used. |
166 | | absl_nullable IsEmpty is_empty = nullptr; |
167 | | |
168 | | absl_nonnull Size size; |
169 | | |
170 | | absl_nonnull Find find; |
171 | | |
172 | | absl_nonnull Has has; |
173 | | |
174 | | absl_nonnull ListKeys list_keys; |
175 | | |
176 | | // If null, a fallback implementation based on `list_keys` is used. |
177 | | absl_nullable ForEach for_each = nullptr; |
178 | | |
179 | | // If null, a fallback implementation based on `list_keys` is used. |
180 | | absl_nullable NewIterator new_iterator = nullptr; |
181 | | |
182 | | absl_nonnull Clone clone; |
183 | | }; |
184 | | |
185 | | class CustomMapValueInterface { |
186 | | public: |
187 | 189k | CustomMapValueInterface() = default; |
188 | | CustomMapValueInterface(const CustomMapValueInterface&) = delete; |
189 | | CustomMapValueInterface(CustomMapValueInterface&&) = delete; |
190 | | |
191 | 86.8k | virtual ~CustomMapValueInterface() = default; |
192 | | |
193 | | CustomMapValueInterface& operator=(const CustomMapValueInterface&) = delete; |
194 | | CustomMapValueInterface& operator=(CustomMapValueInterface&&) = delete; |
195 | | |
196 | | using ForEachCallback = |
197 | | absl::FunctionRef<absl::StatusOr<bool>(const Value&, const Value&)>; |
198 | | |
199 | | private: |
200 | | friend class CustomMapValueInterfaceIterator; |
201 | | friend class CustomMapValue; |
202 | | friend absl::Status common_internal::MapValueEqual( |
203 | | const CustomMapValueInterface& lhs, const MapValue& rhs, |
204 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
205 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
206 | | google::protobuf::Arena* absl_nonnull arena, Value* absl_nonnull result); |
207 | | |
208 | | virtual std::string DebugString() const = 0; |
209 | | |
210 | | virtual absl::Status SerializeTo( |
211 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
212 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
213 | | google::protobuf::io::ZeroCopyOutputStream* absl_nonnull output) const; |
214 | | |
215 | | virtual absl::Status ConvertToJsonObject( |
216 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
217 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
218 | | google::protobuf::Message* absl_nonnull json) const = 0; |
219 | | |
220 | | virtual absl::Status Equal( |
221 | | const MapValue& other, |
222 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
223 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
224 | | google::protobuf::Arena* absl_nonnull arena, Value* absl_nonnull result) const; |
225 | | |
226 | 0 | virtual bool IsZeroValue() const { return IsEmpty(); } |
227 | | |
228 | | // Returns `true` if this map contains no entries, `false` otherwise. |
229 | 0 | virtual bool IsEmpty() const { return Size() == 0; } |
230 | | |
231 | | // Returns the number of entries in this map. |
232 | | virtual size_t Size() const = 0; |
233 | | |
234 | | // See the corresponding member function of `MapValue` for |
235 | | // documentation. |
236 | | virtual absl::Status ListKeys( |
237 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
238 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
239 | | google::protobuf::Arena* absl_nonnull arena, |
240 | | ListValue* absl_nonnull result) const = 0; |
241 | | |
242 | | // See the corresponding member function of `MapValue` for |
243 | | // documentation. |
244 | | virtual absl::Status ForEach( |
245 | | ForEachCallback callback, |
246 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
247 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
248 | | google::protobuf::Arena* absl_nonnull arena) const; |
249 | | |
250 | | // By default, implementations do not guarantee any iteration order. Unless |
251 | | // specified otherwise, assume the iteration order is random. |
252 | | virtual absl::StatusOr<absl_nonnull ValueIteratorPtr> NewIterator() const; |
253 | | |
254 | | virtual CustomMapValue Clone(google::protobuf::Arena* absl_nonnull arena) const = 0; |
255 | | |
256 | | // Tests whether the map contains the given key. If it does, the value |
257 | | // associated with the key is written to `result` and the function returns |
258 | | // true. Otherwise, the function returns false and `result` is set to |
259 | | // `NullValue`. |
260 | | // |
261 | | // A non-ok status is converted to an ErrorValue (e.g. wrong key type). |
262 | | virtual absl::StatusOr<bool> Find( |
263 | | const Value& key, |
264 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
265 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
266 | | google::protobuf::Arena* absl_nonnull arena, Value* absl_nonnull result) const = 0; |
267 | | |
268 | | // Whether the map has the given key. |
269 | | // |
270 | | // A non-ok status is converted to an ErrorValue (e.g. wrong key type). |
271 | | virtual absl::StatusOr<bool> Has( |
272 | | const Value& key, |
273 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
274 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
275 | | google::protobuf::Arena* absl_nonnull arena) const = 0; |
276 | | |
277 | | virtual NativeTypeId GetNativeTypeId() const = 0; |
278 | | |
279 | | struct Content { |
280 | | const CustomMapValueInterface* absl_nonnull interface; |
281 | | google::protobuf::Arena* absl_nullable arena; |
282 | | }; |
283 | | }; |
284 | | |
285 | | // Creates a custom map value from a manual dispatch table `dispatcher` and |
286 | | // opaque data `content` whose format is only know to functions in the manual |
287 | | // dispatch table. The dispatch table should probably be valid for the lifetime |
288 | | // of the process, but at a minimum must outlive all instances of the resulting |
289 | | // value. |
290 | | // |
291 | | // IMPORTANT: This approach to implementing CustomMapValue should only be |
292 | | // used when you know exactly what you are doing. When in doubt, just implement |
293 | | // CustomMapValueInterface. |
294 | | CustomMapValue UnsafeCustomMapValue(const CustomMapValueDispatcher* absl_nonnull |
295 | | dispatcher ABSL_ATTRIBUTE_LIFETIME_BOUND, |
296 | | CustomMapValueContent content); |
297 | | |
298 | | class CustomMapValue final |
299 | | : private common_internal::MapValueMixin<CustomMapValue> { |
300 | | public: |
301 | | static constexpr ValueKind kKind = ValueKind::kMap; |
302 | | |
303 | | // Constructs a custom map value from an implementation of |
304 | | // `CustomMapValueInterface` `interface` whose lifetime is tied to that of |
305 | | // the arena `arena`. |
306 | | CustomMapValue(const CustomMapValueInterface* absl_nonnull |
307 | | interface ABSL_ATTRIBUTE_LIFETIME_BOUND, |
308 | | google::protobuf::Arena* absl_nonnull arena |
309 | 189k | ABSL_ATTRIBUTE_LIFETIME_BOUND) { |
310 | 189k | ABSL_DCHECK(interface != nullptr); |
311 | 189k | ABSL_DCHECK(arena != nullptr); |
312 | 189k | content_ = CustomMapValueContent::From(CustomMapValueInterface::Content{ |
313 | 189k | .interface = interface, .arena = arena}); |
314 | 189k | } |
315 | | |
316 | | // By default, this creates an empty map whose type is `map(dyn, dyn)`. Unless |
317 | | // you can help it, you should use a more specific typed map value. |
318 | | CustomMapValue(); |
319 | | CustomMapValue(const CustomMapValue&) = default; |
320 | | CustomMapValue(CustomMapValue&&) = default; |
321 | | CustomMapValue& operator=(const CustomMapValue&) = default; |
322 | | CustomMapValue& operator=(CustomMapValue&&) = default; |
323 | | |
324 | 0 | static constexpr ValueKind kind() { return kKind; } |
325 | | |
326 | | NativeTypeId GetTypeId() const; |
327 | | |
328 | | absl::string_view GetTypeName() const; |
329 | | |
330 | | std::string DebugString() const; |
331 | | |
332 | | // See Value::SerializeTo(). |
333 | | absl::Status SerializeTo( |
334 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
335 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
336 | | google::protobuf::io::ZeroCopyOutputStream* absl_nonnull output) const; |
337 | | |
338 | | // See Value::ConvertToJson(). |
339 | | absl::Status ConvertToJson( |
340 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
341 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
342 | | google::protobuf::Message* absl_nonnull json) const; |
343 | | |
344 | | // See Value::ConvertToJsonObject(). |
345 | | absl::Status ConvertToJsonObject( |
346 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
347 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
348 | | google::protobuf::Message* absl_nonnull json) const; |
349 | | |
350 | | absl::Status Equal(const Value& other, |
351 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
352 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
353 | | google::protobuf::Arena* absl_nonnull arena, |
354 | | Value* absl_nonnull result) const; |
355 | | using MapValueMixin::Equal; |
356 | | |
357 | | bool IsZeroValue() const; |
358 | | |
359 | | CustomMapValue Clone(google::protobuf::Arena* absl_nonnull arena) const; |
360 | | |
361 | | bool IsEmpty() const; |
362 | | |
363 | | size_t Size() const; |
364 | | |
365 | | // See the corresponding member function of `MapValue` for |
366 | | // documentation. |
367 | | absl::Status Get(const Value& key, |
368 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
369 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
370 | | google::protobuf::Arena* absl_nonnull arena, |
371 | | Value* absl_nonnull result) const; |
372 | | using MapValueMixin::Get; |
373 | | |
374 | | // See the corresponding member function of `MapValue` for |
375 | | // documentation. |
376 | | absl::StatusOr<bool> Find( |
377 | | const Value& key, |
378 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
379 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
380 | | google::protobuf::Arena* absl_nonnull arena, Value* absl_nonnull result) const; |
381 | | using MapValueMixin::Find; |
382 | | |
383 | | // See the corresponding member function of `MapValue` for |
384 | | // documentation. |
385 | | absl::Status Has(const Value& key, |
386 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
387 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
388 | | google::protobuf::Arena* absl_nonnull arena, |
389 | | Value* absl_nonnull result) const; |
390 | | using MapValueMixin::Has; |
391 | | |
392 | | // See the corresponding member function of `MapValue` for |
393 | | // documentation. |
394 | | absl::Status ListKeys( |
395 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
396 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
397 | | google::protobuf::Arena* absl_nonnull arena, ListValue* absl_nonnull result) const; |
398 | | using MapValueMixin::ListKeys; |
399 | | |
400 | | // See the corresponding type declaration of `MapValueInterface` for |
401 | | // documentation. |
402 | | using ForEachCallback = typename CustomMapValueInterface::ForEachCallback; |
403 | | |
404 | | // See the corresponding member function of `MapValue` for |
405 | | // documentation. |
406 | | absl::Status ForEach( |
407 | | ForEachCallback callback, |
408 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
409 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
410 | | google::protobuf::Arena* absl_nonnull arena) const; |
411 | | |
412 | | // See the corresponding member function of `MapValue` for |
413 | | // documentation. |
414 | | absl::StatusOr<absl_nonnull ValueIteratorPtr> NewIterator() const; |
415 | | |
416 | 0 | const CustomMapValueDispatcher* absl_nullable dispatcher() const { |
417 | 0 | return dispatcher_; |
418 | 0 | } |
419 | | |
420 | 0 | CustomMapValueContent content() const { |
421 | 0 | ABSL_DCHECK(dispatcher_ != nullptr); |
422 | 0 | return content_; |
423 | 0 | } |
424 | | |
425 | 28 | const CustomMapValueInterface* absl_nullable interface() const { |
426 | 28 | if (dispatcher_ == nullptr) { |
427 | 28 | return content_.To<CustomMapValueInterface::Content>().interface; |
428 | 28 | } |
429 | 0 | return nullptr; |
430 | 28 | } |
431 | | |
432 | 0 | friend void swap(CustomMapValue& lhs, CustomMapValue& rhs) noexcept { |
433 | 0 | using std::swap; |
434 | 0 | swap(lhs.dispatcher_, rhs.dispatcher_); |
435 | 0 | swap(lhs.content_, rhs.content_); |
436 | 0 | } |
437 | | |
438 | | private: |
439 | | friend class common_internal::ValueMixin<CustomMapValue>; |
440 | | friend class common_internal::MapValueMixin<CustomMapValue>; |
441 | | friend CustomMapValue UnsafeCustomMapValue( |
442 | | const CustomMapValueDispatcher* absl_nonnull dispatcher |
443 | | ABSL_ATTRIBUTE_LIFETIME_BOUND, |
444 | | CustomMapValueContent content); |
445 | | |
446 | | CustomMapValue(const CustomMapValueDispatcher* absl_nonnull dispatcher, |
447 | | CustomMapValueContent content) |
448 | 0 | : dispatcher_(dispatcher), content_(content) { |
449 | 0 | ABSL_DCHECK(dispatcher != nullptr); |
450 | 0 | ABSL_DCHECK(dispatcher->get_type_id != nullptr); |
451 | 0 | ABSL_DCHECK(dispatcher->get_arena != nullptr); |
452 | 0 | ABSL_DCHECK(dispatcher->is_zero_value != nullptr); |
453 | 0 | ABSL_DCHECK(dispatcher->size != nullptr); |
454 | 0 | ABSL_DCHECK(dispatcher->find != nullptr); |
455 | 0 | ABSL_DCHECK(dispatcher->has != nullptr); |
456 | 0 | ABSL_DCHECK(dispatcher->list_keys != nullptr); |
457 | 0 | ABSL_DCHECK(dispatcher->clone != nullptr); |
458 | 0 | } |
459 | | |
460 | | const CustomMapValueDispatcher* absl_nullable dispatcher_ = nullptr; |
461 | | CustomMapValueContent content_ = CustomMapValueContent::Zero(); |
462 | | }; |
463 | | |
464 | 0 | inline std::ostream& operator<<(std::ostream& out, const CustomMapValue& type) { |
465 | 0 | return out << type.DebugString(); |
466 | 0 | } |
467 | | |
468 | | template <> |
469 | | struct NativeTypeTraits<CustomMapValue> final { |
470 | 28 | static NativeTypeId Id(const CustomMapValue& type) { |
471 | 28 | return type.GetTypeId(); |
472 | 28 | } |
473 | | }; |
474 | | |
475 | | inline CustomMapValue UnsafeCustomMapValue( |
476 | | const CustomMapValueDispatcher* absl_nonnull dispatcher |
477 | | ABSL_ATTRIBUTE_LIFETIME_BOUND, |
478 | 0 | CustomMapValueContent content) { |
479 | 0 | return CustomMapValue(dispatcher, content); |
480 | 0 | } |
481 | | |
482 | | } // namespace cel |
483 | | |
484 | | #endif // THIRD_PARTY_CEL_CPP_COMMON_VALUES_PARSED_MAP_VALUE_H_ |