pub mod unformat_money;
pub mod format_number;
pub use format_number::FormatNumber;
pub use unformat_money::{unformat, UnformatError};
pub struct Accounting {
symbol: String,
precision: usize,
thousand: String,
decimal: String,
format_positive: String,
format_negative: String,
format_zero: String
}
impl Default for Accounting {
fn default() -> Self {
let format = "{s}{v}";
Accounting {
symbol: "$".to_string(),
precision: 0,
thousand: ",".to_string(),
decimal: ".".to_string(),
format_positive: format.to_string(),
format_negative: "-".to_string() + format,
format_zero: format.to_string()
}
}
}
impl Accounting {
pub fn new_from(symbol: &str, precision: usize) -> Self {
let mut ac = Self::default();
ac.symbol = symbol.to_string();
ac.precision = precision;
return ac;
}
pub fn new_from_seperator(symbol: &str, precision: usize, thousand: &str, decimal: &str) -> Self {
let mut ac = Self::default();
ac.symbol = symbol.to_string();
ac.precision = precision;
ac.thousand = thousand.to_string();
ac.decimal = decimal.to_string();
return ac;
}
pub fn new(
symbol: &str,
precision: usize,
thousand: &str,
decimal: &str,
format: &str,
format_negative: &str,
format_zero: &str
) -> Self {
Accounting {
symbol: symbol.to_string(),
precision,
thousand: thousand.to_string(),
decimal: decimal.to_string(),
format_positive: format.to_string(),
format_negative: format_negative.to_string(),
format_zero: format_zero.to_string()
}
}
pub fn set_thousand_separator(&mut self, str: &str) {
self.thousand = str.to_string();
}
pub fn set_decimal_separator(&mut self, str: &str) {
self.decimal = str.to_string();
}
pub fn set_format(&mut self, str: &str) {
self.set_format_positive(str);
self.set_format_negative(&format!("-{}", str));
self.set_format_zero(str);
}
pub fn set_format_positive(&mut self, str: &str) {
self.format_positive = str.to_string();
}
pub fn set_format_negative(&mut self, str: &str) {
self.format_negative = str.to_string();
}
pub fn set_format_zero(&mut self, str: &str) {
self.format_zero = str.to_string();
}
pub fn format_money<T:FormatNumber>(&self, value: T) -> String {
let mut number_string = value.format_number(self.precision, &self.thousand, &self.decimal);
let zero_string = 0.format_number(self.precision, &self.thousand, &self.decimal);
let format_string;
if &number_string[0..1] == "-" {
number_string = number_string[1..number_string.len()].to_string();
format_string = &self.format_negative;
} else if number_string == zero_string {
format_string = &self.format_zero;
} else {
format_string = &self.format_positive;
}
let mut result = format_string.replace("{s}", &self.symbol);
result = result.replace("{v}", &number_string);
return result;
}
}
#[cfg(test)]
mod tests {
use super::Accounting;
#[test]
fn test_number_type() {
let ac = Accounting::new_from("$", 2);
assert_eq!(ac.format_money(-1i8), "-$1.00");
assert_eq!(ac.format_money(1u8), "$1.00");
assert_eq!(ac.format_money(-1i16), "-$1.00");
assert_eq!(ac.format_money(1u16), "$1.00");
assert_eq!(ac.format_money(-1i32), "-$1.00");
assert_eq!(ac.format_money(1u32), "$1.00");
assert_eq!(ac.format_money(-1i64), "-$1.00");
assert_eq!(ac.format_money(1u64), "$1.00");
assert_eq!(ac.format_money(-1i128), "-$1.00");
assert_eq!(ac.format_money(1u128), "$1.00");
assert_eq!(ac.format_money(-1isize), "-$1.00");
assert_eq!(ac.format_money(1usize), "$1.00");
assert_eq!(ac.format_money(-1f32), "-$1.00");
assert_eq!(ac.format_money(1f64), "$1.00");
assert_eq!(ac.format_money(-0i32), "$0.00");
assert_eq!(ac.format_money(0u32), "$0.00");
#[cfg(feature="decimal")]
{
let ac = Accounting::new_from("$", 2);
let x = rust_decimal::Decimal::new(0, 1);
assert_eq!(ac.format_money(x), "$0.00");
}
}
#[test]
fn test_accounting_new() {
let ac = Accounting::new_from("$", 2);
assert_eq!(ac.format_money(123456789.213123), "$123,456,789.21");
assert_eq!(ac.format_money(12345678), "$12,345,678.00");
assert_eq!(ac.format_money(-12345678), "-$12,345,678.00");
assert_eq!(ac.format_money(0), "$0.00");
let ac = Accounting::new("$", 0, ",", ".",
"{s} {v}", "-{s} {v}", "{s} {v}");
assert_eq!(ac.format_money(123456789.213123), "$ 123,456,789");
assert_eq!(ac.format_money(12345678), "$ 12,345,678");
assert_eq!(ac.format_money(-12345678), "-$ 12,345,678");
assert_eq!(ac.format_money(0), "$ 0");
let ac = Accounting::new_from_seperator("€", 2, ".", ",");
assert_eq!(ac.format_money(4999.99), "€4.999,99");
let ac = Accounting::new_from("£ ", 0);
assert_eq!(ac.format_money(500000), "£ 500,000");
}
#[test]
fn test_accounting_set() {
let mut ac = Accounting::new_from("GBP", 0);
ac.set_format_positive("{s} {v}");
ac.set_format_negative("{s} ({v})");
ac.set_format_zero("{s} --");
assert_eq!(ac.format_money(1000000), "GBP 1,000,000");
assert_eq!(ac.format_money(-5000), "GBP (5,000)");
assert_eq!(ac.format_money(0), "GBP --");
let mut ac = Accounting::new_from("GBP", 2);
ac.set_format("{s} {v}");
ac.set_format_negative("{s} ({v})");
ac.set_format_zero( "{s} --");
assert_eq!(ac.format_money(1000000), "GBP 1,000,000.00");
assert_eq!(ac.format_money(-5000), "GBP (5,000.00)");
assert_eq!(ac.format_money(0), "GBP --");
let mut ac = Accounting::new_from("€", 2);
ac.set_format_zero("0.-");
assert_eq!(ac.format_money(0), "0.-");
}
}