116 lines
3.8 KiB
Rust
116 lines
3.8 KiB
Rust
use bigdecimal::BigDecimal;
|
|
|
|
pub fn convert(val: BigDecimal, decimal_places: u8, seperator: char, thousands_seperator: Option<char>) -> String{
|
|
let (base, mut exponent) = val.as_bigint_and_exponent();
|
|
let mut base = base.to_str_radix(10);
|
|
|
|
// Negative power of 10, need to move comma to the left
|
|
|
|
let mut res_decimal_places:Vec<char> = Vec::new();
|
|
let mut rev_base = base.chars().rev();
|
|
let mut exp = exponent.clone();
|
|
|
|
//Add decimal places until exponent = 0
|
|
while exp > 0{
|
|
match rev_base.next(){
|
|
Some(next_base_char) => res_decimal_places.push(next_base_char),
|
|
None => res_decimal_places.push('0')
|
|
}
|
|
exp = exp-1;
|
|
}
|
|
|
|
//Reverse decimal places back into right order
|
|
res_decimal_places = res_decimal_places.into_iter().rev().collect::<Vec<char>>();
|
|
|
|
let mut new_base : Vec<char> = rev_base.rev().collect();
|
|
|
|
if let Some(ts) = thousands_seperator{
|
|
new_base = add_thousands_seperator(new_base, ts)
|
|
}
|
|
|
|
if new_base.is_empty(){
|
|
new_base = vec!['0'];
|
|
}
|
|
|
|
if res_decimal_places.len() > 0{
|
|
format!("{}{}{}", new_base.iter().collect::<String>(), seperator, res_decimal_places.iter().collect::<String>())
|
|
}else{
|
|
new_base.iter().collect::<String>()
|
|
}
|
|
|
|
|
|
}
|
|
|
|
pub fn add_thousands_seperator(input: Vec<char>, thousands_seperator: char) -> Vec<char>{
|
|
let mut input = input.into_iter().rev().peekable();
|
|
let mut output : Vec<char> = Vec::new();
|
|
let mut counter = 0;
|
|
|
|
while let Some(val) = input.next(){
|
|
counter = counter+1;
|
|
output.push(val);
|
|
|
|
if counter == 3 && input.peek().is_some(){
|
|
output.push(thousands_seperator);
|
|
counter = 0;
|
|
}
|
|
}
|
|
|
|
output.into_iter().rev().collect()
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use std::str::FromStr;
|
|
|
|
use super::*;
|
|
|
|
#[test]
|
|
pub fn test_convert_positive() {
|
|
let bd = BigDecimal::from_str("54000.16712").unwrap();
|
|
println!("Exponent: {}", bd.as_bigint_and_exponent().1.to_string());
|
|
assert_eq!(convert(bd, 2, ',', Some('.')), String::from("54.000,16712"));
|
|
}
|
|
#[test]
|
|
pub fn test_convert_negative() {
|
|
let bd = BigDecimal::from_str("-54000.16712").unwrap();
|
|
assert_eq!(convert(bd, 2, ',', Some('.')), String::from("-54.000,16712"));
|
|
}
|
|
#[test]
|
|
pub fn test_convert_no_decimal_places() {
|
|
let bd = BigDecimal::from_str("-54000.16712").unwrap();
|
|
assert_eq!(convert(bd, 0, ',', Some('.')), String::from("-54.000"));
|
|
}
|
|
#[test]
|
|
pub fn test_convert_no_thousands_separator() {
|
|
let bd = BigDecimal::from_str("-54000.16712").unwrap();
|
|
assert_eq!(convert(bd, 0, ',', None), String::from("-54000"));
|
|
}
|
|
#[test]
|
|
pub fn test_convert_positive_no_decimal_places() {
|
|
let bd = BigDecimal::from_str("54000").unwrap();
|
|
assert_eq!(convert(bd, 2, ',', Some('.')), String::from("54.000"));
|
|
}
|
|
#[test]
|
|
pub fn test_convert_negative_no_decimal_places() {
|
|
let bd = BigDecimal::from_str("-54000").unwrap();
|
|
assert_eq!(convert(bd, 2, ',', Some('.')), String::from("-54.000"));
|
|
}
|
|
#[test]
|
|
pub fn test_convert2() {
|
|
let bd = BigDecimal::from_str("54000000000000").unwrap();
|
|
assert_eq!(convert(bd, 2, ',', Some('.')), String::from("54.000.000.000.000"));
|
|
}
|
|
#[test]
|
|
pub fn test_convert3() {
|
|
let bd = BigDecimal::from_str("0.000000016712").unwrap();
|
|
println!("Exponent: {}", bd.as_bigint_and_exponent().1.to_string());
|
|
assert_eq!(convert(bd, 0, ',', None), String::from("0"));
|
|
}
|
|
#[test]
|
|
pub fn test_convert4() {
|
|
let bd = BigDecimal::from_str("0.000000016712").unwrap();
|
|
println!("Exponent: {}", bd.as_bigint_and_exponent().1.to_string());
|
|
assert_eq!(convert(bd, 2, ',', None), String::from("0,00"));
|
|
}
|
|
} |