use std::fmt;
use crate::types::Integer;
#[derive(Clone, Debug)]
pub struct Currency {
name: String,
code: String,
numeric_code: Integer,
symbol: String,
fraction_symbol: String,
fractions_per_unit: Integer,
}
impl Currency {
pub fn new(
name: impl Into<String>,
code: impl Into<String>,
numeric_code: Integer,
symbol: impl Into<String>,
fraction_symbol: impl Into<String>,
fractions_per_unit: Integer,
) -> Self {
Currency {
name: name.into(),
code: code.into(),
numeric_code,
symbol: symbol.into(),
fraction_symbol: fraction_symbol.into(),
fractions_per_unit,
}
}
pub fn eur() -> Self {
Currency::new("European Euro", "EUR", 978, "", "", 100)
}
pub fn usd() -> Self {
Currency::new("U.S. dollar", "USD", 840, "$", "\u{a2}", 100)
}
pub fn name(&self) -> &str {
&self.name
}
pub fn code(&self) -> &str {
&self.code
}
pub fn numeric_code(&self) -> Integer {
self.numeric_code
}
pub fn symbol(&self) -> &str {
&self.symbol
}
pub fn fraction_symbol(&self) -> &str {
&self.fraction_symbol
}
pub fn fractions_per_unit(&self) -> Integer {
self.fractions_per_unit
}
}
impl fmt::Display for Currency {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(&self.code)
}
}
impl PartialEq for Currency {
fn eq(&self, other: &Currency) -> bool {
self.name == other.name
}
}
impl Eq for Currency {}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn eur_fields_match_quantlib() {
let eur = Currency::eur();
assert_eq!(eur.name(), "European Euro");
assert_eq!(eur.code(), "EUR");
assert_eq!(eur.numeric_code(), 978);
assert_eq!(eur.symbol(), "");
assert_eq!(eur.fraction_symbol(), "");
assert_eq!(eur.fractions_per_unit(), 100);
}
#[test]
fn usd_fields_match_quantlib() {
let usd = Currency::usd();
assert_eq!(usd.name(), "U.S. dollar");
assert_eq!(usd.code(), "USD");
assert_eq!(usd.numeric_code(), 840);
assert_eq!(usd.symbol(), "$");
assert_eq!(usd.fraction_symbol(), "\u{a2}");
assert_eq!(usd.fractions_per_unit(), 100);
}
#[test]
fn accessors_round_trip_construction() {
let c = Currency::new("British pound sterling", "GBP", 826, "\u{a3}", "p", 100);
assert_eq!(c.name(), "British pound sterling");
assert_eq!(c.code(), "GBP");
assert_eq!(c.numeric_code(), 826);
assert_eq!(c.symbol(), "\u{a3}");
assert_eq!(c.fraction_symbol(), "p");
assert_eq!(c.fractions_per_unit(), 100);
}
#[test]
fn equality_is_by_name() {
assert_eq!(Currency::eur(), Currency::eur());
let gbp = Currency::new("British pound sterling", "GBP", 826, "\u{a3}", "p", 100);
assert_ne!(Currency::eur(), gbp);
let same_name_other_fields = Currency::new("European Euro", "XXX", 0, "z", "z", 1);
assert_eq!(Currency::eur(), same_name_other_fields);
}
#[test]
fn display_prints_iso_code() {
assert_eq!(Currency::eur().to_string(), "EUR");
}
}