alpm_types/
system.rs

1use std::str::FromStr;
2
3use alpm_parsers::iter_str_context;
4use serde::{Deserialize, Serialize};
5use strum::{Display, EnumString, VariantNames};
6use winnow::{ModalResult, Parser, combinator::cut_err, error::StrContext, token::rest};
7
8/// CPU architecture
9///
10/// Members of the Architecture enum can be created from `&str`.
11///
12/// ## Examples
13/// ```
14/// use std::str::FromStr;
15///
16/// use alpm_types::Architecture;
17///
18/// // create Architecture from str
19/// assert_eq!(Architecture::from_str("aarch64"), Ok(Architecture::Aarch64));
20///
21/// // format as String
22/// assert_eq!("aarch64", format!("{}", Architecture::Aarch64));
23/// assert_eq!("any", format!("{}", Architecture::Any));
24/// assert_eq!("arm", format!("{}", Architecture::Arm));
25/// assert_eq!("armv6h", format!("{}", Architecture::Armv6h));
26/// assert_eq!("armv7h", format!("{}", Architecture::Armv7h));
27/// assert_eq!("i386", format!("{}", Architecture::I386));
28/// assert_eq!("i486", format!("{}", Architecture::I486));
29/// assert_eq!("i686", format!("{}", Architecture::I686));
30/// assert_eq!("pentium4", format!("{}", Architecture::Pentium4));
31/// assert_eq!("riscv32", format!("{}", Architecture::Riscv32));
32/// assert_eq!("riscv64", format!("{}", Architecture::Riscv64));
33/// assert_eq!("x86_64", format!("{}", Architecture::X86_64));
34/// assert_eq!("x86_64_v2", format!("{}", Architecture::X86_64V2));
35/// assert_eq!("x86_64_v3", format!("{}", Architecture::X86_64V3));
36/// assert_eq!("x86_64_v4", format!("{}", Architecture::X86_64V4));
37/// ```
38#[derive(
39    Clone,
40    Copy,
41    Debug,
42    Deserialize,
43    Display,
44    EnumString,
45    Eq,
46    Hash,
47    Ord,
48    PartialEq,
49    PartialOrd,
50    Serialize,
51    VariantNames,
52)]
53#[strum(serialize_all = "lowercase")]
54#[serde(rename_all = "lowercase")]
55pub enum Architecture {
56    /// ARMv8 64-bit
57    Aarch64,
58    /// Any architecture
59    Any,
60    /// ARM
61    Arm,
62    /// ARMv6 hard-float
63    Armv6h,
64    /// ARMv7 hard-float
65    Armv7h,
66    /// Intel 386
67    I386,
68    /// Intel 486
69    I486,
70    /// Intel 686
71    I686,
72    /// Intel Pentium 4
73    Pentium4,
74    /// RISC-V 32-bit
75    Riscv32,
76    /// RISC-V 64-bit
77    Riscv64,
78    /// Intel x86_64
79    X86_64,
80    /// Intel x86_64 version 2
81    #[strum(to_string = "x86_64_v2")]
82    X86_64V2,
83    /// Intel x86_64 version 3
84    #[strum(to_string = "x86_64_v3")]
85    X86_64V3,
86    /// Intel x86_64 version 4
87    #[strum(to_string = "x86_64_v4")]
88    X86_64V4,
89}
90
91impl Architecture {
92    /// Recognizes an [`Architecture`] in an input string.
93    ///
94    /// Consumes all input and returns an error if the string doesn't match any architecture.
95    pub fn parser(input: &mut &str) -> ModalResult<Architecture> {
96        cut_err(rest.try_map(Architecture::from_str))
97            .context(StrContext::Label("architecture"))
98            .context_with(iter_str_context!([Architecture::VARIANTS]))
99            .parse_next(input)
100    }
101}
102
103/// ELF architecture format.
104///
105/// This enum represents the _Class_ field in the [_ELF Header_].
106///
107/// ## Examples
108///
109/// ```
110/// use std::str::FromStr;
111///
112/// use alpm_types::ElfArchitectureFormat;
113///
114/// # fn main() -> Result<(), alpm_types::Error> {
115/// // create ElfArchitectureFormat from str
116/// assert_eq!(
117///     ElfArchitectureFormat::from_str("32"),
118///     Ok(ElfArchitectureFormat::Bit32)
119/// );
120/// assert_eq!(
121///     ElfArchitectureFormat::from_str("64"),
122///     Ok(ElfArchitectureFormat::Bit64)
123/// );
124///
125/// // format as String
126/// assert_eq!("32", format!("{}", ElfArchitectureFormat::Bit32));
127/// assert_eq!("64", format!("{}", ElfArchitectureFormat::Bit64));
128/// # Ok(())
129/// # }
130/// ```
131///
132/// [_ELF Header_]: https://en.wikipedia.org/wiki/Executable_and_Linkable_Format#ELF_header
133#[derive(
134    Clone, Copy, Debug, Deserialize, Display, EnumString, Eq, Ord, PartialEq, PartialOrd, Serialize,
135)]
136#[strum(serialize_all = "lowercase")]
137pub enum ElfArchitectureFormat {
138    /// 32-bit
139    #[strum(to_string = "32")]
140    Bit32 = 32,
141    /// 64-bit
142    #[strum(to_string = "64")]
143    Bit64 = 64,
144}
145
146#[cfg(test)]
147mod tests {
148    use std::str::FromStr;
149
150    use rstest::rstest;
151    use strum::ParseError;
152    use winnow::error::ContextError;
153
154    use super::*;
155
156    #[rstest]
157    #[case("aarch64", Ok(Architecture::Aarch64))]
158    #[case("any", Ok(Architecture::Any))]
159    #[case("arm", Ok(Architecture::Arm))]
160    #[case("armv6h", Ok(Architecture::Armv6h))]
161    #[case("armv7h", Ok(Architecture::Armv7h))]
162    #[case("i386", Ok(Architecture::I386))]
163    #[case("i486", Ok(Architecture::I486))]
164    #[case("i686", Ok(Architecture::I686))]
165    #[case("pentium4", Ok(Architecture::Pentium4))]
166    #[case("riscv32", Ok(Architecture::Riscv32))]
167    #[case("riscv64", Ok(Architecture::Riscv64))]
168    #[case("x86_64", Ok(Architecture::X86_64))]
169    #[case("x86_64_v2", Ok(Architecture::X86_64V2))]
170    #[case("x86_64_v3", Ok(Architecture::X86_64V3))]
171    #[case("x86_64_v4", Ok(Architecture::X86_64V4))]
172    #[case("foo", Err(ParseError::VariantNotFound))]
173    fn architecture_from_string(#[case] s: &str, #[case] arch: Result<Architecture, ParseError>) {
174        assert_eq!(Architecture::from_str(s), arch);
175    }
176
177    #[rstest]
178    #[case("aarch64", Ok(Architecture::Aarch64))]
179    #[case("any", Ok(Architecture::Any))]
180    #[case("arm", Ok(Architecture::Arm))]
181    #[case("armv6h", Ok(Architecture::Armv6h))]
182    #[case("armv7h", Ok(Architecture::Armv7h))]
183    #[case("i386", Ok(Architecture::I386))]
184    #[case("i486", Ok(Architecture::I486))]
185    #[case("i686", Ok(Architecture::I686))]
186    #[case("pentium4", Ok(Architecture::Pentium4))]
187    #[case("riscv32", Ok(Architecture::Riscv32))]
188    #[case("riscv64", Ok(Architecture::Riscv64))]
189    #[case("x86_64", Ok(Architecture::X86_64))]
190    #[case("x86_64_v2", Ok(Architecture::X86_64V2))]
191    #[case("x86_64_v3", Ok(Architecture::X86_64V3))]
192    #[case("x86_64_v4", Ok(Architecture::X86_64V4))]
193    fn architecture_parser(
194        #[case] s: &str,
195        #[case] arch: Result<Architecture, winnow::error::ParseError<&str, ContextError>>,
196    ) {
197        assert_eq!(Architecture::parser.parse(s), arch);
198    }
199
200    #[rstest]
201    #[case(Architecture::Aarch64, "aarch64")]
202    #[case(Architecture::Any, "any")]
203    #[case(Architecture::Arm, "arm")]
204    #[case(Architecture::Armv6h, "armv6h")]
205    #[case(Architecture::Armv7h, "armv7h")]
206    #[case(Architecture::I386, "i386")]
207    #[case(Architecture::I486, "i486")]
208    #[case(Architecture::I686, "i686")]
209    #[case(Architecture::Pentium4, "pentium4")]
210    #[case(Architecture::Riscv32, "riscv32")]
211    #[case(Architecture::Riscv64, "riscv64")]
212    #[case(Architecture::X86_64, "x86_64")]
213    #[case(Architecture::X86_64V2, "x86_64_v2")]
214    #[case(Architecture::X86_64V3, "x86_64_v3")]
215    #[case(Architecture::X86_64V4, "x86_64_v4")]
216    fn architecture_format_string(#[case] arch: Architecture, #[case] arch_str: &str) {
217        assert_eq!(arch_str, format!("{arch}"));
218    }
219
220    #[rstest]
221    #[case("32", Ok(ElfArchitectureFormat::Bit32))]
222    #[case("64", Ok(ElfArchitectureFormat::Bit64))]
223    #[case("foo", Err(ParseError::VariantNotFound))]
224    fn elf_architecture_format_from_string(
225        #[case] s: &str,
226        #[case] arch: Result<ElfArchitectureFormat, ParseError>,
227    ) {
228        assert_eq!(ElfArchitectureFormat::from_str(s), arch);
229    }
230
231    #[rstest]
232    #[case(ElfArchitectureFormat::Bit32, "32")]
233    #[case(ElfArchitectureFormat::Bit64, "64")]
234    fn elf_architecture_format_display(
235        #[case] arch: ElfArchitectureFormat,
236        #[case] arch_str: &str,
237    ) {
238        assert_eq!(arch_str, format!("{arch}"));
239    }
240}