1use core::ops;
2
3#[derive(Copy, Clone, PartialEq, Debug)]
4pub enum Number {
5 Defined(f32),
6 Undefined,
7}
8
9pub trait ToNumber {
10 fn to_number(self) -> Number;
11}
12
13pub trait OrElse<T> {
14 fn or_else(self, other: T) -> T;
15}
16
17impl Default for Number {
18 fn default() -> Number {
19 Number::Undefined
20 }
21}
22
23impl OrElse<f32> for Number {
24 fn or_else(self, other: f32) -> f32 {
25 match self {
26 Number::Defined(val) => val,
27 Number::Undefined => other,
28 }
29 }
30}
31
32impl OrElse<Number> for Number {
33 fn or_else(self, other: Number) -> Number {
34 match self {
35 Number::Defined(_) => self,
36 Number::Undefined => other,
37 }
38 }
39}
40
41impl Number {
42 pub fn is_defined(self) -> bool {
43 match self {
44 Number::Defined(_) => true,
45 Number::Undefined => false,
46 }
47 }
48
49 pub fn is_undefined(self) -> bool {
50 match self {
51 Number::Defined(_) => false,
52 Number::Undefined => true,
53 }
54 }
55}
56
57pub trait MinMax<In, Out> {
58 fn maybe_min(self, rhs: In) -> Out;
59 fn maybe_max(self, rhs: In) -> Out;
60}
61
62impl MinMax<Number, Number> for Number {
63 fn maybe_min(self, rhs: Number) -> Number {
64 match self {
65 Number::Defined(val) => match rhs {
66 Number::Defined(other) => Number::Defined(val.min(other)),
67 Number::Undefined => self,
68 },
69 Number::Undefined => Number::Undefined,
70 }
71 }
72
73 fn maybe_max(self, rhs: Number) -> Number {
74 match self {
75 Number::Defined(val) => match rhs {
76 Number::Defined(other) => Number::Defined(val.max(other)),
77 Number::Undefined => self,
78 },
79 Number::Undefined => Number::Undefined,
80 }
81 }
82}
83
84impl MinMax<f32, Number> for Number {
85 fn maybe_min(self, rhs: f32) -> Number {
86 match self {
87 Number::Defined(val) => Number::Defined(val.min(rhs)),
88 Number::Undefined => Number::Undefined,
89 }
90 }
91
92 fn maybe_max(self, rhs: f32) -> Number {
93 match self {
94 Number::Defined(val) => Number::Defined(val.max(rhs)),
95 Number::Undefined => Number::Undefined,
96 }
97 }
98}
99
100impl MinMax<Number, f32> for f32 {
101 fn maybe_min(self, rhs: Number) -> f32 {
102 match rhs {
103 Number::Defined(val) => self.min(val),
104 Number::Undefined => self,
105 }
106 }
107
108 fn maybe_max(self, rhs: Number) -> f32 {
109 match rhs {
110 Number::Defined(val) => self.max(val),
111 Number::Undefined => self,
112 }
113 }
114}
115
116impl ToNumber for f32 {
117 fn to_number(self) -> Number {
118 Number::Defined(self)
119 }
120}
121
122impl ops::Add<f32> for Number {
123 type Output = Number;
124
125 fn add(self, rhs: f32) -> Number {
126 match self {
127 Number::Defined(val) => Number::Defined(val + rhs),
128 Number::Undefined => Number::Undefined,
129 }
130 }
131}
132
133impl ops::Add<Number> for Number {
134 type Output = Number;
135
136 fn add(self, rhs: Number) -> Number {
137 match self {
138 Number::Defined(val) => match rhs {
139 Number::Defined(other) => Number::Defined(val + other),
140 Number::Undefined => self,
141 },
142 Number::Undefined => Number::Undefined,
143 }
144 }
145}
146
147impl ops::Sub<f32> for Number {
148 type Output = Number;
149
150 fn sub(self, rhs: f32) -> Number {
151 match self {
152 Number::Defined(val) => Number::Defined(val - rhs),
153 Number::Undefined => Number::Undefined,
154 }
155 }
156}
157
158impl ops::Sub<Number> for Number {
159 type Output = Number;
160
161 fn sub(self, rhs: Number) -> Number {
162 match self {
163 Number::Defined(val) => match rhs {
164 Number::Defined(other) => Number::Defined(val - other),
165 Number::Undefined => self,
166 },
167 Number::Undefined => Number::Undefined,
168 }
169 }
170}
171
172impl ops::Mul<f32> for Number {
173 type Output = Number;
174
175 fn mul(self, rhs: f32) -> Number {
176 match self {
177 Number::Defined(val) => Number::Defined(val * rhs),
178 Number::Undefined => Number::Undefined,
179 }
180 }
181}
182
183impl ops::Mul<Number> for Number {
184 type Output = Number;
185
186 fn mul(self, rhs: Number) -> Number {
187 match self {
188 Number::Defined(val) => match rhs {
189 Number::Defined(other) => Number::Defined(val * other),
190 Number::Undefined => self,
191 },
192 Number::Undefined => Number::Undefined,
193 }
194 }
195}
196
197impl ops::Div<f32> for Number {
198 type Output = Number;
199
200 fn div(self, rhs: f32) -> Number {
201 match self {
202 Number::Defined(val) => Number::Defined(val / rhs),
203 Number::Undefined => Number::Undefined,
204 }
205 }
206}
207
208impl ops::Div<Number> for Number {
209 type Output = Number;
210
211 fn div(self, rhs: Number) -> Number {
212 match self {
213 Number::Defined(val) => match rhs {
214 Number::Defined(other) => Number::Defined(val / other),
215 Number::Undefined => self,
216 },
217 Number::Undefined => Number::Undefined,
218 }
219 }
220}