use std::borrow::Cow;
use derive_builder::Builder;
use crate::api::eod::Eod;
use crate::api::paged::PaginationError;
use crate::api::{endpoint_prelude::*, ApiError};
#[derive(Debug, Builder, Clone)]
#[builder(setter(strip_option), build_fn(validate = "Self::validate"))]
pub struct Exchanges<'a> {
#[builder(setter(into), default)]
mic: Option<Cow<'a, str>>,
#[builder(setter(into), default)]
tickers: Option<Cow<'a, str>>,
#[builder(setter(into), default)]
eod: Option<Eod<'a>>,
#[builder(setter(into), default)]
search: Option<Cow<'a, str>>,
#[builder(setter(name = "_limit"), default)]
limit: Option<PageLimit>,
#[builder(default)]
offset: Option<u64>,
}
impl<'a> Exchanges<'a> {
pub fn builder() -> ExchangesBuilder<'a> {
ExchangesBuilder::default()
}
}
impl<'a> Endpoint for Exchanges<'a> {
fn method(&self) -> Method {
Method::GET
}
fn endpoint(&self) -> Cow<'static, str> {
let mut endpoint = "exchanges".to_owned();
if let Some(mic) = &self.mic {
endpoint.push_str(&format!("/{}", mic));
if let Some(tickers) = &self.tickers {
endpoint.push_str(&format!("/{}", tickers));
}
if let Some(eod) = &self.eod {
endpoint.push_str(&format!("/{}", eod.endpoint().as_ref()));
}
}
endpoint.into()
}
fn parameters(&self) -> QueryParams {
let mut params = QueryParams::default();
if let Some(eod) = &self.eod {
params = eod.parameters().clone();
}
params
.push_opt("search", self.search.as_ref())
.push_opt("limit", self.limit.clone())
.push_opt("offset", self.offset);
params
}
}
impl<'a> ExchangesBuilder<'a> {
pub fn limit(&mut self, limit: u16) -> Result<&mut Self, ApiError<PaginationError>> {
let new = self;
new.limit = Some(Some(PageLimit::new(limit)?));
Ok(new)
}
fn validate(&self) -> Result<(), String> {
let active_fields = [self.tickers.is_some(), self.eod.is_some()];
let count = active_fields.iter().filter(|x| **x).count();
if count > 1 {
Err("Invalid combinations of `eod`, `tickers` or `intraday`".into())
} else {
Ok(())
}
}
}
#[cfg(test)]
mod tests {
use chrono::NaiveDate;
use crate::api::eod::Eod;
use crate::api::exchanges::Exchanges;
use crate::api::{self, Query};
use crate::test::client::{ExpectedUrl, SingleTestClient};
#[test]
fn exchanges_defaults_are_sufficient() {
Exchanges::builder().build().unwrap();
}
#[test]
fn exchanges() {
let endpoint = ExpectedUrl::builder()
.endpoint("exchanges")
.build()
.unwrap();
let client = SingleTestClient::new_raw(endpoint, "");
let endpoint = Exchanges::builder().build().unwrap();
api::ignore(endpoint).query(&client).unwrap();
}
#[test]
fn exchanges_mic() {
let endpoint = ExpectedUrl::builder()
.endpoint("exchanges/XNAS")
.build()
.unwrap();
let client = SingleTestClient::new_raw(endpoint, "");
let endpoint = Exchanges::builder().mic("XNAS").build().unwrap();
api::ignore(endpoint).query(&client).unwrap();
}
#[test]
fn exchanges_mic_tickers() {
let endpoint = ExpectedUrl::builder()
.endpoint("exchanges/XNAS/tickers")
.build()
.unwrap();
let client = SingleTestClient::new_raw(endpoint, "");
let endpoint = Exchanges::builder()
.mic("XNAS")
.tickers("tickers")
.build()
.unwrap();
api::ignore(endpoint).query(&client).unwrap();
}
#[test]
fn exchanges_mic_eod() {
let endpoint = ExpectedUrl::builder()
.endpoint("exchanges/XNAS/eod")
.add_query_params(&[("limit", "5")])
.build()
.unwrap();
let client = SingleTestClient::new_raw(endpoint, "");
let endpoint = Exchanges::builder()
.mic("XNAS")
.eod(Eod::builder().limit(5).unwrap().build().unwrap())
.build()
.unwrap();
api::ignore(endpoint).query(&client).unwrap();
}
#[test]
fn exchanges_mic_eod_latest() {
let endpoint = ExpectedUrl::builder()
.endpoint("exchanges/XNAS/eod/latest")
.add_query_params(&[("limit", "5")])
.build()
.unwrap();
let client = SingleTestClient::new_raw(endpoint, "");
let endpoint = Exchanges::builder()
.mic("XNAS")
.eod(Eod::builder().latest(true).build().unwrap())
.limit(5)
.unwrap()
.build()
.unwrap();
api::ignore(endpoint).query(&client).unwrap();
}
#[test]
fn exchanges_mic_eod_date() {
let endpoint = ExpectedUrl::builder()
.endpoint("exchanges/XNAS/eod/2023-05-05")
.add_query_params(&[("limit", "5")])
.build()
.unwrap();
let client = SingleTestClient::new_raw(endpoint, "");
let endpoint = Exchanges::builder()
.mic("XNAS")
.eod(
Eod::builder()
.date(NaiveDate::from_ymd_opt(2023, 5, 5).unwrap())
.build()
.unwrap(),
)
.limit(5)
.unwrap()
.build()
.unwrap();
api::ignore(endpoint).query(&client).unwrap();
}
}