1use crate::providers::ExchangeRateProvider;
2use crate::providers::LiveExchangeProvider;
3use rust_decimal::Decimal;
4use std::fmt;
5
6#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
7pub enum CurrencyUnit {
8 USD,
9 EUR,
10 GBP,
11 JPY,
12}
13
14impl CurrencyUnit {
15 pub fn parse(s: &str) -> Option<Self> {
16 match s.to_ascii_uppercase().as_str() {
17 "USD" => Some(Self::USD),
18 "EUR" => Some(Self::EUR),
19 "GBP" => Some(Self::GBP),
20 "JPY" => Some(Self::JPY),
21 _ => None,
22 }
23 }
24
25 pub fn as_str(&self) -> &'static str {
26 match self {
27 Self::USD => "USD",
28 Self::EUR => "EUR",
29 Self::GBP => "GBP",
30 Self::JPY => "JPY",
31 }
32 }
33}
34
35impl fmt::Display for CurrencyUnit {
36 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
37 f.write_str(self.as_str())
38 }
39}
40
41pub fn convert_with_provider<P: ExchangeRateProvider>(
42 value: Decimal,
43 from: CurrencyUnit,
44 to: CurrencyUnit,
45 provider: &P,
46) -> Result<Decimal, String> {
47 let rate = provider.get_rate(from, to)?;
48 Ok(value * rate)
49}
50
51pub fn convert(value: Decimal, from: CurrencyUnit, to: CurrencyUnit) -> Result<Decimal, String> {
56 let provider = LiveExchangeProvider::new(None);
57 convert_with_provider(value, from, to, &provider)
58}