investments 6.2.0

Helps you with managing your investments
Documentation
use lazy_static::lazy_static;
use regex::Regex;
use validator::ValidationError;

use crate::core::GenericResult;
use crate::types::Decimal;

pub fn get_currency_pair(base: &str, quote: &str) -> String {
    format!("{}/{}", base, quote)
}

pub fn parse_currency_pair(pair: &str) -> GenericResult<(&str, &str)> {
    lazy_static! {
        static ref REGEX: Regex = Regex::new(r"^(?P<base>[A-Z]{3})/(?P<quote>[A-Z]{3})$").unwrap();
    }

    let captures = REGEX.captures(pair).ok_or_else(|| format!(
        "Invalid currency pair: {:?}", pair))?;

    Ok((
        captures.name("base").unwrap().as_str(),
        captures.name("quote").unwrap().as_str(),
    ))
}

pub fn parse_forex_code(code: &str) -> GenericResult<(&str, &str, Option<Decimal>)> {
    lazy_static! {
        static ref CODE_REGEX: Regex = Regex::new(
            r"^(?P<base>[A-Z]{3})(?P<quote>[A-Z]{3})_(?:TOD|TOM)$").unwrap();
    }

    let (base, quote, lot_size) = match code {
        "USD000000TOD" | "USD000UTSTOM" => ("USD", "RUB", Some(dec!(1000))),
        "EUR_RUB__TOD" | "EUR_RUB__TOM" => ("EUR", "RUB", Some(dec!(1000))),
        _ => {
            let captures = CODE_REGEX.captures(code).ok_or_else(|| format!(
                "Unsupported forex pair code: {:?}", code))?;
            (
                captures.name("base").unwrap().as_str(),
                captures.name("quote").unwrap().as_str(),
                None,
            )
        },
    };

    Ok((base, quote, lot_size))
}

pub fn validate_currency_pair(pair: &str) -> Result<(), ValidationError> {
    parse_currency_pair(pair).map(|_| ()).map_err(|_|
        ValidationError::new("Invalid currency pair"))
}

pub fn validate_currency_pair_list<P, I>(pairs: P) -> Result<(), ValidationError>
    where
        P: IntoIterator<Item = I>,
        I: AsRef<str>,
{
    for pair in pairs.into_iter() {
        validate_currency_pair(pair.as_ref())?;
    }
    Ok(())
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn forex_code_parsing() {
        assert_eq!(
            parse_forex_code("HKDRUB_TOM").unwrap(),
            ("HKD", "RUB", None),
        );
    }
}