Utility class for CEL number operations. In CEL expressions, comparisons between different numeric types are treated as all happening on the same continuous number line. This generally means that integers and doubles in convertible range are compared after converting to doubles (tolerating some loss of precision). This extends to key lookups -- {1: 'abc'}[1.0f] is expected to work since 1.0 == 1
| 211 | // This extends to key lookups -- {1: 'abc'}[1.0f] is expected to work since |
| 212 | // 1.0 == 1 in CEL. |
| 213 | class Number { |
| 214 | public: |
| 215 | // Factories to resolve ambiguous overload resolution against literals. |
| 216 | static constexpr Number FromInt64(int64_t value) { return Number(value); } |
| 217 | static constexpr Number FromUint64(uint64_t value) { return Number(value); } |
| 218 | static constexpr Number FromDouble(double value) { return Number(value); } |
| 219 | |
| 220 | constexpr explicit Number(double double_value) : value_(double_value) {} |
| 221 | constexpr explicit Number(int64_t int_value) : value_(int_value) {} |
| 222 | constexpr explicit Number(uint64_t uint_value) : value_(uint_value) {} |
| 223 | |
| 224 | // Return a double representation of the value. |
| 225 | CEL_ABSL_VISIT_CONSTEXPR double AsDouble() const { |
| 226 | return absl::visit(internal::ConversionVisitor<double>(), value_); |
| 227 | } |
| 228 | |
| 229 | // Return signed int64 representation for the value. |
| 230 | // Caller must guarantee the underlying value is representatble as an |
| 231 | // int. |
| 232 | CEL_ABSL_VISIT_CONSTEXPR int64_t AsInt() const { |
| 233 | return absl::visit(internal::ConversionVisitor<int64_t>(), value_); |
| 234 | } |
| 235 | |
| 236 | // Return unsigned int64 representation for the value. |
| 237 | // Caller must guarantee the underlying value is representable as an |
| 238 | // uint. |
| 239 | CEL_ABSL_VISIT_CONSTEXPR uint64_t AsUint() const { |
| 240 | return absl::visit(internal::ConversionVisitor<uint64_t>(), value_); |
| 241 | } |
| 242 | |
| 243 | // For key lookups, check if the conversion to signed int is lossless. |
| 244 | CEL_ABSL_VISIT_CONSTEXPR bool LosslessConvertibleToInt() const { |
| 245 | return absl::visit(internal::LosslessConvertibleToIntVisitor(), value_); |
| 246 | } |
| 247 | |
| 248 | // For key lookups, check if the conversion to unsigned int is lossless. |
| 249 | CEL_ABSL_VISIT_CONSTEXPR bool LosslessConvertibleToUint() const { |
| 250 | return absl::visit(internal::LosslessConvertibleToUintVisitor(), value_); |
| 251 | } |
| 252 | |
| 253 | CEL_ABSL_VISIT_CONSTEXPR bool operator<(Number other) const { |
| 254 | return Compare(other) == internal::ComparisonResult::kLesser; |
| 255 | } |
| 256 | |
| 257 | CEL_ABSL_VISIT_CONSTEXPR bool operator<=(Number other) const { |
| 258 | internal::ComparisonResult cmp = Compare(other); |
| 259 | return cmp != internal::ComparisonResult::kGreater && |
| 260 | cmp != internal::ComparisonResult::kNanInequal; |
| 261 | } |
| 262 | |
| 263 | CEL_ABSL_VISIT_CONSTEXPR bool operator>(Number other) const { |
| 264 | return Compare(other) == internal::ComparisonResult::kGreater; |
| 265 | } |
| 266 | |
| 267 | CEL_ABSL_VISIT_CONSTEXPR bool operator>=(Number other) const { |
| 268 | internal::ComparisonResult cmp = Compare(other); |
| 269 | return cmp != internal::ComparisonResult::kLesser && |
| 270 | cmp != internal::ComparisonResult::kNanInequal; |