accounting 0.2.0

accounting is a library for money and currency formatting.
Documentation

use super::FormatNumber;

macro_rules! format_number_int {
    ($x: expr, $p: expr, $t: expr, $d: expr) => {
        {
            let mut x = $x;
            let precision = $p;
            let thousand = $t;
            let decimal = $d;

            let mut result: String = "".to_string();
            let mut minus: bool = false;

            if let Some(neg) = x.checked_neg() {
                if neg > 0 {
                    x = neg;
                    minus = true;
                }
            }

            while x>=1000  {
                result = format!("{}{:03}{}", thousand, x%1000, result);
                x /= 1000;
            }
            result = format!("{}{}", x, result);

            if minus {
                result = format!("-{}", result);
            }
        
            if precision > 0 {
                result = format!("{}{}{}", result, decimal, "0".repeat(precision))
            } 

            result
        }
    };
}


macro_rules! format_number_float {
    ($x: expr, $p: expr, $t: expr, $d: expr) => {
        {
            let x = $x;
            let precision = $p;
            let thousand = $t;
            let decimal = $d;

            let v:Vec<char> = format!("{0:.1$}", x, precision).chars().collect();
    
            let l;
            if let Some(index) = v.iter().position(|&r| r == '.') {
                l = index - 1;
            } else {
                l = v.len() - 1;
            }
            
            let mut buffer = String::new();
            let mut j = 0;
            for i in (0..=l).rev() {
                j += 1;
                buffer.push(v[i]);
                if j==3 && i>0 && !(i==1 && v[0] == '-') {
                    buffer.push(',');
                    j = 0;
                }
            }

            let mut result: String = buffer.chars().rev().collect();
            
            if thousand != "," {
                result = result.replace(",", thousand);
            }

            let mut extra: String = v[l+1..v.len()].into_iter().collect();
            if decimal != "." {
                extra = extra.replace(".", decimal);
            }

            format!("{}{}", result, extra)
        }
    }
    
}

impl FormatNumber for i8 {
    fn format_number(&self, precision: usize, _: &str, decimal: &str) -> String {
        if precision > 0 {
            format!("{}{}{}", *self, decimal, "0".repeat(precision))
        } else {
            self.to_string()
        }
    }
}

impl FormatNumber for u8 {
    fn format_number(&self, precision: usize, _: &str, decimal: &str) -> String {
        if precision > 0 {
            format!("{}{}{}", *self, decimal, "0".repeat(precision))
        } else {
            self.to_string()
        }
    }
}

impl FormatNumber for i16 {
    fn format_number(&self, precision: usize, thousand: &str, decimal: &str) -> String {
        format_number_int!(*self, precision, thousand, decimal)
    }
}

impl FormatNumber for i32 {
    fn format_number(&self, precision: usize, thousand: &str, decimal: &str) -> String {
        format_number_int!(*self, precision, thousand, decimal)
    }
}

impl FormatNumber for i64 {
    fn format_number(&self, precision: usize, thousand: &str, decimal: &str) -> String {
        format_number_int!(*self, precision, thousand, decimal)
    }
}

impl FormatNumber for i128 {
    fn format_number(&self, precision: usize, thousand: &str, decimal: &str) -> String {
        format_number_int!(*self, precision, thousand, decimal)
    }
}

impl FormatNumber for isize {
    fn format_number(&self, precision: usize, thousand: &str, decimal: &str) -> String {
        format_number_int!(*self, precision, thousand, decimal)
    }
}

impl FormatNumber for u16 {
    fn format_number(&self, precision: usize, thousand: &str, decimal: &str) -> String {
        format_number_int!(*self, precision, thousand, decimal)
    }
}

impl FormatNumber for u32 {
    fn format_number(&self, precision: usize, thousand: &str, decimal: &str) -> String {
        format_number_int!(*self, precision, thousand, decimal)
    }
}

impl FormatNumber for u64 {
    fn format_number(&self, precision: usize, thousand: &str, decimal: &str) -> String {
        format_number_int!(*self, precision, thousand, decimal)
    }
}

impl FormatNumber for u128 {
    fn format_number(&self, precision: usize, thousand: &str, decimal: &str) -> String {
        format_number_int!(*self, precision, thousand, decimal)
    }
}

impl FormatNumber for usize {
    fn format_number(&self, precision: usize, thousand: &str, decimal: &str) -> String {
        format_number_int!(*self, precision, thousand, decimal)
    }
}

impl FormatNumber for f32 {
    fn format_number(&self, precision: usize, thousand: &str, decimal: &str) -> String {
        format_number_float!(*self, precision, thousand, decimal)
    }
}

impl FormatNumber for f64 {
    fn format_number(&self, precision: usize, thousand: &str, decimal: &str) -> String {
        format_number_float!(*self, precision, thousand, decimal)
    }
}