Equal operator is defined for all types at plan time. Runtime delegates to the correct implementation for types or returns nullopt if the comparison isn't defined.
| 212 | // the correct implementation for types or returns nullopt if the comparison |
| 213 | // isn't defined. |
| 214 | absl::optional<bool> CelValueEqualImpl(const CelValue& v1, const CelValue& v2) { |
| 215 | if (v1.type() == v2.type()) { |
| 216 | // Message equality is only defined if heterogeneous comparisons are enabled |
| 217 | // to preserve the legacy behavior for equality. |
| 218 | if (CelValue::MessageWrapper lhs, rhs; |
| 219 | v1.GetValue(&lhs) && v2.GetValue(&rhs)) { |
| 220 | return MessageEqual(lhs, rhs); |
| 221 | } |
| 222 | return HomogenousCelValueEqual<HeterogeneousEqualProvider>(v1, v2); |
| 223 | } |
| 224 | |
| 225 | absl::optional<Number> lhs = GetNumberFromCelValue(v1); |
| 226 | absl::optional<Number> rhs = GetNumberFromCelValue(v2); |
| 227 | |
| 228 | if (rhs.has_value() && lhs.has_value()) { |
| 229 | return *lhs == *rhs; |
| 230 | } |
| 231 | |
| 232 | // TODO(uncreated-issue/6): It's currently possible for the interpreter to create a |
| 233 | // map containing an Error. Return no matching overload to propagate an error |
| 234 | // instead of a false result. |
| 235 | if (v1.IsError() || v1.IsUnknownSet() || v2.IsError() || v2.IsUnknownSet()) { |
| 236 | return absl::nullopt; |
| 237 | } |
| 238 | |
| 239 | return false; |
| 240 | } |
| 241 | |
| 242 | } // namespace cel::interop_internal |