sonatina_triple/
lib.rs

1use std::fmt::{Display, Formatter};
2
3use thiserror::Error;
4
5#[derive(Debug, Clone, PartialEq, Eq)]
6pub struct TargetTriple {
7    pub architecture: Architecture,
8    pub chain: Chain,
9    pub version: Version,
10}
11
12impl TargetTriple {
13    pub fn new(architecture: Architecture, chain: Chain, version: Version) -> Self {
14        Self {
15            architecture,
16            chain,
17            version,
18        }
19    }
20    pub fn parse(s: &str) -> Result<Self, InvalidTriple> {
21        let mut triple = s.split('-');
22
23        let arch = Architecture::parse(triple.next().ok_or(InvalidTriple::InvalidFormat(s))?)?;
24        let chain = Chain::parse(triple.next().ok_or(InvalidTriple::InvalidFormat(s))?)?;
25        let version = Version::parse(
26            arch,
27            chain,
28            triple.next().ok_or(InvalidTriple::InvalidFormat(s))?,
29        )?;
30
31        if triple.next().is_none() {
32            Ok(Self::new(arch, chain, version))
33        } else {
34            Err(InvalidTriple::InvalidFormat(s))
35        }
36    }
37}
38
39impl Display for TargetTriple {
40    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
41        write!(f, "{}-{}-{}", self.architecture, self.chain, self.version)
42    }
43}
44
45#[derive(Debug, Clone, Copy, PartialEq, Eq)]
46pub enum Architecture {
47    Evm,
48}
49
50impl Architecture {
51    fn parse(s: &str) -> Result<Self, InvalidTriple> {
52        match s {
53            "evm" => Ok(Self::Evm),
54            _ => Err(InvalidTriple::ArchitectureNotSupported),
55        }
56    }
57}
58
59impl Display for Architecture {
60    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
61        match self {
62            Self::Evm => write!(f, "evm"),
63        }
64    }
65}
66
67#[derive(Debug, Clone, Copy, PartialEq, Eq)]
68pub enum Chain {
69    Ethereum,
70}
71
72impl Chain {
73    fn parse(s: &str) -> Result<Self, InvalidTriple> {
74        match s {
75            "ethereum" => Ok(Chain::Ethereum),
76            _ => Err(InvalidTriple::ChainNotSupported),
77        }
78    }
79}
80
81impl Display for Chain {
82    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
83        match self {
84            Chain::Ethereum => write!(f, "ethereum"),
85        }
86    }
87}
88
89#[derive(Debug, Clone, Copy, PartialEq, Eq)]
90pub enum Version {
91    EvmVersion(EvmVersion),
92}
93
94impl Version {
95    fn parse(arch: Architecture, chain: Chain, s: &str) -> Result<Self, InvalidTriple> {
96        match (arch, chain) {
97            (Architecture::Evm, Chain::Ethereum) => {
98                let evm_version = match s {
99                    "frontier" => EvmVersion::Frontier,
100                    "homestead" => EvmVersion::Homestead,
101                    "byzantium" => EvmVersion::Byzantium,
102                    "constantinople" => EvmVersion::Constantinople,
103                    "istanbul" => EvmVersion::Istanbul,
104                    "london" => EvmVersion::London,
105                    _ => return Err(InvalidTriple::VersionNotSupported),
106                };
107                Ok(Self::EvmVersion(evm_version))
108            }
109        }
110    }
111}
112
113impl Display for Version {
114    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
115        match self {
116            Self::EvmVersion(evm_version) => write!(f, "{}", evm_version),
117        }
118    }
119}
120
121#[derive(Debug, Clone, Copy, PartialEq, Eq)]
122pub enum EvmVersion {
123    Frontier,
124    Homestead,
125    Byzantium,
126    Constantinople,
127    Istanbul,
128    London,
129}
130#[derive(Debug, Clone, Copy, Error)]
131pub enum InvalidTriple<'a> {
132    #[error("the format of triple must be `architecture-chain-version: but got `{0}`")]
133    InvalidFormat(&'a str),
134
135    #[error("given architecture is not supported")]
136    ArchitectureNotSupported,
137
138    #[error("given chain is not supported")]
139    ChainNotSupported,
140
141    #[error("given version is not supported")]
142    VersionNotSupported,
143
144    #[error("given triple consists of invalid combination")]
145    InvalidCombination,
146}
147
148impl Display for EvmVersion {
149    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
150        match self {
151            Self::Frontier => write!(f, "frontier"),
152            Self::Homestead => write!(f, "homestead"),
153            Self::Byzantium => write!(f, "byzantium"),
154            Self::Constantinople => write!(f, "constantinople"),
155            Self::Istanbul => write!(f, "istanbul"),
156            Self::London => write!(f, "london"),
157        }
158    }
159}
160
161#[cfg(test)]
162mod tests {
163    use super::*;
164
165    #[test]
166    fn test() {
167        let target = "evm-ethereum-istanbul";
168        let triple = TargetTriple::parse(target).unwrap();
169
170        assert_eq!(triple.architecture, Architecture::Evm);
171        assert_eq!(triple.chain, Chain::Ethereum);
172        assert_eq!(triple.version, Version::EvmVersion(EvmVersion::Istanbul));
173    }
174}