use types::Error;
pub struct Amount;
impl Amount {
fn unit(amount: u64) -> char {
match amount * 10 {
pico if pico % 1000 > 0 => 'p',
pico if pico % 1000_000 > 0 => 'n',
pico if pico % 1000_000_000 > 0 => 'u',
_ => 'm',
}
}
pub fn decode(amount: &str) -> Result<u64, Error> {
match amount.chars().last() {
Some(a) if a == 'p' => amount[..amount.len() - 1].parse::<u64>().map(|v| v / 10),
Some(a) if a == 'n' => amount[..amount.len() - 1].parse::<u64>().map(|v| v * 100),
Some(a) if a == 'u' => amount[..amount.len() - 1]
.parse::<u64>()
.map(|v| v * 100_000),
Some(a) if a == 'm' => amount[..amount.len() - 1]
.parse::<u64>()
.map(|v| v * 100_000_000),
_ => amount.parse::<u64>(),
}.map_err(Error::ParseIntErr)
}
pub fn encode(amount: u64) -> String {
match amount {
amt if Amount::unit(amt) == 'p' => format!("{}p", amt * 10),
amt if Amount::unit(amt) == 'n' => format!("{}n", amt / 100),
amt if Amount::unit(amt) == 'u' => format!("{}u", amt / 100_000),
amt if Amount::unit(amt) == 'm' => format!("{}m", amt / 100_000_000),
amt => amt.to_string(),
}
}
}
#[cfg(test)]
mod test {
use super::*;
use std::collections::HashMap;
#[test]
fn minimal_amount_used() {
assert_eq!(Some('p'), Amount::encode(1).chars().last());
assert_eq!(Some('p'), Amount::encode(99).chars().last());
assert_eq!(Some('n'), Amount::encode(100).chars().last());
assert_eq!(Some('p'), Amount::encode(101).chars().last());
assert_eq!(Some('n'), Amount::encode(1000).chars().last());
assert_eq!(Some('u'), Amount::encode(100_000).chars().last());
assert_eq!(Some('n'), Amount::encode(101_000).chars().last());
assert_eq!(Some('u'), Amount::encode(1155_400_000).chars().last());
assert_eq!(Some('m'), Amount::encode(100_000_000).chars().last());
assert_eq!(Some('m'), Amount::encode(1000_000_000).chars().last());
assert_eq!(Some('m'), Amount::encode(100_000_000_000).chars().last());
}
#[test]
fn decode() {
assert_eq!(100_000_000u64, Amount::decode("1m").unwrap());
assert_eq!(100_000_000u64, Amount::decode("1000u").unwrap());
assert_eq!(100_000_000u64, Amount::decode("1000000n").unwrap());
assert_eq!(100_000_000u64, Amount::decode("1000000000p").unwrap());
}
}