use std::fmt;
use util::{Error, Result};
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
pub enum Units {
Bch,
Bits,
Sats,
}
impl Units {
pub fn parse(s: &str) -> Result<Units> {
let s = s.to_lowercase();
if s == "bch" || s == "bitcoin" {
return Ok(Units::Bch);
} else if s == "bit" || s == "bits" {
return Ok(Units::Bits);
} else if s == "sat" || s == "sats" {
return Ok(Units::Sats);
} else {
let msg = format!("Unknown units: {}", s);
return Err(Error::BadArgument(msg));
}
}
}
#[derive(PartialEq, Eq, Hash, Clone, Copy)]
pub struct Amount(pub i64);
impl Amount {
pub fn from(amount: f64, units: Units) -> Amount {
match units {
Units::Bch => Amount((amount * 100_000_000.) as i64),
Units::Bits => Amount((amount * 100.) as i64),
Units::Sats => Amount(amount as i64),
}
}
pub fn to(&self, units: Units) -> f64 {
match units {
Units::Bch => self.0 as f64 / 100_000_000.,
Units::Bits => self.0 as f64 / 100.,
Units::Sats => self.0 as f64,
}
}
}
impl fmt::Debug for Amount {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str(&format!("{} bch", self.to(Units::Bch)))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn from_to() {
assert!(Amount(0).to(Units::Bch) == 0.);
assert!(Amount(0).to(Units::Bits) == 0.);
assert!(Amount(0).to(Units::Sats) == 0.);
assert!(Amount(1).to(Units::Bch) == 0.00000001);
assert!(Amount(1).to(Units::Bits) == 0.01);
assert!(Amount(1).to(Units::Sats) == 1.);
assert!(Amount(9).to(Units::Bch) == 0.00000009);
assert!(Amount(9).to(Units::Bits) == 0.09);
assert!(Amount(9).to(Units::Sats) == 9.);
assert!(Amount::from(0., Units::Bch).0 == 0);
assert!(Amount::from(0., Units::Bits).0 == 0);
assert!(Amount::from(0., Units::Sats).0 == 0);
assert!(Amount::from(1., Units::Bch).0 == 100_000_000);
assert!(Amount::from(1., Units::Bits).0 == 100);
assert!(Amount::from(1., Units::Sats).0 == 1);
assert!(Amount::from(9., Units::Bch).0 == 900_000_000);
assert!(Amount::from(9., Units::Bits).0 == 900);
assert!(Amount::from(9., Units::Sats).0 == 9);
assert!(Amount::from(1., Units::Bch).to(Units::Bch) == 1.);
assert!(Amount::from(0.01, Units::Bch).to(Units::Bch) == 0.01);
assert!(Amount::from(99., Units::Bits).to(Units::Bits) == 99.);
assert!(Amount::from(1., Units::Sats).to(Units::Sats) == 1.);
}
}