/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_20260107::Duration>(absl::lts_20260107::Duration, absl::lts_20260107::Duration) Unexecuted instantiation: equality_functions.cc:std::__1::optional<bool> cel::(anonymous namespace)::Inequal<absl::lts_20260107::Time>(absl::lts_20260107::Time, absl::lts_20260107::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 | 532 | absl::optional<bool> Equal(Type lhs, Type rhs) { |
103 | 532 | return lhs == rhs; |
104 | 532 | } equality_functions.cc:std::__1::optional<bool> cel::(anonymous namespace)::Equal<bool>(bool, bool) Line | Count | Source | 102 | 9 | absl::optional<bool> Equal(Type lhs, Type rhs) { | 103 | 9 | return lhs == rhs; | 104 | 9 | } |
equality_functions.cc:std::__1::optional<bool> cel::(anonymous namespace)::Equal<long>(long, long) Line | Count | Source | 102 | 309 | absl::optional<bool> Equal(Type lhs, Type rhs) { | 103 | 309 | return lhs == rhs; | 104 | 309 | } |
equality_functions.cc:std::__1::optional<bool> cel::(anonymous namespace)::Equal<unsigned long>(unsigned long, unsigned long) Line | Count | Source | 102 | 180 | absl::optional<bool> Equal(Type lhs, Type rhs) { | 103 | 180 | return lhs == rhs; | 104 | 180 | } |
equality_functions.cc:std::__1::optional<bool> cel::(anonymous namespace)::Equal<double>(double, double) Line | Count | Source | 102 | 34 | absl::optional<bool> Equal(Type lhs, Type rhs) { | 103 | 34 | return lhs == rhs; | 104 | 34 | } |
Unexecuted instantiation: equality_functions.cc:std::__1::optional<bool> cel::(anonymous namespace)::Equal<absl::lts_20260107::Duration>(absl::lts_20260107::Duration, absl::lts_20260107::Duration) Unexecuted instantiation: equality_functions.cc:std::__1::optional<bool> cel::(anonymous namespace)::Equal<absl::lts_20260107::Time>(absl::lts_20260107::Time, absl::lts_20260107::Time) |
105 | | |
106 | | template <> |
107 | 113 | absl::optional<bool> Equal(const StringValue& lhs, const StringValue& rhs) { |
108 | 113 | return lhs.Equals(rhs); |
109 | 113 | } |
110 | | |
111 | | template <> |
112 | 18 | absl::optional<bool> Equal(const BytesValue& lhs, const BytesValue& rhs) { |
113 | 18 | return lhs.Equals(rhs); |
114 | 18 | } |
115 | | |
116 | | template <> |
117 | 0 | absl::optional<bool> Equal(const NullValue&, const NullValue&) { |
118 | 0 | return true; |
119 | 0 | } |
120 | | |
121 | | template <> |
122 | 2 | absl::optional<bool> Equal(const TypeValue& lhs, const TypeValue& rhs) { |
123 | 2 | return lhs.name() == rhs.name(); |
124 | 2 | } |
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 | 84 | google::protobuf::Arena* absl_nonnull arena) { |
134 | 84 | if (&lhs == &rhs) { |
135 | 0 | return true; |
136 | 0 | } |
137 | 168 | CEL_ASSIGN_OR_RETURN(auto lhs_size, lhs.Size()); |
138 | 168 | CEL_ASSIGN_OR_RETURN(auto rhs_size, rhs.Size()); |
139 | 84 | if (lhs_size != rhs_size) { |
140 | 14 | return false; |
141 | 14 | } |
142 | | |
143 | 74 | for (int i = 0; i < lhs_size; ++i) { |
144 | 20 | CEL_ASSIGN_OR_RETURN(auto lhs_i, |
145 | 20 | lhs.Get(i, descriptor_pool, message_factory, arena)); |
146 | 20 | CEL_ASSIGN_OR_RETURN(auto rhs_i, |
147 | 20 | rhs.Get(i, descriptor_pool, message_factory, arena)); |
148 | 20 | CEL_ASSIGN_OR_RETURN(absl::optional<bool> eq, |
149 | 20 | EqualsProvider()(lhs_i, rhs_i, descriptor_pool, |
150 | 20 | message_factory, arena)); |
151 | 20 | if (!eq.has_value() || !*eq) { |
152 | 16 | return eq; |
153 | 16 | } |
154 | 20 | } |
155 | 54 | return true; |
156 | 70 | } Unexecuted instantiation: equality_functions.cc:absl::lts_20260107::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_20260107::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 | 84 | google::protobuf::Arena* absl_nonnull arena) { | 134 | 84 | if (&lhs == &rhs) { | 135 | 0 | return true; | 136 | 0 | } | 137 | 168 | CEL_ASSIGN_OR_RETURN(auto lhs_size, lhs.Size()); | 138 | 168 | CEL_ASSIGN_OR_RETURN(auto rhs_size, rhs.Size()); | 139 | 84 | if (lhs_size != rhs_size) { | 140 | 14 | return false; | 141 | 14 | } | 142 | | | 143 | 74 | for (int i = 0; i < lhs_size; ++i) { | 144 | 20 | CEL_ASSIGN_OR_RETURN(auto lhs_i, | 145 | 20 | lhs.Get(i, descriptor_pool, message_factory, arena)); | 146 | 20 | CEL_ASSIGN_OR_RETURN(auto rhs_i, | 147 | 20 | rhs.Get(i, descriptor_pool, message_factory, arena)); | 148 | 20 | CEL_ASSIGN_OR_RETURN(absl::optional<bool> eq, | 149 | 20 | EqualsProvider()(lhs_i, rhs_i, descriptor_pool, | 150 | 20 | message_factory, arena)); | 151 | 20 | if (!eq.has_value() || !*eq) { | 152 | 16 | return eq; | 153 | 16 | } | 154 | 20 | } | 155 | 54 | return true; | 156 | 70 | } |
|
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 TypeConversionError(result.GetTypeName(), "bool").NativeValue(); |
173 | 0 | } |
174 | | |
175 | 6.13k | absl::optional<Number> NumberFromValue(const Value& value) { |
176 | 6.13k | if (value.Is<IntValue>()) { |
177 | 2.22k | return Number::FromInt64(value.GetInt().NativeValue()); |
178 | 3.90k | } else if (value.Is<UintValue>()) { |
179 | 1.42k | return Number::FromUint64(value.GetUint().NativeValue()); |
180 | 2.48k | } else if (value.Is<DoubleValue>()) { |
181 | 1.04k | return Number::FromDouble(value.GetDouble().NativeValue()); |
182 | 1.04k | } |
183 | | |
184 | 1.44k | return absl::nullopt; |
185 | 6.13k | } |
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 | 30 | google::protobuf::Arena* absl_nonnull arena) { |
192 | 30 | absl::optional<Number> number = NumberFromValue(key); |
193 | | |
194 | 30 | if (!number.has_value()) { |
195 | 1 | return absl::nullopt; |
196 | 1 | } |
197 | | |
198 | 29 | if (!key.IsInt() && number->LosslessConvertibleToInt()) { |
199 | 5 | absl::optional<Value> entry; |
200 | 5 | CEL_ASSIGN_OR_RETURN(entry, |
201 | 5 | rhs.Find(IntValue(number->AsInt()), descriptor_pool, |
202 | 5 | message_factory, arena)); |
203 | 5 | if (entry) { |
204 | 0 | return entry; |
205 | 0 | } |
206 | 5 | } |
207 | | |
208 | 29 | if (!key.IsUint() && number->LosslessConvertibleToUint()) { |
209 | 19 | absl::optional<Value> entry; |
210 | 19 | CEL_ASSIGN_OR_RETURN(entry, |
211 | 19 | rhs.Find(UintValue(number->AsUint()), descriptor_pool, |
212 | 19 | message_factory, arena)); |
213 | 19 | if (entry) { |
214 | 0 | return entry; |
215 | 0 | } |
216 | 19 | } |
217 | | |
218 | 29 | return absl::nullopt; |
219 | 29 | } |
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 | 50 | google::protobuf::Arena* absl_nonnull arena) { |
229 | 50 | if (&lhs == &rhs) { |
230 | 0 | return true; |
231 | 0 | } |
232 | 50 | if (lhs.Size() != rhs.Size()) { |
233 | 5 | return false; |
234 | 5 | } |
235 | | |
236 | 90 | CEL_ASSIGN_OR_RETURN(auto iter, lhs.NewIterator()); |
237 | | |
238 | 90 | while (iter->HasNext()) { |
239 | 44 | CEL_ASSIGN_OR_RETURN(auto lhs_key, |
240 | 44 | iter->Next(descriptor_pool, message_factory, arena)); |
241 | | |
242 | 44 | absl::optional<Value> entry; |
243 | 44 | CEL_ASSIGN_OR_RETURN( |
244 | 44 | entry, rhs.Find(lhs_key, descriptor_pool, message_factory, arena)); |
245 | | |
246 | 44 | if (!entry && EqualsProvider::kIsHeterogeneous) { |
247 | 30 | CEL_ASSIGN_OR_RETURN( |
248 | 30 | entry, CheckAlternativeNumericType(lhs_key, rhs, descriptor_pool, |
249 | 30 | message_factory, arena)); |
250 | 30 | } |
251 | 44 | if (!entry) { |
252 | 30 | return false; |
253 | 30 | } |
254 | | |
255 | 28 | CEL_ASSIGN_OR_RETURN(auto lhs_value, lhs.Get(lhs_key, descriptor_pool, |
256 | 28 | message_factory, arena)); |
257 | 28 | CEL_ASSIGN_OR_RETURN(absl::optional<bool> eq, |
258 | 14 | EqualsProvider()(lhs_value, *entry, descriptor_pool, |
259 | 14 | message_factory, arena)); |
260 | | |
261 | 14 | if (!eq.has_value() || !*eq) { |
262 | 9 | return eq; |
263 | 9 | } |
264 | 14 | } |
265 | | |
266 | 6 | return true; |
267 | 90 | } Unexecuted instantiation: equality_functions.cc:absl::lts_20260107::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_20260107::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 | 50 | google::protobuf::Arena* absl_nonnull arena) { | 229 | 50 | if (&lhs == &rhs) { | 230 | 0 | return true; | 231 | 0 | } | 232 | 50 | if (lhs.Size() != rhs.Size()) { | 233 | 5 | return false; | 234 | 5 | } | 235 | | | 236 | 90 | CEL_ASSIGN_OR_RETURN(auto iter, lhs.NewIterator()); | 237 | | | 238 | 90 | while (iter->HasNext()) { | 239 | 44 | CEL_ASSIGN_OR_RETURN(auto lhs_key, | 240 | 44 | iter->Next(descriptor_pool, message_factory, arena)); | 241 | | | 242 | 44 | absl::optional<Value> entry; | 243 | 44 | CEL_ASSIGN_OR_RETURN( | 244 | 44 | entry, rhs.Find(lhs_key, descriptor_pool, message_factory, arena)); | 245 | | | 246 | 44 | if (!entry && EqualsProvider::kIsHeterogeneous) { | 247 | 30 | CEL_ASSIGN_OR_RETURN( | 248 | 30 | entry, CheckAlternativeNumericType(lhs_key, rhs, descriptor_pool, | 249 | 30 | message_factory, arena)); | 250 | 30 | } | 251 | 44 | if (!entry) { | 252 | 30 | return false; | 253 | 30 | } | 254 | | | 255 | 28 | CEL_ASSIGN_OR_RETURN(auto lhs_value, lhs.Get(lhs_key, descriptor_pool, | 256 | 28 | message_factory, arena)); | 257 | 28 | CEL_ASSIGN_OR_RETURN(absl::optional<bool> eq, | 258 | 14 | EqualsProvider()(lhs_value, *entry, descriptor_pool, | 259 | 14 | message_factory, arena)); | 260 | | | 261 | 14 | if (!eq.has_value() || !*eq) { | 262 | 9 | return eq; | 263 | 9 | } | 264 | 14 | } | 265 | | | 266 | 6 | return true; | 267 | 90 | } |
|
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( |
288 | 0 | cel::runtime_internal::CreateNoMatchingOverloadError(name)); |
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_20260107::Duration, std::__1::optional<bool> (*)(absl::lts_20260107::Duration, absl::lts_20260107::Duration)>(std::__1::optional<bool> (*)(absl::lts_20260107::Duration, absl::lts_20260107::Duration), std::__1::basic_string_view<char, std::__1::char_traits<char> >)::{lambda(absl::lts_20260107::Duration, absl::lts_20260107::Duration, google::protobuf::DescriptorPool const*, google::protobuf::MessageFactory*, google::protobuf::Arena*)#1}::operator()(absl::lts_20260107::Duration, absl::lts_20260107::Duration, google::protobuf::DescriptorPool const*, google::protobuf::MessageFactory*, google::protobuf::Arena*) constUnexecuted instantiation: equality_functions.cc:cel::(anonymous namespace)::WrapComparison<absl::lts_20260107::Time, std::__1::optional<bool> (*)(absl::lts_20260107::Time, absl::lts_20260107::Time)>(std::__1::optional<bool> (*)(absl::lts_20260107::Time, absl::lts_20260107::Time), std::__1::basic_string_view<char, std::__1::char_traits<char> >)::{lambda(absl::lts_20260107::Time, absl::lts_20260107::Time, google::protobuf::DescriptorPool const*, google::protobuf::MessageFactory*, google::protobuf::Arena*)#1}::operator()(absl::lts_20260107::Time, absl::lts_20260107::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_20260107::Duration, absl::lts_20260107::Duration, google::protobuf::DescriptorPool const*, google::protobuf::MessageFactory*, google::protobuf::Arena*)> cel::(anonymous namespace)::WrapComparison<absl::lts_20260107::Duration, std::__1::optional<bool> (*)(absl::lts_20260107::Duration, absl::lts_20260107::Duration)>(std::__1::optional<bool> (*)(absl::lts_20260107::Duration, absl::lts_20260107::Duration), std::__1::basic_string_view<char, std::__1::char_traits<char> >) Unexecuted instantiation: equality_functions.cc:std::__1::function<cel::Value (absl::lts_20260107::Time, absl::lts_20260107::Time, google::protobuf::DescriptorPool const*, google::protobuf::MessageFactory*, google::protobuf::Arena*)> cel::(anonymous namespace)::WrapComparison<absl::lts_20260107::Time, std::__1::optional<bool> (*)(absl::lts_20260107::Time, absl::lts_20260107::Time)>(std::__1::optional<bool> (*)(absl::lts_20260107::Time, absl::lts_20260107::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_20260107::Status cel::(anonymous namespace)::RegisterEqualityFunctionsForType<bool>(cel::FunctionRegistry&) Unexecuted instantiation: equality_functions.cc:absl::lts_20260107::Status cel::(anonymous namespace)::RegisterEqualityFunctionsForType<long>(cel::FunctionRegistry&) Unexecuted instantiation: equality_functions.cc:absl::lts_20260107::Status cel::(anonymous namespace)::RegisterEqualityFunctionsForType<unsigned long>(cel::FunctionRegistry&) Unexecuted instantiation: equality_functions.cc:absl::lts_20260107::Status cel::(anonymous namespace)::RegisterEqualityFunctionsForType<double>(cel::FunctionRegistry&) Unexecuted instantiation: equality_functions.cc:absl::lts_20260107::Status cel::(anonymous namespace)::RegisterEqualityFunctionsForType<cel::StringValue const&>(cel::FunctionRegistry&) Unexecuted instantiation: equality_functions.cc:absl::lts_20260107::Status cel::(anonymous namespace)::RegisterEqualityFunctionsForType<cel::BytesValue const&>(cel::FunctionRegistry&) Unexecuted instantiation: equality_functions.cc:absl::lts_20260107::Status cel::(anonymous namespace)::RegisterEqualityFunctionsForType<absl::lts_20260107::Duration>(cel::FunctionRegistry&) Unexecuted instantiation: equality_functions.cc:absl::lts_20260107::Status cel::(anonymous namespace)::RegisterEqualityFunctionsForType<absl::lts_20260107::Time>(cel::FunctionRegistry&) Unexecuted instantiation: equality_functions.cc:absl::lts_20260107::Status cel::(anonymous namespace)::RegisterEqualityFunctionsForType<cel::NullValue const&>(cel::FunctionRegistry&) Unexecuted instantiation: equality_functions.cc:absl::lts_20260107::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( |
321 | 0 | cel::runtime_internal::CreateNoMatchingOverloadError(kEqual)); |
322 | 0 | } |
323 | 0 | return BoolValue(*result); |
324 | 0 | }; Unexecuted instantiation: equality_functions.cc:cel::(anonymous namespace)::ComplexEquality<cel::ListValue const&, absl::lts_20260107::FunctionRef<absl::lts_20260107::StatusOr<std::__1::optional<bool> > (cel::ListValue const&, cel::ListValue const&, google::protobuf::DescriptorPool const*, google::protobuf::MessageFactory*, google::protobuf::Arena*)>&>(absl::lts_20260107::FunctionRef<absl::lts_20260107::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_20260107::FunctionRef<absl::lts_20260107::StatusOr<std::__1::optional<bool> > (cel::MapValue const&, cel::MapValue const&, google::protobuf::DescriptorPool const*, google::protobuf::MessageFactory*, google::protobuf::Arena*)>&>(absl::lts_20260107::FunctionRef<absl::lts_20260107::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_20260107::FunctionRef<absl::lts_20260107::StatusOr<std::__1::optional<bool> > (cel::ListValue const&, cel::ListValue const&, google::protobuf::DescriptorPool const*, google::protobuf::MessageFactory*, google::protobuf::Arena*)>&>(absl::lts_20260107::FunctionRef<absl::lts_20260107::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_20260107::FunctionRef<absl::lts_20260107::StatusOr<std::__1::optional<bool> > (cel::MapValue const&, cel::MapValue const&, google::protobuf::DescriptorPool const*, google::protobuf::MessageFactory*, google::protobuf::Arena*)>&>(absl::lts_20260107::FunctionRef<absl::lts_20260107::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( |
338 | 0 | cel::runtime_internal::CreateNoMatchingOverloadError(kInequal)); |
339 | 0 | } |
340 | 0 | return BoolValue(!*result); |
341 | 0 | }; Unexecuted instantiation: equality_functions.cc:cel::(anonymous namespace)::ComplexInequality<cel::ListValue const&, absl::lts_20260107::FunctionRef<absl::lts_20260107::StatusOr<std::__1::optional<bool> > (cel::ListValue const&, cel::ListValue const&, google::protobuf::DescriptorPool const*, google::protobuf::MessageFactory*, google::protobuf::Arena*)>&>(absl::lts_20260107::FunctionRef<absl::lts_20260107::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_20260107::FunctionRef<absl::lts_20260107::StatusOr<std::__1::optional<bool> > (cel::MapValue const&, cel::MapValue const&, google::protobuf::DescriptorPool const*, google::protobuf::MessageFactory*, google::protobuf::Arena*)>&>(absl::lts_20260107::FunctionRef<absl::lts_20260107::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 |
342 | 0 | } Unexecuted instantiation: equality_functions.cc:auto cel::(anonymous namespace)::ComplexInequality<cel::ListValue const&, absl::lts_20260107::FunctionRef<absl::lts_20260107::StatusOr<std::__1::optional<bool> > (cel::ListValue const&, cel::ListValue const&, google::protobuf::DescriptorPool const*, google::protobuf::MessageFactory*, google::protobuf::Arena*)>&>(absl::lts_20260107::FunctionRef<absl::lts_20260107::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_20260107::FunctionRef<absl::lts_20260107::StatusOr<std::__1::optional<bool> > (cel::MapValue const&, cel::MapValue const&, google::protobuf::DescriptorPool const*, google::protobuf::MessageFactory*, google::protobuf::Arena*)>&>(absl::lts_20260107::FunctionRef<absl::lts_20260107::StatusOr<std::__1::optional<bool> > (cel::MapValue const&, cel::MapValue const&, google::protobuf::DescriptorPool const*, google::protobuf::MessageFactory*, google::protobuf::Arena*)>&) |
343 | | |
344 | | template <class Type> |
345 | | absl::Status RegisterComplexEqualityFunctionsForType( |
346 | | absl::FunctionRef<absl::StatusOr<absl::optional<bool>>( |
347 | | Type, Type, const google::protobuf::DescriptorPool* absl_nonnull, |
348 | | google::protobuf::MessageFactory* absl_nonnull, google::protobuf::Arena* absl_nonnull)> |
349 | | op, |
350 | 0 | cel::FunctionRegistry& registry) { |
351 | 0 | using FunctionAdapter = cel::RegisterHelper< |
352 | 0 | BinaryFunctionAdapter<absl::StatusOr<Value>, Type, Type>>; |
353 | | // Inequality |
354 | 0 | CEL_RETURN_IF_ERROR(FunctionAdapter::RegisterGlobalOverload( |
355 | 0 | kInequal, ComplexInequality<Type>(op), registry)); |
356 | | |
357 | | // Equality |
358 | 0 | CEL_RETURN_IF_ERROR(FunctionAdapter::RegisterGlobalOverload( |
359 | 0 | kEqual, ComplexEquality<Type>(op), registry)); |
360 | | |
361 | 0 | return absl::OkStatus(); |
362 | 0 | } Unexecuted instantiation: equality_functions.cc:absl::lts_20260107::Status cel::(anonymous namespace)::RegisterComplexEqualityFunctionsForType<cel::ListValue const&>(absl::lts_20260107::FunctionRef<absl::lts_20260107::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_20260107::Status cel::(anonymous namespace)::RegisterComplexEqualityFunctionsForType<cel::MapValue const&>(absl::lts_20260107::FunctionRef<absl::lts_20260107::StatusOr<std::__1::optional<bool> > (cel::MapValue const&, cel::MapValue const&, google::protobuf::DescriptorPool const*, google::protobuf::MessageFactory*, google::protobuf::Arena*)>, cel::FunctionRegistry&) |
363 | | |
364 | | absl::Status RegisterHomogenousEqualityFunctions( |
365 | 0 | cel::FunctionRegistry& registry) { |
366 | 0 | CEL_RETURN_IF_ERROR(RegisterEqualityFunctionsForType<bool>(registry)); |
367 | | |
368 | 0 | CEL_RETURN_IF_ERROR(RegisterEqualityFunctionsForType<int64_t>(registry)); |
369 | | |
370 | 0 | CEL_RETURN_IF_ERROR(RegisterEqualityFunctionsForType<uint64_t>(registry)); |
371 | | |
372 | 0 | CEL_RETURN_IF_ERROR(RegisterEqualityFunctionsForType<double>(registry)); |
373 | | |
374 | 0 | CEL_RETURN_IF_ERROR( |
375 | 0 | RegisterEqualityFunctionsForType<const cel::StringValue&>(registry)); |
376 | | |
377 | 0 | CEL_RETURN_IF_ERROR( |
378 | 0 | RegisterEqualityFunctionsForType<const cel::BytesValue&>(registry)); |
379 | | |
380 | 0 | CEL_RETURN_IF_ERROR( |
381 | 0 | RegisterEqualityFunctionsForType<absl::Duration>(registry)); |
382 | | |
383 | 0 | CEL_RETURN_IF_ERROR(RegisterEqualityFunctionsForType<absl::Time>(registry)); |
384 | | |
385 | 0 | CEL_RETURN_IF_ERROR( |
386 | 0 | RegisterEqualityFunctionsForType<const cel::NullValue&>(registry)); |
387 | | |
388 | 0 | CEL_RETURN_IF_ERROR( |
389 | 0 | RegisterEqualityFunctionsForType<const cel::TypeValue&>(registry)); |
390 | | |
391 | 0 | CEL_RETURN_IF_ERROR( |
392 | 0 | RegisterComplexEqualityFunctionsForType<const cel::ListValue&>( |
393 | 0 | &ListEqual<HomogenousEqualProvider>, registry)); |
394 | | |
395 | 0 | CEL_RETURN_IF_ERROR( |
396 | 0 | RegisterComplexEqualityFunctionsForType<const cel::MapValue&>( |
397 | 0 | &MapEqual<HomogenousEqualProvider>, registry)); |
398 | | |
399 | 0 | return absl::OkStatus(); |
400 | 0 | } |
401 | | |
402 | 0 | absl::Status RegisterNullMessageEqualityFunctions(FunctionRegistry& registry) { |
403 | | // equals |
404 | 0 | CEL_RETURN_IF_ERROR( |
405 | 0 | (cel::RegisterHelper< |
406 | 0 | BinaryFunctionAdapter<bool, const StructValue&, const NullValue&>>:: |
407 | 0 | RegisterGlobalOverload( |
408 | 0 | kEqual, |
409 | 0 | [](const StructValue&, const NullValue&) { return false; }, |
410 | 0 | registry))); |
411 | | |
412 | 0 | CEL_RETURN_IF_ERROR( |
413 | 0 | (cel::RegisterHelper< |
414 | 0 | BinaryFunctionAdapter<bool, const NullValue&, const StructValue&>>:: |
415 | 0 | RegisterGlobalOverload( |
416 | 0 | kEqual, |
417 | 0 | [](const NullValue&, const StructValue&) { return false; }, |
418 | 0 | registry))); |
419 | | |
420 | | // inequals |
421 | 0 | CEL_RETURN_IF_ERROR( |
422 | 0 | (cel::RegisterHelper< |
423 | 0 | BinaryFunctionAdapter<bool, const StructValue&, const NullValue&>>:: |
424 | 0 | RegisterGlobalOverload( |
425 | 0 | kInequal, |
426 | 0 | [](const StructValue&, const NullValue&) { return true; }, |
427 | 0 | registry))); |
428 | | |
429 | 0 | return cel::RegisterHelper< |
430 | 0 | BinaryFunctionAdapter<bool, const NullValue&, const StructValue&>>:: |
431 | 0 | RegisterGlobalOverload( |
432 | 0 | kInequal, [](const NullValue&, const StructValue&) { return true; }, |
433 | 0 | registry); |
434 | 0 | } |
435 | | |
436 | | template <typename EqualsProvider> |
437 | | absl::StatusOr<absl::optional<bool>> HomogenousValueEqual( |
438 | | const Value& v1, const Value& v2, |
439 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
440 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
441 | 799 | google::protobuf::Arena* absl_nonnull arena) { |
442 | 799 | if (v1.kind() != v2.kind()) { |
443 | 0 | return absl::nullopt; |
444 | 0 | } |
445 | | |
446 | 799 | static_assert(std::is_lvalue_reference_v<decltype(v1.GetString())>, |
447 | 799 | "unexpected value copy"); |
448 | | |
449 | 799 | switch (v1->kind()) { |
450 | 9 | case ValueKind::kBool: |
451 | 9 | return Equal<bool>(v1.GetBool().NativeValue(), |
452 | 9 | v2.GetBool().NativeValue()); |
453 | 0 | case ValueKind::kNull: |
454 | 0 | return Equal<const NullValue&>(v1.GetNull(), v2.GetNull()); |
455 | 309 | case ValueKind::kInt: |
456 | 309 | return Equal<int64_t>(v1.GetInt().NativeValue(), |
457 | 309 | v2.GetInt().NativeValue()); |
458 | 180 | case ValueKind::kUint: |
459 | 180 | return Equal<uint64_t>(v1.GetUint().NativeValue(), |
460 | 180 | v2.GetUint().NativeValue()); |
461 | 34 | case ValueKind::kDouble: |
462 | 34 | return Equal<double>(v1.GetDouble().NativeValue(), |
463 | 34 | v2.GetDouble().NativeValue()); |
464 | 0 | case ValueKind::kDuration: |
465 | 0 | return Equal<absl::Duration>(v1.GetDuration().NativeValue(), |
466 | 0 | v2.GetDuration().NativeValue()); |
467 | 0 | case ValueKind::kTimestamp: |
468 | 0 | return Equal<absl::Time>(v1.GetTimestamp().NativeValue(), |
469 | 0 | v2.GetTimestamp().NativeValue()); |
470 | 2 | case ValueKind::kCelType: |
471 | 2 | return Equal<const TypeValue&>(v1.GetType(), v2.GetType()); |
472 | 113 | case ValueKind::kString: |
473 | 113 | return Equal<const StringValue&>(v1.GetString(), v2.GetString()); |
474 | 18 | case ValueKind::kBytes: |
475 | 18 | return Equal<const cel::BytesValue&>(v1.GetBytes(), v2.GetBytes()); |
476 | 84 | case ValueKind::kList: |
477 | 84 | return ListEqual<EqualsProvider>(v1.GetList(), v2.GetList(), |
478 | 84 | descriptor_pool, message_factory, arena); |
479 | 50 | case ValueKind::kMap: |
480 | 50 | return MapEqual<EqualsProvider>(v1.GetMap(), v2.GetMap(), descriptor_pool, |
481 | 50 | message_factory, arena); |
482 | 0 | case ValueKind::kOpaque: |
483 | 0 | return OpaqueEqual(v1.GetOpaque(), v2.GetOpaque(), descriptor_pool, |
484 | 0 | message_factory, arena); |
485 | 0 | default: |
486 | 0 | return absl::nullopt; |
487 | 799 | } |
488 | 799 | } Unexecuted instantiation: equality_functions.cc:absl::lts_20260107::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_20260107::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 | 441 | 799 | google::protobuf::Arena* absl_nonnull arena) { | 442 | 799 | if (v1.kind() != v2.kind()) { | 443 | 0 | return absl::nullopt; | 444 | 0 | } | 445 | | | 446 | 799 | static_assert(std::is_lvalue_reference_v<decltype(v1.GetString())>, | 447 | 799 | "unexpected value copy"); | 448 | | | 449 | 799 | switch (v1->kind()) { | 450 | 9 | case ValueKind::kBool: | 451 | 9 | return Equal<bool>(v1.GetBool().NativeValue(), | 452 | 9 | v2.GetBool().NativeValue()); | 453 | 0 | case ValueKind::kNull: | 454 | 0 | return Equal<const NullValue&>(v1.GetNull(), v2.GetNull()); | 455 | 309 | case ValueKind::kInt: | 456 | 309 | return Equal<int64_t>(v1.GetInt().NativeValue(), | 457 | 309 | v2.GetInt().NativeValue()); | 458 | 180 | case ValueKind::kUint: | 459 | 180 | return Equal<uint64_t>(v1.GetUint().NativeValue(), | 460 | 180 | v2.GetUint().NativeValue()); | 461 | 34 | case ValueKind::kDouble: | 462 | 34 | return Equal<double>(v1.GetDouble().NativeValue(), | 463 | 34 | v2.GetDouble().NativeValue()); | 464 | 0 | case ValueKind::kDuration: | 465 | 0 | return Equal<absl::Duration>(v1.GetDuration().NativeValue(), | 466 | 0 | v2.GetDuration().NativeValue()); | 467 | 0 | case ValueKind::kTimestamp: | 468 | 0 | return Equal<absl::Time>(v1.GetTimestamp().NativeValue(), | 469 | 0 | v2.GetTimestamp().NativeValue()); | 470 | 2 | case ValueKind::kCelType: | 471 | 2 | return Equal<const TypeValue&>(v1.GetType(), v2.GetType()); | 472 | 113 | case ValueKind::kString: | 473 | 113 | return Equal<const StringValue&>(v1.GetString(), v2.GetString()); | 474 | 18 | case ValueKind::kBytes: | 475 | 18 | return Equal<const cel::BytesValue&>(v1.GetBytes(), v2.GetBytes()); | 476 | 84 | case ValueKind::kList: | 477 | 84 | return ListEqual<EqualsProvider>(v1.GetList(), v2.GetList(), | 478 | 84 | descriptor_pool, message_factory, arena); | 479 | 50 | case ValueKind::kMap: | 480 | 50 | return MapEqual<EqualsProvider>(v1.GetMap(), v2.GetMap(), descriptor_pool, | 481 | 50 | message_factory, arena); | 482 | 0 | case ValueKind::kOpaque: | 483 | 0 | return OpaqueEqual(v1.GetOpaque(), v2.GetOpaque(), descriptor_pool, | 484 | 0 | message_factory, arena); | 485 | 0 | default: | 486 | 0 | return absl::nullopt; | 487 | 799 | } | 488 | 799 | } |
|
489 | | |
490 | | absl::StatusOr<Value> EqualOverloadImpl( |
491 | | const Value& lhs, const Value& rhs, |
492 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
493 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
494 | 0 | google::protobuf::Arena* absl_nonnull arena) { |
495 | 0 | CEL_ASSIGN_OR_RETURN(absl::optional<bool> result, |
496 | 0 | runtime_internal::ValueEqualImpl( |
497 | 0 | lhs, rhs, descriptor_pool, message_factory, arena)); |
498 | 0 | if (result.has_value()) { |
499 | 0 | return BoolValue(*result); |
500 | 0 | } |
501 | 0 | return ErrorValue( |
502 | 0 | cel::runtime_internal::CreateNoMatchingOverloadError(kEqual)); |
503 | 0 | } |
504 | | |
505 | | absl::StatusOr<Value> InequalOverloadImpl( |
506 | | const Value& lhs, const Value& rhs, |
507 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
508 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
509 | 0 | google::protobuf::Arena* absl_nonnull arena) { |
510 | 0 | CEL_ASSIGN_OR_RETURN(absl::optional<bool> result, |
511 | 0 | runtime_internal::ValueEqualImpl( |
512 | 0 | lhs, rhs, descriptor_pool, message_factory, arena)); |
513 | 0 | if (result.has_value()) { |
514 | 0 | return BoolValue(!*result); |
515 | 0 | } |
516 | 0 | return ErrorValue( |
517 | 0 | cel::runtime_internal::CreateNoMatchingOverloadError(kInequal)); |
518 | 0 | } |
519 | | |
520 | | absl::Status RegisterHeterogeneousEqualityFunctions( |
521 | 0 | cel::FunctionRegistry& registry) { |
522 | 0 | using Adapter = cel::RegisterHelper< |
523 | 0 | BinaryFunctionAdapter<absl::StatusOr<Value>, const Value&, const Value&>>; |
524 | 0 | CEL_RETURN_IF_ERROR( |
525 | 0 | Adapter::RegisterGlobalOverload(kEqual, &EqualOverloadImpl, registry)); |
526 | | |
527 | 0 | CEL_RETURN_IF_ERROR(Adapter::RegisterGlobalOverload( |
528 | 0 | kInequal, &InequalOverloadImpl, registry)); |
529 | | |
530 | 0 | return absl::OkStatus(); |
531 | 0 | } |
532 | | |
533 | | absl::StatusOr<absl::optional<bool>> HomogenousEqualProvider::operator()( |
534 | | const Value& lhs, const Value& rhs, |
535 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
536 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
537 | 0 | google::protobuf::Arena* absl_nonnull arena) const { |
538 | 0 | return HomogenousValueEqual<HomogenousEqualProvider>( |
539 | 0 | lhs, rhs, descriptor_pool, message_factory, arena); |
540 | 0 | } |
541 | | |
542 | | absl::StatusOr<absl::optional<bool>> HeterogeneousEqualProvider::operator()( |
543 | | const Value& lhs, const Value& rhs, |
544 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
545 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
546 | 34 | google::protobuf::Arena* absl_nonnull arena) const { |
547 | 34 | return runtime_internal::ValueEqualImpl(lhs, rhs, descriptor_pool, |
548 | 34 | message_factory, arena); |
549 | 34 | } |
550 | | |
551 | | } // namespace |
552 | | |
553 | | namespace runtime_internal { |
554 | | |
555 | | absl::StatusOr<absl::optional<bool>> ValueEqualImpl( |
556 | | const Value& v1, const Value& v2, |
557 | | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
558 | | google::protobuf::MessageFactory* absl_nonnull message_factory, |
559 | 3.85k | google::protobuf::Arena* absl_nonnull arena) { |
560 | 3.85k | if (v1.kind() == v2.kind()) { |
561 | 799 | if (v1.IsStruct() && v2.IsStruct()) { |
562 | 0 | CEL_ASSIGN_OR_RETURN( |
563 | 0 | Value result, |
564 | 0 | v1.GetStruct().Equal(v2, descriptor_pool, message_factory, arena)); |
565 | 0 | if (result.IsBool()) { |
566 | 0 | return result.GetBool().NativeValue(); |
567 | 0 | } |
568 | 0 | return false; |
569 | 0 | } |
570 | 799 | return HomogenousValueEqual<HeterogeneousEqualProvider>( |
571 | 799 | v1, v2, descriptor_pool, message_factory, arena); |
572 | 799 | } |
573 | | |
574 | 3.05k | absl::optional<Number> lhs = NumberFromValue(v1); |
575 | 3.05k | absl::optional<Number> rhs = NumberFromValue(v2); |
576 | | |
577 | 3.05k | if (rhs.has_value() && lhs.has_value()) { |
578 | 1.76k | return *lhs == *rhs; |
579 | 1.76k | } |
580 | | |
581 | | // TODO(uncreated-issue/6): It's currently possible for the interpreter to create a |
582 | | // map containing an Error. Return no matching overload to propagate an error |
583 | | // instead of a false result. |
584 | 1.29k | if (v1.IsError() || v1.IsUnknown() || v2.IsError() || v2.IsUnknown()) { |
585 | 0 | return absl::nullopt; |
586 | 0 | } |
587 | | |
588 | 1.29k | return false; |
589 | 1.29k | } |
590 | | |
591 | | } // namespace runtime_internal |
592 | | |
593 | | absl::Status RegisterEqualityFunctions(FunctionRegistry& registry, |
594 | 14.5k | const RuntimeOptions& options) { |
595 | 14.5k | if (options.enable_heterogeneous_equality) { |
596 | 14.5k | if (options.enable_fast_builtins) { |
597 | | // If enabled, the evaluator provides an implementation that works |
598 | | // directly on the value stack. |
599 | 14.5k | return absl::OkStatus(); |
600 | 14.5k | } |
601 | | // Heterogeneous equality uses one generic overload that delegates to the |
602 | | // right equality implementation at runtime. |
603 | 14.5k | CEL_RETURN_IF_ERROR(RegisterHeterogeneousEqualityFunctions(registry)); |
604 | 0 | } else { |
605 | 0 | CEL_RETURN_IF_ERROR(RegisterHomogenousEqualityFunctions(registry)); |
606 | | |
607 | 0 | CEL_RETURN_IF_ERROR(RegisterNullMessageEqualityFunctions(registry)); |
608 | 0 | } |
609 | 0 | return absl::OkStatus(); |
610 | 14.5k | } |
611 | | |
612 | | } // namespace cel |