use core::ops::{Add, Div, Mul, Sub}; #[derive(Copy, Clone, PartialEq, Debug)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub enum Number { Defined(f32), Undefined, } pub trait OrElse { fn or_else(self, other: T) -> T; } impl Default for Number { fn default() -> Self { Self::Undefined } } impl OrElse for Number { fn or_else(self, other: f32) -> f32 { match self { Number::Defined(val) => val, Number::Undefined => other, } } } impl OrElse for Number { fn or_else(self, other: Self) -> Self { match self { Number::Defined(_) => self, Number::Undefined => other, } } } impl Number { pub fn is_defined(self) -> bool { match self { Number::Defined(_) => true, Number::Undefined => false, } } pub fn is_undefined(self) -> bool { match self { Number::Defined(_) => false, Number::Undefined => true, } } } pub trait MinMax { fn maybe_min(self, rhs: In) -> Out; fn maybe_max(self, rhs: In) -> Out; } impl MinMax for Number { fn maybe_min(self, rhs: Self) -> Self { match (self, rhs) { (Number::Defined(l), Number::Defined(r)) => Number::Defined(l.min(r)), (Number::Defined(_), _) => self, _ => Number::Undefined, } } fn maybe_max(self, rhs: Self) -> Self { match (self, rhs) { (Number::Defined(l), Number::Defined(r)) => Number::Defined(l.max(r)), (Number::Defined(_), _) => self, _ => Number::Undefined, } } } impl MinMax for Number { fn maybe_min(self, rhs: f32) -> Self { match self { Number::Defined(val) => Number::Defined(val.min(rhs)), Number::Undefined => Number::Undefined, } } fn maybe_max(self, rhs: f32) -> Self { match self { Number::Defined(val) => Number::Defined(val.max(rhs)), Number::Undefined => Number::Undefined, } } } impl MinMax for f32 { fn maybe_min(self, rhs: Number) -> f32 { match rhs { Number::Defined(val) => self.min(val), Number::Undefined => self, } } fn maybe_max(self, rhs: Number) -> f32 { match rhs { Number::Defined(val) => self.max(val), Number::Undefined => self, } } } impl From for Number { fn from(v: f32) -> Self { Self::Defined(v) } } impl Add for Number { type Output = Number; fn add(self, rhs: f32) -> Self { match self { Number::Defined(val) => Number::Defined(val + rhs), Number::Undefined => Number::Undefined, } } } impl Add for Number { type Output = Number; fn add(self, rhs: Self) -> Self { match (self, rhs) { (Number::Defined(l), Number::Defined(r)) => Number::Defined(l + r), (Number::Defined(_), _) => self, _ => Number::Undefined, } } } impl Sub for Number { type Output = Number; fn sub(self, rhs: f32) -> Self { match self { Number::Defined(val) => Number::Defined(val - rhs), Number::Undefined => Number::Undefined, } } } impl Sub for Number { type Output = Number; fn sub(self, rhs: Self) -> Self { match (self, rhs) { (Number::Defined(l), Number::Defined(r)) => Number::Defined(l - r), (Number::Defined(_), _) => self, _ => Number::Undefined, } } } impl Mul for Number { type Output = Number; fn mul(self, rhs: f32) -> Self { match self { Number::Defined(val) => Number::Defined(val * rhs), Number::Undefined => Number::Undefined, } } } impl Mul for Number { type Output = Number; fn mul(self, rhs: Self) -> Self { match (self, rhs) { (Number::Defined(l), Number::Defined(r)) => Number::Defined(l * r), (Number::Defined(_), _) => self, _ => Number::Undefined, } } } impl Div for Number { type Output = Number; fn div(self, rhs: f32) -> Self { match self { Number::Defined(val) => Number::Defined(val / rhs), Number::Undefined => Number::Undefined, } } } impl Div for Number { type Output = Number; fn div(self, rhs: Self) -> Self { match (self, rhs) { (Number::Defined(l), Number::Defined(r)) => Number::Defined(l / r), (Number::Defined(_), _) => self, _ => Number::Undefined, } } }