azul_layout/
number.rs

1// MIT License
2//
3// Copyright (c) 2018 Visly Inc.
4//
5// Permission is hereby granted, free of charge, to any person obtaining a copy
6// of this software and associated documentation files (the "Software"), to deal
7// in the Software without restriction, including without limitation the rights
8// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9// copies of the Software, and to permit persons to whom the Software is
10// furnished to do so, subject to the following conditions:
11//
12// The above copyright notice and this permission notice shall be included in all
13// copies or substantial portions of the Software.
14//
15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21// SOFTWARE.
22
23use 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}