architecture 0.1.0

Commonly used constants for architectures, platforms, and related targets
Documentation
use core::fmt;
use core::str::FromStr;

use crate::architecture::ParseError;

/// Operating system / platform.
///
/// Variants use Rust-canonical naming from target triples.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[non_exhaustive]
pub enum Platform {
    Aix,
    Android,
    Cuda,
    Darwin,
    DragonFly,
    Emscripten,
    EspIdf,
    FreeBsd,
    Fuchsia,
    Haiku,
    Hermit,
    Horizon,
    Hurd,
    Illumos,
    Ios,
    L4Re,
    Linux,
    NetBsd,
    Nto,
    OpenBsd,
    Psp,
    Redox,
    Solaris,
    SolidAsp3,
    TvOs,
    Uefi,
    Unknown,
    VisionOs,
    Vita,
    VxWorks,
    Wasi,
    WatchOs,
    Windows,
}

impl fmt::Display for Platform {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let s = match self {
            Self::Aix => "aix",
            Self::Android => "android",
            Self::Cuda => "cuda",
            Self::Darwin => "darwin",
            Self::DragonFly => "dragonfly",
            Self::Emscripten => "emscripten",
            Self::EspIdf => "espidf",
            Self::FreeBsd => "freebsd",
            Self::Fuchsia => "fuchsia",
            Self::Haiku => "haiku",
            Self::Hermit => "hermit",
            Self::Horizon => "horizon",
            Self::Hurd => "hurd",
            Self::Illumos => "illumos",
            Self::Ios => "ios",
            Self::L4Re => "l4re",
            Self::Linux => "linux",
            Self::NetBsd => "netbsd",
            Self::Nto => "nto",
            Self::OpenBsd => "openbsd",
            Self::Psp => "psp",
            Self::Redox => "redox",
            Self::Solaris => "solaris",
            Self::SolidAsp3 => "solid_asp3",
            Self::TvOs => "tvos",
            Self::Uefi => "uefi",
            Self::Unknown => "unknown",
            Self::VisionOs => "visionos",
            Self::Vita => "vita",
            Self::VxWorks => "vxworks",
            Self::Wasi => "wasi",
            Self::WatchOs => "watchos",
            Self::Windows => "windows",
        };
        f.write_str(s)
    }
}

impl FromStr for Platform {
    type Err = ParseError;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "aix" => Ok(Self::Aix),
            "android" => Ok(Self::Android),
            "cuda" => Ok(Self::Cuda),
            "darwin" => Ok(Self::Darwin),
            "dragonfly" => Ok(Self::DragonFly),
            "emscripten" => Ok(Self::Emscripten),
            "espidf" => Ok(Self::EspIdf),
            "freebsd" => Ok(Self::FreeBsd),
            "fuchsia" => Ok(Self::Fuchsia),
            "haiku" => Ok(Self::Haiku),
            "hermit" => Ok(Self::Hermit),
            "horizon" => Ok(Self::Horizon),
            "hurd" => Ok(Self::Hurd),
            "illumos" => Ok(Self::Illumos),
            "ios" => Ok(Self::Ios),
            "l4re" => Ok(Self::L4Re),
            "linux" => Ok(Self::Linux),
            "netbsd" => Ok(Self::NetBsd),
            "nto" => Ok(Self::Nto),
            "openbsd" => Ok(Self::OpenBsd),
            "psp" => Ok(Self::Psp),
            "redox" => Ok(Self::Redox),
            "solaris" => Ok(Self::Solaris),
            "solid_asp3" => Ok(Self::SolidAsp3),
            "tvos" => Ok(Self::TvOs),
            "uefi" => Ok(Self::Uefi),
            "unknown" => Ok(Self::Unknown),
            "visionos" => Ok(Self::VisionOs),
            "vita" => Ok(Self::Vita),
            "vxworks" => Ok(Self::VxWorks),
            "wasi" => Ok(Self::Wasi),
            "watchos" => Ok(Self::WatchOs),
            "windows" => Ok(Self::Windows),

            // Common aliases
            "macos" | "osx" => Ok(Self::Darwin),

            _ => Err(ParseError(())),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn display_roundtrip() {
        let variants = [
            Platform::Aix,
            Platform::Android,
            Platform::Cuda,
            Platform::Darwin,
            Platform::DragonFly,
            Platform::Emscripten,
            Platform::EspIdf,
            Platform::FreeBsd,
            Platform::Fuchsia,
            Platform::Haiku,
            Platform::Hermit,
            Platform::Horizon,
            Platform::Hurd,
            Platform::Illumos,
            Platform::Ios,
            Platform::L4Re,
            Platform::Linux,
            Platform::NetBsd,
            Platform::Nto,
            Platform::OpenBsd,
            Platform::Psp,
            Platform::Redox,
            Platform::Solaris,
            Platform::SolidAsp3,
            Platform::TvOs,
            Platform::Uefi,
            Platform::Unknown,
            Platform::VisionOs,
            Platform::Vita,
            Platform::VxWorks,
            Platform::Wasi,
            Platform::WatchOs,
            Platform::Windows,
        ];

        for variant in variants {
            let s = variant.to_string();
            let parsed: Platform = s.parse().unwrap();
            assert_eq!(variant, parsed, "roundtrip failed for {s}");
        }
    }

    #[test]
    fn aliases() {
        assert_eq!("macos".parse::<Platform>().unwrap(), Platform::Darwin);
        assert_eq!("osx".parse::<Platform>().unwrap(), Platform::Darwin);
    }

    #[test]
    fn parse_error() {
        assert!("not_a_platform".parse::<Platform>().is_err());
    }
}