reifydb_value/value/number/safe/
add.rs1pub trait SafeAdd: Sized {
5 fn checked_add(&self, r: &Self) -> Option<Self>;
6 fn saturating_add(&self, r: &Self) -> Self;
7 fn wrapping_add(&self, r: &Self) -> Self;
8}
9
10macro_rules! impl_safe_add {
11 ($($t:ty),*) => {
12 $(
13 impl SafeAdd for $t {
14 fn checked_add(&self, r: &Self) -> Option<Self> {
15 <$t>::checked_add(*self, *r)
16 }
17 fn saturating_add(&self, r: &Self) -> Self {
18 <$t>::saturating_add(*self, *r)
19 }
20 fn wrapping_add(&self, r: &Self) -> Self {
21 <$t>::wrapping_add(*self, *r)
22 }
23 }
24 )*
25 };
26}
27
28impl_safe_add!(i8, i16, i32, i64, i128, u8, u16, u32, u64, u128);
29
30use crate::value::decimal::Decimal;
31
32impl SafeAdd for Decimal {
33 fn checked_add(&self, r: &Self) -> Option<Self> {
34 Decimal::checked_add(self, r)
35 }
36
37 fn saturating_add(&self, r: &Self) -> Self {
38 Decimal::saturating_add(self, r)
39 }
40
41 fn wrapping_add(&self, r: &Self) -> Self {
42 Decimal::saturating_add(self, r)
43 }
44}
45
46impl SafeAdd for f32 {
47 fn checked_add(&self, r: &Self) -> Option<Self> {
48 let result = *self + *r;
49 if result.is_infinite() && self.is_finite() && r.is_finite() {
50 None
51 } else {
52 Some(result)
53 }
54 }
55
56 fn saturating_add(&self, r: &Self) -> Self {
57 let result = *self + *r;
58 if result.is_infinite() {
59 if result.is_sign_positive() {
60 f32::MAX
61 } else {
62 f32::MIN
63 }
64 } else {
65 result
66 }
67 }
68
69 fn wrapping_add(&self, r: &Self) -> Self {
70 *self + *r
71 }
72}
73
74impl SafeAdd for f64 {
75 fn checked_add(&self, r: &Self) -> Option<Self> {
76 let result = *self + *r;
77 if result.is_infinite() && self.is_finite() && r.is_finite() {
78 None
79 } else {
80 Some(result)
81 }
82 }
83
84 fn saturating_add(&self, r: &Self) -> Self {
85 let result = *self + *r;
86 if result.is_infinite() {
87 if result.is_sign_positive() {
88 f64::MAX
89 } else {
90 f64::MIN
91 }
92 } else {
93 result
94 }
95 }
96
97 fn wrapping_add(&self, r: &Self) -> Self {
98 *self + *r
99 }
100}
101
102#[cfg(test)]
103pub mod tests {
104
105 macro_rules! define_tests {
106 ($($t:ty => $mod:ident),*) => {
107 $(
108 mod $mod {
109 use super::super::SafeAdd;
110
111 #[test]
112 fn checked_add_happy() {
113 let x: $t = 10;
114 let y: $t = 20;
115 assert_eq!(SafeAdd::checked_add(&x, &y), Some(30));
116 }
117
118 #[test]
119 fn checked_add_unhappy() {
120 let x: $t = <$t>::MAX;
121 let y: $t = 1;
122 assert_eq!(SafeAdd::checked_add(&x, &y), None);
123 }
124
125 #[test]
126 fn saturating_add_happy() {
127 let x: $t = 10;
128 let y: $t = 20;
129 assert_eq!(SafeAdd::saturating_add(&x, &y), 30);
130 }
131
132 #[test]
133 fn saturating_add_unhappy() {
134 let x: $t = <$t>::MAX;
135 let y: $t = 1;
136 assert_eq!(SafeAdd::saturating_add(&x, &y), <$t>::MAX);
137 }
138
139 #[test]
140 fn wrapping_add_happy() {
141 let x: $t = 10;
142 let y: $t = 20;
143 assert_eq!(SafeAdd::wrapping_add(&x, &y), 30);
144 }
145
146 #[test]
147 fn wrapping_add_unhappy() {
148 let x: $t = <$t>::MAX;
149 let y: $t = 1;
150 assert_eq!(SafeAdd::wrapping_add(&x, &y), <$t>::MIN);
151 }
152 }
153 )*
154 };
155 }
156
157 define_tests!(
158 i8 => i8_tests,
159 i16 => i16_tests,
160 i32 => i32_tests,
161 i64 => i64_tests,
162 i128 => i128_tests,
163 u8 => u8_tests,
164 u16 => u16_tests,
165 u32 => u32_tests,
166 u64 => u64_tests,
167 u128 => u128_tests
168 );
169}