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, int::Int, uint::Uint};
31
32impl SafeAdd for Int {
33 fn checked_add(&self, r: &Self) -> Option<Self> {
34 Some(Int::from(&self.0 + &r.0))
35 }
36
37 fn saturating_add(&self, r: &Self) -> Self {
38 Int::from(&self.0 + &r.0)
39 }
40
41 fn wrapping_add(&self, r: &Self) -> Self {
42 Int::from(&self.0 + &r.0)
43 }
44}
45
46impl SafeAdd for Uint {
47 fn checked_add(&self, r: &Self) -> Option<Self> {
48 Some(Uint::from(&self.0 + &r.0))
49 }
50
51 fn saturating_add(&self, r: &Self) -> Self {
52 Uint::from(&self.0 + &r.0)
53 }
54
55 fn wrapping_add(&self, r: &Self) -> Self {
56 Uint::from(&self.0 + &r.0)
57 }
58}
59
60impl SafeAdd for Decimal {
61 fn checked_add(&self, r: &Self) -> Option<Self> {
62 let result = self.inner() + r.inner();
63 Some(Decimal::from(result))
64 }
65
66 fn saturating_add(&self, r: &Self) -> Self {
67 let result = self.inner() + r.inner();
68 Decimal::from(result)
69 }
70
71 fn wrapping_add(&self, r: &Self) -> Self {
72 let result = self.inner() + r.inner();
73 Decimal::from(result)
74 }
75}
76
77impl SafeAdd for f32 {
78 fn checked_add(&self, r: &Self) -> Option<Self> {
79 let result = *self + *r;
80 if result.is_finite() {
81 Some(result)
82 } else {
83 None
84 }
85 }
86
87 fn saturating_add(&self, r: &Self) -> Self {
88 let result = *self + *r;
89 if result.is_infinite() {
90 if result.is_sign_positive() {
91 f32::MAX
92 } else {
93 f32::MIN
94 }
95 } else {
96 result
97 }
98 }
99
100 fn wrapping_add(&self, r: &Self) -> Self {
101 *self + *r
102 }
103}
104
105impl SafeAdd for f64 {
106 fn checked_add(&self, r: &Self) -> Option<Self> {
107 let result = *self + *r;
108 if result.is_finite() {
109 Some(result)
110 } else {
111 None
112 }
113 }
114
115 fn saturating_add(&self, r: &Self) -> Self {
116 let result = *self + *r;
117 if result.is_infinite() {
118 if result.is_sign_positive() {
119 f64::MAX
120 } else {
121 f64::MIN
122 }
123 } else {
124 result
125 }
126 }
127
128 fn wrapping_add(&self, r: &Self) -> Self {
129 *self + *r
130 }
131}
132
133#[cfg(test)]
134pub mod tests {
135
136 macro_rules! define_tests {
137 ($($t:ty => $mod:ident),*) => {
138 $(
139 mod $mod {
140 use super::super::SafeAdd;
141
142 #[test]
143 fn checked_add_happy() {
144 let x: $t = 10;
145 let y: $t = 20;
146 assert_eq!(SafeAdd::checked_add(&x, &y), Some(30));
147 }
148
149 #[test]
150 fn checked_add_unhappy() {
151 let x: $t = <$t>::MAX;
152 let y: $t = 1;
153 assert_eq!(SafeAdd::checked_add(&x, &y), None);
154 }
155
156 #[test]
157 fn saturating_add_happy() {
158 let x: $t = 10;
159 let y: $t = 20;
160 assert_eq!(SafeAdd::saturating_add(&x, &y), 30);
161 }
162
163 #[test]
164 fn saturating_add_unhappy() {
165 let x: $t = <$t>::MAX;
166 let y: $t = 1;
167 assert_eq!(SafeAdd::saturating_add(&x, &y), <$t>::MAX);
168 }
169
170 #[test]
171 fn wrapping_add_happy() {
172 let x: $t = 10;
173 let y: $t = 20;
174 assert_eq!(SafeAdd::wrapping_add(&x, &y), 30);
175 }
176
177 #[test]
178 fn wrapping_add_unhappy() {
179 let x: $t = <$t>::MAX;
180 let y: $t = 1;
181 assert_eq!(SafeAdd::wrapping_add(&x, &y), <$t>::MIN);
182 }
183 }
184 )*
185 };
186 }
187
188 define_tests!(
189 i8 => i8_tests,
190 i16 => i16_tests,
191 i32 => i32_tests,
192 i64 => i64_tests,
193 i128 => i128_tests,
194 u8 => u8_tests,
195 u16 => u16_tests,
196 u32 => u32_tests,
197 u64 => u64_tests,
198 u128 => u128_tests
199 );
200}