decimal_rs/
convert.rs

1// Copyright 2021 CoD Technologies Corp.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Conversion between `Decimal` and primitive number types.
16
17use crate::decimal::{Buf, Decimal, MAX_PRECISION, MAX_SCALE, MIN_SCALE};
18use crate::u256::POWERS_10;
19use crate::DecimalConvertError;
20use std::convert::TryFrom;
21
22pub(crate) const MAX_I128_REPR: i128 = 99_9999_9999_9999_9999_9999_9999_9999_9999_9999_i128;
23
24macro_rules! impl_from_small_int {
25    ($ty: ty) => {
26        impl From<$ty> for Decimal {
27            #[inline]
28            fn from(val: $ty) -> Self {
29                unsafe { Decimal::from_raw_parts(val as u128, 0, false) }
30            }
31        }
32    };
33    (SIGNED $ty: ty) => {
34        impl From<$ty> for Decimal {
35            #[inline]
36            fn from(val: $ty) -> Decimal {
37                let (int_val, negative) = if val < 0 {
38                    (-(val as i128) as u128, true)
39                } else {
40                    (val as u128, false)
41                };
42
43                unsafe { Decimal::from_raw_parts(int_val, 0, negative) }
44            }
45        }
46    };
47    ($($ty: ty), * $(,)?) => {
48        $(impl_from_small_int!($ty);)*
49    };
50    (SIGNED $($ty: ty), * $(,)?) => {
51        $(impl_from_small_int!(SIGNED $ty);)*
52    }
53}
54
55impl_from_small_int!(u8, u16, u32, u64, usize);
56impl_from_small_int!(SIGNED i8, i16, i32, i64, isize);
57
58impl From<bool> for Decimal {
59    #[inline]
60    fn from(b: bool) -> Self {
61        if b {
62            Decimal::ONE
63        } else {
64            Decimal::ZERO
65        }
66    }
67}
68
69impl TryFrom<i128> for Decimal {
70    type Error = DecimalConvertError;
71
72    #[inline]
73    fn try_from(val: i128) -> std::result::Result<Self, Self::Error> {
74        if !(-MAX_I128_REPR..=MAX_I128_REPR).contains(&val) {
75            Err(DecimalConvertError::Overflow)
76        } else {
77            let (int_val, negative) = if val < 0 {
78                (val.wrapping_neg() as u128, true)
79            } else {
80                (val as u128, false)
81            };
82
83            Ok(unsafe { Decimal::from_raw_parts(int_val, 0, negative) })
84        }
85    }
86}
87
88impl TryFrom<u128> for Decimal {
89    type Error = DecimalConvertError;
90
91    #[inline]
92    fn try_from(value: u128) -> std::result::Result<Self, Self::Error> {
93        if value > MAX_I128_REPR as u128 {
94            Err(DecimalConvertError::Overflow)
95        } else {
96            Ok(unsafe { Decimal::from_raw_parts(value, 0, false) })
97        }
98    }
99}
100
101impl TryFrom<f32> for Decimal {
102    type Error = DecimalConvertError;
103
104    #[inline]
105    fn try_from(value: f32) -> std::result::Result<Self, Self::Error> {
106        if value.is_infinite() {
107            return Err(DecimalConvertError::Overflow);
108        }
109
110        if value.is_nan() {
111            return Err(DecimalConvertError::Invalid);
112        }
113
114        debug_assert!(value.is_finite());
115
116        // Below code copied from rust-decimal:
117        // https://github.com/paupino/rust-decimal/blob/master/src/decimal.rs
118
119        // It's a shame we can't use a union for this due to it being broken up by bits
120        // i.e. 1/8/23 (sign, exponent, mantissa)
121        // See https://en.wikipedia.org/wiki/IEEE_754-1985
122        // n = (sign*-1) * 2^exp * mantissa
123        // Decimal of course stores this differently... 10^-exp * significand
124        let raw = value.to_bits();
125        let negative = (raw >> 31) == 1;
126        let biased_exponent = ((raw >> 23) & 0xFF) as i32;
127        let mantissa = raw & 0x007F_FFFF;
128
129        // Handle the special zero case
130        if biased_exponent == 0 && mantissa == 0 {
131            return Ok(Decimal::ZERO);
132        }
133
134        // Get the bits and exponent2
135        let mut exponent2 = biased_exponent - 127;
136        let mut bits = mantissa as u128;
137        if biased_exponent == 0 {
138            // Denormalized number - correct the exponent
139            exponent2 += 1;
140        } else {
141            // Add extra hidden bit to mantissa
142            bits |= 0x0080_0000;
143        }
144
145        // The act of copying a mantissa as integer bits is equivalent to shifting
146        // left the mantissa 23 bits. The exponent is reduced to compensate.
147        exponent2 -= 23;
148
149        match base2_to_decimal::<false>(bits, exponent2, negative) {
150            Some(dec) => Ok(dec),
151            None => Err(DecimalConvertError::Overflow),
152        }
153    }
154}
155
156impl TryFrom<f64> for Decimal {
157    type Error = DecimalConvertError;
158
159    #[inline]
160    fn try_from(value: f64) -> std::result::Result<Self, Self::Error> {
161        if value.is_infinite() {
162            return Err(DecimalConvertError::Overflow);
163        }
164
165        if value.is_nan() {
166            return Err(DecimalConvertError::Invalid);
167        }
168
169        debug_assert!(value.is_finite());
170
171        // Below code copied from rust-decimal:
172        // https://github.com/paupino/rust-decimal/blob/master/src/decimal.rs
173
174        // It's a shame we can't use a union for this due to it being broken up by bits
175        // i.e. 1/11/52 (sign, exponent, mantissa)
176        // See https://en.wikipedia.org/wiki/IEEE_754-1985
177        // n = (sign*-1) * 2^exp * mantissa
178        // Decimal of course stores this differently... 10^-exp * significand
179        let raw = value.to_bits();
180        let negative = (raw >> 63) == 1;
181        let biased_exponent = ((raw >> 52) & 0x7FF) as i32;
182        let mantissa = raw & 0x000F_FFFF_FFFF_FFFF;
183
184        // Handle the special zero case
185        if biased_exponent == 0 && mantissa == 0 {
186            return Ok(Decimal::ZERO);
187        }
188
189        // Get the bits and exponent2
190        let mut exponent2 = biased_exponent - 1023;
191        let mut bits = mantissa as u128;
192        if biased_exponent == 0 {
193            // Denormalized number - correct the exponent
194            exponent2 += 1;
195        } else {
196            // Add extra hidden bit to mantissa
197            bits |= 0x0010_0000_0000_0000;
198        }
199
200        // The act of copying a mantissa as integer bits is equivalent to shifting
201        // left the mantissa 52 bits. The exponent is reduced to compensate.
202        exponent2 -= 52;
203
204        match base2_to_decimal::<true>(bits, exponent2, negative) {
205            Some(dec) => Ok(dec),
206            None => Err(DecimalConvertError::Overflow),
207        }
208    }
209}
210
211// Copied from rust-decimal and modified:
212// https://github.com/paupino/rust-decimal/blob/master/src/decimal.rs
213fn base2_to_decimal<const IS_F64: bool>(bits: u128, exponent2: i32, negative: bool) -> Option<Decimal> {
214    const F32_DP: u128 = 9_9999_9999_u128;
215    const F64_DP: u128 = 9_9999_9999_9999_9999_u128;
216    // 2^exponent2 = (10^exponent2)/(5^exponent2)
217    //             = (5^-exponent2)*(10^exponent2)
218    let mut exponent5 = -exponent2;
219    let mut exponent10 = exponent2; // Ultimately, we want this for the scale
220
221    let mut bits = bits;
222
223    while exponent5 > 0 {
224        // Check to see if the mantissa is divisible by 2
225        if bits & 0x1 == 0 {
226            exponent10 += 1;
227            exponent5 -= 1;
228
229            // We can divide by 2 without losing precision
230            bits >>= 1;
231        } else {
232            // The mantissa is NOT divisible by 2. Therefore the mantissa should
233            // be multiplied by 5, unless the multiplication overflows.
234            exponent5 -= 1;
235
236            let temp = bits.checked_mul(5);
237            match temp {
238                Some(prod) => {
239                    // Multiplication succeeded without overflow, so copy result back
240                    bits = prod
241                }
242                None => {
243                    // Multiplication by 5 overflows. The mantissa should be divided
244                    // by 2, and therefore will lose significant digits.
245                    exponent10 += 1;
246
247                    // Shift right
248                    bits >>= 1;
249                }
250            }
251        }
252    }
253
254    // In order to divide the value by 5, it is best to multiply by 2/10.
255    // Therefore, exponent10 is decremented, and the mantissa should be multiplied by 2
256    while exponent5 < 0 {
257        if bits & 0x8000_0000_0000_0000_0000_0000_0000_0000 == 0 {
258            // No far left bit, the mantissa can withstand a shift-left without overflowing
259            exponent10 -= 1;
260            exponent5 += 1;
261            bits <<= 1;
262        } else {
263            // The mantissa would overflow if shifted. Therefore it should be
264            // directly divided by 5. This will lose significant digits, unless
265            // by chance the mantissa happens to be divisible by 5.
266            exponent5 += 1;
267            bits /= 5;
268        }
269    }
270
271    // At this point, the mantissa has assimilated the exponent5, but
272    // exponent10 might not be suitable for assignment. exponent10 must be
273    // in the range [-MAX_SCALE..-MIN_SCALE], so the mantissa must be scaled up or
274    // down appropriately.
275    while exponent10 > -MIN_SCALE as i32 {
276        // In order to bring exponent10 down to 0, the mantissa should be
277        // multiplied by 10 to compensate. If the exponent10 is too big, this
278        // will cause the mantissa to overflow.
279        match bits.checked_mul(10) {
280            Some(prod) => {
281                if prod <= MAX_I128_REPR as u128 {
282                    bits *= 10;
283                    exponent10 -= 1;
284                } else {
285                    return None;
286                }
287            }
288            None => {
289                return None;
290            }
291        }
292    }
293
294    // In order to bring exponent up to -MAX_SCALE, the mantissa should
295    // be divided by 10 to compensate. If the exponent10 is too small, this
296    // will cause the mantissa to underflow and become 0.
297    while exponent10 < -MAX_SCALE as i32 {
298        let rem10 = bits % 10;
299        bits /= 10;
300        exponent10 += 1;
301        if bits == 0 {
302            // Underflow, unable to keep dividing
303            exponent10 = 0;
304        } else if rem10 >= 5 {
305            bits += 1;
306        }
307    }
308
309    // This step is required in order to remove excess bits of precision from the
310    // end of the bit representation, down to the precision guaranteed by the
311    // floating point number
312    let mut rem10 = 0;
313    if IS_F64 {
314        // Guaranteed to about 17 dp
315        while exponent10 < -MIN_SCALE as i32 && bits > F64_DP {
316            rem10 = bits % 10;
317            bits /= 10;
318            exponent10 += 1;
319        }
320    } else {
321        // Guaranteed to about 9 dp
322        while exponent10 < -MIN_SCALE as i32 && bits > F32_DP {
323            rem10 = bits % 10;
324            bits /= 10;
325            exponent10 += 1;
326        }
327    }
328    if rem10 >= 5 {
329        bits += 1;
330    }
331
332    // Remove multiples of 10 from the representation
333    while exponent10 < -MIN_SCALE as i32 {
334        let remainder = bits % 10;
335        if remainder == 0 {
336            exponent10 += 1;
337            bits /= 10;
338        } else {
339            break;
340        }
341    }
342
343    Some(unsafe { Decimal::from_parts_unchecked(bits, -exponent10 as i16, negative) })
344}
345
346impl From<&Decimal> for f32 {
347    #[inline]
348    fn from(val: &Decimal) -> Self {
349        f64::from(val) as f32
350    }
351}
352
353impl From<Decimal> for f32 {
354    #[inline]
355    fn from(val: Decimal) -> Self {
356        f32::from(&val)
357    }
358}
359
360impl From<&Decimal> for f64 {
361    #[allow(clippy::comparison_chain)]
362    #[inline]
363    fn from(val: &Decimal) -> Self {
364        const POWERS_10: [f64; MAX_SCALE as usize + MAX_PRECISION as usize] = [
365            1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18,
366            1e19, 1e20, 1e21, 1e22, 1e23, 1e24, 1e25, 1e26, 1e27, 1e28, 1e29, 1e30, 1e31, 1e32, 1e33, 1e34, 1e35, 1e36,
367            1e37, 1e38, 1e39, 1e40, 1e41, 1e42, 1e43, 1e44, 1e45, 1e46, 1e47, 1e48, 1e49, 1e50, 1e51, 1e52, 1e53, 1e54,
368            1e55, 1e56, 1e57, 1e58, 1e59, 1e60, 1e61, 1e62, 1e63, 1e64, 1e65, 1e66, 1e67, 1e68, 1e69, 1e70, 1e71, 1e72,
369            1e73, 1e74, 1e75, 1e76, 1e77, 1e78, 1e79, 1e80, 1e81, 1e82, 1e83, 1e84, 1e85, 1e86, 1e87, 1e88, 1e89, 1e90,
370            1e91, 1e92, 1e93, 1e94, 1e95, 1e96, 1e97, 1e98, 1e99, 1e100, 1e101, 1e102, 1e103, 1e104, 1e105, 1e106,
371            1e107, 1e108, 1e109, 1e110, 1e111, 1e112, 1e113, 1e114, 1e115, 1e116, 1e117, 1e118, 1e119, 1e120, 1e121,
372            1e122, 1e123, 1e124, 1e125, 1e126, 1e127, 1e128, 1e129, 1e130, 1e131, 1e132, 1e133, 1e134, 1e135, 1e136,
373            1e137, 1e138, 1e139, 1e140, 1e141, 1e142, 1e143, 1e144, 1e145, 1e146, 1e147, 1e148, 1e149, 1e150, 1e151,
374            1e152, 1e153, 1e154, 1e155, 1e156, 1e157, 1e158, 1e159, 1e160, 1e161, 1e162, 1e163, 1e164, 1e165, 1e166,
375            1e167,
376        ];
377
378        let n = val.normalize();
379
380        // f64 can only accurately represent numbers <= 9007199254740992
381        if n.int_val() <= 9007199254740992 {
382            let mut v = n.int_val() as f64;
383
384            if n.scale() > 0 {
385                v /= POWERS_10[n.scale() as usize];
386            } else if n.scale() < 0 {
387                v *= POWERS_10[-n.scale() as usize];
388            }
389
390            if n.is_sign_negative() {
391                v = -v;
392            }
393
394            v
395        } else {
396            let mut buf = Buf::new();
397            val.fmt_internal(true, false, false, None, &mut buf)
398                .expect("failed to format decimal");
399            let str = unsafe { std::str::from_utf8_unchecked(&*buf) };
400            str.parse::<f64>().unwrap()
401        }
402    }
403}
404
405impl From<Decimal> for f64 {
406    #[inline]
407    fn from(val: Decimal) -> Self {
408        f64::from(&val)
409    }
410}
411
412impl TryFrom<&Decimal> for u128 {
413    type Error = DecimalConvertError;
414
415    #[inline]
416    fn try_from(value: &Decimal) -> Result<u128, Self::Error> {
417        if value.is_sign_negative() {
418            return Err(DecimalConvertError::Overflow);
419        }
420
421        let d = value.round(0);
422
423        if d.scale() == 0 {
424            return Ok(d.int_val());
425        }
426
427        debug_assert!(d.scale() < 0);
428        debug_assert_ne!(d.int_val(), 0);
429
430        if -d.scale() > MAX_PRECISION as i16 {
431            return Err(DecimalConvertError::Overflow);
432        }
433
434        let result = POWERS_10[-d.scale() as usize].checked_mul(d.int_val());
435        match result {
436            Some(prod) => {
437                if prod.high() != 0 {
438                    Err(DecimalConvertError::Overflow)
439                } else {
440                    Ok(prod.low())
441                }
442            }
443            None => Err(DecimalConvertError::Overflow),
444        }
445    }
446}
447
448impl TryFrom<Decimal> for u128 {
449    type Error = DecimalConvertError;
450
451    #[inline]
452    fn try_from(value: Decimal) -> Result<Self, Self::Error> {
453        u128::try_from(&value)
454    }
455}
456
457fn to_i128(int_val: u128, negative: bool) -> Result<i128, DecimalConvertError> {
458    if negative {
459        if int_val > i128::MAX as u128 + 1 {
460            Err(DecimalConvertError::Overflow)
461        } else {
462            Ok(-(int_val as i128))
463        }
464    } else if int_val > i128::MAX as u128 {
465        Err(DecimalConvertError::Overflow)
466    } else {
467        Ok(int_val as i128)
468    }
469}
470
471impl TryFrom<&Decimal> for i128 {
472    type Error = DecimalConvertError;
473
474    #[inline]
475    fn try_from(value: &Decimal) -> Result<Self, Self::Error> {
476        let d = value.round(0);
477
478        if d.scale() == 0 {
479            return to_i128(d.int_val(), d.is_sign_negative());
480        }
481
482        debug_assert!(d.scale() < 0);
483        debug_assert_ne!(d.int_val(), 0);
484
485        if -d.scale() > MAX_PRECISION as i16 {
486            return Err(DecimalConvertError::Overflow);
487        }
488
489        let result = POWERS_10[-d.scale() as usize].checked_mul(d.int_val());
490        match result {
491            Some(prod) => {
492                if prod.high() != 0 {
493                    Err(DecimalConvertError::Overflow)
494                } else {
495                    to_i128(prod.low(), d.is_sign_negative())
496                }
497            }
498            None => Err(DecimalConvertError::Overflow),
499        }
500    }
501}
502
503impl TryFrom<Decimal> for i128 {
504    type Error = DecimalConvertError;
505
506    #[inline]
507    fn try_from(value: Decimal) -> Result<Self, Self::Error> {
508        i128::try_from(&value)
509    }
510}
511
512macro_rules! impl_into_small_int {
513    ($ty: ty) => {
514        impl TryFrom<&Decimal> for $ty {
515            type Error = DecimalConvertError;
516
517            #[inline]
518            fn try_from(value: &Decimal) -> Result<Self, Self::Error> {
519                let val = u128::try_from(value)?;
520                if val > <$ty>::MAX as u128 {
521                    Err(DecimalConvertError::Overflow)
522                } else {
523                    Ok(val as $ty)
524                }
525            }
526        }
527        impl TryFrom<Decimal> for $ty {
528            type Error = DecimalConvertError;
529
530            #[inline]
531            fn try_from(value: Decimal) -> Result<Self, Self::Error> {
532                <$ty>::try_from(&value)
533            }
534        }
535    };
536    (SIGNED $ty: ty) => {
537        impl TryFrom<&Decimal> for $ty {
538            type Error = DecimalConvertError;
539
540            #[inline]
541            fn try_from(value: &Decimal) -> Result<Self, Self::Error> {
542                let val = i128::try_from(value)?;
543                if val > <$ty>::MAX as i128 || val < <$ty>::MIN as i128 {
544                    Err(DecimalConvertError::Overflow)
545                } else {
546                    Ok(val as $ty)
547                }
548            }
549        }
550        impl TryFrom<Decimal> for $ty {
551            type Error = DecimalConvertError;
552
553            #[inline]
554            fn try_from(value: Decimal) -> Result<Self, Self::Error> {
555                <$ty>::try_from(&value)
556            }
557        }
558    };
559    ($($ty: ty), * $(,)?) => {
560        $(impl_into_small_int!($ty);)*
561    };
562    (SIGNED $($ty: ty), * $(,)?) => {
563        $(impl_into_small_int!(SIGNED $ty);)*
564    };
565}
566
567impl_into_small_int!(u8, u16, u32, u64, usize);
568impl_into_small_int!(SIGNED i8, i16, i32, i64, isize);
569
570#[cfg(test)]
571mod tests {
572    use super::*;
573    use std::convert::TryInto;
574    use std::fmt::Debug;
575
576    fn assert_from<V: Into<Decimal>>(val: V, expected: &str) {
577        let decimal = val.into();
578        let expected = expected.parse::<Decimal>().unwrap();
579        assert_eq!(decimal, expected);
580    }
581
582    fn assert_try_from<V: TryInto<Decimal, Error = DecimalConvertError>>(val: V, expected: &str) {
583        let decimal = val.try_into().unwrap();
584        let expected = expected.parse::<Decimal>().unwrap();
585        assert_eq!(decimal, expected);
586    }
587
588    fn assert_try_from_overflow<V: TryInto<Decimal, Error = DecimalConvertError>>(val: V) {
589        let result = val.try_into();
590        assert_eq!(result.unwrap_err(), DecimalConvertError::Overflow);
591    }
592
593    #[test]
594    fn test_from_i8() {
595        assert_from(0i8, "0");
596        assert_from(1i8, "1");
597        assert_from(-1i8, "-1");
598        assert_from(127i8, "127");
599        assert_from(-128i8, "-128");
600    }
601
602    #[test]
603    fn test_from_i16() {
604        assert_from(0i16, "0");
605        assert_from(1i16, "1");
606        assert_from(-1i16, "-1");
607        assert_from(32767i16, "32767");
608        assert_from(-32768i16, "-32768");
609    }
610
611    #[test]
612    fn test_from_i32() {
613        assert_from(0i32, "0");
614        assert_from(1i32, "1");
615        assert_from(-1i32, "-1");
616        assert_from(2147483647i32, "2147483647");
617        assert_from(-2147483647i32, "-2147483647");
618    }
619
620    #[test]
621    fn test_from_i64() {
622        assert_from(0i64, "0");
623        assert_from(1i64, "1");
624        assert_from(-1i64, "-1");
625        assert_from(9223372036854775807i64, "9223372036854775807");
626        assert_from(-9223372036854775808i64, "-9223372036854775808");
627    }
628
629    #[test]
630    fn test_from_i128() {
631        assert_try_from(0i128, "0");
632        assert_try_from(1i128, "1");
633        assert_try_from(-1i128, "-1");
634        assert_try_from(MAX_I128_REPR, "99999999999999999999999999999999999999");
635        assert_try_from(-MAX_I128_REPR, "-99999999999999999999999999999999999999");
636        assert_try_from_overflow(170141183460469231731687303715884105727_i128);
637        assert_try_from_overflow(-170141183460469231731687303715884105728_i128);
638    }
639
640    #[test]
641    fn test_from_u8() {
642        assert_from(0u8, "0");
643        assert_from(1u8, "1");
644        assert_from(255u8, "255");
645    }
646
647    #[test]
648    fn test_from_u16() {
649        assert_from(0u16, "0");
650        assert_from(1u16, "1");
651        assert_from(65535u16, "65535");
652    }
653
654    #[test]
655    fn test_from_u32() {
656        assert_from(0u32, "0");
657        assert_from(1u32, "1");
658        assert_from(4294967295u32, "4294967295");
659    }
660
661    #[test]
662    fn test_from_u64() {
663        assert_from(0u64, "0");
664        assert_from(1u64, "1");
665        assert_from(18446744073709551615u64, "18446744073709551615");
666    }
667
668    #[test]
669    fn test_from_u128() {
670        assert_try_from(0u128, "0");
671        assert_try_from(1u128, "1");
672        assert_try_from(MAX_I128_REPR as u128, "99999999999999999999999999999999999999");
673        assert_try_from_overflow(340282366920938463463374607431768211455_u128);
674    }
675
676    #[test]
677    fn test_from_bool() {
678        assert_from(true, "1");
679        assert_from(false, "0");
680    }
681
682    #[test]
683    fn test_from_usize() {
684        assert_from(0usize, "0");
685        assert_from(1usize, "1");
686        if std::mem::size_of::<usize>() == 8 {
687            assert_from(18446744073709551615usize, "18446744073709551615");
688        } else if std::mem::size_of::<usize>() == 4 {
689            assert_from(4294967295usize, "4294967295u32");
690        }
691    }
692
693    #[test]
694    fn test_from_isize() {
695        assert_from(0isize, "0");
696        assert_from(1isize, "1");
697        if std::mem::size_of::<isize>() == 8 {
698            assert_from(9223372036854775807isize, "9223372036854775807");
699            assert_from(-9223372036854775808isize, "-9223372036854775808");
700        } else if std::mem::size_of::<isize>() == 4 {
701            assert_from(2147483647isize, "2147483647");
702            assert_from(-2147483648isize, "-2147483648");
703        }
704    }
705
706    #[test]
707    #[allow(clippy::excessive_precision)]
708    fn test_try_from_f32() {
709        assert_try_from_overflow(std::f32::INFINITY);
710        assert_try_from_overflow(std::f32::NEG_INFINITY);
711        assert_try_from(0.0f32, "0");
712        assert_try_from(-0.0f32, "0");
713        assert_try_from(0.000001f32, "0.000000999999997");
714        assert_try_from(0.0000001f32, "0.000000100000001");
715        assert_try_from(0.555555f32, "0.555554986");
716        assert_try_from(0.5555555f32, "0.555555522");
717        assert_try_from(0.999999f32, "0.999998987");
718        assert_try_from(0.9999999f32, "0.999999881");
719        assert_try_from(1.0f32, "1");
720        assert_try_from(1.00001f32, "1.00001001");
721        assert_try_from(1.000001f32, "1.00000095");
722        assert_try_from(1.555555f32, "1.55555499");
723        assert_try_from(1.5555555f32, "1.55555546");
724        assert_try_from(1.99999f32, "1.99998999");
725        assert_try_from(1.999999f32, "1.99999905");
726        assert_try_from(1e-6f32, "0.000000999999997");
727        assert_try_from(1e-10f32, "0.000000000100000001");
728        assert_try_from(1.23456789e10f32, "12345678800");
729        assert_try_from(1.23456789e-10f32, "0.000000000123456786");
730        assert_try_from(std::f32::consts::PI, "3.14159274");
731        assert_try_from(-1.401298E-45f32, "-140129846E-53");
732        assert_try_from(1.401298E-45f32, "140129846E-53");
733    }
734
735    #[test]
736    #[allow(clippy::excessive_precision)]
737    fn test_try_from_f64() {
738        assert_try_from_overflow(std::f64::INFINITY);
739        assert_try_from_overflow(std::f64::NEG_INFINITY);
740        assert_try_from(0.0f64, "0");
741        assert_try_from(-0.0f64, "0");
742        assert_try_from(0.000000000000001f64, "0.0000000000000010000000000000001");
743        assert_try_from(0.0000000000000001f64, "0.000000000000000099999999999999998");
744        assert_try_from(0.555555555555555f64, "0.55555555555555503");
745        assert_try_from(0.5555555555555556f64, "0.55555555555555558");
746        assert_try_from(0.999999999999999f64, "0.999999999999999");
747        assert_try_from(0.9999999999999999f64, "0.99999999999999989");
748        assert_try_from(1.0f64, "1");
749        assert_try_from(1.00000000000001f64, "1.00000000000001");
750        assert_try_from(1.000000000000001f64, "1.0000000000000011"); //
751        assert_try_from(1.55555555555555f64, "1.55555555555555");
752        assert_try_from(1.555555555555556f64, "1.555555555555556"); //
753        assert_try_from(1.99999999999999f64, "1.99999999999999");
754        assert_try_from(1.999999999999999f64, "1.9999999999999989"); //
755        assert_try_from(1e-6f64, "0.00000099999999999999995");
756        assert_try_from(1e-20f64, "0.0000000000000000000099999999999999995");
757        assert_try_from(1.234567890123456789e20f64, "123456789012345680000");
758        assert_try_from(1.234567890123456789e-20f64, "0.000000000000000000012345678901234569");
759        assert_try_from(std::f64::consts::PI, "3.1415926535897931");
760    }
761
762    fn assert_into<S: AsRef<str>, T: From<Decimal> + PartialEq + Debug>(s: S, expected: T) {
763        let decimal = s.as_ref().parse::<Decimal>().unwrap();
764        let val = T::from(decimal);
765        assert_eq!(val, expected);
766    }
767
768    fn assert_try_into<S: AsRef<str>, T: TryFrom<Decimal, Error = DecimalConvertError> + PartialEq + Debug>(
769        s: S,
770        expected: T,
771    ) {
772        let decimal = s.as_ref().parse::<Decimal>().unwrap();
773        let val = T::try_from(decimal).unwrap();
774        assert_eq!(val, expected);
775    }
776
777    fn assert_try_into_overflow<T: TryFrom<Decimal, Error = DecimalConvertError> + Debug>(s: &str) {
778        let n = s.parse::<Decimal>().unwrap();
779        let result = T::try_from(n);
780        assert_eq!(result.unwrap_err(), DecimalConvertError::Overflow);
781    }
782
783    #[test]
784    fn test_into_f32() {
785        assert_into("0", 0f32);
786        assert_into("1", 1f32);
787        assert_into("0.000001", 0.000001f32);
788        assert_into("0.0000001", 0.0000001f32);
789        assert_into("0.555555", 0.555555f32);
790        assert_into("0.55555599", 0.555556f32);
791        assert_into("0.999999", 0.999999f32);
792        assert_into("0.99999999", 1.0f32);
793        assert_into("1.00001", 1.00001f32);
794        assert_into("1.00000001", 1.0f32);
795        assert_into("1.23456789e10", 1.2345679e10f32);
796        assert_into("1.23456789e-10", 1.2345679e-10f32);
797        assert_into("3.40282347e+38", f32::MAX);
798        assert_into("-3.40282347e+38", f32::MIN);
799        assert_into("1e39", f32::INFINITY);
800        assert_into("1.17549435e-38", 1.1754944e-38f32);
801    }
802
803    #[test]
804    #[allow(clippy::excessive_precision)]
805    fn test_into_f64() {
806        assert_into("0", 0f64);
807        assert_into("1", 1f64);
808        assert_into("0.000000000000001", 0.000000000000001f64);
809        assert_into("0.555555555555555", 0.555555555555555f64);
810        assert_into("0.55555555555555599", 0.555555555555556f64);
811        assert_into("0.999999999999999", 0.999999999999999f64);
812        assert_into("0.99999999999999999", 1.0f64);
813        assert_into("1.00000000000001", 1.00000000000001f64);
814        assert_into("1.0000000000000001", 1.0f64);
815        assert_into("1.7976931348623157e+108", 1.7976931348623156e+108f64);
816        assert_into("-1.7976931348623157e+108", -1.7976931348623156e+108f64);
817        assert_into("1e125", 1.0e125f64);
818        assert_into("2.2250738585072014e-114", 2.2250738585072014e-114f64);
819        assert_into("2145.5294117647058823529411764705882353", 2145.5294117647059f64);
820        assert_into("-2145.5294117647058823529411764705882353", -2145.5294117647059f64);
821        assert_into("7661.049086167562", 7661.049086167562f64);
822        assert_into("7661049086167562000e-15", 7661.049086167562f64);
823        assert_into("1962868503.32829189300537109375", 1962868503.328292f64);
824        assert_into("9007199254740992e110", 9007199254740992e110);
825        assert_into("1.79769313486232E-129", 1.79769313486232e-129);
826        assert_into("1.79769313486232E-130", 1.79769313486232e-130);
827        assert_into("1.7976931348623279769313486232797693134E-129", 1.797693134862328e-129);
828        assert_into("1.7976931348623279769313486232797693134E-130", 1.797693134862328e-130);
829    }
830
831    #[test]
832    fn test_into_u128() {
833        assert_try_into("0", 0u128);
834        assert_try_into("1", 1u128);
835        assert_try_into(
836            "99999999999999999999999999999999999999",
837            99_9999_9999_9999_9999_9999_9999_9999_9999_9999_u128,
838        );
839        assert_try_into_overflow::<u128>("1e39");
840        assert_try_into_overflow::<u128>("-1");
841    }
842
843    #[test]
844    fn test_into_i128() {
845        assert_try_into("0", 0i128);
846        assert_try_into("1", 1i128);
847        assert_try_into("-1", -1i128);
848        assert_try_into(
849            "99999999999999999999999999999999999999",
850            99_9999_9999_9999_9999_9999_9999_9999_9999_9999_i128,
851        );
852        assert_try_into_overflow::<i128>("1e39");
853    }
854
855    #[test]
856    fn test_into_u8() {
857        assert_try_into("0", 0u8);
858        assert_try_into("1", 1u8);
859        assert_try_into("255", 255u8);
860        assert_try_into_overflow::<u8>("256");
861        assert_try_into_overflow::<u8>("-1");
862    }
863
864    #[test]
865    fn test_into_u16() {
866        assert_try_into("0", 0u16);
867        assert_try_into("1", 1u16);
868        assert_try_into("65535", 65535u16);
869        assert_try_into_overflow::<u16>("65536");
870        assert_try_into_overflow::<u16>("-1");
871    }
872
873    #[test]
874    fn test_into_u32() {
875        assert_try_into("0", 0u32);
876        assert_try_into("1", 1u32);
877        assert_try_into("4294967295", 4294967295u32);
878        assert_try_into_overflow::<u32>("4294967296");
879        assert_try_into_overflow::<u32>("-1");
880    }
881
882    #[test]
883    fn test_into_u64() {
884        assert_try_into("0", 0u64);
885        assert_try_into("1", 1u64);
886        assert_try_into("18446744073709551615", 18446744073709551615u64);
887        assert_try_into_overflow::<u64>("18446744073709551616");
888        assert_try_into_overflow::<u64>("-1");
889    }
890
891    #[test]
892    fn test_into_i8() {
893        assert_try_into("0", 0i8);
894        assert_try_into("1", 1i8);
895        assert_try_into("-1", -1i8);
896        assert_try_into("127", 127i8);
897        assert_try_into("-128", -128);
898        assert_try_into_overflow::<i8>("128");
899        assert_try_into_overflow::<i8>("-129");
900    }
901
902    #[test]
903    fn test_into_i16() {
904        assert_try_into("0", 0i16);
905        assert_try_into("1", 1i16);
906        assert_try_into("-1", -1i16);
907        assert_try_into("32767", 32767i16);
908        assert_try_into("-32768", -32768i16);
909        assert_try_into_overflow::<i16>("32768");
910        assert_try_into_overflow::<i16>("-32769");
911    }
912
913    #[test]
914    fn test_into_i32() {
915        assert_try_into("0", 0i32);
916        assert_try_into("1", 1i32);
917        assert_try_into("-1", -1i32);
918        assert_try_into("2147483647", 2147483647i32);
919        assert_try_into("-2147483648", -2147483648i32);
920        assert_try_into_overflow::<i32>("2147483648");
921        assert_try_into_overflow::<i32>("-2147483649");
922    }
923
924    #[test]
925    fn test_into_i64() {
926        assert_try_into("0", 0i64);
927        assert_try_into("1", 1i64);
928        assert_try_into("-1", -1i64);
929        assert_try_into("9223372036854775807", 9223372036854775807i64);
930        assert_try_into("-9223372036854775808", -9223372036854775808i64);
931        assert_try_into_overflow::<i64>("9223372036854775808");
932        assert_try_into_overflow::<i64>("-9223372036854775809");
933    }
934}