bignumber 0.1.1

A Rust library for arbitrary-precision decimal and non-decimal arithmetic
Documentation
use crate::BigNumberError;

const DEFAULT_PRECISION: usize = if cfg!(feature = "precision-1024") {
    1024
} else if cfg!(feature = "precision-512") {
    512
} else {
    256
};

pub struct BigNumber {
    pub value: dashu_float::DBig,
}

impl Clone for BigNumber {
    #[inline]
    fn clone(&self) -> Self {
        Self {
            value: self.value.clone(),
        }
    }
}

impl BigNumber {
    pub fn of(val: &str) -> Result<BigNumber, BigNumberError> {
        let value = match val.strip_prefix("0x") {
            Some(hex) => {
                let value_hex =
                    dashu_float::FBig::<dashu_float::round::mode::HalfAway, 16>::from_str_native(
                        hex,
                    );
                if let Ok(x) = value_hex {
                    dashu_float::DBig::from_str_native(&x.repr().significand().to_string())
                } else {
                    return Err(BigNumberError::ParseError);
                }
            }
            None => dashu_float::DBig::from_str_native(val),
        };

        match value {
            Ok(x) => Ok(BigNumber {
                value: x.with_precision(DEFAULT_PRECISION).value(),
            }),
            Err(_) => Err(BigNumberError::ParseError),
        }
    }

    pub fn of_precision(val: &str, precision: usize) -> Result<BigNumber, BigNumberError> {
        let value = match val.strip_prefix("0x") {
            Some(hex) => {
                let value_hex =
                    dashu_float::FBig::<dashu_float::round::mode::HalfAway, 16>::from_str_native(
                        hex,
                    );
                if let Ok(x) = value_hex {
                    dashu_float::DBig::from_str_native(&x.repr().significand().to_string())
                } else {
                    return Err(BigNumberError::ParseError);
                }
            }
            None => dashu_float::DBig::from_str_native(val),
        };

        match value {
            Ok(x) => Ok(BigNumber {
                value: x.with_precision(precision).value(),
            }),
            Err(_) => Err(BigNumberError::ParseError),
        }
    }

    pub fn is_zero(&self) -> bool {
        self.value.repr().is_zero()
    }

    pub fn to_precision(&self, precision: usize) -> BigNumber {
        BigNumber {
            value: self.value.clone().with_precision(precision).value(),
        }
    }
}

#[cfg(test)]
mod tests {
    use std::ops::Div;

    use super::*;

    #[test]
    fn test_hex_string() {
        assert_eq!(BigNumber::of("0x42").unwrap().to_string(), "66");
    }

    #[test]
    fn test_hex_string_big() {
        assert_eq!(
            BigNumber::of("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF")
                .unwrap()
                .to_string(),
            "115792089237316195423570985008687907853269984665640564039457584007913129639935"
        );
    }

    #[test]
    fn test_hex_string_big_div() {
        assert_eq!(
            BigNumber::of("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF")
                .unwrap()
                .div(BigNumber::from(1e18))
                .to_string(),
            "115792089237316195423570985008687907853269984665640564039457.584007913129639935"
        );
    }
}