tawasuyu

tawasuyu/taffy

A high performance rust-powered UI layout library

Rust 740HTML 687Markdown 12TOML 72455 Definiciones

⎇ 2e0d1bd2f08d3e477e564acfbed30c9caa2e0440 src/math.rs Rust · 230 líneas · 7.0 KB Historia Quién tocó qué crudo

Remove manual map implementation in maybe math (#161) 03fc09079 · TimJentzsch ·

1//! Contains numerical helper traits and functions
2
3/// A trait to conveniently calculate minimums and maximums when some data may not be defined
4///
5/// If the left-hand value is [`None`], these operations return [`None`].
6/// If the right-hand value is [`None`], it is treated as zero.
7pub(crate) trait MaybeMath<In, Out> {
8    /// Returns the minimum of `self` and `rhs`
9    fn maybe_min(self, rhs: In) -> Out;
10
11    /// Returns the maximum of `self` and `rhs`
12    fn maybe_max(self, rhs: In) -> Out;
13
14    /// Adds `self` and `rhs`.
15    fn maybe_add(self, rhs: In) -> Out;
16
17    /// Subtracts rhs from `self`, treating [`None`] values as default
18    fn maybe_sub(self, rhs: In) -> Out;
19}
20
21impl MaybeMath<Option<f32>, Option<f32>> for Option<f32> {
22    fn maybe_min(self, rhs: Option<f32>) -> Option<f32> {
23        match (self, rhs) {
24            (Some(l), Some(r)) => Some(l.min(r)),
25            (Some(_l), None) => self,
26            (None, Some(_r)) => None,
27            (None, None) => None,
28        }
29    }
30
31    fn maybe_max(self, rhs: Option<f32>) -> Option<f32> {
32        match (self, rhs) {
33            (Some(l), Some(r)) => Some(l.max(r)),
34            (Some(_l), None) => self,
35            (None, Some(_r)) => None,
36            (None, None) => None,
37        }
38    }
39
40    fn maybe_add(self, rhs: Option<f32>) -> Option<f32> {
41        match (self, rhs) {
42            (Some(l), Some(r)) => Some(l + r),
43            (Some(_l), None) => self,
44            (None, Some(_r)) => None,
45            (None, None) => None,
46        }
47    }
48
49    fn maybe_sub(self, rhs: Option<f32>) -> Option<f32> {
50        match (self, rhs) {
51            (Some(l), Some(r)) => Some(l - r),
52            (Some(_l), None) => self,
53            (None, Some(_r)) => None,
54            (None, None) => None,
55        }
56    }
57}
58
59impl MaybeMath<f32, Option<f32>> for Option<f32> {
60    fn maybe_min(self, rhs: f32) -> Option<f32> {
61        self.map(|val| val.min(rhs))
62    }
63
64    fn maybe_max(self, rhs: f32) -> Option<f32> {
65        self.map(|val| val.max(rhs))
66    }
67
68    fn maybe_add(self, rhs: f32) -> Option<f32> {
69        self.map(|val| val + rhs)
70    }
71
72    fn maybe_sub(self, rhs: f32) -> Option<f32> {
73        self.map(|val| val - rhs)
74    }
75}
76
77impl MaybeMath<Option<f32>, f32> for f32 {
78    fn maybe_min(self, rhs: Option<f32>) -> f32 {
79        match rhs {
80            Some(val) => self.min(val),
81            None => self,
82        }
83    }
84
85    fn maybe_max(self, rhs: Option<f32>) -> f32 {
86        match rhs {
87            Some(val) => self.max(val),
88            None => self,
89        }
90    }
91
92    fn maybe_add(self, rhs: Option<f32>) -> f32 {
93        match rhs {
94            Some(val) => self + val,
95            None => self,
96        }
97    }
98
99    fn maybe_sub(self, rhs: Option<f32>) -> f32 {
100        match rhs {
101            Some(val) => self - val,
102            None => self,
103        }
104    }
105}
106
107#[cfg(test)]
108mod tests {
109    mod lhs_option_f32_rhs_option_f32 {
110
111        use crate::math::MaybeMath;
112        use rstest::rstest;
113
114        #[rstest]
115        #[case(Some(3.0), Some(5.0), Some(3.0))]
116        #[case(Some(5.0), Some(3.0), Some(3.0))]
117        #[case(Some(3.0), None, Some(3.0))]
118        #[case(None, Some(3.0), None)]
119        #[case(None, None, None)]
120        fn test_maybe_min(#[case] lhs: Option<f32>, #[case] rhs: Option<f32>, #[case] expected: Option<f32>) {
121            assert_eq!(lhs.maybe_min(rhs), expected);
122        }
123
124        #[rstest]
125        #[case(Some(3.0), Some(5.0), Some(5.0))]
126        #[case(Some(5.0), Some(3.0), Some(5.0))]
127        #[case(Some(3.0), None, Some(3.0))]
128        #[case(None, Some(3.0), None)]
129        #[case(None, None, None)]
130        fn test_maybe_max(#[case] lhs: Option<f32>, #[case] rhs: Option<f32>, #[case] expected: Option<f32>) {
131            assert_eq!(lhs.maybe_max(rhs), expected);
132        }
133
134        #[rstest]
135        #[case(Some(3.0), Some(5.0), Some(8.0))]
136        #[case(Some(5.0), Some(3.0), Some(8.0))]
137        #[case(Some(3.0), None, Some(3.0))]
138        #[case(None, Some(3.0), None)]
139        #[case(None, None, None)]
140        fn test_maybe_add(#[case] lhs: Option<f32>, #[case] rhs: Option<f32>, #[case] expected: Option<f32>) {
141            assert_eq!(lhs.maybe_add(rhs), expected);
142        }
143
144        #[rstest]
145        #[case(Some(3.0), Some(5.0), Some(-2.0))]
146        #[case(Some(5.0), Some(3.0), Some(2.0))]
147        #[case(Some(3.0), None, Some(3.0))]
148        #[case(None, Some(3.0), None)]
149        #[case(None, None, None)]
150        fn test_maybe_sub(#[case] lhs: Option<f32>, #[case] rhs: Option<f32>, #[case] expected: Option<f32>) {
151            assert_eq!(lhs.maybe_sub(rhs), expected);
152        }
153    }
154
155    mod lhs_option_f32_rhs_f32 {
156
157        use crate::math::MaybeMath;
158        use rstest::rstest;
159
160        #[rstest]
161        #[case(Some(3.0), 5.0, Some(3.0))]
162        #[case(Some(5.0), 3.0, Some(3.0))]
163        #[case(None, 3.0, None)]
164        fn test_maybe_min(#[case] lhs: Option<f32>, #[case] rhs: f32, #[case] expected: Option<f32>) {
165            assert_eq!(lhs.maybe_min(rhs), expected);
166        }
167
168        #[rstest]
169        #[case(Some(3.0), 5.0, Some(5.0))]
170        #[case(Some(5.0), 3.0, Some(5.0))]
171        #[case(None, 3.0, None)]
172        fn test_maybe_max(#[case] lhs: Option<f32>, #[case] rhs: f32, #[case] expected: Option<f32>) {
173            assert_eq!(lhs.maybe_max(rhs), expected);
174        }
175
176        #[rstest]
177        #[case(Some(3.0), 5.0, Some(8.0))]
178        #[case(Some(5.0), 3.0, Some(8.0))]
179        #[case(None, 3.0, None)]
180        fn test_maybe_add(#[case] lhs: Option<f32>, #[case] rhs: f32, #[case] expected: Option<f32>) {
181            assert_eq!(lhs.maybe_add(rhs), expected);
182        }
183
184        #[rstest]
185        #[case(Some(3.0), 5.0, Some(-2.0))]
186        #[case(Some(5.0), 3.0, Some(2.0))]
187        #[case(None, 3.0, None)]
188        fn test_maybe_sub(#[case] lhs: Option<f32>, #[case] rhs: f32, #[case] expected: Option<f32>) {
189            assert_eq!(lhs.maybe_sub(rhs), expected);
190        }
191    }
192
193    mod lhs_f32_rhs_option_f32 {
194
195        use crate::math::MaybeMath;
196        use rstest::rstest;
197
198        #[rstest]
199        #[case(3.0, Some(5.0), 3.0)]
200        #[case(5.0, Some(3.0), 3.0)]
201        #[case(3.0, None, 3.0)]
202        fn test_maybe_min(#[case] lhs: f32, #[case] rhs: Option<f32>, #[case] expected: f32) {
203            assert_eq!(lhs.maybe_min(rhs), expected);
204        }
205
206        #[rstest]
207        #[case(3.0, Some(5.0), 5.0)]
208        #[case(5.0, Some(3.0), 5.0)]
209        #[case(3.0, None, 3.0)]
210        fn test_maybe_max(#[case] lhs: f32, #[case] rhs: Option<f32>, #[case] expected: f32) {
211            assert_eq!(lhs.maybe_max(rhs), expected);
212        }
213
214        #[rstest]
215        #[case(3.0, Some(5.0), 8.0)]
216        #[case(5.0, Some(3.0), 8.0)]
217        #[case(3.0, None, 3.0)]
218        fn test_maybe_add(#[case] lhs: f32, #[case] rhs: Option<f32>, #[case] expected: f32) {
219            assert_eq!(lhs.maybe_add(rhs), expected);
220        }
221
222        #[rstest]
223        #[case(3.0, Some(5.0), -2.0)]
224        #[case(5.0, Some(3.0), 2.0)]
225        #[case(3.0, None, 3.0)]
226        fn test_maybe_sub(#[case] lhs: f32, #[case] rhs: Option<f32>, #[case] expected: f32) {
227            assert_eq!(lhs.maybe_sub(rhs), expected);
228        }
229    }
230}