use std::sync::{Mutex, MutexGuard, OnceLock};
use numbat_exchange_rates::parse_exchange_rates;
#[derive(Debug)]
pub(crate) enum ExchangeRates {
Real(numbat_exchange_rates::ExchangeRates),
TestRates,
}
static EXCHANGE_RATES: OnceLock<Mutex<Option<ExchangeRates>>> = OnceLock::new();
pub struct ExchangeRatesCache {}
impl ExchangeRatesCache {
pub fn new() -> Self {
Self {}
}
pub fn get_rate(&self, currency: &str) -> Option<f64> {
let rates = Self::fetch();
rates
.as_ref()
.and_then(|er| match er {
ExchangeRates::Real(er) => er.get(currency),
ExchangeRates::TestRates => Some(&1.0),
})
.cloned()
}
pub fn set_from_xml(xml_content: &str) {
EXCHANGE_RATES
.set(Mutex::new(
parse_exchange_rates(xml_content).map(ExchangeRates::Real),
))
.unwrap();
}
#[cfg(feature = "fetch-exchangerates")]
pub fn fetch() -> MutexGuard<'static, Option<ExchangeRates>> {
EXCHANGE_RATES
.get_or_init(|| {
Mutex::new(numbat_exchange_rates::fetch_exchange_rates().map(ExchangeRates::Real))
})
.lock()
.unwrap()
}
#[cfg(not(feature = "fetch-exchangerates"))]
pub fn fetch() -> MutexGuard<'static, Option<ExchangeRates>> {
EXCHANGE_RATES
.get_or_init(|| Mutex::new(None))
.lock()
.unwrap()
}
pub fn use_test_rates() {
EXCHANGE_RATES.get_or_init(|| Mutex::new(Some(ExchangeRates::TestRates)));
}
}