use core::convert::TryFrom;
use crate::{Decimal, DecimalError};
macro_rules! impl_from_int {
() => {
impl_from_int!(u8, i8, u16, i16, u32, i32, u64, i64, i128);
};
($($t:ty),*) => {
$(
impl From<$t> for Decimal {
#[inline]
fn from(i: $t) -> Self
{
Decimal { coeff: i128::from(i), n_frac_digits: 0 }
}
}
)*
}
}
impl_from_int!();
impl TryFrom<u128> for Decimal {
type Error = DecimalError;
#[inline]
fn try_from(i: u128) -> Result<Self, Self::Error> {
match i128::try_from(i) {
Err(_) => Err(DecimalError::InternalOverflow),
Ok(i) => Ok(Self::from(i)),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
fn check_from_int<T>(numbers: &[T])
where
T: Into<i128> + Copy,
Decimal: From<T>,
{
for n in numbers {
let d = Decimal::from(*n);
assert_eq!(d.coefficient(), (*n).into());
assert_eq!(d.n_frac_digits(), 0);
}
}
#[test]
fn test_from_u8() {
let numbers: [u8; 4] = [0, 1, 28, 255];
check_from_int::<u8>(&numbers);
}
#[test]
fn test_from_i8() {
let numbers: [i8; 7] = [-128, -38, -1, 0, 1, 28, 127];
check_from_int::<i8>(&numbers);
}
#[test]
fn test_from_u64() {
let numbers: [u64; 4] = [0, 1, 2128255, u64::MAX];
check_from_int::<u64>(&numbers);
}
#[test]
fn test_from_i64() {
let numbers: [i64; 4] = [0, -1, 2128255, i64::MIN];
check_from_int::<i64>(&numbers);
}
#[test]
fn test_from_i128() {
let numbers: [i128; 7] = [
-0x8000_0000_0000_0000_0000_0000_0000_0000,
-3830009274,
-1,
0,
1,
2829773566410082,
0x7FFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF,
];
check_from_int::<i128>(&numbers);
}
#[test]
fn test_from_u128_ok() {
let numbers: [u128; 4] =
[0, 1, 2128255, 0x7FFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF];
for n in numbers {
match Decimal::try_from(n) {
Err(_) => panic!("Misconfigured test case!"),
Ok(d) => match i128::try_from(n) {
Err(_) => panic!("Should never happen!"),
Ok(i) => {
assert_eq!(d.coefficient(), i);
assert_eq!(d.n_frac_digits(), 0);
}
},
}
}
}
#[test]
fn test_from_u128_err() {
let i = 0x8000_0000_0000_0000_0000_0000_0000_0000_u128;
let res = Decimal::try_from(i);
assert_eq!(res.unwrap_err(), DecimalError::InternalOverflow);
}
#[test]
fn test_from() {
let si = -358_i32;
let dsi = Decimal::from(si);
assert_eq!(dsi.coefficient(), i128::from(si));
assert_eq!(dsi.n_frac_digits(), 0);
let ui = 38_u64.pow(12);
let dui = Decimal::from(ui);
assert_eq!(dui.coefficient(), i128::from(ui));
assert_eq!(dui.n_frac_digits(), 0);
}
#[test]
fn test_into() {
let ui = 38_u8;
let dui: Decimal = ui.into();
assert_eq!(dui.coefficient(), i128::from(ui));
assert_eq!(dui.n_frac_digits(), 0);
let si = -1234567890123456789_i64;
let dsi: Decimal = si.into();
assert_eq!(dsi.coefficient(), i128::from(si));
assert_eq!(dsi.n_frac_digits(), 0);
}
}