reifydb_value/value/number/safe/convert/
mod.rs1pub trait SafeConvert<T>: Sized {
5 fn checked_convert(self) -> Option<T>;
6 fn saturating_convert(self) -> T;
7 fn wrapping_convert(self) -> T;
8}
9
10macro_rules! impl_safe_convert {
11 ($src:ty => $($dst:ty),*) => {
12 $(
13 impl SafeConvert<$dst> for $src {
14 fn checked_convert(self) -> Option<$dst> {
15 <$dst>::try_from(self).ok()
16 }
17
18 fn saturating_convert(self) -> $dst {
19 if let Ok(v) = <$dst>::try_from(self) {
20 v
21 } else if self < 0 {
22 0
23 } else {
24 <$dst>::MAX
25 }
26 }
27
28 fn wrapping_convert(self) -> $dst {
29 self as $dst
30 }
31 }
32 )*
33 };
34}
35
36macro_rules! impl_safe_unsigned_convert {
37 ($src:ty => $($dst:ty),*) => {
38 $(
39 impl SafeConvert<$dst> for $src {
40 fn checked_convert(self) -> Option<$dst> {
41 <$dst>::try_from(self).ok()
42 }
43
44 fn saturating_convert(self) -> $dst {
45 if self > <$dst>::MAX as $src {
46 <$dst>::MAX
47 }else{
48 self as $dst
49 }
50 }
51
52 fn wrapping_convert(self) -> $dst {
53 self as $dst
54 }
55 }
56 )*
57 };
58}
59
60macro_rules! impl_safe_convert_signed_to_float {
61 ($mantissa_bits:expr; $src:ty => $($float:ty),* $(,)?) => {
62 $(
63 impl SafeConvert<$float> for $src {
64 fn checked_convert(self) -> Option<$float> {
65 let val = self as i128;
66 let max_exact = 1i128 << $mantissa_bits;
67 if val >= -max_exact && val <= max_exact {
68 Some(self as $float)
69 } else {
70 None
71 }
72 }
73
74 fn saturating_convert(self) -> $float {
75 let max_exact = 1i128 << $mantissa_bits;
76 let min = -max_exact;
77 let max = max_exact;
78 let val = self as i128;
79 if val < min {
80 min as $float
81 } else if val > max {
82 max as $float
83 } else {
84 self as $float
85 }
86 }
87
88 fn wrapping_convert(self) -> $float {
89 self as $float
90 }
91 }
92 )*
93 };
94}
95
96macro_rules! impl_safe_convert_unsigned_to_float {
97 ($mantissa_bits:expr; $src:ty => $($float:ty),* $(,)?) => {
98 $(
99 impl SafeConvert<$float> for $src {
100 fn checked_convert(self) -> Option<$float> {
101 if self as u64 <= (1u64 << $mantissa_bits) {
102 Some(self as $float)
103 } else {
104 None
105 }
106 }
107
108 fn saturating_convert(self) -> $float {
109 let max_exact = 1u64 << $mantissa_bits;
110 let max = max_exact as u128;
111 let val = self as u128;
112 if val > max {
113 max as $float
114 } else {
115 self as $float
116 }
117 }
118
119 fn wrapping_convert(self) -> $float {
120 self as $float
121 }
122 }
123 )*
124 };
125}
126
127macro_rules! impl_safe_convert_float_to_signed {
128 ($src:ty => $($dst:ty),* $(,)?) => {
129 $(
130 impl SafeConvert<$dst> for $src {
131 fn checked_convert(self) -> Option<$dst> {
132 if self.is_nan() || self.is_infinite() {
133 return None;
134 }
135
136 let min_val = <$dst>::MIN as $src;
137 let max_val = <$dst>::MAX as $src;
138
139 if self < min_val || self > max_val {
140 None
141 } else {
142 Some(self as $dst)
143 }
144 }
145
146 fn saturating_convert(self) -> $dst {
147 if self.is_nan() {
148 return 0;
149 }
150
151 if self.is_infinite() {
152 return if self.is_sign_positive() { <$dst>::MAX } else { <$dst>::MIN };
153 }
154
155 let min_val = <$dst>::MIN as $src;
156 let max_val = <$dst>::MAX as $src;
157
158 if self < min_val {
159 <$dst>::MIN
160 } else if self > max_val {
161 <$dst>::MAX
162 } else {
163 self as $dst
164 }
165 }
166
167 fn wrapping_convert(self) -> $dst {
168 if self.is_nan() {
169 return 0;
170 }
171
172 if self.is_infinite() {
173 return if self.is_sign_positive() { <$dst>::MAX } else { <$dst>::MIN };
174 }
175
176 self as $dst
177 }
178 }
179 )*
180 };
181}
182
183macro_rules! impl_safe_convert_float_to_unsigned {
184 ($src:ty => $($dst:ty),* $(,)?) => {
185 $(
186 impl SafeConvert<$dst> for $src {
187 fn checked_convert(self) -> Option<$dst> {
188 if self.is_nan() || self.is_infinite() || self < 0.0 {
189 return None;
190 }
191
192 let max_val = <$dst>::MAX as $src;
193
194 if self > max_val {
195 None
196 } else {
197 Some(self as $dst)
198 }
199 }
200
201 fn saturating_convert(self) -> $dst {
202 if self.is_nan() || self < 0.0 {
203 return 0;
204 }
205
206 if self.is_infinite() {
207 return <$dst>::MAX;
208 }
209
210 let max_val = <$dst>::MAX as $src;
211
212 if self > max_val {
213 <$dst>::MAX
214 } else {
215 self as $dst
216 }
217 }
218
219 fn wrapping_convert(self) -> $dst {
220 if self.is_nan() || self < 0.0 {
221 return 0;
222 }
223
224 if self.is_infinite() {
225 return <$dst>::MAX;
226 }
227
228 self as $dst
229 }
230 }
231 )*
232 };
233}
234
235use arrow_buffer::i256;
236
237use crate::value::decimal::Decimal;
238
239fn narrow_i256<T: TryFrom<i128> + TryFrom<u128>>(value: i256) -> Option<T> {
240 match value.to_i128() {
241 Some(value) => T::try_from(value).ok(),
242 None => match value.to_parts() {
243 (low, 0) => T::try_from(low).ok(),
244 _ => None,
245 },
246 }
247}
248
249macro_rules! impl_safe_convert_promote {
250 ($src:ty => $($dst:ty),* $(,)?) => {
251 $(
252 impl SafeConvert<$dst> for $src {
253 fn checked_convert(self) -> Option<$dst> {
254 Some(self as $dst)
255 }
256
257 fn saturating_convert(self) -> $dst {
258 self as $dst
259 }
260
261 fn wrapping_convert(self) -> $dst {
262 self as $dst
263 }
264 }
265 )*
266 };
267}
268
269macro_rules! impl_safe_convert_demote {
270 ($src:ty => $($dst:ty),* $(,)?) => {
271 $(
272 impl SafeConvert<$dst> for $src {
273 fn checked_convert(self) -> Option<$dst> {
274 <$dst>::try_from(self).ok()
275 }
276
277 fn saturating_convert(self) -> $dst {
278 match <$dst>::try_from(self) {
279 Ok(v) => v,
280 Err(_) => {
281 if self < <$dst>::MIN as $src {
282 <$dst>::MIN
283 } else {
284 <$dst>::MAX
285 }
286 }
287 }
288 }
289
290 fn wrapping_convert(self) -> $dst {
291 self as $dst
292 }
293 }
294 )*
295 };
296}
297
298macro_rules! impl_safe_convert_unsigned_demote {
299 ($src:ty => $($dst:ty),* $(,)?) => {
300 $(
301 impl SafeConvert<$dst> for $src {
302 fn checked_convert(self) -> Option<$dst> {
303 <$dst>::try_from(self).ok()
304 }
305
306 fn saturating_convert(self) -> $dst {
307 if self > <$dst>::MAX as $src {
308 <$dst>::MAX
309 } else {
310 self as $dst
311 }
312 }
313
314 fn wrapping_convert(self) -> $dst {
315 self as $dst
316 }
317 }
318 )*
319 };
320}
321
322macro_rules! impl_safe_convert_float_demote {
323 ($src:ty => $dst:ty) => {
324 impl SafeConvert<$dst> for $src {
325 fn checked_convert(self) -> Option<$dst> {
326 let demoted = self as $dst;
327 if self.is_finite() && demoted.is_finite() {
328 Some(demoted)
329 } else {
330 None
331 }
332 }
333
334 fn saturating_convert(self) -> $dst {
335 if self.is_nan() {
336 <$dst>::NAN
337 } else if self <= <$dst>::MIN as $src {
338 <$dst>::MIN
339 } else if self >= <$dst>::MAX as $src {
340 <$dst>::MAX
341 } else {
342 self as $dst
343 }
344 }
345
346 fn wrapping_convert(self) -> $dst {
347 self as $dst
348 }
349 }
350 };
351}
352
353macro_rules! impl_safe_convert_self {
354 ($($ty:ty),* $(,)?) => {
355 $(
356 impl SafeConvert<$ty> for $ty {
357 fn checked_convert(self) -> Option<$ty> {
358 Some(self)
359 }
360
361 fn saturating_convert(self) -> $ty {
362 self
363 }
364
365 fn wrapping_convert(self) -> $ty {
366 self
367 }
368 }
369 )*
370 };
371}
372
373macro_rules! impl_safe_convert_to_decimal_from_int {
374 ($($src:ty),* $(,)?) => {
375 $(
376 impl SafeConvert<Decimal> for $src {
377 fn checked_convert(self) -> Option<Decimal> {
378 Some(Decimal::from(self))
379 }
380
381 fn saturating_convert(self) -> Decimal {
382 Decimal::from(self)
383 }
384
385 fn wrapping_convert(self) -> Decimal {
386 Decimal::from(self)
387 }
388 }
389 )*
390 };
391}
392
393macro_rules! impl_safe_convert_to_decimal_from_large_int {
394 ($($src:ty),* $(,)?) => {
395 $(
396 impl SafeConvert<Decimal> for $src {
397 fn checked_convert(self) -> Option<Decimal> {
398 Some(Decimal::from(self))
399 }
400
401 fn saturating_convert(self) -> Decimal {
402 Decimal::from(self)
403 }
404
405 fn wrapping_convert(self) -> Decimal {
406 Decimal::from(self)
407 }
408 }
409 )*
410 };
411}
412
413macro_rules! impl_safe_convert_to_decimal_from_uint {
414 ($($src:ty),* $(,)?) => {
415 $(
416 impl SafeConvert<Decimal> for $src {
417 fn checked_convert(self) -> Option<Decimal> {
418 Some(Decimal::from(self))
419 }
420
421 fn saturating_convert(self) -> Decimal {
422 Decimal::from(self)
423 }
424
425 fn wrapping_convert(self) -> Decimal {
426 Decimal::from(self)
427 }
428 }
429 )*
430 };
431}
432
433macro_rules! impl_safe_convert_to_decimal_from_float {
434 ($($src:ty => $from:ident),* $(,)?) => {
435 $(
436 impl SafeConvert<Decimal> for $src {
437 fn checked_convert(self) -> Option<Decimal> {
438 Decimal::$from(self)
439 }
440
441 fn saturating_convert(self) -> Decimal {
442 Decimal::from(self)
443 }
444
445 fn wrapping_convert(self) -> Decimal {
446 Decimal::from(self)
447 }
448 }
449 )*
450 };
451}
452
453impl_safe_convert_self!(i8, i16, i32, i64, i128, u8, u16, u32, u64, u128, f32, f64);
454impl_safe_convert_self!(Decimal);
455
456pub mod decimal;
457pub mod f32;
458pub mod f64;
459pub mod i128;
460pub mod i16;
461pub mod i32;
462pub mod i64;
463pub mod i8;
464pub mod u128;
465pub mod u16;
466pub mod u32;
467pub mod u64;
468pub mod u8;