1use std::str::FromStr;
2
3use alpm_parsers::iter_str_context;
4use serde::{Deserialize, Serialize};
5use strum::{Display, EnumString, VariantNames};
6use winnow::{
7 ModalResult,
8 Parser,
9 combinator::cut_err,
10 error::{StrContext, StrContextValue},
11 token::rest,
12};
13
14#[derive(
45 Clone,
46 Copy,
47 Debug,
48 Deserialize,
49 Display,
50 EnumString,
51 Eq,
52 Hash,
53 Ord,
54 PartialEq,
55 PartialOrd,
56 Serialize,
57 VariantNames,
58)]
59#[strum(serialize_all = "lowercase")]
60#[serde(rename_all = "lowercase")]
61pub enum Architecture {
62 Aarch64,
64 Any,
66 Arm,
68 Armv6h,
70 Armv7h,
72 I386,
74 I486,
76 I686,
78 Pentium4,
80 Riscv32,
82 Riscv64,
84 X86_64,
86 #[strum(to_string = "x86_64_v2")]
88 X86_64V2,
89 #[strum(to_string = "x86_64_v3")]
91 X86_64V3,
92 #[strum(to_string = "x86_64_v4")]
94 X86_64V4,
95}
96
97impl Architecture {
98 pub fn parser(input: &mut &str) -> ModalResult<Architecture> {
102 cut_err(rest.try_map(Architecture::from_str))
103 .context(StrContext::Label("architecture"))
104 .context(StrContext::Expected(StrContextValue::Description(
105 "an alpm-architecture:",
106 )))
107 .context_with(iter_str_context!([Architecture::VARIANTS]))
108 .parse_next(input)
109 }
110}
111
112#[derive(
143 Clone, Copy, Debug, Deserialize, Display, EnumString, Eq, Ord, PartialEq, PartialOrd, Serialize,
144)]
145#[strum(serialize_all = "lowercase")]
146pub enum ElfArchitectureFormat {
147 #[strum(to_string = "32")]
149 Bit32 = 32,
150 #[strum(to_string = "64")]
152 Bit64 = 64,
153}
154
155#[cfg(test)]
156mod tests {
157 use std::str::FromStr;
158
159 use rstest::rstest;
160 use strum::ParseError;
161 use winnow::error::ContextError;
162
163 use super::*;
164
165 #[rstest]
166 #[case("aarch64", Ok(Architecture::Aarch64))]
167 #[case("any", Ok(Architecture::Any))]
168 #[case("arm", Ok(Architecture::Arm))]
169 #[case("armv6h", Ok(Architecture::Armv6h))]
170 #[case("armv7h", Ok(Architecture::Armv7h))]
171 #[case("i386", Ok(Architecture::I386))]
172 #[case("i486", Ok(Architecture::I486))]
173 #[case("i686", Ok(Architecture::I686))]
174 #[case("pentium4", Ok(Architecture::Pentium4))]
175 #[case("riscv32", Ok(Architecture::Riscv32))]
176 #[case("riscv64", Ok(Architecture::Riscv64))]
177 #[case("x86_64", Ok(Architecture::X86_64))]
178 #[case("x86_64_v2", Ok(Architecture::X86_64V2))]
179 #[case("x86_64_v3", Ok(Architecture::X86_64V3))]
180 #[case("x86_64_v4", Ok(Architecture::X86_64V4))]
181 #[case("foo", Err(ParseError::VariantNotFound))]
182 fn architecture_from_string(#[case] s: &str, #[case] arch: Result<Architecture, ParseError>) {
183 assert_eq!(Architecture::from_str(s), arch);
184 }
185
186 #[rstest]
187 #[case("aarch64", Ok(Architecture::Aarch64))]
188 #[case("any", Ok(Architecture::Any))]
189 #[case("arm", Ok(Architecture::Arm))]
190 #[case("armv6h", Ok(Architecture::Armv6h))]
191 #[case("armv7h", Ok(Architecture::Armv7h))]
192 #[case("i386", Ok(Architecture::I386))]
193 #[case("i486", Ok(Architecture::I486))]
194 #[case("i686", Ok(Architecture::I686))]
195 #[case("pentium4", Ok(Architecture::Pentium4))]
196 #[case("riscv32", Ok(Architecture::Riscv32))]
197 #[case("riscv64", Ok(Architecture::Riscv64))]
198 #[case("x86_64", Ok(Architecture::X86_64))]
199 #[case("x86_64_v2", Ok(Architecture::X86_64V2))]
200 #[case("x86_64_v3", Ok(Architecture::X86_64V3))]
201 #[case("x86_64_v4", Ok(Architecture::X86_64V4))]
202 fn architecture_parser(
203 #[case] s: &str,
204 #[case] arch: Result<Architecture, winnow::error::ParseError<&str, ContextError>>,
205 ) {
206 assert_eq!(Architecture::parser.parse(s), arch);
207 }
208
209 #[rstest]
210 #[case(Architecture::Aarch64, "aarch64")]
211 #[case(Architecture::Any, "any")]
212 #[case(Architecture::Arm, "arm")]
213 #[case(Architecture::Armv6h, "armv6h")]
214 #[case(Architecture::Armv7h, "armv7h")]
215 #[case(Architecture::I386, "i386")]
216 #[case(Architecture::I486, "i486")]
217 #[case(Architecture::I686, "i686")]
218 #[case(Architecture::Pentium4, "pentium4")]
219 #[case(Architecture::Riscv32, "riscv32")]
220 #[case(Architecture::Riscv64, "riscv64")]
221 #[case(Architecture::X86_64, "x86_64")]
222 #[case(Architecture::X86_64V2, "x86_64_v2")]
223 #[case(Architecture::X86_64V3, "x86_64_v3")]
224 #[case(Architecture::X86_64V4, "x86_64_v4")]
225 fn architecture_format_string(#[case] arch: Architecture, #[case] arch_str: &str) {
226 assert_eq!(arch_str, format!("{arch}"));
227 }
228
229 #[rstest]
230 #[case("32", Ok(ElfArchitectureFormat::Bit32))]
231 #[case("64", Ok(ElfArchitectureFormat::Bit64))]
232 #[case("foo", Err(ParseError::VariantNotFound))]
233 fn elf_architecture_format_from_string(
234 #[case] s: &str,
235 #[case] arch: Result<ElfArchitectureFormat, ParseError>,
236 ) {
237 assert_eq!(ElfArchitectureFormat::from_str(s), arch);
238 }
239
240 #[rstest]
241 #[case(ElfArchitectureFormat::Bit32, "32")]
242 #[case(ElfArchitectureFormat::Bit64, "64")]
243 fn elf_architecture_format_display(
244 #[case] arch: ElfArchitectureFormat,
245 #[case] arch_str: &str,
246 ) {
247 assert_eq!(arch_str, format!("{arch}"));
248 }
249}