three_commas_types/
pair.rs

1use std::{borrow::Cow, fmt};
2
3use serde::{de::Error, Deserialize, Serialize};
4use smol_str::SmolStr;
5
6#[derive(Debug, Clone, PartialEq, Eq, Hash)]
7pub struct Pair {
8  quote: SmolStr,
9  base: SmolStr,
10}
11
12impl fmt::Display for Pair {
13  fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
14    write!(f, "{}/{}", &*self.base, &*self.quote)
15  }
16}
17
18impl Pair {
19  pub fn new(base: impl AsRef<str>, quote: impl AsRef<str>) -> Self {
20    Pair {
21      quote: SmolStr::new(quote),
22      base: SmolStr::new(base),
23    }
24  }
25
26  #[inline]
27  pub fn quote(&self) -> &str {
28    &*self.quote
29  }
30
31  #[inline]
32  pub fn base(&self) -> &str {
33    &*self.base
34  }
35}
36
37impl Serialize for Pair {
38  fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
39  where
40    S: serde::Serializer,
41  {
42    let mut s = String::with_capacity(self.base.len() + self.quote.len() + 1);
43    s.push_str(&self.quote);
44    s.push('_');
45    s.push_str(&self.base);
46
47    s.serialize(serializer)
48  }
49}
50
51impl<'de> Deserialize<'de> for Pair {
52  fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
53  where
54    D: serde::Deserializer<'de>,
55  {
56    let pair = <Cow<str> as Deserialize>::deserialize(deserializer)?;
57    match pair.split_once('_') {
58      Some((quote, base)) => Ok(Pair {
59        quote: quote.into(),
60        base: base.into(),
61      }),
62      None => Err(<D::Error as Error>::custom(format!(
63        "Expected 3commas pair string on the format of QUOTE_BASE, but got '{}'",
64        pair
65      ))),
66    }
67  }
68}
69
70#[cfg(test)]
71mod tests {
72  use super::*;
73
74  #[test]
75  fn roundtrip() {
76    let json = "\"USDT_ETH\"";
77    let pair: Pair = serde_json::from_str(json).expect("parsed successfully");
78
79    assert_eq!(pair.base(), "ETH", "base");
80    assert_eq!(pair.quote(), "USDT", "quote");
81    assert_eq!(format!("{}", pair), "ETH/USDT");
82
83    let serialized = serde_json::to_string(&pair).expect("serialized successfully");
84    assert_eq!(serialized, json);
85  }
86}