1#![allow(clippy::manual_clamp)]
3
4use crate::geometry::Size;
5use crate::style::AvailableSpace;
6
7pub(crate) trait MaybeMath<In, Out> {
12 fn maybe_min(self, rhs: In) -> Out;
14
15 fn maybe_max(self, rhs: In) -> Out;
17
18 fn maybe_clamp(self, min: In, max: In) -> Out;
20
21 fn maybe_add(self, rhs: In) -> Out;
23
24 fn maybe_sub(self, rhs: In) -> Out;
26}
27
28impl MaybeMath<Option<f32>, Option<f32>> for Option<f32> {
29 fn maybe_min(self, rhs: Option<f32>) -> Option<f32> {
30 match (self, rhs) {
31 (Some(l), Some(r)) => Some(l.min(r)),
32 (Some(_l), None) => self,
33 (None, Some(_r)) => None,
34 (None, None) => None,
35 }
36 }
37
38 fn maybe_max(self, rhs: Option<f32>) -> Option<f32> {
39 match (self, rhs) {
40 (Some(l), Some(r)) => Some(l.max(r)),
41 (Some(_l), None) => self,
42 (None, Some(_r)) => None,
43 (None, None) => None,
44 }
45 }
46
47 fn maybe_clamp(self, min: Option<f32>, max: Option<f32>) -> Option<f32> {
48 match (self, min, max) {
49 (Some(base), Some(min), Some(max)) => Some(base.min(max).max(min)),
50 (Some(base), None, Some(max)) => Some(base.min(max)),
51 (Some(base), Some(min), None) => Some(base.max(min)),
52 (Some(_), None, None) => self,
53 (None, _, _) => None,
54 }
55 }
56
57 fn maybe_add(self, rhs: Option<f32>) -> Option<f32> {
58 match (self, rhs) {
59 (Some(l), Some(r)) => Some(l + r),
60 (Some(_l), None) => self,
61 (None, Some(_r)) => None,
62 (None, None) => None,
63 }
64 }
65
66 fn maybe_sub(self, rhs: Option<f32>) -> Option<f32> {
67 match (self, rhs) {
68 (Some(l), Some(r)) => Some(l - r),
69 (Some(_l), None) => self,
70 (None, Some(_r)) => None,
71 (None, None) => None,
72 }
73 }
74}
75
76impl MaybeMath<f32, Option<f32>> for Option<f32> {
77 fn maybe_min(self, rhs: f32) -> Option<f32> {
78 self.map(|val| val.min(rhs))
79 }
80
81 fn maybe_max(self, rhs: f32) -> Option<f32> {
82 self.map(|val| val.max(rhs))
83 }
84
85 fn maybe_clamp(self, min: f32, max: f32) -> Option<f32> {
86 self.map(|val| val.min(max).max(min))
87 }
88
89 fn maybe_add(self, rhs: f32) -> Option<f32> {
90 self.map(|val| val + rhs)
91 }
92
93 fn maybe_sub(self, rhs: f32) -> Option<f32> {
94 self.map(|val| val - rhs)
95 }
96}
97
98impl MaybeMath<Option<f32>, f32> for f32 {
99 fn maybe_min(self, rhs: Option<f32>) -> f32 {
100 match rhs {
101 Some(val) => self.min(val),
102 None => self,
103 }
104 }
105
106 fn maybe_max(self, rhs: Option<f32>) -> f32 {
107 match rhs {
108 Some(val) => self.max(val),
109 None => self,
110 }
111 }
112
113 fn maybe_clamp(self, min: Option<f32>, max: Option<f32>) -> f32 {
114 match (min, max) {
115 (Some(min), Some(max)) => self.min(max).max(min),
116 (None, Some(max)) => self.min(max),
117 (Some(min), None) => self.max(min),
118 (None, None) => self,
119 }
120 }
121
122 fn maybe_add(self, rhs: Option<f32>) -> f32 {
123 match rhs {
124 Some(val) => self + val,
125 None => self,
126 }
127 }
128
129 fn maybe_sub(self, rhs: Option<f32>) -> f32 {
130 match rhs {
131 Some(val) => self - val,
132 None => self,
133 }
134 }
135}
136
137impl MaybeMath<f32, AvailableSpace> for AvailableSpace {
138 fn maybe_min(self, rhs: f32) -> AvailableSpace {
139 match self {
140 AvailableSpace::Definite(val) => AvailableSpace::Definite(val.min(rhs)),
141 AvailableSpace::MinContent => AvailableSpace::Definite(rhs),
142 AvailableSpace::MaxContent => AvailableSpace::Definite(rhs),
143 }
144 }
145 fn maybe_max(self, rhs: f32) -> AvailableSpace {
146 match self {
147 AvailableSpace::Definite(val) => AvailableSpace::Definite(val.max(rhs)),
148 AvailableSpace::MinContent => AvailableSpace::MinContent,
149 AvailableSpace::MaxContent => AvailableSpace::MaxContent,
150 }
151 }
152
153 fn maybe_clamp(self, min: f32, max: f32) -> AvailableSpace {
154 match self {
155 AvailableSpace::Definite(val) => AvailableSpace::Definite(val.min(max).max(min)),
156 AvailableSpace::MinContent => AvailableSpace::MinContent,
157 AvailableSpace::MaxContent => AvailableSpace::MaxContent,
158 }
159 }
160
161 fn maybe_add(self, rhs: f32) -> AvailableSpace {
162 match self {
163 AvailableSpace::Definite(val) => AvailableSpace::Definite(val + rhs),
164 AvailableSpace::MinContent => AvailableSpace::MinContent,
165 AvailableSpace::MaxContent => AvailableSpace::MaxContent,
166 }
167 }
168 fn maybe_sub(self, rhs: f32) -> AvailableSpace {
169 match self {
170 AvailableSpace::Definite(val) => AvailableSpace::Definite(val - rhs),
171 AvailableSpace::MinContent => AvailableSpace::MinContent,
172 AvailableSpace::MaxContent => AvailableSpace::MaxContent,
173 }
174 }
175}
176
177impl MaybeMath<Option<f32>, AvailableSpace> for AvailableSpace {
178 fn maybe_min(self, rhs: Option<f32>) -> AvailableSpace {
179 match (self, rhs) {
180 (AvailableSpace::Definite(val), Some(rhs)) => AvailableSpace::Definite(val.min(rhs)),
181 (AvailableSpace::Definite(val), None) => AvailableSpace::Definite(val),
182 (AvailableSpace::MinContent, Some(rhs)) => AvailableSpace::Definite(rhs),
183 (AvailableSpace::MinContent, None) => AvailableSpace::MinContent,
184 (AvailableSpace::MaxContent, Some(rhs)) => AvailableSpace::Definite(rhs),
185 (AvailableSpace::MaxContent, None) => AvailableSpace::MaxContent,
186 }
187 }
188 fn maybe_max(self, rhs: Option<f32>) -> AvailableSpace {
189 match (self, rhs) {
190 (AvailableSpace::Definite(val), Some(rhs)) => AvailableSpace::Definite(val.max(rhs)),
191 (AvailableSpace::Definite(val), None) => AvailableSpace::Definite(val),
192 (AvailableSpace::MinContent, _) => AvailableSpace::MinContent,
193 (AvailableSpace::MaxContent, _) => AvailableSpace::MaxContent,
194 }
195 }
196
197 fn maybe_clamp(self, min: Option<f32>, max: Option<f32>) -> AvailableSpace {
198 match (self, min, max) {
199 (AvailableSpace::Definite(val), Some(min), Some(max)) => AvailableSpace::Definite(val.min(max).max(min)),
200 (AvailableSpace::Definite(val), None, Some(max)) => AvailableSpace::Definite(val.min(max)),
201 (AvailableSpace::Definite(val), Some(min), None) => AvailableSpace::Definite(val.max(min)),
202 (AvailableSpace::Definite(val), None, None) => AvailableSpace::Definite(val),
203 (AvailableSpace::MinContent, _, _) => AvailableSpace::MinContent,
204 (AvailableSpace::MaxContent, _, _) => AvailableSpace::MaxContent,
205 }
206 }
207
208 fn maybe_add(self, rhs: Option<f32>) -> AvailableSpace {
209 match (self, rhs) {
210 (AvailableSpace::Definite(val), Some(rhs)) => AvailableSpace::Definite(val + rhs),
211 (AvailableSpace::Definite(val), None) => AvailableSpace::Definite(val),
212 (AvailableSpace::MinContent, _) => AvailableSpace::MinContent,
213 (AvailableSpace::MaxContent, _) => AvailableSpace::MaxContent,
214 }
215 }
216 fn maybe_sub(self, rhs: Option<f32>) -> AvailableSpace {
217 match (self, rhs) {
218 (AvailableSpace::Definite(val), Some(rhs)) => AvailableSpace::Definite(val - rhs),
219 (AvailableSpace::Definite(val), None) => AvailableSpace::Definite(val),
220 (AvailableSpace::MinContent, _) => AvailableSpace::MinContent,
221 (AvailableSpace::MaxContent, _) => AvailableSpace::MaxContent,
222 }
223 }
224}
225
226impl<In, Out, T: MaybeMath<In, Out>> MaybeMath<Size<In>, Size<Out>> for Size<T> {
227 fn maybe_min(self, rhs: Size<In>) -> Size<Out> {
228 Size { width: self.width.maybe_min(rhs.width), height: self.height.maybe_min(rhs.height) }
229 }
230
231 fn maybe_max(self, rhs: Size<In>) -> Size<Out> {
232 Size { width: self.width.maybe_max(rhs.width), height: self.height.maybe_max(rhs.height) }
233 }
234
235 fn maybe_clamp(self, min: Size<In>, max: Size<In>) -> Size<Out> {
236 Size {
237 width: self.width.maybe_clamp(min.width, max.width),
238 height: self.height.maybe_clamp(min.height, max.height),
239 }
240 }
241
242 fn maybe_add(self, rhs: Size<In>) -> Size<Out> {
243 Size { width: self.width.maybe_add(rhs.width), height: self.height.maybe_add(rhs.height) }
244 }
245
246 fn maybe_sub(self, rhs: Size<In>) -> Size<Out> {
247 Size { width: self.width.maybe_sub(rhs.width), height: self.height.maybe_sub(rhs.height) }
248 }
249}
250
251#[cfg(test)]
252mod tests {
253 mod lhs_option_f32_rhs_option_f32 {
254 use crate::util::MaybeMath;
255
256 #[test]
257 fn test_maybe_min() {
258 assert_eq!(Some(3.0).maybe_min(Some(5.0)), Some(3.0));
259 assert_eq!(Some(5.0).maybe_min(Some(3.0)), Some(3.0));
260 assert_eq!(Some(3.0).maybe_min(None), Some(3.0));
261 assert_eq!(None.maybe_min(Some(3.0)), None);
262 assert_eq!(None.maybe_min(None), None);
263 }
264
265 #[test]
266 fn test_maybe_max() {
267 assert_eq!(Some(3.0).maybe_max(Some(5.0)), Some(5.0));
268 assert_eq!(Some(5.0).maybe_max(Some(3.0)), Some(5.0));
269 assert_eq!(Some(3.0).maybe_max(None), Some(3.0));
270 assert_eq!(None.maybe_max(Some(3.0)), None);
271 assert_eq!(None.maybe_max(None), None);
272 }
273
274 #[test]
275 fn test_maybe_add() {
276 assert_eq!(Some(3.0).maybe_add(Some(5.0)), Some(8.0));
277 assert_eq!(Some(5.0).maybe_add(Some(3.0)), Some(8.0));
278 assert_eq!(Some(3.0).maybe_add(None), Some(3.0));
279 assert_eq!(None.maybe_add(Some(3.0)), None);
280 assert_eq!(None.maybe_add(None), None);
281 }
282
283 #[test]
284 fn test_maybe_sub() {
285 assert_eq!(Some(3.0).maybe_sub(Some(5.0)), Some(-2.0));
286 assert_eq!(Some(5.0).maybe_sub(Some(3.0)), Some(2.0));
287 assert_eq!(Some(3.0).maybe_sub(None), Some(3.0));
288 assert_eq!(None.maybe_sub(Some(3.0)), None);
289 assert_eq!(None.maybe_sub(None), None);
290 }
291 }
292
293 mod lhs_option_f32_rhs_f32 {
294 use crate::util::MaybeMath;
295
296 #[test]
297 fn test_maybe_min() {
298 assert_eq!(Some(3.0).maybe_min(5.0), Some(3.0));
299 assert_eq!(Some(5.0).maybe_min(3.0), Some(3.0));
300 assert_eq!(None.maybe_min(3.0), None);
301 }
302
303 #[test]
304 fn test_maybe_max() {
305 assert_eq!(Some(3.0).maybe_max(5.0), Some(5.0));
306 assert_eq!(Some(5.0).maybe_max(3.0), Some(5.0));
307 assert_eq!(None.maybe_max(3.0), None);
308 }
309
310 #[test]
311 fn test_maybe_add() {
312 assert_eq!(Some(3.0).maybe_add(5.0), Some(8.0));
313 assert_eq!(Some(5.0).maybe_add(3.0), Some(8.0));
314 assert_eq!(None.maybe_add(3.0), None);
315 }
316
317 #[test]
318 fn test_maybe_sub() {
319 assert_eq!(Some(3.0).maybe_sub(5.0), Some(-2.0));
320 assert_eq!(Some(5.0).maybe_sub(3.0), Some(2.0));
321 assert_eq!(None.maybe_sub(3.0), None);
322 }
323 }
324
325 mod lhs_f32_rhs_option_f32 {
326 use crate::util::MaybeMath;
327
328 #[test]
329 fn test_maybe_min() {
330 assert_eq!(3.0.maybe_min(Some(5.0)), 3.0);
331 assert_eq!(5.0.maybe_min(Some(3.0)), 3.0);
332 assert_eq!(3.0.maybe_min(None), 3.0);
333 }
334
335 #[test]
336 fn test_maybe_max() {
337 assert_eq!(3.0.maybe_max(Some(5.0)), 5.0);
338 assert_eq!(5.0.maybe_max(Some(3.0)), 5.0);
339 assert_eq!(3.0.maybe_max(None), 3.0);
340 }
341
342 #[test]
343 fn test_maybe_add() {
344 assert_eq!(3.0.maybe_add(Some(5.0)), 8.0);
345 assert_eq!(5.0.maybe_add(Some(3.0)), 8.0);
346 assert_eq!(3.0.maybe_add(None), 3.0);
347 }
348
349 #[test]
350 fn test_maybe_sub() {
351 assert_eq!(3.0.maybe_sub(Some(5.0)), -2.0);
352 assert_eq!(5.0.maybe_sub(Some(3.0)), 2.0);
353 assert_eq!(3.0.maybe_sub(None), 3.0);
354 }
355 }
356}