1use serde::{Deserialize, Serialize};
2
3use crate::{Currency, Exchange};
4
5#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
7pub struct Symbol {
8 pub eg: Exchange,
9 pub bs: Currency, pub qt: Currency, }
12
13impl Symbol {
14 pub fn new(eg: Exchange, cb: Currency, cq: Currency) -> Self {
15 Self {
16 eg,
17 bs: cb.to_uppercase(),
18 qt: cq.to_uppercase(),
19 }
20 }
21}
22
23impl std::fmt::Display for Symbol {
24 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
25 write!(f, "{}:{}/{}", self.eg, self.bs, self.qt)
26 }
27}
28
29#[derive(thiserror::Error, Debug)]
30pub enum SymbolError {
31 #[error("bad symbol {0}")]
32 BadSymbol(String),
33}
34
35impl TryFrom<(Exchange, &str)> for Symbol {
36 type Error = SymbolError;
37
38 fn try_from((eg, text): (Exchange, &str)) -> Result<Self, Self::Error> {
39 let parts1 = text.split('/').collect::<Vec<&str>>();
40 if parts1.len() != 2 {
41 return Err(SymbolError::BadSymbol(text.to_string()));
42 }
43 let cb = parts1[0];
44 let cq = parts1[1];
45 Ok(Self::new(eg, cb.to_string(), cq.to_string()))
46 }
47}
48
49impl TryFrom<&str> for Symbol {
50 type Error = SymbolError;
51
52 fn try_from(text: &str) -> Result<Self, Self::Error> {
53 let parts0 = text.split(':').collect::<Vec<&str>>();
54 if parts0.len() != 2 {
55 return Err(SymbolError::BadSymbol(text.to_string()));
56 }
57 Self::try_from((parts0[0].to_string(), parts0[1]))
58 }
59}
60
61impl TryFrom<String> for Symbol {
62 type Error = SymbolError;
63
64 fn try_from(text: String) -> Result<Self, Self::Error> {
65 Self::try_from(text.as_str())
66 }
67}