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