EinsatzOnline/src/helper/bigdecimal_to_string.rs

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"));
}
}