/proc/self/cwd/runtime/standard/equality_functions.cc
Line | Count | Source |
1 | | // Copyright 2022 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 "runtime/standard/equality_functions.h" |
16 | | |
17 | | #include <cstdint> |
18 | | #include <functional> |
19 | | #include <optional> |
20 | | #include <type_traits> |
21 | | #include <utility> |
22 | | |
23 | | #include "absl/base/nullability.h" |
24 | | #include "absl/functional/function_ref.h" |
25 | | #include "absl/status/status.h" |
26 | | #include "absl/status/statusor.h" |
27 | | #include "absl/strings/string_view.h" |
28 | | #include "absl/time/time.h" |
29 | | #include "absl/types/optional.h" |
30 | | #include "base/builtins.h" |
31 | | #include "base/function_adapter.h" |
32 | | #include "common/value.h" |
33 | | #include "common/value_kind.h" |
34 | | #include "internal/number.h" |
35 | | #include "internal/status_macros.h" |
36 | | #include "runtime/function_registry.h" |
37 | | #include "runtime/internal/errors.h" |
38 | | #include "runtime/register_function_helper.h" |
39 | | #include "runtime/runtime_options.h" |
40 | | #include "google/protobuf/arena.h" |
41 | | #include "google/protobuf/descriptor.h" |
42 | | #include "google/protobuf/message.h" |
43 | | |
44 | | namespace cel { |
45 | | namespace { |
46 | | |
47 | | using ::cel::builtin::kEqual; |
48 | | using ::cel::builtin::kInequal; |
49 | | using ::cel::internal::Number; |
50 | | |
51 | | // Declaration for the functors for generic equality operator. |
52 | | // Equal only defined for same-typed values. |
53 | | // Nullopt is returned if equality is not defined. |
54 | | struct HomogenousEqualProvider { |
55 | | static constexpr bool kIsHeterogeneous = false; |
56 | | absl::StatusOr<absl::optional<bool>> operator()( |
57 | | const Value& lhs, const Value& rhs, |
58 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
59 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
60 | | google::protobuf::Arena* absl_nonnull arena) const; |
61 | | }; |
62 | | |
63 | | // Equal defined between compatible types. |
64 | | // Nullopt is returned if equality is not defined. |
65 | | struct HeterogeneousEqualProvider { |
66 | | static constexpr bool kIsHeterogeneous = true; |
67 | | |
68 | | absl::StatusOr<absl::optional<bool>> operator()( |
69 | | const Value& lhs, const Value& rhs, |
70 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
71 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
72 | | google::protobuf::Arena* absl_nonnull arena) const; |
73 | | }; |
74 | | |
75 | | // Comparison template functions |
76 | | template <class Type> |
77 | 0 | absl::optional<bool> Inequal(Type lhs, Type rhs) { |
78 | 0 | return lhs != rhs; |
79 | 0 | } Unexecuted instantiation: equality_functions.cc:std::__1::optional<bool> cel::(anonymous namespace)::Inequal<bool>(bool, bool) Unexecuted instantiation: equality_functions.cc:std::__1::optional<bool> cel::(anonymous namespace)::Inequal<long>(long, long) Unexecuted instantiation: equality_functions.cc:std::__1::optional<bool> cel::(anonymous namespace)::Inequal<unsigned long>(unsigned long, unsigned long) Unexecuted instantiation: equality_functions.cc:std::__1::optional<bool> cel::(anonymous namespace)::Inequal<double>(double, double) Unexecuted instantiation: equality_functions.cc:std::__1::optional<bool> cel::(anonymous namespace)::Inequal<absl::lts_20260526::Duration>(absl::lts_20260526::Duration, absl::lts_20260526::Duration) Unexecuted instantiation: equality_functions.cc:std::__1::optional<bool> cel::(anonymous namespace)::Inequal<absl::lts_20260526::Time>(absl::lts_20260526::Time, absl::lts_20260526::Time) |
80 | | |
81 | | template <> |
82 | 0 | absl::optional<bool> Inequal(const StringValue& lhs, const StringValue& rhs) { |
83 | 0 | return !lhs.Equals(rhs); |
84 | 0 | } |
85 | | |
86 | | template <> |
87 | 0 | absl::optional<bool> Inequal(const BytesValue& lhs, const BytesValue& rhs) { |
88 | 0 | return !lhs.Equals(rhs); |
89 | 0 | } |
90 | | |
91 | | template <> |
92 | 0 | absl::optional<bool> Inequal(const NullValue&, const NullValue&) { |
93 | 0 | return false; |
94 | 0 | } |
95 | | |
96 | | template <> |
97 | 0 | absl::optional<bool> Inequal(const TypeValue& lhs, const TypeValue& rhs) { |
98 | 0 | return lhs.name() != rhs.name(); |
99 | 0 | } |
100 | | |
101 | | template <class Type> |
102 | 15.0k | absl::optional<bool> Equal(Type lhs, Type rhs) { |
103 | 15.0k | return lhs == rhs; |
104 | 15.0k | } equality_functions.cc:std::__1::optional<bool> cel::(anonymous namespace)::Equal<bool>(bool, bool) Line | Count | Source | 102 | 408 | absl::optional<bool> Equal(Type lhs, Type rhs) { | 103 | 408 | return lhs == rhs; | 104 | 408 | } |
equality_functions.cc:std::__1::optional<bool> cel::(anonymous namespace)::Equal<long>(long, long) Line | Count | Source | 102 | 4.89k | absl::optional<bool> Equal(Type lhs, Type rhs) { | 103 | 4.89k | return lhs == rhs; | 104 | 4.89k | } |
equality_functions.cc:std::__1::optional<bool> cel::(anonymous namespace)::Equal<unsigned long>(unsigned long, unsigned long) Line | Count | Source | 102 | 8.25k | absl::optional<bool> Equal(Type lhs, Type rhs) { | 103 | 8.25k | return lhs == rhs; | 104 | 8.25k | } |
equality_functions.cc:std::__1::optional<bool> cel::(anonymous namespace)::Equal<double>(double, double) Line | Count | Source | 102 | 777 | absl::optional<bool> Equal(Type lhs, Type rhs) { | 103 | 777 | return lhs == rhs; | 104 | 777 | } |
equality_functions.cc:std::__1::optional<bool> cel::(anonymous namespace)::Equal<absl::lts_20260526::Duration>(absl::lts_20260526::Duration, absl::lts_20260526::Duration) Line | Count | Source | 102 | 145 | absl::optional<bool> Equal(Type lhs, Type rhs) { | 103 | 145 | return lhs == rhs; | 104 | 145 | } |
equality_functions.cc:std::__1::optional<bool> cel::(anonymous namespace)::Equal<absl::lts_20260526::Time>(absl::lts_20260526::Time, absl::lts_20260526::Time) Line | Count | Source | 102 | 529 | absl::optional<bool> Equal(Type lhs, Type rhs) { | 103 | 529 | return lhs == rhs; | 104 | 529 | } |
|
105 | | |
106 | | template <> |
107 | 327 | absl::optional<bool> Equal(const StringValue& lhs, const StringValue& rhs) { |
108 | 327 | return lhs.Equals(rhs); |
109 | 327 | } |
110 | | |
111 | | template <> |
112 | 720 | absl::optional<bool> Equal(const BytesValue& lhs, const BytesValue& rhs) { |
113 | 720 | return lhs.Equals(rhs); |
114 | 720 | } |
115 | | |
116 | | template <> |
117 | 0 | absl::optional<bool> Equal(const NullValue&, const NullValue&) { |
118 | 0 | return true; |
119 | 0 | } |
120 | | |
121 | | template <> |
122 | 1.74k | absl::optional<bool> Equal(const TypeValue& lhs, const TypeValue& rhs) { |
123 | 1.74k | return lhs.name() == rhs.name(); |
124 | 1.74k | } |
125 | | |
126 | | // Equality for lists. Template parameter provides either heterogeneous or |
127 | | // homogenous equality for comparing members. |
128 | | template <typename EqualsProvider> |
129 | | absl::StatusOr<absl::optional<bool>> ListEqual( |
130 | | const ListValue& lhs, const ListValue& rhs, |
131 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
132 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
133 | 2.67k | google::protobuf::Arena* absl_nonnull arena) { |
134 | 2.67k | if (&lhs == &rhs) { |
135 | 0 | return true; |
136 | 0 | } |
137 | 5.35k | CEL_ASSIGN_OR_RETURN(auto lhs_size, lhs.Size()); |
138 | 5.35k | CEL_ASSIGN_OR_RETURN(auto rhs_size, rhs.Size()); |
139 | 2.67k | if (lhs_size != rhs_size) { |
140 | 540 | return false; |
141 | 540 | } |
142 | | |
143 | 2.23k | for (int i = 0; i < lhs_size; ++i) { |
144 | 1.82k | CEL_ASSIGN_OR_RETURN(auto lhs_i, |
145 | 1.82k | lhs.Get(i, descriptor_pool, message_factory, arena)); |
146 | 1.82k | CEL_ASSIGN_OR_RETURN(auto rhs_i, |
147 | 1.82k | rhs.Get(i, descriptor_pool, message_factory, arena)); |
148 | 1.82k | CEL_ASSIGN_OR_RETURN(absl::optional<bool> eq, |
149 | 1.82k | EqualsProvider()(lhs_i, rhs_i, descriptor_pool, |
150 | 1.82k | message_factory, arena)); |
151 | 1.82k | if (!eq.has_value() || !*eq) { |
152 | 1.72k | return eq; |
153 | 1.72k | } |
154 | 1.82k | } |
155 | 414 | return true; |
156 | 2.13k | } Unexecuted instantiation: equality_functions.cc:absl::lts_20260526::StatusOr<std::__1::optional<bool> > cel::(anonymous namespace)::ListEqual<cel::(anonymous namespace)::HomogenousEqualProvider>(cel::ListValue const&, cel::ListValue const&, google::protobuf::DescriptorPool const*, google::protobuf::MessageFactory*, google::protobuf::Arena*) equality_functions.cc:absl::lts_20260526::StatusOr<std::__1::optional<bool> > cel::(anonymous namespace)::ListEqual<cel::(anonymous namespace)::HeterogeneousEqualProvider>(cel::ListValue const&, cel::ListValue const&, google::protobuf::DescriptorPool const*, google::protobuf::MessageFactory*, google::protobuf::Arena*) Line | Count | Source | 133 | 2.67k | google::protobuf::Arena* absl_nonnull arena) { | 134 | 2.67k | if (&lhs == &rhs) { | 135 | 0 | return true; | 136 | 0 | } | 137 | 5.35k | CEL_ASSIGN_OR_RETURN(auto lhs_size, lhs.Size()); | 138 | 5.35k | CEL_ASSIGN_OR_RETURN(auto rhs_size, rhs.Size()); | 139 | 2.67k | if (lhs_size != rhs_size) { | 140 | 540 | return false; | 141 | 540 | } | 142 | | | 143 | 2.23k | for (int i = 0; i < lhs_size; ++i) { | 144 | 1.82k | CEL_ASSIGN_OR_RETURN(auto lhs_i, | 145 | 1.82k | lhs.Get(i, descriptor_pool, message_factory, arena)); | 146 | 1.82k | CEL_ASSIGN_OR_RETURN(auto rhs_i, | 147 | 1.82k | rhs.Get(i, descriptor_pool, message_factory, arena)); | 148 | 1.82k | CEL_ASSIGN_OR_RETURN(absl::optional<bool> eq, | 149 | 1.82k | EqualsProvider()(lhs_i, rhs_i, descriptor_pool, | 150 | 1.82k | message_factory, arena)); | 151 | 1.82k | if (!eq.has_value() || !*eq) { | 152 | 1.72k | return eq; | 153 | 1.72k | } | 154 | 1.82k | } | 155 | 414 | return true; | 156 | 2.13k | } |
|
157 | | |
158 | | // Opaque types only support heterogeneous equality, and by extension that means |
159 | | // optionals. Heterogeneous equality being enabled is enforced by |
160 | | // `EnableOptionalTypes`. |
161 | | absl::StatusOr<absl::optional<bool>> OpaqueEqual( |
162 | | const OpaqueValue& lhs, const OpaqueValue& rhs, |
163 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
164 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
165 | 0 | google::protobuf::Arena* absl_nonnull arena) { |
166 | 0 | Value result; |
167 | 0 | CEL_RETURN_IF_ERROR( |
168 | 0 | lhs.Equal(rhs, descriptor_pool, message_factory, arena, &result)); |
169 | 0 | if (auto bool_value = result.AsBool(); bool_value) { |
170 | 0 | return bool_value->NativeValue(); |
171 | 0 | } |
172 | 0 | return common_internal::MakeTypeConversionError(result.GetTypeName(), "bool"); |
173 | 0 | } |
174 | | |
175 | 133k | absl::optional<Number> NumberFromValue(const Value& value) { |
176 | 133k | if (value.Is<IntValue>()) { |
177 | 51.0k | return Number::FromInt64(value.GetInt().NativeValue()); |
178 | 82.7k | } else if (value.Is<UintValue>()) { |
179 | 44.9k | return Number::FromUint64(value.GetUint().NativeValue()); |
180 | 44.9k | } else if (value.Is<DoubleValue>()) { |
181 | 18.7k | return Number::FromDouble(value.GetDouble().NativeValue()); |
182 | 18.7k | } |
183 | | |
184 | 19.1k | return std::nullopt; |
185 | 133k | } |
186 | | |
187 | | absl::StatusOr<absl::optional<Value>> CheckAlternativeNumericType( |
188 | | const Value& key, const MapValue& rhs, |
189 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
190 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
191 | 5.00k | google::protobuf::Arena* absl_nonnull arena) { |
192 | 5.00k | absl::optional<Number> number = NumberFromValue(key); |
193 | | |
194 | 5.00k | if (!number.has_value()) { |
195 | 2.51k | return std::nullopt; |
196 | 2.51k | } |
197 | | |
198 | 2.48k | if (!key.IsInt() && number->LosslessConvertibleToInt()) { |
199 | 708 | absl::optional<Value> entry; |
200 | 708 | CEL_ASSIGN_OR_RETURN(entry, |
201 | 708 | rhs.Find(IntValue(number->AsInt()), descriptor_pool, |
202 | 708 | message_factory, arena)); |
203 | 708 | if (entry) { |
204 | 324 | return entry; |
205 | 324 | } |
206 | 708 | } |
207 | | |
208 | 2.16k | if (!key.IsUint() && number->LosslessConvertibleToUint()) { |
209 | 1.23k | absl::optional<Value> entry; |
210 | 1.23k | CEL_ASSIGN_OR_RETURN(entry, |
211 | 1.23k | rhs.Find(UintValue(number->AsUint()), descriptor_pool, |
212 | 1.23k | message_factory, arena)); |
213 | 1.23k | if (entry) { |
214 | 97 | return entry; |
215 | 97 | } |
216 | 1.23k | } |
217 | | |
218 | 2.06k | return std::nullopt; |
219 | 2.16k | } |
220 | | |
221 | | // Equality for maps. Template parameter provides either heterogeneous or |
222 | | // homogenous equality for comparing values. |
223 | | template <typename EqualsProvider> |
224 | | absl::StatusOr<absl::optional<bool>> MapEqual( |
225 | | const MapValue& lhs, const MapValue& rhs, |
226 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
227 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
228 | 10.0k | google::protobuf::Arena* absl_nonnull arena) { |
229 | 10.0k | if (&lhs == &rhs) { |
230 | 0 | return true; |
231 | 0 | } |
232 | 10.0k | if (lhs.Size() != rhs.Size()) { |
233 | 3.42k | return false; |
234 | 3.42k | } |
235 | | |
236 | 13.2k | CEL_ASSIGN_OR_RETURN(auto iter, lhs.NewIterator()); |
237 | | |
238 | 13.2k | while (iter->HasNext()) { |
239 | 6.30k | CEL_ASSIGN_OR_RETURN(auto lhs_key, |
240 | 6.30k | iter->Next(descriptor_pool, message_factory, arena)); |
241 | | |
242 | 6.30k | absl::optional<Value> entry; |
243 | 6.30k | CEL_ASSIGN_OR_RETURN( |
244 | 6.30k | entry, rhs.Find(lhs_key, descriptor_pool, message_factory, arena)); |
245 | | |
246 | 6.30k | if (!entry && EqualsProvider::kIsHeterogeneous) { |
247 | 5.00k | CEL_ASSIGN_OR_RETURN( |
248 | 5.00k | entry, CheckAlternativeNumericType(lhs_key, rhs, descriptor_pool, |
249 | 5.00k | message_factory, arena)); |
250 | 5.00k | } |
251 | 6.30k | if (!entry) { |
252 | 4.58k | return false; |
253 | 4.58k | } |
254 | | |
255 | 3.42k | CEL_ASSIGN_OR_RETURN(auto lhs_value, lhs.Get(lhs_key, descriptor_pool, |
256 | 3.42k | message_factory, arena)); |
257 | 3.42k | CEL_ASSIGN_OR_RETURN(absl::optional<bool> eq, |
258 | 1.71k | EqualsProvider()(lhs_value, *entry, descriptor_pool, |
259 | 1.71k | message_factory, arena)); |
260 | | |
261 | 1.71k | if (!eq.has_value() || !*eq) { |
262 | 687 | return eq; |
263 | 687 | } |
264 | 1.71k | } |
265 | | |
266 | 1.37k | return true; |
267 | 13.2k | } Unexecuted instantiation: equality_functions.cc:absl::lts_20260526::StatusOr<std::__1::optional<bool> > cel::(anonymous namespace)::MapEqual<cel::(anonymous namespace)::HomogenousEqualProvider>(cel::MapValue const&, cel::MapValue const&, google::protobuf::DescriptorPool const*, google::protobuf::MessageFactory*, google::protobuf::Arena*) equality_functions.cc:absl::lts_20260526::StatusOr<std::__1::optional<bool> > cel::(anonymous namespace)::MapEqual<cel::(anonymous namespace)::HeterogeneousEqualProvider>(cel::MapValue const&, cel::MapValue const&, google::protobuf::DescriptorPool const*, google::protobuf::MessageFactory*, google::protobuf::Arena*) Line | Count | Source | 228 | 10.0k | google::protobuf::Arena* absl_nonnull arena) { | 229 | 10.0k | if (&lhs == &rhs) { | 230 | 0 | return true; | 231 | 0 | } | 232 | 10.0k | if (lhs.Size() != rhs.Size()) { | 233 | 3.42k | return false; | 234 | 3.42k | } | 235 | | | 236 | 13.2k | CEL_ASSIGN_OR_RETURN(auto iter, lhs.NewIterator()); | 237 | | | 238 | 13.2k | while (iter->HasNext()) { | 239 | 6.30k | CEL_ASSIGN_OR_RETURN(auto lhs_key, | 240 | 6.30k | iter->Next(descriptor_pool, message_factory, arena)); | 241 | | | 242 | 6.30k | absl::optional<Value> entry; | 243 | 6.30k | CEL_ASSIGN_OR_RETURN( | 244 | 6.30k | entry, rhs.Find(lhs_key, descriptor_pool, message_factory, arena)); | 245 | | | 246 | 6.30k | if (!entry && EqualsProvider::kIsHeterogeneous) { | 247 | 5.00k | CEL_ASSIGN_OR_RETURN( | 248 | 5.00k | entry, CheckAlternativeNumericType(lhs_key, rhs, descriptor_pool, | 249 | 5.00k | message_factory, arena)); | 250 | 5.00k | } | 251 | 6.30k | if (!entry) { | 252 | 4.58k | return false; | 253 | 4.58k | } | 254 | | | 255 | 3.42k | CEL_ASSIGN_OR_RETURN(auto lhs_value, lhs.Get(lhs_key, descriptor_pool, | 256 | 3.42k | message_factory, arena)); | 257 | 3.42k | CEL_ASSIGN_OR_RETURN(absl::optional<bool> eq, | 258 | 1.71k | EqualsProvider()(lhs_value, *entry, descriptor_pool, | 259 | 1.71k | message_factory, arena)); | 260 | | | 261 | 1.71k | if (!eq.has_value() || !*eq) { | 262 | 687 | return eq; | 263 | 687 | } | 264 | 1.71k | } | 265 | | | 266 | 1.37k | return true; | 267 | 13.2k | } |
|
268 | | |
269 | | // Helper for wrapping ==/!= implementations. |
270 | | // Name should point to a static constexpr string so the lambda capture is safe. |
271 | | template <typename Type, typename Op> |
272 | | std::function<Value(Type, Type, const google::protobuf::DescriptorPool* absl_nonnull, |
273 | | google::protobuf::MessageFactory* absl_nonnull, |
274 | | google::protobuf::Arena* absl_nonnull)> |
275 | 0 | WrapComparison(Op op, absl::string_view name) { |
276 | 0 | return [op = std::move(op), name]( |
277 | 0 | Type lhs, Type rhs, |
278 | 0 | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
279 | 0 | google::protobuf::MessageFactory* absl_nonnull message_factory, |
280 | 0 | google::protobuf::Arena* absl_nonnull arena) -> Value { |
281 | 0 | absl::optional<bool> result = op(lhs, rhs); |
282 | |
|
283 | 0 | if (result.has_value()) { |
284 | 0 | return BoolValue(*result); |
285 | 0 | } |
286 | | |
287 | 0 | return ErrorValue::From( |
288 | 0 | cel::runtime_internal::CreateNoMatchingOverloadError(name), arena); |
289 | 0 | }; Unexecuted instantiation: equality_functions.cc:cel::(anonymous namespace)::WrapComparison<bool, std::__1::optional<bool> (*)(bool, bool)>(std::__1::optional<bool> (*)(bool, bool), std::__1::basic_string_view<char, std::__1::char_traits<char> >)::{lambda(bool, bool, google::protobuf::DescriptorPool const*, google::protobuf::MessageFactory*, google::protobuf::Arena*)#1}::operator()(bool, bool, google::protobuf::DescriptorPool const*, google::protobuf::MessageFactory*, google::protobuf::Arena*) constUnexecuted instantiation: equality_functions.cc:cel::(anonymous namespace)::WrapComparison<long, std::__1::optional<bool> (*)(long, long)>(std::__1::optional<bool> (*)(long, long), std::__1::basic_string_view<char, std::__1::char_traits<char> >)::{lambda(long, long, google::protobuf::DescriptorPool const*, google::protobuf::MessageFactory*, google::protobuf::Arena*)#1}::operator()(long, long, google::protobuf::DescriptorPool const*, google::protobuf::MessageFactory*, google::protobuf::Arena*) constUnexecuted instantiation: equality_functions.cc:cel::(anonymous namespace)::WrapComparison<unsigned long, std::__1::optional<bool> (*)(unsigned long, unsigned long)>(std::__1::optional<bool> (*)(unsigned long, unsigned long), std::__1::basic_string_view<char, std::__1::char_traits<char> >)::{lambda(unsigned long, unsigned long, google::protobuf::DescriptorPool const*, google::protobuf::MessageFactory*, google::protobuf::Arena*)#1}::operator()(unsigned long, unsigned long, google::protobuf::DescriptorPool const*, google::protobuf::MessageFactory*, google::protobuf::Arena*) constUnexecuted instantiation: equality_functions.cc:cel::(anonymous namespace)::WrapComparison<double, std::__1::optional<bool> (*)(double, double)>(std::__1::optional<bool> (*)(double, double), std::__1::basic_string_view<char, std::__1::char_traits<char> >)::{lambda(double, double, google::protobuf::DescriptorPool const*, google::protobuf::MessageFactory*, google::protobuf::Arena*)#1}::operator()(double, double, google::protobuf::DescriptorPool const*, google::protobuf::MessageFactory*, google::protobuf::Arena*) constUnexecuted instantiation: equality_functions.cc:cel::(anonymous namespace)::WrapComparison<cel::StringValue const&, std::__1::optional<bool> (*)(cel::StringValue const&, cel::StringValue const&)>(std::__1::optional<bool> (*)(cel::StringValue const&, cel::StringValue const&), std::__1::basic_string_view<char, std::__1::char_traits<char> >)::{lambda(cel::StringValue const&, cel::StringValue const&, google::protobuf::DescriptorPool const*, google::protobuf::MessageFactory*, google::protobuf::Arena*)#1}::operator()(cel::StringValue const&, cel::StringValue const&, google::protobuf::DescriptorPool const*, google::protobuf::MessageFactory*, google::protobuf::Arena*) constUnexecuted instantiation: equality_functions.cc:cel::(anonymous namespace)::WrapComparison<cel::BytesValue const&, std::__1::optional<bool> (*)(cel::BytesValue const&, cel::BytesValue const&)>(std::__1::optional<bool> (*)(cel::BytesValue const&, cel::BytesValue const&), std::__1::basic_string_view<char, std::__1::char_traits<char> >)::{lambda(cel::BytesValue const&, cel::BytesValue const&, google::protobuf::DescriptorPool const*, google::protobuf::MessageFactory*, google::protobuf::Arena*)#1}::operator()(cel::BytesValue const&, cel::BytesValue const&, google::protobuf::DescriptorPool const*, google::protobuf::MessageFactory*, google::protobuf::Arena*) constUnexecuted instantiation: equality_functions.cc:cel::(anonymous namespace)::WrapComparison<absl::lts_20260526::Duration, std::__1::optional<bool> (*)(absl::lts_20260526::Duration, absl::lts_20260526::Duration)>(std::__1::optional<bool> (*)(absl::lts_20260526::Duration, absl::lts_20260526::Duration), std::__1::basic_string_view<char, std::__1::char_traits<char> >)::{lambda(absl::lts_20260526::Duration, absl::lts_20260526::Duration, google::protobuf::DescriptorPool const*, google::protobuf::MessageFactory*, google::protobuf::Arena*)#1}::operator()(absl::lts_20260526::Duration, absl::lts_20260526::Duration, google::protobuf::DescriptorPool const*, google::protobuf::MessageFactory*, google::protobuf::Arena*) constUnexecuted instantiation: equality_functions.cc:cel::(anonymous namespace)::WrapComparison<absl::lts_20260526::Time, std::__1::optional<bool> (*)(absl::lts_20260526::Time, absl::lts_20260526::Time)>(std::__1::optional<bool> (*)(absl::lts_20260526::Time, absl::lts_20260526::Time), std::__1::basic_string_view<char, std::__1::char_traits<char> >)::{lambda(absl::lts_20260526::Time, absl::lts_20260526::Time, google::protobuf::DescriptorPool const*, google::protobuf::MessageFactory*, google::protobuf::Arena*)#1}::operator()(absl::lts_20260526::Time, absl::lts_20260526::Time, google::protobuf::DescriptorPool const*, google::protobuf::MessageFactory*, google::protobuf::Arena*) constUnexecuted instantiation: equality_functions.cc:cel::(anonymous namespace)::WrapComparison<cel::NullValue const&, std::__1::optional<bool> (*)(cel::NullValue const&, cel::NullValue const&)>(std::__1::optional<bool> (*)(cel::NullValue const&, cel::NullValue const&), std::__1::basic_string_view<char, std::__1::char_traits<char> >)::{lambda(cel::NullValue const&, cel::NullValue const&, google::protobuf::DescriptorPool const*, google::protobuf::MessageFactory*, google::protobuf::Arena*)#1}::operator()(cel::NullValue const&, cel::NullValue const&, google::protobuf::DescriptorPool const*, google::protobuf::MessageFactory*, google::protobuf::Arena*) constUnexecuted instantiation: equality_functions.cc:cel::(anonymous namespace)::WrapComparison<cel::TypeValue const&, std::__1::optional<bool> (*)(cel::TypeValue const&, cel::TypeValue const&)>(std::__1::optional<bool> (*)(cel::TypeValue const&, cel::TypeValue const&), std::__1::basic_string_view<char, std::__1::char_traits<char> >)::{lambda(cel::TypeValue const&, cel::TypeValue const&, google::protobuf::DescriptorPool const*, google::protobuf::MessageFactory*, google::protobuf::Arena*)#1}::operator()(cel::TypeValue const&, cel::TypeValue const&, google::protobuf::DescriptorPool const*, google::protobuf::MessageFactory*, google::protobuf::Arena*) const |
290 | 0 | } Unexecuted instantiation: equality_functions.cc:std::__1::function<cel::Value (bool, bool, google::protobuf::DescriptorPool const*, google::protobuf::MessageFactory*, google::protobuf::Arena*)> cel::(anonymous namespace)::WrapComparison<bool, std::__1::optional<bool> (*)(bool, bool)>(std::__1::optional<bool> (*)(bool, bool), std::__1::basic_string_view<char, std::__1::char_traits<char> >) Unexecuted instantiation: equality_functions.cc:std::__1::function<cel::Value (long, long, google::protobuf::DescriptorPool const*, google::protobuf::MessageFactory*, google::protobuf::Arena*)> cel::(anonymous namespace)::WrapComparison<long, std::__1::optional<bool> (*)(long, long)>(std::__1::optional<bool> (*)(long, long), std::__1::basic_string_view<char, std::__1::char_traits<char> >) Unexecuted instantiation: equality_functions.cc:std::__1::function<cel::Value (unsigned long, unsigned long, google::protobuf::DescriptorPool const*, google::protobuf::MessageFactory*, google::protobuf::Arena*)> cel::(anonymous namespace)::WrapComparison<unsigned long, std::__1::optional<bool> (*)(unsigned long, unsigned long)>(std::__1::optional<bool> (*)(unsigned long, unsigned long), std::__1::basic_string_view<char, std::__1::char_traits<char> >) Unexecuted instantiation: equality_functions.cc:std::__1::function<cel::Value (double, double, google::protobuf::DescriptorPool const*, google::protobuf::MessageFactory*, google::protobuf::Arena*)> cel::(anonymous namespace)::WrapComparison<double, std::__1::optional<bool> (*)(double, double)>(std::__1::optional<bool> (*)(double, double), std::__1::basic_string_view<char, std::__1::char_traits<char> >) Unexecuted instantiation: equality_functions.cc:std::__1::function<cel::Value (cel::StringValue const&, cel::StringValue const&, google::protobuf::DescriptorPool const*, google::protobuf::MessageFactory*, google::protobuf::Arena*)> cel::(anonymous namespace)::WrapComparison<cel::StringValue const&, std::__1::optional<bool> (*)(cel::StringValue const&, cel::StringValue const&)>(std::__1::optional<bool> (*)(cel::StringValue const&, cel::StringValue const&), std::__1::basic_string_view<char, std::__1::char_traits<char> >) Unexecuted instantiation: equality_functions.cc:std::__1::function<cel::Value (cel::BytesValue const&, cel::BytesValue const&, google::protobuf::DescriptorPool const*, google::protobuf::MessageFactory*, google::protobuf::Arena*)> cel::(anonymous namespace)::WrapComparison<cel::BytesValue const&, std::__1::optional<bool> (*)(cel::BytesValue const&, cel::BytesValue const&)>(std::__1::optional<bool> (*)(cel::BytesValue const&, cel::BytesValue const&), std::__1::basic_string_view<char, std::__1::char_traits<char> >) Unexecuted instantiation: equality_functions.cc:std::__1::function<cel::Value (absl::lts_20260526::Duration, absl::lts_20260526::Duration, google::protobuf::DescriptorPool const*, google::protobuf::MessageFactory*, google::protobuf::Arena*)> cel::(anonymous namespace)::WrapComparison<absl::lts_20260526::Duration, std::__1::optional<bool> (*)(absl::lts_20260526::Duration, absl::lts_20260526::Duration)>(std::__1::optional<bool> (*)(absl::lts_20260526::Duration, absl::lts_20260526::Duration), std::__1::basic_string_view<char, std::__1::char_traits<char> >) Unexecuted instantiation: equality_functions.cc:std::__1::function<cel::Value (absl::lts_20260526::Time, absl::lts_20260526::Time, google::protobuf::DescriptorPool const*, google::protobuf::MessageFactory*, google::protobuf::Arena*)> cel::(anonymous namespace)::WrapComparison<absl::lts_20260526::Time, std::__1::optional<bool> (*)(absl::lts_20260526::Time, absl::lts_20260526::Time)>(std::__1::optional<bool> (*)(absl::lts_20260526::Time, absl::lts_20260526::Time), std::__1::basic_string_view<char, std::__1::char_traits<char> >) Unexecuted instantiation: equality_functions.cc:std::__1::function<cel::Value (cel::NullValue const&, cel::NullValue const&, google::protobuf::DescriptorPool const*, google::protobuf::MessageFactory*, google::protobuf::Arena*)> cel::(anonymous namespace)::WrapComparison<cel::NullValue const&, std::__1::optional<bool> (*)(cel::NullValue const&, cel::NullValue const&)>(std::__1::optional<bool> (*)(cel::NullValue const&, cel::NullValue const&), std::__1::basic_string_view<char, std::__1::char_traits<char> >) Unexecuted instantiation: equality_functions.cc:std::__1::function<cel::Value (cel::TypeValue const&, cel::TypeValue const&, google::protobuf::DescriptorPool const*, google::protobuf::MessageFactory*, google::protobuf::Arena*)> cel::(anonymous namespace)::WrapComparison<cel::TypeValue const&, std::__1::optional<bool> (*)(cel::TypeValue const&, cel::TypeValue const&)>(std::__1::optional<bool> (*)(cel::TypeValue const&, cel::TypeValue const&), std::__1::basic_string_view<char, std::__1::char_traits<char> >) |
291 | | |
292 | | // Helper method |
293 | | // |
294 | | // Registers all equality functions for template parameters type. |
295 | | template <class Type> |
296 | 0 | absl::Status RegisterEqualityFunctionsForType(cel::FunctionRegistry& registry) { |
297 | 0 | using FunctionAdapter = |
298 | 0 | cel::RegisterHelper<BinaryFunctionAdapter<Value, Type, Type>>; |
299 | | // Inequality |
300 | 0 | CEL_RETURN_IF_ERROR(FunctionAdapter::RegisterGlobalOverload( |
301 | 0 | kInequal, WrapComparison<Type>(&Inequal<Type>, kInequal), registry)); |
302 | | |
303 | | // Equality |
304 | 0 | CEL_RETURN_IF_ERROR(FunctionAdapter::RegisterGlobalOverload( |
305 | 0 | kEqual, WrapComparison<Type>(&Equal<Type>, kEqual), registry)); |
306 | | |
307 | 0 | return absl::OkStatus(); |
308 | 0 | } Unexecuted instantiation: equality_functions.cc:absl::lts_20260526::Status cel::(anonymous namespace)::RegisterEqualityFunctionsForType<bool>(cel::FunctionRegistry&) Unexecuted instantiation: equality_functions.cc:absl::lts_20260526::Status cel::(anonymous namespace)::RegisterEqualityFunctionsForType<long>(cel::FunctionRegistry&) Unexecuted instantiation: equality_functions.cc:absl::lts_20260526::Status cel::(anonymous namespace)::RegisterEqualityFunctionsForType<unsigned long>(cel::FunctionRegistry&) Unexecuted instantiation: equality_functions.cc:absl::lts_20260526::Status cel::(anonymous namespace)::RegisterEqualityFunctionsForType<double>(cel::FunctionRegistry&) Unexecuted instantiation: equality_functions.cc:absl::lts_20260526::Status cel::(anonymous namespace)::RegisterEqualityFunctionsForType<cel::StringValue const&>(cel::FunctionRegistry&) Unexecuted instantiation: equality_functions.cc:absl::lts_20260526::Status cel::(anonymous namespace)::RegisterEqualityFunctionsForType<cel::BytesValue const&>(cel::FunctionRegistry&) Unexecuted instantiation: equality_functions.cc:absl::lts_20260526::Status cel::(anonymous namespace)::RegisterEqualityFunctionsForType<absl::lts_20260526::Duration>(cel::FunctionRegistry&) Unexecuted instantiation: equality_functions.cc:absl::lts_20260526::Status cel::(anonymous namespace)::RegisterEqualityFunctionsForType<absl::lts_20260526::Time>(cel::FunctionRegistry&) Unexecuted instantiation: equality_functions.cc:absl::lts_20260526::Status cel::(anonymous namespace)::RegisterEqualityFunctionsForType<cel::NullValue const&>(cel::FunctionRegistry&) Unexecuted instantiation: equality_functions.cc:absl::lts_20260526::Status cel::(anonymous namespace)::RegisterEqualityFunctionsForType<cel::TypeValue const&>(cel::FunctionRegistry&) |
309 | | |
310 | | template <typename Type, typename Op> |
311 | 0 | auto ComplexEquality(Op&& op) { |
312 | 0 | return [op = std::forward<Op>(op)]( |
313 | 0 | const Type& t1, const Type& t2, |
314 | 0 | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
315 | 0 | google::protobuf::MessageFactory* absl_nonnull message_factory, |
316 | 0 | google::protobuf::Arena* absl_nonnull arena) -> absl::StatusOr<Value> { |
317 | 0 | CEL_ASSIGN_OR_RETURN(absl::optional<bool> result, |
318 | 0 | op(t1, t2, descriptor_pool, message_factory, arena)); |
319 | 0 | if (!result.has_value()) { |
320 | 0 | return ErrorValue::From( |
321 | 0 | cel::runtime_internal::CreateNoMatchingOverloadError(kEqual), arena); |
322 | 0 | } |
323 | 0 | return BoolValue(*result); |
324 | 0 | }; Unexecuted instantiation: equality_functions.cc:cel::(anonymous namespace)::ComplexEquality<cel::ListValue const&, absl::lts_20260526::FunctionRef<absl::lts_20260526::StatusOr<std::__1::optional<bool> > (cel::ListValue const&, cel::ListValue const&, google::protobuf::DescriptorPool const*, google::protobuf::MessageFactory*, google::protobuf::Arena*)>&>(absl::lts_20260526::FunctionRef<absl::lts_20260526::StatusOr<std::__1::optional<bool> > (cel::ListValue const&, cel::ListValue const&, google::protobuf::DescriptorPool const*, google::protobuf::MessageFactory*, google::protobuf::Arena*)>&)::{lambda(cel::ListValue const&, cel::ListValue const&, google::protobuf::DescriptorPool const*, google::protobuf::MessageFactory*, google::protobuf::Arena*)#1}::operator()(cel::ListValue const&, cel::ListValue const&, google::protobuf::DescriptorPool const*, google::protobuf::MessageFactory*, google::protobuf::Arena*) constUnexecuted instantiation: equality_functions.cc:cel::(anonymous namespace)::ComplexEquality<cel::MapValue const&, absl::lts_20260526::FunctionRef<absl::lts_20260526::StatusOr<std::__1::optional<bool> > (cel::MapValue const&, cel::MapValue const&, google::protobuf::DescriptorPool const*, google::protobuf::MessageFactory*, google::protobuf::Arena*)>&>(absl::lts_20260526::FunctionRef<absl::lts_20260526::StatusOr<std::__1::optional<bool> > (cel::MapValue const&, cel::MapValue const&, google::protobuf::DescriptorPool const*, google::protobuf::MessageFactory*, google::protobuf::Arena*)>&)::{lambda(cel::MapValue const&, cel::MapValue const&, google::protobuf::DescriptorPool const*, google::protobuf::MessageFactory*, google::protobuf::Arena*)#1}::operator()(cel::MapValue const&, cel::MapValue const&, google::protobuf::DescriptorPool const*, google::protobuf::MessageFactory*, google::protobuf::Arena*) const |
325 | 0 | } Unexecuted instantiation: equality_functions.cc:auto cel::(anonymous namespace)::ComplexEquality<cel::ListValue const&, absl::lts_20260526::FunctionRef<absl::lts_20260526::StatusOr<std::__1::optional<bool> > (cel::ListValue const&, cel::ListValue const&, google::protobuf::DescriptorPool const*, google::protobuf::MessageFactory*, google::protobuf::Arena*)>&>(absl::lts_20260526::FunctionRef<absl::lts_20260526::StatusOr<std::__1::optional<bool> > (cel::ListValue const&, cel::ListValue const&, google::protobuf::DescriptorPool const*, google::protobuf::MessageFactory*, google::protobuf::Arena*)>&) Unexecuted instantiation: equality_functions.cc:auto cel::(anonymous namespace)::ComplexEquality<cel::MapValue const&, absl::lts_20260526::FunctionRef<absl::lts_20260526::StatusOr<std::__1::optional<bool> > (cel::MapValue const&, cel::MapValue const&, google::protobuf::DescriptorPool const*, google::protobuf::MessageFactory*, google::protobuf::Arena*)>&>(absl::lts_20260526::FunctionRef<absl::lts_20260526::StatusOr<std::__1::optional<bool> > (cel::MapValue const&, cel::MapValue const&, google::protobuf::DescriptorPool const*, google::protobuf::MessageFactory*, google::protobuf::Arena*)>&) |
326 | | |
327 | | template <typename Type, typename Op> |
328 | 0 | auto ComplexInequality(Op&& op) { |
329 | 0 | return [op = std::forward<Op>(op)]( |
330 | 0 | Type t1, Type t2, |
331 | 0 | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
332 | 0 | google::protobuf::MessageFactory* absl_nonnull message_factory, |
333 | 0 | google::protobuf::Arena* absl_nonnull arena) -> absl::StatusOr<Value> { |
334 | 0 | CEL_ASSIGN_OR_RETURN(absl::optional<bool> result, |
335 | 0 | op(t1, t2, descriptor_pool, message_factory, arena)); |
336 | 0 | if (!result.has_value()) { |
337 | 0 | return ErrorValue::From( |
338 | 0 | cel::runtime_internal::CreateNoMatchingOverloadError(kInequal), |
339 | 0 | arena); |
340 | 0 | } |
341 | 0 | return BoolValue(!*result); |
342 | 0 | }; Unexecuted instantiation: equality_functions.cc:cel::(anonymous namespace)::ComplexInequality<cel::ListValue const&, absl::lts_20260526::FunctionRef<absl::lts_20260526::StatusOr<std::__1::optional<bool> > (cel::ListValue const&, cel::ListValue const&, google::protobuf::DescriptorPool const*, google::protobuf::MessageFactory*, google::protobuf::Arena*)>&>(absl::lts_20260526::FunctionRef<absl::lts_20260526::StatusOr<std::__1::optional<bool> > (cel::ListValue const&, cel::ListValue const&, google::protobuf::DescriptorPool const*, google::protobuf::MessageFactory*, google::protobuf::Arena*)>&)::{lambda(cel::ListValue const&, cel::ListValue const&, google::protobuf::DescriptorPool const*, google::protobuf::MessageFactory*, google::protobuf::Arena*)#1}::operator()(cel::ListValue const&, cel::ListValue const&, google::protobuf::DescriptorPool const*, google::protobuf::MessageFactory*, google::protobuf::Arena*) constUnexecuted instantiation: equality_functions.cc:cel::(anonymous namespace)::ComplexInequality<cel::MapValue const&, absl::lts_20260526::FunctionRef<absl::lts_20260526::StatusOr<std::__1::optional<bool> > (cel::MapValue const&, cel::MapValue const&, google::protobuf::DescriptorPool const*, google::protobuf::MessageFactory*, google::protobuf::Arena*)>&>(absl::lts_20260526::FunctionRef<absl::lts_20260526::StatusOr<std::__1::optional<bool> > (cel::MapValue const&, cel::MapValue const&, google::protobuf::DescriptorPool const*, google::protobuf::MessageFactory*, google::protobuf::Arena*)>&)::{lambda(cel::MapValue const&, cel::MapValue const&, google::protobuf::DescriptorPool const*, google::protobuf::MessageFactory*, google::protobuf::Arena*)#1}::operator()(cel::MapValue const&, cel::MapValue const&, google::protobuf::DescriptorPool const*, google::protobuf::MessageFactory*, google::protobuf::Arena*) const |
343 | 0 | } Unexecuted instantiation: equality_functions.cc:auto cel::(anonymous namespace)::ComplexInequality<cel::ListValue const&, absl::lts_20260526::FunctionRef<absl::lts_20260526::StatusOr<std::__1::optional<bool> > (cel::ListValue const&, cel::ListValue const&, google::protobuf::DescriptorPool const*, google::protobuf::MessageFactory*, google::protobuf::Arena*)>&>(absl::lts_20260526::FunctionRef<absl::lts_20260526::StatusOr<std::__1::optional<bool> > (cel::ListValue const&, cel::ListValue const&, google::protobuf::DescriptorPool const*, google::protobuf::MessageFactory*, google::protobuf::Arena*)>&) Unexecuted instantiation: equality_functions.cc:auto cel::(anonymous namespace)::ComplexInequality<cel::MapValue const&, absl::lts_20260526::FunctionRef<absl::lts_20260526::StatusOr<std::__1::optional<bool> > (cel::MapValue const&, cel::MapValue const&, google::protobuf::DescriptorPool const*, google::protobuf::MessageFactory*, google::protobuf::Arena*)>&>(absl::lts_20260526::FunctionRef<absl::lts_20260526::StatusOr<std::__1::optional<bool> > (cel::MapValue const&, cel::MapValue const&, google::protobuf::DescriptorPool const*, google::protobuf::MessageFactory*, google::protobuf::Arena*)>&) |
344 | | |
345 | | template <class Type> |
346 | | absl::Status RegisterComplexEqualityFunctionsForType( |
347 | | absl::FunctionRef<absl::StatusOr<absl::optional<bool>>( |
348 | | Type, Type, const google::protobuf::DescriptorPool* absl_nonnull, |
349 | | google::protobuf::MessageFactory* absl_nonnull, google::protobuf::Arena* absl_nonnull)> |
350 | | op, |
351 | 0 | cel::FunctionRegistry& registry) { |
352 | 0 | using FunctionAdapter = cel::RegisterHelper< |
353 | 0 | BinaryFunctionAdapter<absl::StatusOr<Value>, Type, Type>>; |
354 | | // Inequality |
355 | 0 | CEL_RETURN_IF_ERROR(FunctionAdapter::RegisterGlobalOverload( |
356 | 0 | kInequal, ComplexInequality<Type>(op), registry)); |
357 | | |
358 | | // Equality |
359 | 0 | CEL_RETURN_IF_ERROR(FunctionAdapter::RegisterGlobalOverload( |
360 | 0 | kEqual, ComplexEquality<Type>(op), registry)); |
361 | | |
362 | 0 | return absl::OkStatus(); |
363 | 0 | } Unexecuted instantiation: equality_functions.cc:absl::lts_20260526::Status cel::(anonymous namespace)::RegisterComplexEqualityFunctionsForType<cel::ListValue const&>(absl::lts_20260526::FunctionRef<absl::lts_20260526::StatusOr<std::__1::optional<bool> > (cel::ListValue const&, cel::ListValue const&, google::protobuf::DescriptorPool const*, google::protobuf::MessageFactory*, google::protobuf::Arena*)>, cel::FunctionRegistry&) Unexecuted instantiation: equality_functions.cc:absl::lts_20260526::Status cel::(anonymous namespace)::RegisterComplexEqualityFunctionsForType<cel::MapValue const&>(absl::lts_20260526::FunctionRef<absl::lts_20260526::StatusOr<std::__1::optional<bool> > (cel::MapValue const&, cel::MapValue const&, google::protobuf::DescriptorPool const*, google::protobuf::MessageFactory*, google::protobuf::Arena*)>, cel::FunctionRegistry&) |
364 | | |
365 | | absl::Status RegisterHomogenousEqualityFunctions( |
366 | 0 | cel::FunctionRegistry& registry) { |
367 | 0 | CEL_RETURN_IF_ERROR(RegisterEqualityFunctionsForType<bool>(registry)); |
368 | | |
369 | 0 | CEL_RETURN_IF_ERROR(RegisterEqualityFunctionsForType<int64_t>(registry)); |
370 | | |
371 | 0 | CEL_RETURN_IF_ERROR(RegisterEqualityFunctionsForType<uint64_t>(registry)); |
372 | | |
373 | 0 | CEL_RETURN_IF_ERROR(RegisterEqualityFunctionsForType<double>(registry)); |
374 | | |
375 | 0 | CEL_RETURN_IF_ERROR( |
376 | 0 | RegisterEqualityFunctionsForType<const cel::StringValue&>(registry)); |
377 | | |
378 | 0 | CEL_RETURN_IF_ERROR( |
379 | 0 | RegisterEqualityFunctionsForType<const cel::BytesValue&>(registry)); |
380 | | |
381 | 0 | CEL_RETURN_IF_ERROR( |
382 | 0 | RegisterEqualityFunctionsForType<absl::Duration>(registry)); |
383 | | |
384 | 0 | CEL_RETURN_IF_ERROR(RegisterEqualityFunctionsForType<absl::Time>(registry)); |
385 | | |
386 | 0 | CEL_RETURN_IF_ERROR( |
387 | 0 | RegisterEqualityFunctionsForType<const cel::NullValue&>(registry)); |
388 | | |
389 | 0 | CEL_RETURN_IF_ERROR( |
390 | 0 | RegisterEqualityFunctionsForType<const cel::TypeValue&>(registry)); |
391 | | |
392 | 0 | CEL_RETURN_IF_ERROR( |
393 | 0 | RegisterComplexEqualityFunctionsForType<const cel::ListValue&>( |
394 | 0 | &ListEqual<HomogenousEqualProvider>, registry)); |
395 | | |
396 | 0 | CEL_RETURN_IF_ERROR( |
397 | 0 | RegisterComplexEqualityFunctionsForType<const cel::MapValue&>( |
398 | 0 | &MapEqual<HomogenousEqualProvider>, registry)); |
399 | | |
400 | 0 | return absl::OkStatus(); |
401 | 0 | } |
402 | | |
403 | 0 | absl::Status RegisterNullMessageEqualityFunctions(FunctionRegistry& registry) { |
404 | | // equals |
405 | 0 | CEL_RETURN_IF_ERROR( |
406 | 0 | (cel::RegisterHelper< |
407 | 0 | BinaryFunctionAdapter<bool, const StructValue&, const NullValue&>>:: |
408 | 0 | RegisterGlobalOverload( |
409 | 0 | kEqual, |
410 | 0 | [](const StructValue&, const NullValue&) { return false; }, |
411 | 0 | registry))); |
412 | | |
413 | 0 | CEL_RETURN_IF_ERROR( |
414 | 0 | (cel::RegisterHelper< |
415 | 0 | BinaryFunctionAdapter<bool, const NullValue&, const StructValue&>>:: |
416 | 0 | RegisterGlobalOverload( |
417 | 0 | kEqual, |
418 | 0 | [](const NullValue&, const StructValue&) { return false; }, |
419 | 0 | registry))); |
420 | | |
421 | | // inequals |
422 | 0 | CEL_RETURN_IF_ERROR( |
423 | 0 | (cel::RegisterHelper< |
424 | 0 | BinaryFunctionAdapter<bool, const StructValue&, const NullValue&>>:: |
425 | 0 | RegisterGlobalOverload( |
426 | 0 | kInequal, |
427 | 0 | [](const StructValue&, const NullValue&) { return true; }, |
428 | 0 | registry))); |
429 | | |
430 | 0 | return cel::RegisterHelper< |
431 | 0 | BinaryFunctionAdapter<bool, const NullValue&, const StructValue&>>:: |
432 | 0 | RegisterGlobalOverload( |
433 | 0 | kInequal, [](const NullValue&, const StructValue&) { return true; }, |
434 | 0 | registry); |
435 | 0 | } |
436 | | |
437 | | template <typename EqualsProvider> |
438 | | absl::StatusOr<absl::optional<bool>> HomogenousValueEqual( |
439 | | const Value& v1, const Value& v2, |
440 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
441 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
442 | 30.5k | google::protobuf::Arena* absl_nonnull arena) { |
443 | 30.5k | if (v1.kind() != v2.kind()) { |
444 | 0 | return std::nullopt; |
445 | 0 | } |
446 | | |
447 | 30.5k | static_assert(std::is_lvalue_reference_v<decltype(v1.GetString())>, |
448 | 30.5k | "unexpected value copy"); |
449 | | |
450 | 30.5k | switch (v1->kind()) { |
451 | 408 | case ValueKind::kBool: |
452 | 408 | return Equal<bool>(v1.GetBool().NativeValue(), |
453 | 408 | v2.GetBool().NativeValue()); |
454 | 0 | case ValueKind::kNull: |
455 | 0 | return Equal<const NullValue&>(v1.GetNull(), v2.GetNull()); |
456 | 4.89k | case ValueKind::kInt: |
457 | 4.89k | return Equal<int64_t>(v1.GetInt().NativeValue(), |
458 | 4.89k | v2.GetInt().NativeValue()); |
459 | 8.25k | case ValueKind::kUint: |
460 | 8.25k | return Equal<uint64_t>(v1.GetUint().NativeValue(), |
461 | 8.25k | v2.GetUint().NativeValue()); |
462 | 777 | case ValueKind::kDouble: |
463 | 777 | return Equal<double>(v1.GetDouble().NativeValue(), |
464 | 777 | v2.GetDouble().NativeValue()); |
465 | 145 | case ValueKind::kDuration: |
466 | 145 | return Equal<absl::Duration>(v1.GetDuration().NativeValue(), |
467 | 145 | v2.GetDuration().NativeValue()); |
468 | 529 | case ValueKind::kTimestamp: |
469 | 529 | return Equal<absl::Time>(v1.GetTimestamp().NativeValue(), |
470 | 529 | v2.GetTimestamp().NativeValue()); |
471 | 1.74k | case ValueKind::kCelType: |
472 | 1.74k | return Equal<const TypeValue&>(v1.GetType(), v2.GetType()); |
473 | 327 | case ValueKind::kString: |
474 | 327 | return Equal<const StringValue&>(v1.GetString(), v2.GetString()); |
475 | 720 | case ValueKind::kBytes: |
476 | 720 | return Equal<const cel::BytesValue&>(v1.GetBytes(), v2.GetBytes()); |
477 | 2.67k | case ValueKind::kList: |
478 | 2.67k | return ListEqual<EqualsProvider>(v1.GetList(), v2.GetList(), |
479 | 2.67k | descriptor_pool, message_factory, arena); |
480 | 10.0k | case ValueKind::kMap: |
481 | 10.0k | return MapEqual<EqualsProvider>(v1.GetMap(), v2.GetMap(), descriptor_pool, |
482 | 10.0k | message_factory, arena); |
483 | 0 | case ValueKind::kOpaque: |
484 | 0 | return OpaqueEqual(v1.GetOpaque(), v2.GetOpaque(), descriptor_pool, |
485 | 0 | message_factory, arena); |
486 | 0 | default: |
487 | 0 | return std::nullopt; |
488 | 30.5k | } |
489 | 30.5k | } Unexecuted instantiation: equality_functions.cc:absl::lts_20260526::StatusOr<std::__1::optional<bool> > cel::(anonymous namespace)::HomogenousValueEqual<cel::(anonymous namespace)::HomogenousEqualProvider>(cel::Value const&, cel::Value const&, google::protobuf::DescriptorPool const*, google::protobuf::MessageFactory*, google::protobuf::Arena*) equality_functions.cc:absl::lts_20260526::StatusOr<std::__1::optional<bool> > cel::(anonymous namespace)::HomogenousValueEqual<cel::(anonymous namespace)::HeterogeneousEqualProvider>(cel::Value const&, cel::Value const&, google::protobuf::DescriptorPool const*, google::protobuf::MessageFactory*, google::protobuf::Arena*) Line | Count | Source | 442 | 30.5k | google::protobuf::Arena* absl_nonnull arena) { | 443 | 30.5k | if (v1.kind() != v2.kind()) { | 444 | 0 | return std::nullopt; | 445 | 0 | } | 446 | | | 447 | 30.5k | static_assert(std::is_lvalue_reference_v<decltype(v1.GetString())>, | 448 | 30.5k | "unexpected value copy"); | 449 | | | 450 | 30.5k | switch (v1->kind()) { | 451 | 408 | case ValueKind::kBool: | 452 | 408 | return Equal<bool>(v1.GetBool().NativeValue(), | 453 | 408 | v2.GetBool().NativeValue()); | 454 | 0 | case ValueKind::kNull: | 455 | 0 | return Equal<const NullValue&>(v1.GetNull(), v2.GetNull()); | 456 | 4.89k | case ValueKind::kInt: | 457 | 4.89k | return Equal<int64_t>(v1.GetInt().NativeValue(), | 458 | 4.89k | v2.GetInt().NativeValue()); | 459 | 8.25k | case ValueKind::kUint: | 460 | 8.25k | return Equal<uint64_t>(v1.GetUint().NativeValue(), | 461 | 8.25k | v2.GetUint().NativeValue()); | 462 | 777 | case ValueKind::kDouble: | 463 | 777 | return Equal<double>(v1.GetDouble().NativeValue(), | 464 | 777 | v2.GetDouble().NativeValue()); | 465 | 145 | case ValueKind::kDuration: | 466 | 145 | return Equal<absl::Duration>(v1.GetDuration().NativeValue(), | 467 | 145 | v2.GetDuration().NativeValue()); | 468 | 529 | case ValueKind::kTimestamp: | 469 | 529 | return Equal<absl::Time>(v1.GetTimestamp().NativeValue(), | 470 | 529 | v2.GetTimestamp().NativeValue()); | 471 | 1.74k | case ValueKind::kCelType: | 472 | 1.74k | return Equal<const TypeValue&>(v1.GetType(), v2.GetType()); | 473 | 327 | case ValueKind::kString: | 474 | 327 | return Equal<const StringValue&>(v1.GetString(), v2.GetString()); | 475 | 720 | case ValueKind::kBytes: | 476 | 720 | return Equal<const cel::BytesValue&>(v1.GetBytes(), v2.GetBytes()); | 477 | 2.67k | case ValueKind::kList: | 478 | 2.67k | return ListEqual<EqualsProvider>(v1.GetList(), v2.GetList(), | 479 | 2.67k | descriptor_pool, message_factory, arena); | 480 | 10.0k | case ValueKind::kMap: | 481 | 10.0k | return MapEqual<EqualsProvider>(v1.GetMap(), v2.GetMap(), descriptor_pool, | 482 | 10.0k | message_factory, arena); | 483 | 0 | case ValueKind::kOpaque: | 484 | 0 | return OpaqueEqual(v1.GetOpaque(), v2.GetOpaque(), descriptor_pool, | 485 | 0 | message_factory, arena); | 486 | 0 | default: | 487 | 0 | return std::nullopt; | 488 | 30.5k | } | 489 | 30.5k | } |
|
490 | | |
491 | | absl::StatusOr<Value> EqualOverloadImpl( |
492 | | const Value& lhs, const Value& rhs, |
493 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
494 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
495 | 0 | google::protobuf::Arena* absl_nonnull arena) { |
496 | 0 | CEL_ASSIGN_OR_RETURN(absl::optional<bool> result, |
497 | 0 | runtime_internal::ValueEqualImpl( |
498 | 0 | lhs, rhs, descriptor_pool, message_factory, arena)); |
499 | 0 | if (result.has_value()) { |
500 | 0 | return BoolValue(*result); |
501 | 0 | } |
502 | 0 | return ErrorValue::From( |
503 | 0 | cel::runtime_internal::CreateNoMatchingOverloadError(kEqual), arena); |
504 | 0 | } |
505 | | |
506 | | absl::StatusOr<Value> InequalOverloadImpl( |
507 | | const Value& lhs, const Value& rhs, |
508 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
509 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
510 | 0 | google::protobuf::Arena* absl_nonnull arena) { |
511 | 0 | CEL_ASSIGN_OR_RETURN(absl::optional<bool> result, |
512 | 0 | runtime_internal::ValueEqualImpl( |
513 | 0 | lhs, rhs, descriptor_pool, message_factory, arena)); |
514 | 0 | if (result.has_value()) { |
515 | 0 | return BoolValue(!*result); |
516 | 0 | } |
517 | 0 | return ErrorValue::From( |
518 | 0 | cel::runtime_internal::CreateNoMatchingOverloadError(kInequal), arena); |
519 | 0 | } |
520 | | |
521 | | absl::Status RegisterHeterogeneousEqualityFunctions( |
522 | 0 | cel::FunctionRegistry& registry) { |
523 | 0 | using Adapter = cel::RegisterHelper< |
524 | 0 | BinaryFunctionAdapter<absl::StatusOr<Value>, const Value&, const Value&>>; |
525 | 0 | CEL_RETURN_IF_ERROR( |
526 | 0 | Adapter::RegisterGlobalOverload(kEqual, &EqualOverloadImpl, registry)); |
527 | | |
528 | 0 | CEL_RETURN_IF_ERROR(Adapter::RegisterGlobalOverload( |
529 | 0 | kInequal, &InequalOverloadImpl, registry)); |
530 | | |
531 | 0 | return absl::OkStatus(); |
532 | 0 | } |
533 | | |
534 | | absl::StatusOr<absl::optional<bool>> HomogenousEqualProvider::operator()( |
535 | | const Value& lhs, const Value& rhs, |
536 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
537 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
538 | 0 | google::protobuf::Arena* absl_nonnull arena) const { |
539 | 0 | return HomogenousValueEqual<HomogenousEqualProvider>( |
540 | 0 | lhs, rhs, descriptor_pool, message_factory, arena); |
541 | 0 | } |
542 | | |
543 | | absl::StatusOr<absl::optional<bool>> HeterogeneousEqualProvider::operator()( |
544 | | const Value& lhs, const Value& rhs, |
545 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
546 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
547 | 3.53k | google::protobuf::Arena* absl_nonnull arena) const { |
548 | 3.53k | return runtime_internal::ValueEqualImpl(lhs, rhs, descriptor_pool, |
549 | 3.53k | message_factory, arena); |
550 | 3.53k | } |
551 | | |
552 | | } // namespace |
553 | | |
554 | | namespace runtime_internal { |
555 | | |
556 | | absl::StatusOr<absl::optional<bool>> ValueEqualImpl( |
557 | | const Value& v1, const Value& v2, |
558 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
559 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
560 | 94.9k | google::protobuf::Arena* absl_nonnull arena) { |
561 | 94.9k | if (v1.kind() == v2.kind()) { |
562 | 30.5k | if (v1.IsStruct() && v2.IsStruct()) { |
563 | 0 | CEL_ASSIGN_OR_RETURN( |
564 | 0 | Value result, |
565 | 0 | v1.GetStruct().Equal(v2, descriptor_pool, message_factory, arena)); |
566 | 0 | if (result.IsBool()) { |
567 | 0 | return result.GetBool().NativeValue(); |
568 | 0 | } |
569 | 0 | return false; |
570 | 0 | } |
571 | 30.5k | return HomogenousValueEqual<HeterogeneousEqualProvider>( |
572 | 30.5k | v1, v2, descriptor_pool, message_factory, arena); |
573 | 30.5k | } |
574 | | |
575 | 64.4k | absl::optional<Number> lhs = NumberFromValue(v1); |
576 | 64.4k | absl::optional<Number> rhs = NumberFromValue(v2); |
577 | | |
578 | 64.4k | if (rhs.has_value() && lhs.has_value()) { |
579 | 49.5k | return *lhs == *rhs; |
580 | 49.5k | } |
581 | | |
582 | | // TODO(uncreated-issue/6): It's currently possible for the interpreter to create a |
583 | | // map containing an Error. Return no matching overload to propagate an error |
584 | | // instead of a false result. |
585 | 14.9k | if (v1.IsError() || v1.IsUnknown() || v2.IsError() || v2.IsUnknown()) { |
586 | 0 | return std::nullopt; |
587 | 0 | } |
588 | | |
589 | 14.9k | return false; |
590 | 14.9k | } |
591 | | |
592 | | } // namespace runtime_internal |
593 | | |
594 | | absl::Status RegisterEqualityFunctions(FunctionRegistry& registry, |
595 | 22.7k | const RuntimeOptions& options) { |
596 | 22.7k | if (options.enable_heterogeneous_equality) { |
597 | 22.7k | if (options.enable_fast_builtins) { |
598 | | // If enabled, the evaluator provides an implementation that works |
599 | | // directly on the value stack. |
600 | 22.7k | return absl::OkStatus(); |
601 | 22.7k | } |
602 | | // Heterogeneous equality uses one generic overload that delegates to the |
603 | | // right equality implementation at runtime. |
604 | 0 | CEL_RETURN_IF_ERROR(RegisterHeterogeneousEqualityFunctions(registry)); |
605 | 0 | } else { |
606 | 0 | CEL_RETURN_IF_ERROR(RegisterHomogenousEqualityFunctions(registry)); |
607 | | |
608 | 0 | CEL_RETURN_IF_ERROR(RegisterNullMessageEqualityFunctions(registry)); |
609 | 0 | } |
610 | 0 | return absl::OkStatus(); |
611 | 22.7k | } |
612 | | |
613 | | } // namespace cel |