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 // The logic here is subtle and critical;
61 // explicit match statements make it more clear what's going on
62 #[allow(clippy::manual_map)]
63 fn maybe_min(self, rhs: f32) -> Option<f32> {
64 match self {
65 Some(val) => Some(val.min(rhs)),
66 None => None,
67 }
68 }
69
70 #[allow(clippy::manual_map)]
71 fn maybe_max(self, rhs: f32) -> Option<f32> {
72 match self {
73 Some(val) => Some(val.max(rhs)),
74 None => None,
75 }
76 }
77
78 #[allow(clippy::manual_map)]
79 fn maybe_add(self, rhs: f32) -> Option<f32> {
80 match self {
81 Some(val) => Some(val + rhs),
82 None => None,
83 }
84 }
85
86 #[allow(clippy::manual_map)]
87 fn maybe_sub(self, rhs: f32) -> Option<f32> {
88 match self {
89 Some(val) => Some(val - rhs),
90 None => None,
91 }
92 }
93}
94
95impl MaybeMath<Option<f32>, f32> for f32 {
96 fn maybe_min(self, rhs: Option<f32>) -> f32 {
97 match rhs {
98 Some(val) => self.min(val),
99 None => self,
100 }
101 }
102
103 fn maybe_max(self, rhs: Option<f32>) -> f32 {
104 match rhs {
105 Some(val) => self.max(val),
106 None => self,
107 }
108 }
109
110 fn maybe_add(self, rhs: Option<f32>) -> f32 {
111 match rhs {
112 Some(val) => self + val,
113 None => self,
114 }
115 }
116
117 fn maybe_sub(self, rhs: Option<f32>) -> f32 {
118 match rhs {
119 Some(val) => self - val,
120 None => self,
121 }
122 }
123}