pub mod frequency_formulas;
mod currency;
use self::frequency_formulas::*;
use crate::common;
use crate::error::ReturnError;
use crate::date::DatePreference;
use crate::traits::{self, MakingList, MakingUrlFormat, EnumSpecific, ConvertingToRustEnum};
#[derive(Debug)]
pub struct ExchangeType {
buying: bool,
selling: bool,
}
impl ExchangeType {
pub fn new() -> ExchangeType {
ExchangeType {
buying: false,
selling: true,
}
}
pub fn from(buying: bool, selling: bool) -> ExchangeType {
ExchangeType {
buying,
selling
}
}
pub fn select_buying_type(&mut self) {
self.buying = true;
self.selling = false;
}
pub fn select_selling_type(&mut self) {
self.buying = false;
self.selling = true;
}
pub fn select_both_types(&mut self) {
self.buying = true;
self.selling = true;
}
pub(crate) fn is_selling_type(&self) -> bool {
self.selling
}
pub(crate) fn is_buying_type(&self) -> bool {
self.buying
}
pub(crate) fn are_both_types(&self) -> bool {
if self.is_selling_type() && self.is_buying_type() { return true }
false
}
}
impl traits::MakingList for ExchangeType {
fn make_required_list(&self) -> Vec<&str> {
let mut exchange_type_list = Vec::new();
if self.buying {
exchange_type_list.push("A");
}
if self.selling {
exchange_type_list.push("S");
}
exchange_type_list
}
}
#[derive(Debug)]
pub enum CurrencyCode {
Usd,
Aud,
Dkk,
Eur,
Gbp,
Chf,
Sek,
Cad,
Kwd,
Nok,
Sar,
Jpy,
Bgn,
Ron,
Rub,
Irr,
Cny,
Pkr,
Qar,
}
impl ToString for CurrencyCode {
fn to_string(&self) -> String {
match self {
&Self::Usd => String::from("USD"),
&Self::Aud => String::from("AUD"),
&Self::Dkk => String::from("DKK"),
&Self::Eur => String::from("EUR"),
&Self::Gbp => String::from("GBP"),
&Self::Chf => String::from("CHF"),
&Self::Sek => String::from("SEK"),
&Self::Cad => String::from("CAD"),
&Self::Kwd => String::from("KWD"),
&Self::Nok => String::from("NOK"),
&Self::Sar => String::from("SAR"),
&Self::Jpy => String::from("JPY"),
&Self::Bgn => String::from("BGN"),
&Self::Ron => String::from("RON"),
&Self::Rub => String::from("RUB"),
&Self::Irr => String::from("IRR"),
&Self::Cny => String::from("CNY"),
&Self::Pkr => String::from("PKR"),
&Self::Qar => String::from("QAR"),
}
}
}
impl EnumSpecific for CurrencyCode {}
impl ConvertingToRustEnum<CurrencyCode> for &str {
fn convert(&self) -> CurrencyCode {
let lower_case_currency = &*self.to_ascii_lowercase();
return match lower_case_currency {
"usd" => CurrencyCode::Usd,
"aud" => CurrencyCode::Aud,
"dkk" => CurrencyCode::Dkk,
"eur" => CurrencyCode::Eur,
"gbp" => CurrencyCode::Gbp,
"chf" => CurrencyCode::Chf,
"sek" => CurrencyCode::Sek,
"cad" => CurrencyCode::Cad,
"kwd" => CurrencyCode::Kwd,
"nok" => CurrencyCode::Nok,
"sar" => CurrencyCode::Sar,
"jpy" => CurrencyCode::Jpy,
"bgn" => CurrencyCode::Bgn,
"ron" => CurrencyCode::Ron,
"rub" => CurrencyCode::Rub,
"irr" => CurrencyCode::Irr,
"cny" => CurrencyCode::Cny,
"pkr" => CurrencyCode::Pkr,
_ => CurrencyCode::Qar,
}
}
}
pub struct CurrencyCodes {
pub usd: bool,
pub aud: bool,
pub dkk: bool,
pub eur: bool,
pub gbp: bool,
pub chf: bool,
pub sek: bool,
pub cad: bool,
pub kwd: bool,
pub nok: bool,
pub sar: bool,
pub jpy: bool,
pub bgn: bool,
pub ron: bool,
pub rub: bool,
pub irr: bool,
pub cny: bool,
pub pkr: bool,
pub qar: bool,
}
impl Default for CurrencyCodes {
fn default() -> CurrencyCodes {
CurrencyCodes {
usd: false,
aud: false,
dkk: false,
eur: false,
gbp: false,
chf: false,
sek: false,
cad: false,
kwd: false,
nok: false,
sar: false,
jpy: false,
bgn: false,
ron: false,
rub: false,
irr: false,
cny: false,
pkr: false,
qar: false,
}
}
}
impl CurrencyCodes {
pub fn new() -> CurrencyCodes {
CurrencyCodes {
usd: true,
..Default::default()
}
}
pub fn reset(&mut self) {
*self = CurrencyCodes{
usd: true,
..Default::default()
};
}
pub fn include_all(&mut self) {
self.usd = true;
self.aud = true;
self.dkk = true;
self.eur = true;
self.gbp = true;
self.chf = true;
self.sek = true;
self.cad = true;
self.kwd = true;
self.nok = true;
self.sar = true;
self.jpy = true;
self.bgn = true;
self.ron = true;
self.rub = true;
self.irr = true;
self.cny = true;
self.pkr = true;
self.qar = true;
}
pub fn exclude_all(&mut self) {
*self = CurrencyCodes::default();
}
pub fn is_all_excluded(&self) -> bool {
if self.usd { return false }
if self.aud { return false }
if self.dkk { return false }
if self.eur { return false }
if self.gbp { return false }
if self.chf { return false }
if self.sek { return false }
if self.cad { return false }
if self.kwd { return false }
if self.nok { return false }
if self.sar { return false }
if self.jpy { return false }
if self.bgn { return false }
if self.ron { return false }
if self.rub { return false }
if self.irr { return false }
if self.cny { return false }
if self.pkr { return false }
if self.qar { return false }
true
}
}
impl traits::MakingList for CurrencyCodes {
fn make_required_list(&self) -> Vec<&str> {
let mut currency_codes = Vec::new();
if self.usd { currency_codes.push("USD"); }
if self.aud { currency_codes.push("AUD"); }
if self.dkk { currency_codes.push("DKK"); }
if self.eur { currency_codes.push("EUR"); }
if self.gbp { currency_codes.push("GBP"); }
if self.chf { currency_codes.push("CHF"); }
if self.sek { currency_codes.push("SEK"); }
if self.cad { currency_codes.push("CAD"); }
if self.kwd { currency_codes.push("KWD"); }
if self.nok { currency_codes.push("NOK"); }
if self.sar { currency_codes.push("SAR"); }
if self.jpy { currency_codes.push("JPY"); }
if self.bgn { currency_codes.push("BGN"); }
if self.ron { currency_codes.push("RON"); }
if self.rub { currency_codes.push("RUB"); }
if self.irr { currency_codes.push("IRR"); }
if self.cny { currency_codes.push("CNY"); }
if self.pkr { currency_codes.push("PKR"); }
if self.qar { currency_codes.push("QAR"); }
currency_codes
}
}
pub struct CurrencySeries {
pub ytl_mode: bool,
pub exchange_type: ExchangeType,
pub currency_code: CurrencyCode,
pub date_preference: DatePreference,
}
impl CurrencySeries {
fn generate_series_as_url_format(&self) -> Result<String, ReturnError> {
let exchange_types = self.exchange_type.make_required_list();
let series_format: String;
if exchange_types.is_empty() {
return Err(ReturnError::EmptyExchangeType);
}
if exchange_types.len() == 2 {
series_format =
<Self as MakingUrlFormat>::generate_two_combined_currencies_format(
&<Self as MakingUrlFormat>::generate_currency_format_for_combination(
&self.currency_code.to_string(),
exchange_types[0],
self.ytl_mode
),
&<Self as MakingUrlFormat>::generate_currency_format_for_combination(
&self.currency_code.to_string(),
exchange_types[1],
self.ytl_mode
)
);
}
else {
series_format =
<Self as MakingUrlFormat>::generate_currency_format(
&self.currency_code.to_string(),
exchange_types[0], self.ytl_mode
);
}
Ok(series_format)
}
pub fn from(
exchange_type: ExchangeType,
currency_code: CurrencyCode,
date_preference: DatePreference,
ytl_mode: bool
) -> CurrencySeries {
CurrencySeries {
ytl_mode,
exchange_type,
currency_code,
date_preference,
}
}
pub fn get_data(&self, evds: &common::Evds) -> Result<String, ReturnError> {
let url_root = "https://evds2.tcmb.gov.tr/service/evds/";
let series_format = self.generate_series_as_url_format()?;
let url = format!(
"{}{}&{}&{}&{}",
url_root,
series_format,
self.date_preference.generate_url_format(),
evds.get_return_format_as_url(),
evds.get_api_key_as_url());
currency::make_request(&url)
}
pub fn get_advanced_data(
&self,
evds: &common::Evds,
advanced_processes: &AdvancedProcesses
) -> Result<String, ReturnError> {
let url_root = "https://evds2.tcmb.gov.tr/service/evds/";
if self.exchange_type.are_both_types() {
return Err(ReturnError::SingleExchangeTypeExpected)
}
let series_format = self.generate_series_as_url_format()?;
let url = format!(
"{}{}&{}&{}&{}&{}&{}&{}",
url_root, series_format,
self.date_preference.generate_url_format(),
evds.get_return_format_as_url(),
evds.get_api_key_as_url(),
advanced_processes.get_aggregation_type_as_url_format(),
advanced_processes.get_formula_as_url_format(),
advanced_processes.get_data_frequency_as_url_format()
);
currency::make_request(&url)
}
}
impl traits::MakingUrlFormat for CurrencySeries {}
pub struct MultipleCurrencySeries {
pub ytl_mode: bool,
pub exchange_type: ExchangeType,
pub currency_codes: CurrencyCodes,
pub date_preference: DatePreference,
}
impl MultipleCurrencySeries {
fn generate_multiple_series_as_url_format(&self) -> Result<String, ReturnError> {
let currency_codes = self.currency_codes.make_required_list();
let exchange_types = self.exchange_type.make_required_list();
let series_format: String;
if currency_codes.is_empty() {
return Err(ReturnError::EmptyCurrencyCodes);
}
if exchange_types.is_empty() {
return Err(ReturnError::EmptyExchangeType);
}
if exchange_types.len() == 2 {
series_format = <Self as MakingUrlFormat>::generate_two_combined_currencies_format(
&<Self as MakingUrlFormat>::generate_multiple_currency_format_for_combination(
self.currency_codes.make_required_list(),
exchange_types[0],
self.ytl_mode
),
&<Self as MakingUrlFormat>::generate_multiple_currency_format_for_combination(
self.currency_codes.make_required_list(),
exchange_types[1],
self.ytl_mode
)
);
}
else {
series_format = <Self as MakingUrlFormat>::generate_multiple_currency_format(
self.currency_codes.make_required_list(),
exchange_types[0],
self.ytl_mode
);
}
Ok(series_format)
}
pub fn from(
exchange_type: ExchangeType,
currency_codes: CurrencyCodes,
date_preference: DatePreference,
ytl_mode: bool,
) -> MultipleCurrencySeries {
MultipleCurrencySeries {
ytl_mode,
exchange_type,
currency_codes,
date_preference,
}
}
pub fn get_multiple_data(&self, evds: &common::Evds) -> Result<String, ReturnError> {
let url_root = "https://evds2.tcmb.gov.tr/service/evds/";
let series_format = self.generate_multiple_series_as_url_format()?;
let url = format!(
"{}{}&{}&{}&{}",
url_root, series_format,
self.date_preference.generate_url_format(),
evds.get_return_format_as_url(),
evds.get_api_key_as_url()
);
currency::make_request(&url)
}
}
impl traits::MakingUrlFormat for MultipleCurrencySeries {}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn should_make_default() {
let mut currency_codes = CurrencyCodes {
aud: true,
qar: true,
usd: true,
kwd: true,
..Default::default()
};
currency_codes.sar = true;
assert!(!currency_codes.is_all_excluded());
let currency_codes_list = currency_codes.make_required_list();
for code in currency_codes_list {
println!("{}", &code);
}
}
}