rateslib/fx/rates/
fxpair.rs

1use crate::fx::rates::ccy::Ccy;
2use pyo3::exceptions::PyValueError;
3use pyo3::PyErr;
4use serde::{Deserialize, Serialize};
5use std::fmt;
6
7/// A container of a two-pair `Ccy` cross.
8#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
9pub struct FXPair(pub(crate) Ccy, pub(crate) Ccy);
10
11impl FXPair {
12    /// Constructs a new `FXPair`, as a combination of two distinct `Ccy`s.
13    pub fn try_new(lhs: &str, rhs: &str) -> Result<Self, PyErr> {
14        let lhs_ = Ccy::try_new(lhs)?;
15        let rhs_ = Ccy::try_new(rhs)?;
16        if lhs_ == rhs_ {
17            return Err(PyValueError::new_err(
18                "`FXPair` must be created from two distinct currencies, not same.",
19            ));
20        }
21        Ok(FXPair(lhs_, rhs_))
22    }
23}
24
25impl fmt::Display for FXPair {
26    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
27        write!(f, "{}{}", self.0.name, self.1.name)
28    }
29}
30
31#[cfg(test)]
32mod tests {
33    use super::*;
34
35    #[test]
36    fn fxpair_creation() {
37        let a = FXPair::try_new("usd", "eur").unwrap();
38        let b = FXPair::try_new("USD", "EUR").unwrap();
39        assert_eq!(a, b)
40    }
41
42    #[test]
43    fn fxpair_creation_error() {
44        match FXPair::try_new("usd", "USD") {
45            Ok(_) => assert!(false),
46            Err(_) => assert!(true),
47        }
48    }
49}