Skip to main content

horto_os_ui_shared/remote/
arch.rs

1//! Map box `uname -m` to GitHub Release target triples.
2
3use crate::error::{HortoError, Result};
4
5/// Box architecture labels used for Release assets and local cache paths.
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
7pub enum BoxArch {
8    /// `x86_64` / amd64.
9    Amd64,
10    /// `aarch64` / arm64.
11    Arm64,
12}
13
14impl BoxArch {
15    /// Rust target triple for Release tar.gz assets.
16    #[must_use]
17    pub const fn target_triple(self) -> &'static str {
18        match self {
19            Self::Amd64 => "x86_64-unknown-linux-gnu",
20            Self::Arm64 => "aarch64-unknown-linux-gnu",
21        }
22    }
23
24    /// Short arch label used in cache directories.
25    #[must_use]
26    pub const fn cache_label(self) -> &'static str {
27        match self {
28            Self::Amd64 => "amd64",
29            Self::Arm64 => "arm64",
30        }
31    }
32}
33
34/// Parse `uname -m` output into a supported box architecture.
35///
36/// # Errors
37///
38/// Returns [`crate::HortoError::Message`] when the machine string is empty or unsupported.
39pub fn box_arch_from_uname(uname_m: &str) -> Result<BoxArch> {
40    let trimmed = uname_m.trim();
41    match trimmed {
42        "x86_64" | "amd64" => Ok(BoxArch::Amd64),
43        "aarch64" | "arm64" => Ok(BoxArch::Arm64),
44        "" => Err(HortoError::msg("empty uname -m from remote host")),
45        other => Err(HortoError::msg(format!(
46            "unsupported box architecture: {other} (need x86_64 or aarch64)"
47        ))),
48    }
49}
50
51#[cfg(test)]
52mod tests {
53    use super::*;
54
55    #[test]
56    fn maps_common_unames() {
57        assert_eq!(box_arch_from_uname("x86_64\n").unwrap(), BoxArch::Amd64);
58        assert_eq!(box_arch_from_uname("amd64").unwrap(), BoxArch::Amd64);
59        assert_eq!(box_arch_from_uname("aarch64").unwrap(), BoxArch::Arm64);
60        assert_eq!(box_arch_from_uname("arm64").unwrap(), BoxArch::Arm64);
61    }
62
63    #[test]
64    fn rejects_unknown() {
65        assert!(box_arch_from_uname("riscv64").is_err());
66        assert!(box_arch_from_uname("").is_err());
67    }
68
69    #[test]
70    fn triples_match_release_assets() {
71        assert_eq!(BoxArch::Amd64.target_triple(), "x86_64-unknown-linux-gnu");
72        assert_eq!(BoxArch::Arm64.target_triple(), "aarch64-unknown-linux-gnu");
73        assert_eq!(BoxArch::Amd64.cache_label(), "amd64");
74        assert_eq!(BoxArch::Arm64.cache_label(), "arm64");
75    }
76}