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