reifydb_value/value/number/safe/convert/
int.rs1use bigdecimal::BigDecimal as BigDecimalInner;
5
6use super::*;
7
8macro_rules! impl_safe_convert_int_to_signed {
9 ($($dst:ty),*) => {
10 $(
11 impl SafeConvert<$dst> for Int {
12 fn checked_convert(self) -> Option<$dst> {
13 <$dst>::try_from(&self.0).ok()
14 }
15
16 fn saturating_convert(self) -> $dst {
17 if let Ok(val) = <$dst>::try_from(&self.0) {
18 val
19 } else if self.0 < BigInt::from(0) {
20 <$dst>::MIN
21 } else {
22 <$dst>::MAX
23 }
24 }
25
26 fn wrapping_convert(self) -> $dst {
27 if let Some(val) = self.0.to_i64() {
28 val as $dst
29 } else if let Some(val) = self.0.to_i128() {
30 val as $dst
31 } else {
32
33 self.saturating_convert()
34 }
35 }
36 }
37 )*
38 };
39}
40
41macro_rules! impl_safe_convert_int_to_unsigned {
42 ($($dst:ty),*) => {
43 $(
44 impl SafeConvert<$dst> for Int {
45 fn checked_convert(self) -> Option<$dst> {
46 if self.0 >= BigInt::from(0) {
47 <$dst>::try_from(&self.0).ok()
48 } else {
49 None
50 }
51 }
52
53 fn saturating_convert(self) -> $dst {
54 if self.0 < BigInt::from(0) {
55 0
56 } else if let Ok(val) = <$dst>::try_from(&self.0) {
57 val
58 } else {
59 <$dst>::MAX
60 }
61 }
62
63 fn wrapping_convert(self) -> $dst {
64 if self.0 < BigInt::from(0) {
65 0
66 } else if let Ok(val) = <$dst>::try_from(&self.0) {
67 val
68 } else {
69 self.saturating_convert()
70 }
71 }
72 }
73 )*
74 };
75}
76
77macro_rules! impl_safe_convert_int_to_float {
78 ($($dst:ty),*) => {
79 $(
80 impl SafeConvert<$dst> for Int {
81 fn checked_convert(self) -> Option<$dst> {
82 self.0.to_f64().and_then(|f| {
83 if f.is_finite() {
84 Some(f as $dst)
85 } else {
86 None
87 }
88 })
89 }
90
91 fn saturating_convert(self) -> $dst {
92 if let Some(f) = self.0.to_f64() {
93 if f.is_finite() {
94 f as $dst
95 } else if f.is_sign_negative() {
96 <$dst>::MIN
97 } else {
98 <$dst>::MAX
99 }
100 } else if self.0 < BigInt::from(0) {
101 <$dst>::MIN
102 } else {
103 <$dst>::MAX
104 }
105 }
106
107 fn wrapping_convert(self) -> $dst {
108 self.saturating_convert()
109 }
110 }
111 )*
112 };
113}
114
115impl_safe_convert_int_to_signed!(i8, i16, i32, i64, i128);
116impl_safe_convert_int_to_unsigned!(u8, u16, u32, u64, u128);
117impl_safe_convert_int_to_float!(f32, f64);
118
119impl SafeConvert<Uint> for Int {
120 fn checked_convert(self) -> Option<Uint> {
121 if self.0 >= BigInt::from(0) {
122 Some(Uint(self.0))
123 } else {
124 None
125 }
126 }
127
128 fn saturating_convert(self) -> Uint {
129 if self.0 >= BigInt::from(0) {
130 Uint(self.0)
131 } else {
132 Uint::zero()
133 }
134 }
135
136 fn wrapping_convert(self) -> Uint {
137 Uint(self.0.abs())
138 }
139}
140
141impl SafeConvert<Decimal> for Int {
142 fn checked_convert(self) -> Option<Decimal> {
143 let big_decimal = BigDecimalInner::from(self.0);
144 Some(Decimal::from(big_decimal))
145 }
146
147 fn saturating_convert(self) -> Decimal {
148 let big_decimal = BigDecimalInner::from(self.0);
149 Decimal::from(big_decimal)
150 }
151
152 fn wrapping_convert(self) -> Decimal {
153 self.saturating_convert()
154 }
155}
156
157#[cfg(test)]
158pub mod tests {
159 use super::*;
160
161 mod i8 {
162 use super::*;
163
164 #[test]
165 fn test_checked_convert() {
166 let x = Int::from(-128);
167 let y: Option<i8> = x.checked_convert();
168 assert_eq!(y, Some(-128i8));
169 }
170
171 #[test]
172 fn test_checked_convert_overflow() {
173 let x = Int::from(128);
174 let y: Option<i8> = x.checked_convert();
175 assert_eq!(y, None);
176 }
177
178 #[test]
179 fn test_saturating_convert() {
180 let x = Int::from(200);
181 let y: i8 = x.saturating_convert();
182 assert_eq!(y, i8::MAX);
183 }
184
185 #[test]
186 fn test_wrapping_convert() {
187 let x = Int::from(-129);
188 let y: i8 = x.wrapping_convert();
189 assert_eq!(y, i8::MAX);
190 }
191 }
192
193 mod i32 {
194 use super::*;
195
196 #[test]
197 fn test_checked_convert() {
198 let x = Int::from(-2147483648i64);
199 let y: Option<i32> = x.checked_convert();
200 assert_eq!(y, Some(-2147483648i32));
201 }
202
203 #[test]
204 fn test_saturating_convert() {
205 let x = Int::from(2147483648i64);
206 let y: i32 = x.saturating_convert();
207 assert_eq!(y, i32::MAX);
208 }
209 }
210
211 mod u8 {
212 use super::*;
213
214 #[test]
215 fn test_checked_convert_positive() {
216 let x = Int::from(42);
217 let y: Option<u8> = x.checked_convert();
218 assert_eq!(y, Some(42u8));
219 }
220
221 #[test]
222 fn test_checked_convert_negative() {
223 let x = Int::from(-1);
224 let y: Option<u8> = x.checked_convert();
225 assert_eq!(y, None);
226 }
227
228 #[test]
229 fn test_saturating_convert() {
230 let x = Int::from(-10);
231 let y: u8 = x.saturating_convert();
232 assert_eq!(y, 0u8);
233 }
234 }
235
236 mod u32 {
237 use super::*;
238
239 #[test]
240 fn test_checked_convert() {
241 let x = Int::from(4294967295u64);
242 let y: Option<u32> = x.checked_convert();
243 assert_eq!(y, Some(4294967295u32));
244 }
245
246 #[test]
247 fn test_saturating_convert() {
248 let x = Int::from(4294967296u64);
249 let y: u32 = x.saturating_convert();
250 assert_eq!(y, u32::MAX);
251 }
252 }
253
254 mod f32 {
255 use super::*;
256
257 #[test]
258 fn test_checked_convert() {
259 let x = Int::from(42);
260 let y: Option<f32> = x.checked_convert();
261 assert_eq!(y, Some(42.0f32));
262 }
263
264 #[test]
265 fn test_saturating_convert() {
266 let x = Int::from(-1000);
267 let y: f32 = x.saturating_convert();
268 assert_eq!(y, -1000.0f32);
269 }
270 }
271
272 mod f64 {
273 use super::*;
274
275 #[test]
276 fn test_checked_convert() {
277 let x = Int::from(42);
278 let y: Option<f64> = x.checked_convert();
279 assert_eq!(y, Some(42.0f64));
280 }
281
282 #[test]
283 fn test_saturating_convert() {
284 let x = Int::from(-1000);
285 let y: f64 = x.saturating_convert();
286 assert_eq!(y, -1000.0f64);
287 }
288 }
289
290 mod uint {
291 use super::*;
292
293 #[test]
294 fn test_checked_convert_positive() {
295 let x = Int::from(42);
296 let y: Option<Uint> = x.checked_convert();
297 assert!(y.is_some());
298 assert_eq!(y.unwrap().to_string(), "42");
299 }
300
301 #[test]
302 fn test_checked_convert_negative() {
303 let x = Int::from(-1);
304 let y: Option<Uint> = x.checked_convert();
305 assert!(y.is_none());
306 }
307
308 #[test]
309 fn test_saturating_convert() {
310 let x = Int::from(-100);
311 let y: Uint = x.saturating_convert();
312 assert_eq!(y.to_string(), "0");
313 }
314
315 #[test]
316 fn test_wrapping_convert() {
317 let x = Int::from(-1);
318 let y: Uint = x.wrapping_convert();
319 assert_eq!(y.to_string(), "1");
320 }
321 }
322
323 mod decimal {
324 use super::*;
325
326 #[test]
327 fn test_checked_convert() {
328 let x = Int::from(12345);
329 let y: Option<Decimal> = x.checked_convert();
330 assert!(y.is_some());
331 let decimal = y.unwrap();
332 assert_eq!(decimal.to_string(), "12345");
333 }
334
335 #[test]
336 fn test_checked_convert_zero() {
337 let x = Int::from(0);
338 let y: Option<Decimal> = x.checked_convert();
339 assert!(y.is_some());
340 let decimal = y.unwrap();
341 assert_eq!(decimal.to_string(), "0");
342 }
343
344 #[test]
345 fn test_checked_convert_large() {
346 let x = Int::from(i128::MAX);
348 let y: Option<Decimal> = x.checked_convert();
349 assert!(y.is_some());
350 let decimal = y.unwrap();
351 assert_eq!(decimal.to_string(), "170141183460469231731687303715884105727");
352 }
353
354 #[test]
355 fn test_saturating_convert() {
356 let x = Int::from(-999999);
357 let y: Decimal = x.saturating_convert();
358 assert_eq!(y.to_string(), "-999999");
359 }
360
361 #[test]
362 fn test_wrapping_convert() {
363 let x = Int::from(42);
364 let y: Decimal = x.wrapping_convert();
365 assert_eq!(y.to_string(), "42");
366 }
367 }
368
369 mod self_conversion {
370 use super::*;
371
372 #[test]
373 fn test_checked_convert() {
374 let x = Int::from(42);
375 let y: Option<Int> = x.clone().checked_convert();
376 assert_eq!(y, Some(x));
377 }
378
379 #[test]
380 fn test_saturating_convert() {
381 let x = Int::from(-100);
382 let y: Int = x.clone().saturating_convert();
383 assert_eq!(y, x);
384 }
385
386 #[test]
387 fn test_wrapping_convert() {
388 let x = Int::from(999);
389 let y: Int = x.clone().wrapping_convert();
390 assert_eq!(y, x);
391 }
392 }
393}