1use std::ops;
24
25#[derive(Copy, Clone, PartialEq, Debug)]
26pub enum Number {
27 Defined(f32),
28 Undefined,
29}
30
31pub trait ToNumber {
32 fn to_number(self) -> Number;
33}
34
35pub trait OrElse<T> {
36 fn or_else(self, other: T) -> T;
37}
38
39impl Default for Number {
40 fn default() -> Number {
41 Number::Undefined
42 }
43}
44
45impl OrElse<f32> for Number {
46 fn or_else(self, other: f32) -> f32 {
47 match self {
48 Number::Defined(val) => val,
49 Number::Undefined => other,
50 }
51 }
52}
53
54impl OrElse<Number> for Number {
55 fn or_else(self, other: Number) -> Number {
56 match self {
57 Number::Defined(_) => self,
58 Number::Undefined => other,
59 }
60 }
61}
62
63impl Number {
64 #[inline]
65 pub fn is_defined(self) -> bool {
66 match self {
67 Number::Defined(_) => true,
68 Number::Undefined => false,
69 }
70 }
71
72 #[inline]
73 pub fn is_undefined(self) -> bool {
74 match self {
75 Number::Defined(_) => false,
76 Number::Undefined => true,
77 }
78 }
79
80 #[inline]
81 pub fn to_option(&self) -> Option<f32> {
82 match self {
83 Number::Defined(f) => Some(*f),
84 Number::Undefined => None,
85 }
86 }
87
88 #[inline]
89 pub fn unwrap_or_zero(&self) -> f32 {
90 match self {
91 Number::Defined(d) => *d,
92 Number::Undefined => 0.0,
93 }
94 }
95}
96
97pub trait MinMax<In, Out> {
98 fn maybe_min(self, rhs: In) -> Out;
99 fn maybe_max(self, rhs: In) -> Out;
100}
101
102impl MinMax<Number, Number> for Number {
103 #[inline]
104 fn maybe_min(self, rhs: Number) -> Number {
105 match self {
106 Number::Defined(val) => match rhs {
107 Number::Defined(other) => Number::Defined(val.min(other)),
108 Number::Undefined => self,
109 },
110 Number::Undefined => Number::Undefined,
111 }
112 }
113
114 #[inline]
115 fn maybe_max(self, rhs: Number) -> Number {
116 match self {
117 Number::Defined(val) => match rhs {
118 Number::Defined(other) => Number::Defined(val.max(other)),
119 Number::Undefined => self,
120 },
121 Number::Undefined => Number::Undefined,
122 }
123 }
124}
125
126impl MinMax<f32, Number> for Number {
127 #[inline]
128 fn maybe_min(self, rhs: f32) -> Number {
129 match self {
130 Number::Defined(val) => Number::Defined(val.min(rhs)),
131 Number::Undefined => Number::Undefined,
132 }
133 }
134
135 #[inline]
136 fn maybe_max(self, rhs: f32) -> Number {
137 match self {
138 Number::Defined(val) => Number::Defined(val.max(rhs)),
139 Number::Undefined => Number::Undefined,
140 }
141 }
142}
143
144impl MinMax<Number, f32> for f32 {
145 #[inline]
146 fn maybe_min(self, rhs: Number) -> f32 {
147 match rhs {
148 Number::Defined(val) => self.min(val),
149 Number::Undefined => self,
150 }
151 }
152
153 #[inline]
154 fn maybe_max(self, rhs: Number) -> f32 {
155 match rhs {
156 Number::Defined(val) => self.max(val),
157 Number::Undefined => self,
158 }
159 }
160}
161
162impl ToNumber for f32 {
163 #[inline]
164 fn to_number(self) -> Number {
165 Number::Defined(self)
166 }
167}
168
169impl ops::Add<f32> for Number {
170 type Output = Number;
171
172 #[inline]
173 fn add(self, rhs: f32) -> Number {
174 match self {
175 Number::Defined(val) => Number::Defined(val + rhs),
176 Number::Undefined => Number::Undefined,
177 }
178 }
179}
180
181impl ops::Add<Number> for Number {
182 type Output = Number;
183
184 #[inline]
185 fn add(self, rhs: Number) -> Number {
186 match self {
187 Number::Defined(val) => match rhs {
188 Number::Defined(other) => Number::Defined(val + other),
189 Number::Undefined => self,
190 },
191 Number::Undefined => Number::Undefined,
192 }
193 }
194}
195
196impl ops::AddAssign<Number> for Number {
197 #[inline]
198 fn add_assign(&mut self, other: Self) {
199 *self = *self + other;
200 }
201}
202
203impl ops::Sub<f32> for Number {
204 type Output = Number;
205
206 #[inline]
207 fn sub(self, rhs: f32) -> Number {
208 match self {
209 Number::Defined(val) => Number::Defined(val - rhs),
210 Number::Undefined => Number::Undefined,
211 }
212 }
213}
214
215impl ops::Sub<Number> for Number {
216 type Output = Number;
217
218 #[inline]
219 fn sub(self, rhs: Number) -> Number {
220 match self {
221 Number::Defined(val) => match rhs {
222 Number::Defined(other) => Number::Defined(val - other),
223 Number::Undefined => self,
224 },
225 Number::Undefined => Number::Undefined,
226 }
227 }
228}
229
230impl ops::Mul<f32> for Number {
231 type Output = Number;
232
233 #[inline]
234 fn mul(self, rhs: f32) -> Number {
235 match self {
236 Number::Defined(val) => Number::Defined(val * rhs),
237 Number::Undefined => Number::Undefined,
238 }
239 }
240}
241
242impl ops::Mul<Number> for Number {
243 type Output = Number;
244
245 #[inline]
246 fn mul(self, rhs: Number) -> Number {
247 match self {
248 Number::Defined(val) => match rhs {
249 Number::Defined(other) => Number::Defined(val * other),
250 Number::Undefined => self,
251 },
252 Number::Undefined => Number::Undefined,
253 }
254 }
255}
256
257impl ops::Div<f32> for Number {
258 type Output = Number;
259
260 #[inline]
261 fn div(self, rhs: f32) -> Number {
262 match self {
263 Number::Defined(val) => Number::Defined(val / rhs),
264 Number::Undefined => Number::Undefined,
265 }
266 }
267}
268
269impl ops::Div<Number> for Number {
270 type Output = Number;
271
272 #[inline]
273 fn div(self, rhs: Number) -> Number {
274 match self {
275 Number::Defined(val) => match rhs {
276 Number::Defined(other) => Number::Defined(val / other),
277 Number::Undefined => self,
278 },
279 Number::Undefined => Number::Undefined,
280 }
281 }
282}