eosio_core/
symbol_code.rs

1//! TODO docs
2
3use crate::{ScopeName, Symbol};
4use eosio_bytes::{NumBytes, Read, Write};
5use eosio_numstr::{symbol_from_str, symbol_to_string, symbol_to_utf8};
6use std::convert::TryFrom;
7use std::fmt;
8use std::str::FromStr;
9
10pub use eosio_numstr::ParseSymbolError;
11
12/// TODO docs
13#[derive(
14    Debug,
15    PartialEq,
16    Eq,
17    Clone,
18    Copy,
19    Default,
20    Read,
21    Write,
22    NumBytes,
23    Hash,
24    PartialOrd,
25    Ord,
26)]
27#[eosio_bytes_root_path = "::eosio_bytes"]
28pub struct SymbolCode(u64);
29
30impl From<u64> for SymbolCode {
31    #[inline]
32    fn from(n: u64) -> Self {
33        Self(n)
34    }
35}
36
37impl From<SymbolCode> for u64 {
38    #[inline]
39    fn from(s: SymbolCode) -> Self {
40        s.0
41    }
42}
43
44impl From<SymbolCode> for [u8; 7] {
45    #[inline]
46    fn from(s: SymbolCode) -> Self {
47        symbol_to_utf8(s.0)
48    }
49}
50
51impl From<SymbolCode> for ScopeName {
52    #[inline]
53    fn from(symbol: SymbolCode) -> Self {
54        let value: u64 = symbol.into();
55        value.into()
56    }
57}
58
59impl From<ScopeName> for SymbolCode {
60    #[inline]
61    fn from(scope: ScopeName) -> Self {
62        let value: u64 = scope.into();
63        value.into()
64    }
65}
66
67impl fmt::Display for SymbolCode {
68    #[inline]
69    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
70        write!(f, "{}", symbol_to_string(self.0 << 8))
71    }
72}
73
74impl SymbolCode {
75    /// TODO docs
76    #[inline]
77    pub fn is_valid(&self) -> bool {
78        let chars = symbol_to_utf8(self.0);
79        for &c in &chars {
80            if c == b' ' {
81                continue;
82            }
83            if !(b'A' <= c && c <= b'Z') {
84                return false;
85            }
86        }
87        true
88    }
89
90    /// TODO docs
91    #[inline]
92    pub const fn as_u64(&self) -> u64 {
93        self.0
94    }
95}
96
97impl TryFrom<&str> for SymbolCode {
98    type Error = ParseSymbolError;
99    #[inline]
100    fn try_from(value: &str) -> Result<Self, Self::Error> {
101        let symbol: Symbol = symbol_from_str(0, value)?.into();
102        Ok(symbol.code())
103    }
104}
105
106impl TryFrom<String> for SymbolCode {
107    type Error = ParseSymbolError;
108    #[inline]
109    fn try_from(value: String) -> Result<Self, Self::Error> {
110        Self::try_from(value.as_str())
111    }
112}
113
114impl FromStr for SymbolCode {
115    type Err = ParseSymbolError;
116    #[inline]
117    fn from_str(s: &str) -> Result<Self, Self::Err> {
118        Self::try_from(s)
119    }
120}
121
122#[cfg(test)]
123mod tests {
124    use super::*;
125    use eosio_numstr::symbol_code;
126    use eosio_numstr_macros::s;
127
128    macro_rules! test_to_string {
129        ($($name:ident, $value:expr, $expected:expr)*) => ($(
130            #[test]
131            fn $name() {
132                assert_eq!(
133                    SymbolCode::from(symbol_code($value)).to_string(),
134                    $expected
135                );
136            }
137        )*)
138    }
139
140    test_to_string! {
141        to_string, s!(4, EOS), "EOS"
142        to_string_zero_precision, s!(0, TGFT), "TGFT"
143        to_string_nine_precision, s!(9, SYS), "SYS"
144    }
145
146    macro_rules! test_from_str_ok {
147        ($($name:ident, $input:expr, $expected:expr)*) => ($(
148            #[test]
149            fn $name() {
150                let ok = Ok(Symbol::from($expected).code());
151                assert_eq!(SymbolCode::from_str($input), ok);
152                assert_eq!(SymbolCode::try_from($input), ok);
153            }
154        )*)
155    }
156
157    test_from_str_ok! {
158        from_str_ok1, "TST", s!(0, TST)
159        from_str_ok2, "EOS", s!(4, EOS)
160        from_str_ok3, "TGFT", s!(0, TGFT)
161    }
162
163    macro_rules! test_from_str_err {
164        ($($name:ident, $input:expr, $expected:expr)*) => ($(
165            #[test]
166            fn $name() {
167            let err = Err($expected);
168            assert_eq!(SymbolCode::from_str($input), err);
169            assert_eq!(SymbolCode::try_from($input), err);
170            }
171        )*)
172    }
173
174    test_from_str_err! {
175        from_str_bad_char,
176        "tst",
177        ParseSymbolError::BadChar('t')
178    }
179
180}