gioser

tawasuyu/taffy

A high performance rust-powered UI layout library

Rust 684HTML 640Markdown 12TOML 62286 Sutichaykuna

⎇ 0.1.x src/number.rs Rust · 227 siq'ikuna · 5.5 KB Ñawpa willay Pi imata llamkarqan ch'uya

Document entire crate (#96) de9123e02 · Alice Cecile ·

1//! Contains the [`Number`] type and associated methods
2
3use core::ops::{Add, Div, Mul, Sub};
4
5/// A [`f32`] that may be undefined
6///
7/// NOTE: this should *really* be an [`Option<f32>`],
8/// but we're optimizing for backwards compatibility for now.
9#[derive(Copy, Clone, PartialEq, Debug)]
10#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11pub enum Number {
12    /// Pretend this is [`Some(f32)`]
13    ///
14    /// WARNING: the contained value may be NaN
15    Defined(f32),
16    /// Pretend this is [`None`]
17    Undefined,
18}
19
20/// An extension method used for [`Number`]
21pub trait OrElse<T> {
22    /// Returns the contained value if it is defined, otherwise returns `other`
23    fn or_else(self, other: T) -> T;
24}
25
26impl Default for Number {
27    fn default() -> Self {
28        Self::Undefined
29    }
30}
31
32impl OrElse<f32> for Number {
33    fn or_else(self, other: f32) -> f32 {
34        match self {
35            Number::Defined(val) => val,
36            Number::Undefined => other,
37        }
38    }
39}
40
41impl OrElse<Self> for Number {
42    fn or_else(self, other: Self) -> Self {
43        match self {
44            Number::Defined(_) => self,
45            Number::Undefined => other,
46        }
47    }
48}
49
50impl Number {
51    /// Is the number defined?
52    pub fn is_defined(self) -> bool {
53        match self {
54            Number::Defined(_) => true,
55            Number::Undefined => false,
56        }
57    }
58
59    /// Is the number undefined?
60    pub fn is_undefined(self) -> bool {
61        match self {
62            Number::Defined(_) => false,
63            Number::Undefined => true,
64        }
65    }
66}
67
68/// An extension trait for [`Number`]
69pub trait MinMax<In, Out> {
70    /// Returns the minimum of self and rhs
71    ///
72    /// If either either value is invalid, returns the other value.
73    fn maybe_min(self, rhs: In) -> Out;
74    /// Returns the maximum of self and rhs
75    ///
76    /// If either either value is invalid, returns the other value.
77    fn maybe_max(self, rhs: In) -> Out;
78}
79
80impl MinMax<Self, Self> for Number {
81    fn maybe_min(self, rhs: Self) -> Self {
82        match (self, rhs) {
83            (Number::Defined(l), Number::Defined(r)) => Number::Defined(l.min(r)),
84            (Number::Defined(_), _) => self,
85            _ => Number::Undefined,
86        }
87    }
88
89    fn maybe_max(self, rhs: Self) -> Self {
90        match (self, rhs) {
91            (Number::Defined(l), Number::Defined(r)) => Number::Defined(l.max(r)),
92            (Number::Defined(_), _) => self,
93            _ => Number::Undefined,
94        }
95    }
96}
97
98impl MinMax<f32, Number> for Number {
99    fn maybe_min(self, rhs: f32) -> Self {
100        match self {
101            Number::Defined(val) => Number::Defined(val.min(rhs)),
102            Number::Undefined => Number::Undefined,
103        }
104    }
105
106    fn maybe_max(self, rhs: f32) -> Self {
107        match self {
108            Number::Defined(val) => Number::Defined(val.max(rhs)),
109            Number::Undefined => Number::Undefined,
110        }
111    }
112}
113
114impl MinMax<Number, f32> for f32 {
115    fn maybe_min(self, rhs: Number) -> f32 {
116        match rhs {
117            Number::Defined(val) => self.min(val),
118            Number::Undefined => self,
119        }
120    }
121
122    fn maybe_max(self, rhs: Number) -> f32 {
123        match rhs {
124            Number::Defined(val) => self.max(val),
125            Number::Undefined => self,
126        }
127    }
128}
129
130impl From<f32> for Number {
131    #[must_use]
132    fn from(v: f32) -> Self {
133        Self::Defined(v)
134    }
135}
136
137impl Add<f32> for Number {
138    type Output = Number;
139
140    fn add(self, rhs: f32) -> Self {
141        match self {
142            Number::Defined(val) => Number::Defined(val + rhs),
143            Number::Undefined => Number::Undefined,
144        }
145    }
146}
147
148impl Add<Number> for Number {
149    type Output = Number;
150
151    fn add(self, rhs: Self) -> Self {
152        match (self, rhs) {
153            (Number::Defined(l), Number::Defined(r)) => Number::Defined(l + r),
154            (Number::Defined(_), _) => self,
155            _ => Number::Undefined,
156        }
157    }
158}
159
160impl Sub<f32> for Number {
161    type Output = Number;
162
163    fn sub(self, rhs: f32) -> Self {
164        match self {
165            Number::Defined(val) => Number::Defined(val - rhs),
166            Number::Undefined => Number::Undefined,
167        }
168    }
169}
170
171impl Sub<Number> for Number {
172    type Output = Number;
173
174    fn sub(self, rhs: Self) -> Self {
175        match (self, rhs) {
176            (Number::Defined(l), Number::Defined(r)) => Number::Defined(l - r),
177            (Number::Defined(_), _) => self,
178            _ => Number::Undefined,
179        }
180    }
181}
182
183impl Mul<f32> for Number {
184    type Output = Number;
185
186    fn mul(self, rhs: f32) -> Self {
187        match self {
188            Number::Defined(val) => Number::Defined(val * rhs),
189            Number::Undefined => Number::Undefined,
190        }
191    }
192}
193
194impl Mul<Number> for Number {
195    type Output = Number;
196
197    fn mul(self, rhs: Self) -> Self {
198        match (self, rhs) {
199            (Number::Defined(l), Number::Defined(r)) => Number::Defined(l * r),
200            (Number::Defined(_), _) => self,
201            _ => Number::Undefined,
202        }
203    }
204}
205
206impl Div<f32> for Number {
207    type Output = Number;
208
209    fn div(self, rhs: f32) -> Self {
210        match self {
211            Number::Defined(val) => Number::Defined(val / rhs),
212            Number::Undefined => Number::Undefined,
213        }
214    }
215}
216
217impl Div<Number> for Number {
218    type Output = Number;
219
220    fn div(self, rhs: Self) -> Self {
221        match (self, rhs) {
222            (Number::Defined(l), Number::Defined(r)) => Number::Defined(l / r),
223            (Number::Defined(_), _) => self,
224            _ => Number::Undefined,
225        }
226    }
227}