fugue_arch/
lib.rs

1use fugue_bytes::endian::Endian;
2
3use std::fmt;
4use std::str::FromStr;
5
6use thiserror::Error;
7
8#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
9#[derive(serde::Deserialize, serde::Serialize)]
10pub struct ArchitectureDef {
11    processor: String,
12    endian: Endian,
13    bits: usize,
14    variant: String,
15}
16
17#[derive(Debug, Error)]
18pub enum ArchDefParseError {
19    #[error("could not parse processor name")]
20    ParseProcessor,
21    #[error("could not parse endian")]
22    ParseEndian,
23    #[error("could not parse bitness")]
24    ParseBits,
25    #[error("could not parse processor variant")]
26    ParseVariant,
27    #[error("could not parse architecture definition: incorrect format")]
28    ParseFormat,
29}
30
31impl FromStr for ArchitectureDef {
32    type Err = ArchDefParseError;
33
34    fn from_str(s: &str) -> Result<Self, Self::Err> {
35        let parts = s.splitn(4, ':').collect::<Vec<_>>();
36        if !matches!(parts.len(), 3 | 4) {
37            return Err(ArchDefParseError::ParseFormat);
38        }
39
40        let processor = parts[0];
41        let endian = match parts[1] {
42            "le" | "LE" => Endian::Little,
43            "be" | "BE" => Endian::Big,
44            _ => return Err(ArchDefParseError::ParseEndian),
45        };
46        let bits = parts[2]
47            .parse::<usize>()
48            .map_err(|_| ArchDefParseError::ParseBits)?;
49
50        Ok(ArchitectureDef::new(
51            processor,
52            endian,
53            bits,
54            *parts.get(3).unwrap_or(&"default"),
55        ))
56    }
57}
58
59impl fmt::Display for ArchitectureDef {
60    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
61        write!(
62            f,
63            "processor: {}, endian: {}, bits: {}, variant: {}",
64            self.processor,
65            if self.endian.is_big() { "big" } else { "little" },
66            self.bits,
67            self.variant,
68        )
69    }
70}
71
72impl ArchitectureDef {
73    pub fn new<P, V>(processor: P, endian: Endian, bits: usize, variant: V) -> Self
74    where P: Into<String>,
75          V: Into<String> {
76        Self {
77            processor: processor.into(),
78            endian,
79            bits,
80            variant: variant.into(),
81        }
82    }
83
84    pub fn is_little(&self) -> bool {
85        self.endian.is_little()
86    }
87
88    pub fn is_big(&self) -> bool {
89        self.endian.is_big()
90    }
91
92    pub fn endian(&self) -> Endian {
93        self.endian
94    }
95
96    pub fn bits(&self) -> usize {
97        self.bits
98    }
99
100    pub fn processor(&self) -> &str {
101        &self.processor
102    }
103
104    pub fn variant(&self) -> &str {
105        &self.variant
106    }
107}