macro_rules! international_currency_symbol {
() => {
"\u{00A4}"
};
}
pub(super) use international_currency_symbol;
use super::Mudra;
#[allow(private_bounds)]
pub trait Currency: Sealed {
fn code(&self) -> &'static str;
fn mudra(&self) -> Mudra;
fn name(&self) -> &'static str;
fn numeric(&self) -> u16;
#[doc = concat!(
"Returns the commonly used symbol of the currency. ",
"If there is no symbol associated, the international currency symbol `",
international_currency_symbol!(),
"` is returned"
)]
fn symbol(&self) -> &'static str;
}
trait Sealed {}
#[rustfmt::skip]
macro_rules! define_currency {
(
$currency:ident,
$code:literal,
$name:literal,
$numeric:literal
$(,)?
) => {
#[doc = concat!($numeric , " - ", $name, " (", international_currency_symbol!(), ")")]
#[derive(Debug, Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct $currency;
impl $currency {
const CODE: &'static str = $code;
const MUDRA: Mudra = Mudra::$currency;
const NAME: &'static str = $name;
const NUMERIC: u16 = $numeric;
const SYMBOL: &'static str = international_currency_symbol!();
}
impl TryFrom<Mudra> for $currency {
type Error = ();
#[doc = concat!(
"Returns [`", $code, "`] ", "when `mudra` is [`Mudra::", $code, "`], else `Err(())`.",
)]
fn try_from(mudra: Mudra) -> Result<Self, Self::Error> {
Self::try_from(&mudra)
}
}
impl TryFrom<&Mudra> for $currency {
type Error = ();
#[doc = concat!(
"Returns [`", $code, "`] ", "when `mudra` is [`Mudra::", $code, "`], else `Err(())`.",
)]
fn try_from(mudra: &Mudra) -> Result<Self, Self::Error> {
match mudra {
Mudra::$currency => Ok(Self),
_ => Err(()),
}
}
}
impl From<$currency> for Mudra {
#[doc = concat!("Returns [`Mudra::", $code, "`].")]
fn from(currency: $currency) -> Self {
Self::from(¤cy)
}
}
impl From<&$currency> for Mudra {
#[doc = concat!("Returns [`Mudra::", $code, "`].")]
fn from(_currency: &$currency) -> Self {
Self::$currency
}
}
impl Currency for $currency {
#[doc = concat!("Returns", " `", $code, "`.")]
fn code(&self) -> &'static str {
Self::CODE
}
#[doc = concat!("Returns", " [`Mudra::", $code, "`].")]
fn mudra(&self) -> Mudra {
Self::MUDRA
}
#[doc = concat!("Returns", " `", $name, "`.")]
fn name(&self) -> &'static str {
Self::NAME
}
#[doc = concat!("Returns", " `", $numeric, "`.")]
fn numeric(&self) -> u16 {
Self::NUMERIC
}
#[doc = concat!("Returns", " `", international_currency_symbol!(), "`.")]
fn symbol(&self) -> &'static str {
Self::SYMBOL
}
}
impl Sealed for $currency {}
};
(
$currency:ident,
$code:literal,
$name:literal,
$numeric:literal,
$symbol:literal
$(,)?
) => {
#[doc = concat!($numeric, " - ", $name, " (", $symbol, ")")]
#[derive(Debug, Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct $currency;
impl $currency {
const CODE: &'static str = $code;
const MUDRA: Mudra = Mudra::$currency;
const NAME: &'static str = $name;
const NUMERIC: u16 = $numeric;
const SYMBOL: &'static str = $symbol;
}
impl TryFrom<Mudra> for $currency {
type Error = ();
#[doc = concat!(
"Returns [`", $code, "`] ", "when `mudra` is [`Mudra::", $code, "`], else `Err(())`.",
)]
fn try_from(mudra: Mudra) -> Result<Self, Self::Error> {
Self::try_from(&mudra)
}
}
impl TryFrom<&Mudra> for $currency {
type Error = ();
#[doc = concat!(
"Returns [`", $code, "`] ", "when `mudra` is [`Mudra::", $code, "`], else `Err(())`.",
)]
fn try_from(mudra: &Mudra) -> Result<Self, Self::Error> {
match mudra {
Mudra::$currency => Ok(Self),
_ => Err(()),
}
}
}
impl From<$currency> for Mudra {
#[doc = concat!("Returns [`Mudra::", $code, "`].")]
fn from(currency: $currency) -> Self {
Self::from(¤cy)
}
}
impl From<&$currency> for Mudra {
#[doc = concat!("Returns [`Mudra::", $code, "`].")]
fn from(_currency: &$currency) -> Self {
Self::$currency
}
}
impl Currency for $currency {
#[doc = concat!("Returns", " `", $code, "`.")]
fn code(&self) -> &'static str {
Self::CODE
}
#[doc = concat!("Returns", " [`Mudra::", $code, "`].")]
fn mudra(&self) -> Mudra {
Self::MUDRA
}
#[doc = concat!("Returns", " `", $name, "`.")]
fn name(&self) -> &'static str {
Self::NAME
}
#[doc = concat!("Returns", " `", $numeric, "`.")]
fn numeric(&self) -> u16 {
Self::NUMERIC
}
#[doc = concat!("Returns", " `", $symbol, "`.")]
fn symbol(&self) -> &'static str {
Self::SYMBOL
}
}
impl Sealed for $currency {}
};
}
define_currency!(
AED,
"AED",
"United Arab Emirates dirham",
784,
"\u{062F}\u{002E}\u{0625}",
);
define_currency!(ARS, "ARS", "Argentine peso", 32, "\u{0024}");
define_currency!(AUD, "AUD", "Australian dollar", 36, "\u{0024}");
define_currency!(BGN, "BGN", "Bulgarian lev", 975, "\u{043B}\u{0432}\u{002E}");
define_currency!(
BHD,
"BHD",
"Bahraini dinar",
48,
"\u{002E}\u{062F}\u{002E}\u{0628}",
);
define_currency!(BOV, "BOV", "Bolivian Mvdol", 984);
define_currency!(BRL, "BRL", "Brazilian real", 986, "\u{0024}");
define_currency!(CAD, "CAD", "Canadian dollar", 124, "\u{0024}");
define_currency!(CHF, "CHF", "Swiss franc", 756);
define_currency!(CLP, "CLP", "Chilean peso", 152, "\u{0024}");
define_currency!(CNY, "CNY", "Renminbi", 156, "\u{00A5}");
define_currency!(COP, "COP", "Colombian peso", 170, "\u{0024}");
define_currency!(CZK, "CZK", "Czech koruna", 203, "\u{004B}\u{010D}");
define_currency!(DKK, "DKK", "Danish krone", 208, "\u{006B}\u{0072}");
define_currency!(EUR, "EUR", "Euro", 978, "\u{20AC}");
define_currency!(GBP, "GBP", "Pound sterling", 826, "\u{00A3}");
define_currency!(HKD, "HKD", "Hong Kong dollar", 344, "\u{0024}");
define_currency!(HUF, "HUF", "Hungarian forint", 348, "\u{0046}\u{0074}");
define_currency!(IDR, "IDR", "Indonesian rupiah", 360, "\u{0052}\u{0070}");
define_currency!(ILS, "ILS", "Israeli new shekel", 376, "\u{20AA}");
define_currency!(INR, "INR", "Indian rupee", 356, "\u{20B9}");
define_currency!(JPY, "JPY", "Japanese yen", 392, "\u{00A5}");
define_currency!(KRW, "KRW", "South Korean won", 410, "\u{20A9}");
define_currency!(MXN, "MXN", "Mexican peso", 484, "\u{0024}");
define_currency!(MYR, "MYR", "Malaysian ringgit", 458, "\u{0052}\u{004D}");
define_currency!(NOK, "NOK", "Norwegian krone", 578, "\u{006B}\u{0072}");
define_currency!(NZD, "NZD", "New Zealand dollar", 554, "\u{0024}");
define_currency!(PEN, "PEN", "Peruvian sol", 604, "\u{0053}\u{002F}");
define_currency!(PHP, "PHP", "Philippine peso", 608, "\u{20B1}");
define_currency!(PLN, "PLN", "Polish zloty", 985, "\u{007A}\u{0142}");
define_currency!(RON, "RON", "Romanian leu", 946, "\u{004C}");
define_currency!(RUB, "RUB", "Russian ruble", 643, "\u{20BD}");
define_currency!(SAR, "SAR", "Saudi riyal", 682, "\u{0631}\u{002E}\u{0633}");
define_currency!(SEK, "SEK", "Swedish krona", 752, "\u{006B}\u{0072}");
define_currency!(SGD, "SGD", "Singapore dollar", 702, "\u{0024}");
define_currency!(THB, "THB", "Thai baht", 764, "\u{0E3F}");
define_currency!(TRY, "TRY", "Turkish lira", 949, "\u{20BA}");
define_currency!(TWD, "TWD", "New Taiwan dollar", 901, "\u{0024}");
define_currency!(USD, "USD", "United States dollar", 840, "\u{0024}");
define_currency!(ZAR, "ZAR", "South African rand", 710, "\u{0052}");
#[cfg(test)]
mod tests {
use super::Currency;
use super::{BOV, USD};
#[test]
fn has_code_name_numeric_and_international_currency_symbol() {
let currency = BOV;
assert_eq!(currency.code(), "BOV");
assert_eq!(currency.name(), "Bolivian Mvdol");
assert_eq!(currency.numeric(), 984);
assert_eq!(currency.symbol(), "¤");
}
#[test]
fn has_code_name_numeric_symbol() {
let currency = USD;
assert_eq!(currency.code(), "USD");
assert_eq!(currency.name(), "United States dollar");
assert_eq!(currency.numeric(), 840);
assert_eq!(currency.symbol(), "$");
}
}