use serde::Deserialize;
use crate::api::ApiClient;
use crate::deserialize::from_str;
use crate::error::{Error, Result};
#[derive(Default)]
pub struct Exchange {
real_time: RealtimeExchangeRate,
}
#[derive(Debug, Deserialize, Clone, Default)]
struct RealtimeExchangeRate {
#[serde(rename = "1. From_Currency Code")]
from_code: String,
#[serde(rename = "2. From_Currency Name")]
from_name: String,
#[serde(rename = "3. To_Currency Code")]
to_code: String,
#[serde(rename = "4. To_Currency Name")]
to_name: String,
#[serde(rename = "5. Exchange Rate", deserialize_with = "from_str")]
rate: f64,
#[serde(rename = "6. Last Refreshed")]
last_refreshed: String,
#[serde(rename = "7. Time Zone")]
time_zone: String,
#[serde(rename = "8. Bid Price")]
bid_price: String,
#[serde(rename = "9. Ask Price")]
ask_price: String,
}
impl Exchange {
#[must_use]
pub fn rate(&self) -> f64 {
self.real_time.rate
}
#[must_use]
pub fn refreshed_time(&self) -> &str {
&self.real_time.last_refreshed
}
#[must_use]
pub fn time_zone(&self) -> &str {
&self.real_time.time_zone
}
#[must_use]
pub fn code_from(&self) -> &str {
&self.real_time.from_code
}
#[must_use]
pub fn name_from(&self) -> &str {
&self.real_time.from_name
}
#[must_use]
pub fn code_to(&self) -> &str {
&self.real_time.to_code
}
#[must_use]
pub fn name_to(&self) -> &str {
&self.real_time.to_name
}
#[must_use]
pub fn bid_price(&self) -> Option<f64> {
self.real_time.bid_price.trim().parse::<f64>().ok()
}
#[must_use]
pub fn ask_price(&self) -> Option<f64> {
self.real_time.ask_price.trim().parse::<f64>().ok()
}
}
#[derive(Debug, Deserialize)]
pub(crate) struct ExchangeHelper {
#[serde(rename = "Realtime Currency Exchange Rate")]
real_time: Option<RealtimeExchangeRate>,
}
impl ExchangeHelper {
fn convert(self) -> Result<Exchange> {
let mut exchange = Exchange::default();
if self.real_time.is_none() {
return Err(Error::EmptyResponse);
}
exchange.real_time = self.real_time.unwrap();
Ok(exchange)
}
}
pub struct ExchangeBuilder<'a> {
api_client: &'a ApiClient,
from_currency: &'a str,
to_currency: &'a str,
}
impl<'a> ExchangeBuilder<'a> {
crate::json_data_struct!(Exchange, ExchangeHelper);
#[must_use]
pub fn new(api_client: &'a ApiClient, from_currency: &'a str, to_currency: &'a str) -> Self {
Self {
api_client,
from_currency,
to_currency,
}
}
fn create_url(&self) -> String {
format!(
"query?function=CURRENCY_EXCHANGE_RATE&from_currency={}&to_currency={}",
self.from_currency, self.to_currency
)
}
}