quant_primitives/
symbol.rs1use serde::{Deserialize, Serialize};
4use std::str::FromStr;
5use thiserror::Error;
6
7use crate::crypto_classifier::{is_crypto_base, is_crypto_quote};
8
9#[derive(Debug, Error, PartialEq, Eq)]
11pub enum SymbolError {
12 #[error("invalid symbol format: {0}")]
14 InvalidFormat(String),
15}
16
17#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
19pub struct Symbol {
20 base: String,
21 quote: String,
22}
23
24impl Symbol {
25 pub fn base(&self) -> &str {
27 &self.base
28 }
29
30 pub fn quote(&self) -> &str {
32 &self.quote
33 }
34
35 pub fn canonical(&self) -> String {
37 format!("{}/{}", self.base, self.quote)
38 }
39
40 pub fn is_crypto(&self) -> bool {
49 is_crypto_quote(&self.quote) || is_crypto_base(&self.base)
50 }
51}
52
53impl FromStr for Symbol {
54 type Err = SymbolError;
55
56 fn from_str(s: &str) -> Result<Self, Self::Err> {
57 if let Some((base, quote)) = s.split_once('/') {
59 return Ok(Self {
60 base: base.to_uppercase(),
61 quote: quote.to_uppercase(),
62 });
63 }
64 if let Some((base, quote)) = s.split_once('-') {
66 return Ok(Self {
67 base: base.to_uppercase(),
68 quote: quote.to_uppercase(),
69 });
70 }
71 Err(SymbolError::InvalidFormat(s.to_string()))
72 }
73}
74
75#[cfg(test)]
76#[path = "symbol_tests.rs"]
77mod tests;