decimal-wad 0.1.8

Math for preserving precision floats up to 18 decimal places.
Documentation
use std::convert::TryFrom;

use crate::error::*;

/// Scale of precision
pub const SCALE: usize = 18;
/// Identity
pub const WAD: u64 = 1_000_000_000_000_000_000;
/// Half of identity
pub const HALF_WAD: u64 = 500_000_000_000_000_000;
/// Scale for percentages
pub const PERCENT_SCALER: u64 = 10_000_000_000_000_000;

/// Scale for bips (100 bp = 1 percent)
pub const BPS_SCALER: u64 = PERCENT_SCALER / 100;

// For code generated by the macros
#[allow(clippy::assign_op_pattern)]
#[allow(clippy::ptr_offset_with_cast)]
#[allow(clippy::reversed_empty_ranges)]
#[allow(clippy::manual_range_contains)]
pub mod uint {
    use super::*;
    use ::uint::construct_uint;

    construct_uint! {
        /// U192 with 192 bits consisting of 3 x 64-bit words
        pub struct U192(3);
    }

    construct_uint! {
        /// U128 with 128 bits consisting of 2 x 64-bit words
        pub struct U128(2);
    }

    impl From<U128> for U192 {
        fn from(value: U128) -> U192 {
            let U128(ref arr) = value;
            let mut ret = [0; 3];
            ret[0] = arr[0];
            ret[1] = arr[1];
            U192(ret)
        }
    }

    impl TryFrom<U192> for U128 {
        type Error = DecimalError;

        fn try_from(value: U192) -> Result<U128, DecimalError> {
            let U192(ref arr) = value;
            if arr[2] != 0 {
                return Err(DecimalError::MathOverflow);
            }
            let mut ret = [0; 2];
            ret[0] = arr[0];
            ret[1] = arr[1];
            Ok(U128(ret))
        }
    }
}

/// Try to subtract, return an error on underflow
pub trait TrySub: Sized {
    /// Subtract
    fn try_sub(self, rhs: Self) -> Result<Self, DecimalError>;
}

/// Try to subtract, return an error on overflow
pub trait TryAdd: Sized {
    /// Add
    fn try_add(self, rhs: Self) -> Result<Self, DecimalError>;
}

/// Try to divide, return an error on overflow or divide by zero
pub trait TryDiv<RHS>: Sized {
    /// Divide
    fn try_div(self, rhs: RHS) -> Result<Self, DecimalError>;
}

/// Try to multiply, return an error on overflow
pub trait TryMul<RHS>: Sized {
    /// Multiply
    fn try_mul(self, rhs: RHS) -> Result<Self, DecimalError>;
}