use crate::triple::{Endianness, PointerWidth, Triple};
use alloc::boxed::Box;
use alloc::string::String;
use core::fmt;
use core::hash::{Hash, Hasher};
use core::str::FromStr;
#[non_exhaustive]
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[allow(missing_docs)]
pub enum Architecture {
Unknown,
Arm(ArmArchitecture),
AmdGcn,
Aarch64(Aarch64Architecture),
Asmjs,
Hexagon,
X86_32(X86_32Architecture),
Mips32(Mips32Architecture),
Mips64(Mips64Architecture),
Msp430,
Nvptx64,
Powerpc,
Powerpc64,
Powerpc64le,
Riscv32(Riscv32Architecture),
Riscv64(Riscv64Architecture),
S390x,
Sparc,
Sparc64,
Sparcv9,
Wasm32,
Wasm64,
X86_64,
}
#[non_exhaustive]
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[allow(missing_docs)]
pub enum ArmArchitecture {
Arm,
Armeb,
Armv4,
Armv4t,
Armv5t,
Armv5te,
Armv5tej,
Armv6,
Armv6j,
Armv6k,
Armv6z,
Armv6kz,
Armv6t2,
Armv6m,
Armv7,
Armv7a,
Armv7ve,
Armv7m,
Armv7r,
Armv7s,
Armv8,
Armv8a,
Armv8_1a,
Armv8_2a,
Armv8_3a,
Armv8_4a,
Armv8_5a,
Armv8mBase,
Armv8mMain,
Armv8r,
Armebv7r,
Thumbeb,
Thumbv6m,
Thumbv7a,
Thumbv7em,
Thumbv7m,
Thumbv7neon,
Thumbv8mBase,
Thumbv8mMain,
}
#[non_exhaustive]
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[allow(missing_docs)]
pub enum Aarch64Architecture {
Aarch64,
Aarch64be,
}
impl ArmArchitecture {
pub fn is_thumb(self) -> bool {
match self {
Self::Arm
| Self::Armeb
| Self::Armv4
| Self::Armv4t
| Self::Armv5t
| Self::Armv5te
| Self::Armv5tej
| Self::Armv6
| Self::Armv6j
| Self::Armv6k
| Self::Armv6z
| Self::Armv6kz
| Self::Armv6t2
| Self::Armv6m
| Self::Armv7
| Self::Armv7a
| Self::Armv7ve
| Self::Armv7m
| Self::Armv7r
| Self::Armv7s
| Self::Armv8
| Self::Armv8a
| Self::Armv8_1a
| Self::Armv8_2a
| Self::Armv8_3a
| Self::Armv8_4a
| Self::Armv8_5a
| Self::Armv8mBase
| Self::Armv8mMain
| Self::Armv8r
| Self::Armebv7r => false,
Self::Thumbeb
| Self::Thumbv6m
| Self::Thumbv7a
| Self::Thumbv7em
| Self::Thumbv7m
| Self::Thumbv7neon
| Self::Thumbv8mBase
| Self::Thumbv8mMain => true,
}
}
pub fn pointer_width(self) -> PointerWidth {
match self {
Self::Arm
| Self::Armeb
| Self::Armv4
| Self::Armv4t
| Self::Armv5t
| Self::Armv5te
| Self::Armv5tej
| Self::Armv6
| Self::Armv6j
| Self::Armv6k
| Self::Armv6z
| Self::Armv6kz
| Self::Armv6t2
| Self::Armv6m
| Self::Armv7
| Self::Armv7a
| Self::Armv7ve
| Self::Armv7m
| Self::Armv7r
| Self::Armv7s
| Self::Armv8
| Self::Armv8a
| Self::Armv8_1a
| Self::Armv8_2a
| Self::Armv8_3a
| Self::Armv8_4a
| Self::Armv8_5a
| Self::Armv8mBase
| Self::Armv8mMain
| Self::Armv8r
| Self::Armebv7r
| Self::Thumbeb
| Self::Thumbv6m
| Self::Thumbv7a
| Self::Thumbv7em
| Self::Thumbv7m
| Self::Thumbv7neon
| Self::Thumbv8mBase
| Self::Thumbv8mMain => PointerWidth::U32,
}
}
pub fn endianness(self) -> Endianness {
match self {
Self::Arm
| Self::Armv4
| Self::Armv4t
| Self::Armv5t
| Self::Armv5te
| Self::Armv5tej
| Self::Armv6
| Self::Armv6j
| Self::Armv6k
| Self::Armv6z
| Self::Armv6kz
| Self::Armv6t2
| Self::Armv6m
| Self::Armv7
| Self::Armv7a
| Self::Armv7ve
| Self::Armv7m
| Self::Armv7r
| Self::Armv7s
| Self::Armv8
| Self::Armv8a
| Self::Armv8_1a
| Self::Armv8_2a
| Self::Armv8_3a
| Self::Armv8_4a
| Self::Armv8_5a
| Self::Armv8mBase
| Self::Armv8mMain
| Self::Armv8r
| Self::Thumbv6m
| Self::Thumbv7a
| Self::Thumbv7em
| Self::Thumbv7m
| Self::Thumbv7neon
| Self::Thumbv8mBase
| Self::Thumbv8mMain => Endianness::Little,
Self::Armeb | Self::Armebv7r | Self::Thumbeb => Endianness::Big,
}
}
}
impl Aarch64Architecture {
pub fn is_thumb(self) -> bool {
match self {
Self::Aarch64 | Self::Aarch64be => false,
}
}
pub fn pointer_width(self) -> PointerWidth {
match self {
Self::Aarch64 | Self::Aarch64be => PointerWidth::U64,
}
}
pub fn endianness(self) -> Endianness {
match self {
Self::Aarch64 => Endianness::Little,
Self::Aarch64be => Endianness::Big,
}
}
}
#[non_exhaustive]
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[allow(missing_docs)]
pub enum Riscv32Architecture {
Riscv32,
Riscv32i,
Riscv32imac,
Riscv32imc,
}
#[non_exhaustive]
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[allow(missing_docs)]
pub enum Riscv64Architecture {
Riscv64,
Riscv64gc,
Riscv64imac,
}
#[non_exhaustive]
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[allow(missing_docs)]
pub enum X86_32Architecture {
I386,
I586,
I686,
}
#[non_exhaustive]
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[allow(missing_docs)]
pub enum Mips32Architecture {
Mips,
Mipsel,
Mipsisa32r6,
Mipsisa32r6el,
}
#[non_exhaustive]
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[allow(missing_docs)]
pub enum Mips64Architecture {
Mips64,
Mips64el,
Mipsisa64r6,
Mipsisa64r6el,
}
#[derive(Clone, Debug, Eq)]
pub enum CustomVendor {
Owned(Box<String>),
Static(&'static str),
}
impl CustomVendor {
pub fn as_str(&self) -> &str {
match self {
Self::Owned(s) => s,
Self::Static(s) => s,
}
}
}
impl PartialEq for CustomVendor {
fn eq(&self, other: &Self) -> bool {
self.as_str() == other.as_str()
}
}
impl Hash for CustomVendor {
fn hash<H: Hasher>(&self, state: &mut H) {
self.as_str().hash(state)
}
}
#[non_exhaustive]
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
#[allow(missing_docs)]
pub enum Vendor {
Unknown,
Amd,
Apple,
Experimental,
Fortanix,
Nvidia,
Pc,
Rumprun,
Sun,
Uwp,
Wrs,
Custom(CustomVendor),
}
#[non_exhaustive]
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[allow(missing_docs)]
pub enum OperatingSystem {
Unknown,
AmdHsa,
Bitrig,
Cloudabi,
Cuda,
Darwin,
Dragonfly,
Emscripten,
Freebsd,
Fuchsia,
Haiku,
Hermit,
Illumos,
Ios,
L4re,
Linux,
MacOSX { major: u16, minor: u16, patch: u16 },
Nebulet,
Netbsd,
None_,
Openbsd,
Psp,
Redox,
Solaris,
Uefi,
VxWorks,
Wasi,
Windows,
}
#[non_exhaustive]
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[allow(missing_docs)]
pub enum Environment {
Unknown,
AmdGiz,
Android,
Androideabi,
Eabi,
Eabihf,
Gnu,
Gnuabi64,
Gnueabi,
Gnueabihf,
Gnuspe,
Gnux32,
Macabi,
Musl,
Musleabi,
Musleabihf,
Muslabi64,
Msvc,
Kernel,
Uclibc,
Sgx,
Softfloat,
Spe,
}
#[non_exhaustive]
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[allow(missing_docs)]
pub enum BinaryFormat {
Unknown,
Elf,
Coff,
Macho,
Wasm,
}
impl Architecture {
pub fn endianness(self) -> Result<Endianness, ()> {
match self {
Self::Unknown => Err(()),
Self::Arm(arm) => Ok(arm.endianness()),
Self::Aarch64(aarch) => Ok(aarch.endianness()),
Self::AmdGcn
| Self::Asmjs
| Self::Hexagon
| Self::X86_32(_)
| Self::Mips64(Mips64Architecture::Mips64el)
| Self::Mips32(Mips32Architecture::Mipsel)
| Self::Mips32(Mips32Architecture::Mipsisa32r6el)
| Self::Mips64(Mips64Architecture::Mipsisa64r6el)
| Self::Msp430
| Self::Nvptx64
| Self::Powerpc64le
| Self::Riscv32(_)
| Self::Riscv64(_)
| Self::Wasm32
| Self::Wasm64
| Self::X86_64 => Ok(Endianness::Little),
Self::Mips32(Mips32Architecture::Mips)
| Self::Mips64(Mips64Architecture::Mips64)
| Self::Mips32(Mips32Architecture::Mipsisa32r6)
| Self::Mips64(Mips64Architecture::Mipsisa64r6)
| Self::Powerpc
| Self::Powerpc64
| Self::S390x
| Self::Sparc
| Self::Sparc64
| Self::Sparcv9 => Ok(Endianness::Big),
}
}
pub fn pointer_width(self) -> Result<PointerWidth, ()> {
match self {
Self::Unknown => Err(()),
Self::Msp430 => Ok(PointerWidth::U16),
Self::Arm(arm) => Ok(arm.pointer_width()),
Self::Aarch64(aarch) => Ok(aarch.pointer_width()),
Self::Asmjs
| Self::Hexagon
| Self::X86_32(_)
| Self::Riscv32(_)
| Self::Sparc
| Self::Wasm32
| Self::Mips32(_)
| Self::Powerpc => Ok(PointerWidth::U32),
Self::AmdGcn
| Self::Powerpc64le
| Self::Riscv64(_)
| Self::X86_64
| Self::Mips64(_)
| Self::Nvptx64
| Self::Powerpc64
| Self::S390x
| Self::Sparc64
| Self::Sparcv9
| Self::Wasm64 => Ok(PointerWidth::U64),
}
}
}
pub(crate) fn default_binary_format(triple: &Triple) -> BinaryFormat {
match triple.operating_system {
OperatingSystem::None_ => match triple.environment {
Environment::Eabi | Environment::Eabihf => BinaryFormat::Elf,
_ => BinaryFormat::Unknown,
},
OperatingSystem::Darwin | OperatingSystem::Ios | OperatingSystem::MacOSX { .. } => {
BinaryFormat::Macho
}
OperatingSystem::Windows => BinaryFormat::Coff,
OperatingSystem::Nebulet
| OperatingSystem::Emscripten
| OperatingSystem::VxWorks
| OperatingSystem::Wasi
| OperatingSystem::Unknown => match triple.architecture {
Architecture::Wasm32 | Architecture::Wasm64 => BinaryFormat::Wasm,
_ => BinaryFormat::Unknown,
},
_ => BinaryFormat::Elf,
}
}
impl fmt::Display for ArmArchitecture {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let s = match *self {
Self::Arm => "arm",
Self::Armeb => "armeb",
Self::Armv4 => "armv4",
Self::Armv4t => "armv4t",
Self::Armv5t => "armv5t",
Self::Armv5te => "armv5te",
Self::Armv5tej => "armv5tej",
Self::Armv6 => "armv6",
Self::Armv6j => "armv6j",
Self::Armv6k => "armv6k",
Self::Armv6z => "armv6z",
Self::Armv6kz => "armv6kz",
Self::Armv6t2 => "armv6t2",
Self::Armv6m => "armv6m",
Self::Armv7 => "armv7",
Self::Armv7a => "armv7a",
Self::Armv7ve => "armv7ve",
Self::Armv7m => "armv7m",
Self::Armv7r => "armv7r",
Self::Armv7s => "armv7s",
Self::Armv8 => "armv8",
Self::Armv8a => "armv8a",
Self::Armv8_1a => "armv8.1a",
Self::Armv8_2a => "armv8.2a",
Self::Armv8_3a => "armv8.3a",
Self::Armv8_4a => "armv8.4a",
Self::Armv8_5a => "armv8.5a",
Self::Armv8mBase => "armv8m.base",
Self::Armv8mMain => "armv8m.main",
Self::Armv8r => "armv8r",
Self::Thumbeb => "thumbeb",
Self::Thumbv6m => "thumbv6m",
Self::Thumbv7a => "thumbv7a",
Self::Thumbv7em => "thumbv7em",
Self::Thumbv7m => "thumbv7m",
Self::Thumbv7neon => "thumbv7neon",
Self::Thumbv8mBase => "thumbv8m.base",
Self::Thumbv8mMain => "thumbv8m.main",
Self::Armebv7r => "armebv7r",
};
f.write_str(s)
}
}
impl fmt::Display for Aarch64Architecture {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let s = match *self {
Self::Aarch64 => "aarch64",
Self::Aarch64be => "aarch64be",
};
f.write_str(s)
}
}
impl fmt::Display for Riscv32Architecture {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let s = match *self {
Self::Riscv32 => "riscv32",
Self::Riscv32i => "riscv32i",
Self::Riscv32imac => "riscv32imac",
Self::Riscv32imc => "riscv32imc",
};
f.write_str(s)
}
}
impl fmt::Display for Riscv64Architecture {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let s = match *self {
Self::Riscv64 => "riscv64",
Self::Riscv64gc => "riscv64gc",
Self::Riscv64imac => "riscv64imac",
};
f.write_str(s)
}
}
impl fmt::Display for X86_32Architecture {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let s = match *self {
Self::I386 => "i386",
Self::I586 => "i586",
Self::I686 => "i686",
};
f.write_str(s)
}
}
impl fmt::Display for Mips32Architecture {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let s = match *self {
Self::Mips => "mips",
Self::Mipsel => "mipsel",
Self::Mipsisa32r6 => "mipsisa32r6",
Self::Mipsisa32r6el => "mipsisa32r6el",
};
f.write_str(s)
}
}
impl fmt::Display for Mips64Architecture {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let s = match *self {
Self::Mips64 => "mips64",
Self::Mips64el => "mips64el",
Self::Mipsisa64r6 => "mipsisa64r6",
Self::Mipsisa64r6el => "mipsisa64r6el",
};
f.write_str(s)
}
}
impl fmt::Display for Architecture {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Self::Arm(arm) => arm.fmt(f),
Self::Aarch64(aarch) => aarch.fmt(f),
Self::Unknown => f.write_str("unknown"),
Self::AmdGcn => f.write_str("amdgcn"),
Self::Asmjs => f.write_str("asmjs"),
Self::Hexagon => f.write_str("hexagon"),
Self::X86_32(x86_32) => x86_32.fmt(f),
Self::Mips32(mips32) => mips32.fmt(f),
Self::Mips64(mips64) => mips64.fmt(f),
Self::Msp430 => f.write_str("msp430"),
Self::Nvptx64 => f.write_str("nvptx64"),
Self::Powerpc => f.write_str("powerpc"),
Self::Powerpc64 => f.write_str("powerpc64"),
Self::Powerpc64le => f.write_str("powerpc64le"),
Self::Riscv32(riscv32) => riscv32.fmt(f),
Self::Riscv64(riscv64) => riscv64.fmt(f),
Self::S390x => f.write_str("s390x"),
Self::Sparc => f.write_str("sparc"),
Self::Sparc64 => f.write_str("sparc64"),
Self::Sparcv9 => f.write_str("sparcv9"),
Self::Wasm32 => f.write_str("wasm32"),
Self::Wasm64 => f.write_str("wasm64"),
Self::X86_64 => f.write_str("x86_64"),
}
}
}
impl FromStr for ArmArchitecture {
type Err = ();
fn from_str(s: &str) -> Result<Self, ()> {
Ok(match s {
"arm" => Self::Arm,
"armeb" => Self::Armeb,
"armv4" => Self::Armv4,
"armv4t" => Self::Armv4t,
"armv5t" => Self::Armv5t,
"armv5te" => Self::Armv5te,
"armv5tej" => Self::Armv5tej,
"armv6" => Self::Armv6,
"armv6j" => Self::Armv6j,
"armv6k" => Self::Armv6k,
"armv6z" => Self::Armv6z,
"armv6kz" => Self::Armv6kz,
"armv6t2" => Self::Armv6t2,
"armv6m" => Self::Armv6m,
"armv7" => Self::Armv7,
"armv7a" => Self::Armv7a,
"armv7ve" => Self::Armv7ve,
"armv7m" => Self::Armv7m,
"armv7r" => Self::Armv7r,
"armv7s" => Self::Armv7s,
"armv8" => Self::Armv8,
"armv8a" => Self::Armv8a,
"armv8.1a" => Self::Armv8_1a,
"armv8.2a" => Self::Armv8_2a,
"armv8.3a" => Self::Armv8_3a,
"armv8.4a" => Self::Armv8_4a,
"armv8.5a" => Self::Armv8_5a,
"armv8m.base" => Self::Armv8mBase,
"armv8m.main" => Self::Armv8mMain,
"armv8r" => Self::Armv8r,
"thumbeb" => Self::Thumbeb,
"thumbv6m" => Self::Thumbv6m,
"thumbv7a" => Self::Thumbv7a,
"thumbv7em" => Self::Thumbv7em,
"thumbv7m" => Self::Thumbv7m,
"thumbv7neon" => Self::Thumbv7neon,
"thumbv8m.base" => Self::Thumbv8mBase,
"thumbv8m.main" => Self::Thumbv8mMain,
"armebv7r" => Self::Armebv7r,
_ => return Err(()),
})
}
}
impl FromStr for Aarch64Architecture {
type Err = ();
fn from_str(s: &str) -> Result<Self, ()> {
Ok(match s {
"aarch64" => Self::Aarch64,
"arm64" => Self::Aarch64,
"aarch64be" => Self::Aarch64be,
_ => return Err(()),
})
}
}
impl FromStr for Riscv32Architecture {
type Err = ();
fn from_str(s: &str) -> Result<Self, ()> {
Ok(match s {
"riscv32" => Self::Riscv32,
"riscv32i" => Self::Riscv32i,
"riscv32imac" => Self::Riscv32imac,
"riscv32imc" => Self::Riscv32imc,
_ => return Err(()),
})
}
}
impl FromStr for Riscv64Architecture {
type Err = ();
fn from_str(s: &str) -> Result<Self, ()> {
Ok(match s {
"riscv64" => Self::Riscv64,
"riscv64gc" => Self::Riscv64gc,
"riscv64imac" => Self::Riscv64imac,
_ => return Err(()),
})
}
}
impl FromStr for X86_32Architecture {
type Err = ();
fn from_str(s: &str) -> Result<Self, ()> {
Ok(match s {
"i386" => Self::I386,
"i586" => Self::I586,
"i686" => Self::I686,
_ => return Err(()),
})
}
}
impl FromStr for Mips32Architecture {
type Err = ();
fn from_str(s: &str) -> Result<Self, ()> {
Ok(match s {
"mips" => Self::Mips,
"mipsel" => Self::Mipsel,
"mipsisa32r6" => Self::Mipsisa32r6,
"mipsisa32r6el" => Self::Mipsisa32r6el,
_ => return Err(()),
})
}
}
impl FromStr for Mips64Architecture {
type Err = ();
fn from_str(s: &str) -> Result<Self, ()> {
Ok(match s {
"mips64" => Self::Mips64,
"mips64el" => Self::Mips64el,
"mipsisa64r6" => Self::Mipsisa64r6,
"mipsisa64r6el" => Self::Mipsisa64r6el,
_ => return Err(()),
})
}
}
impl FromStr for Architecture {
type Err = ();
fn from_str(s: &str) -> Result<Self, ()> {
Ok(match s {
"unknown" => Self::Unknown,
"amdgcn" => Self::AmdGcn,
"asmjs" => Self::Asmjs,
"hexagon" => Self::Hexagon,
"msp430" => Self::Msp430,
"nvptx64" => Self::Nvptx64,
"powerpc" => Self::Powerpc,
"powerpc64" => Self::Powerpc64,
"powerpc64le" => Self::Powerpc64le,
"s390x" => Self::S390x,
"sparc" => Self::Sparc,
"sparc64" => Self::Sparc64,
"sparcv9" => Self::Sparcv9,
"wasm32" => Self::Wasm32,
"wasm64" => Self::Wasm64,
"x86_64" => Self::X86_64,
_ => {
if let Ok(arm) = ArmArchitecture::from_str(s) {
Self::Arm(arm)
} else if let Ok(aarch64) = Aarch64Architecture::from_str(s) {
Self::Aarch64(aarch64)
} else if let Ok(riscv32) = Riscv32Architecture::from_str(s) {
Self::Riscv32(riscv32)
} else if let Ok(riscv64) = Riscv64Architecture::from_str(s) {
Self::Riscv64(riscv64)
} else if let Ok(x86_32) = X86_32Architecture::from_str(s) {
Self::X86_32(x86_32)
} else if let Ok(mips32) = Mips32Architecture::from_str(s) {
Self::Mips32(mips32)
} else if let Ok(mips64) = Mips64Architecture::from_str(s) {
Self::Mips64(mips64)
} else {
return Err(());
}
}
})
}
}
impl fmt::Display for Vendor {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let s = match *self {
Self::Unknown => "unknown",
Self::Amd => "amd",
Self::Apple => "apple",
Self::Experimental => "experimental",
Self::Fortanix => "fortanix",
Self::Nvidia => "nvidia",
Self::Pc => "pc",
Self::Rumprun => "rumprun",
Self::Sun => "sun",
Self::Uwp => "uwp",
Self::Wrs => "wrs",
Self::Custom(ref name) => name.as_str(),
};
f.write_str(s)
}
}
impl FromStr for Vendor {
type Err = ();
fn from_str(s: &str) -> Result<Self, ()> {
Ok(match s {
"unknown" => Self::Unknown,
"amd" => Self::Amd,
"apple" => Self::Apple,
"experimental" => Self::Experimental,
"fortanix" => Self::Fortanix,
"nvidia" => Self::Nvidia,
"pc" => Self::Pc,
"rumprun" => Self::Rumprun,
"sun" => Self::Sun,
"uwp" => Self::Uwp,
"wrs" => Self::Wrs,
custom => {
use alloc::borrow::ToOwned;
if custom.is_empty() {
return Err(());
}
if Architecture::from_str(custom).is_ok()
|| OperatingSystem::from_str(custom).is_ok()
|| Environment::from_str(custom).is_ok()
|| BinaryFormat::from_str(custom).is_ok()
{
return Err(());
}
if !custom.chars().next().unwrap().is_ascii_lowercase() {
return Err(());
}
let has_restricted = custom.chars().any(|c: char| {
!(c.is_ascii_lowercase() || c.is_ascii_digit() || c == '_' || c == '.')
});
if has_restricted {
return Err(());
}
Self::Custom(CustomVendor::Owned(Box::new(custom.to_owned())))
}
})
}
}
impl fmt::Display for OperatingSystem {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let s = match *self {
Self::Unknown => "unknown",
Self::AmdHsa => "amdhsa",
Self::Bitrig => "bitrig",
Self::Cloudabi => "cloudabi",
Self::Cuda => "cuda",
Self::Darwin => "darwin",
Self::Dragonfly => "dragonfly",
Self::Emscripten => "emscripten",
Self::Freebsd => "freebsd",
Self::Fuchsia => "fuchsia",
Self::Haiku => "haiku",
Self::Hermit => "hermit",
Self::Illumos => "illumos",
Self::Ios => "ios",
Self::L4re => "l4re",
Self::Linux => "linux",
Self::MacOSX {
major,
minor,
patch,
} => {
return write!(f, "macosx{}.{}.{}", major, minor, patch);
}
Self::Nebulet => "nebulet",
Self::Netbsd => "netbsd",
Self::None_ => "none",
Self::Openbsd => "openbsd",
Self::Psp => "psp",
Self::Redox => "redox",
Self::Solaris => "solaris",
Self::Uefi => "uefi",
Self::VxWorks => "vxworks",
Self::Wasi => "wasi",
Self::Windows => "windows",
};
f.write_str(s)
}
}
impl FromStr for OperatingSystem {
type Err = ();
fn from_str(s: &str) -> Result<Self, ()> {
if s.starts_with("macosx") {
let s = &s["macosx".len()..];
let mut parts = s.split('.').map(|num| num.parse::<u16>());
macro_rules! get_part {
() => {
if let Some(Ok(part)) = parts.next() {
part
} else {
return Err(());
}
};
}
let major = get_part!();
let minor = get_part!();
let patch = get_part!();
if parts.next().is_some() {
return Err(());
}
return Ok(Self::MacOSX {
major,
minor,
patch,
});
}
Ok(match s {
"unknown" => Self::Unknown,
"amdhsa" => Self::AmdHsa,
"bitrig" => Self::Bitrig,
"cloudabi" => Self::Cloudabi,
"cuda" => Self::Cuda,
"darwin" => Self::Darwin,
"dragonfly" => Self::Dragonfly,
"emscripten" => Self::Emscripten,
"freebsd" => Self::Freebsd,
"fuchsia" => Self::Fuchsia,
"haiku" => Self::Haiku,
"hermit" => Self::Hermit,
"illumos" => Self::Illumos,
"ios" => Self::Ios,
"l4re" => Self::L4re,
"linux" => Self::Linux,
"nebulet" => Self::Nebulet,
"netbsd" => Self::Netbsd,
"none" => Self::None_,
"openbsd" => Self::Openbsd,
"psp" => Self::Psp,
"redox" => Self::Redox,
"solaris" => Self::Solaris,
"uefi" => Self::Uefi,
"vxworks" => Self::VxWorks,
"wasi" => Self::Wasi,
"windows" => Self::Windows,
_ => return Err(()),
})
}
}
impl fmt::Display for Environment {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let s = match *self {
Self::Unknown => "unknown",
Self::AmdGiz => "amdgiz",
Self::Android => "android",
Self::Androideabi => "androideabi",
Self::Eabi => "eabi",
Self::Eabihf => "eabihf",
Self::Gnu => "gnu",
Self::Gnuabi64 => "gnuabi64",
Self::Gnueabi => "gnueabi",
Self::Gnueabihf => "gnueabihf",
Self::Gnuspe => "gnuspe",
Self::Gnux32 => "gnux32",
Self::Macabi => "macabi",
Self::Musl => "musl",
Self::Musleabi => "musleabi",
Self::Musleabihf => "musleabihf",
Self::Muslabi64 => "muslabi64",
Self::Msvc => "msvc",
Self::Kernel => "kernel",
Self::Uclibc => "uclibc",
Self::Sgx => "sgx",
Self::Softfloat => "softfloat",
Self::Spe => "spe",
};
f.write_str(s)
}
}
impl FromStr for Environment {
type Err = ();
fn from_str(s: &str) -> Result<Self, ()> {
Ok(match s {
"unknown" => Self::Unknown,
"amdgiz" => Self::AmdGiz,
"android" => Self::Android,
"androideabi" => Self::Androideabi,
"eabi" => Self::Eabi,
"eabihf" => Self::Eabihf,
"gnu" => Self::Gnu,
"gnuabi64" => Self::Gnuabi64,
"gnueabi" => Self::Gnueabi,
"gnueabihf" => Self::Gnueabihf,
"gnuspe" => Self::Gnuspe,
"gnux32" => Self::Gnux32,
"macabi" => Self::Macabi,
"musl" => Self::Musl,
"musleabi" => Self::Musleabi,
"musleabihf" => Self::Musleabihf,
"muslabi64" => Self::Muslabi64,
"msvc" => Self::Msvc,
"kernel" => Self::Kernel,
"uclibc" => Self::Uclibc,
"sgx" => Self::Sgx,
"softfloat" => Self::Softfloat,
"spe" => Self::Spe,
_ => return Err(()),
})
}
}
impl fmt::Display for BinaryFormat {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let s = match *self {
Self::Unknown => "unknown",
Self::Elf => "elf",
Self::Coff => "coff",
Self::Macho => "macho",
Self::Wasm => "wasm",
};
f.write_str(s)
}
}
impl FromStr for BinaryFormat {
type Err = ();
fn from_str(s: &str) -> Result<Self, ()> {
Ok(match s {
"unknown" => Self::Unknown,
"elf" => Self::Elf,
"coff" => Self::Coff,
"macho" => Self::Macho,
"wasm" => Self::Wasm,
_ => return Err(()),
})
}
}
#[cfg(test)]
mod tests {
use super::*;
use alloc::string::ToString;
#[test]
fn roundtrip_known_triples() {
let targets = [
"aarch64-apple-ios",
"aarch64-fuchsia",
"aarch64-linux-android",
"aarch64-pc-windows-msvc",
"aarch64-unknown-cloudabi",
"aarch64-unknown-freebsd",
"aarch64-unknown-hermit",
"aarch64-unknown-linux-gnu",
"aarch64-unknown-linux-musl",
"aarch64-unknown-netbsd",
"aarch64-unknown-none",
"aarch64-unknown-none-softfloat",
"aarch64-unknown-openbsd",
"aarch64-unknown-redox",
"aarch64-uwp-windows-msvc",
"aarch64-wrs-vxworks",
"amdgcn-amd-amdhsa",
"amdgcn-amd-amdhsa-amdgiz",
"armebv7r-none-eabi",
"armebv7r-none-eabihf",
"arm-linux-androideabi",
"arm-unknown-linux-gnueabi",
"arm-unknown-linux-gnueabihf",
"arm-unknown-linux-musleabi",
"arm-unknown-linux-musleabihf",
"armv4t-unknown-linux-gnueabi",
"armv5te-unknown-linux-gnueabi",
"armv5te-unknown-linux-musleabi",
"armv6-unknown-freebsd",
"armv6-unknown-netbsd-eabihf",
"armv7a-none-eabi",
"armv7a-none-eabihf",
"armv7-apple-ios",
"armv7-linux-androideabi",
"armv7r-none-eabi",
"armv7r-none-eabihf",
"armv7s-apple-ios",
"armv7-unknown-cloudabi-eabihf",
"armv7-unknown-freebsd",
"armv7-unknown-linux-gnueabi",
"armv7-unknown-linux-gnueabihf",
"armv7-unknown-linux-musleabi",
"armv7-unknown-linux-musleabihf",
"armv7-unknown-netbsd-eabihf",
"armv7-wrs-vxworks-eabihf",
"asmjs-unknown-emscripten",
"hexagon-unknown-linux-musl",
"i386-apple-ios",
"i586-pc-windows-msvc",
"i586-unknown-linux-gnu",
"i586-unknown-linux-musl",
"i686-apple-darwin",
"i686-linux-android",
"i686-apple-macosx10.7.0",
"i686-pc-windows-gnu",
"i686-pc-windows-msvc",
"i686-unknown-cloudabi",
"i686-unknown-dragonfly",
"i686-unknown-freebsd",
"i686-unknown-haiku",
"i686-unknown-linux-gnu",
"i686-unknown-linux-musl",
"i686-unknown-netbsd",
"i686-unknown-openbsd",
"i686-unknown-uefi",
"i686-uwp-windows-gnu",
"i686-uwp-windows-msvc",
"i686-wrs-vxworks",
"mips64el-unknown-linux-gnuabi64",
"mips64el-unknown-linux-muslabi64",
"mips64-unknown-linux-gnuabi64",
"mips64-unknown-linux-muslabi64",
"mipsel-sony-psp",
"mipsel-unknown-linux-gnu",
"mipsel-unknown-linux-musl",
"mipsel-unknown-linux-uclibc",
"mipsisa32r6el-unknown-linux-gnu",
"mipsisa32r6-unknown-linux-gnu",
"mipsisa64r6el-unknown-linux-gnuabi64",
"mipsisa64r6-unknown-linux-gnuabi64",
"mips-unknown-linux-gnu",
"mips-unknown-linux-musl",
"mips-unknown-linux-uclibc",
"msp430-none-elf",
"nvptx64-nvidia-cuda",
"powerpc64le-unknown-linux-gnu",
"powerpc64le-unknown-linux-musl",
"powerpc64-unknown-freebsd",
"powerpc64-unknown-linux-gnu",
"powerpc64-unknown-linux-musl",
"powerpc64-wrs-vxworks",
"powerpc-unknown-linux-gnu",
"powerpc-unknown-linux-gnuspe",
"powerpc-unknown-linux-musl",
"powerpc-unknown-netbsd",
"powerpc-wrs-vxworks",
"powerpc-wrs-vxworks-spe",
"riscv32imac-unknown-none-elf",
"riscv32imc-unknown-none-elf",
"riscv32i-unknown-none-elf",
"riscv64gc-unknown-linux-gnu",
"riscv64gc-unknown-none-elf",
"riscv64imac-unknown-none-elf",
"s390x-unknown-linux-gnu",
"sparc64-unknown-linux-gnu",
"sparc64-unknown-netbsd",
"sparc64-unknown-openbsd",
"sparc-unknown-linux-gnu",
"sparcv9-sun-solaris",
"thumbv6m-none-eabi",
"thumbv7a-pc-windows-msvc",
"thumbv7a-uwp-windows-msvc",
"thumbv7em-none-eabi",
"thumbv7em-none-eabihf",
"thumbv7m-none-eabi",
"thumbv7neon-linux-androideabi",
"thumbv7neon-unknown-linux-gnueabihf",
"thumbv7neon-unknown-linux-musleabihf",
"thumbv8m.base-none-eabi",
"thumbv8m.main-none-eabi",
"thumbv8m.main-none-eabihf",
"wasm32-experimental-emscripten",
"wasm32-unknown-emscripten",
"wasm32-unknown-unknown",
"wasm64-unknown-unknown",
"wasm32-wasi",
"wasm64-wasi",
"x86_64-apple-darwin",
"x86_64-apple-ios",
"x86_64-fortanix-unknown-sgx",
"x86_64-fuchsia",
"x86_64-linux-android",
"x86_64-linux-kernel",
"x86_64-apple-macosx10.7.0",
"x86_64-pc-solaris",
"x86_64-pc-windows-gnu",
"x86_64-pc-windows-msvc",
"x86_64-rumprun-netbsd",
"x86_64-sun-solaris",
"x86_64-unknown-bitrig",
"x86_64-unknown-cloudabi",
"x86_64-unknown-dragonfly",
"x86_64-unknown-freebsd",
"x86_64-unknown-haiku",
"x86_64-unknown-hermit",
"x86_64-unknown-hermit-kernel",
"x86_64-unknown-illumos",
"x86_64-unknown-l4re-uclibc",
"x86_64-unknown-linux-gnu",
"x86_64-unknown-linux-gnux32",
"x86_64-unknown-linux-musl",
"x86_64-unknown-netbsd",
"x86_64-unknown-openbsd",
"x86_64-unknown-redox",
"x86_64-unknown-uefi",
"x86_64-uwp-windows-gnu",
"x86_64-uwp-windows-msvc",
"x86_64-wrs-vxworks",
];
for target in targets.iter() {
let t = Triple::from_str(target).expect("can't parse target");
assert_ne!(t.architecture, Architecture::Unknown);
assert_eq!(t.to_string(), *target);
}
}
#[test]
fn thumbv7em_none_eabihf() {
let t = Triple::from_str("thumbv7em-none-eabihf").expect("can't parse target");
assert_eq!(
t.architecture,
Architecture::Arm(ArmArchitecture::Thumbv7em)
);
assert_eq!(t.vendor, Vendor::Unknown);
assert_eq!(t.operating_system, OperatingSystem::None_);
assert_eq!(t.environment, Environment::Eabihf);
assert_eq!(t.binary_format, BinaryFormat::Elf);
}
#[test]
fn custom_vendors() {
assert!(Triple::from_str("x86_64--linux").is_err());
assert!(Triple::from_str("x86_64-42-linux").is_err());
assert!(Triple::from_str("x86_64-__customvendor__-linux").is_err());
assert!(Triple::from_str("x86_64-^-linux").is_err());
assert!(Triple::from_str("x86_64- -linux").is_err());
assert!(Triple::from_str("x86_64-CustomVendor-linux").is_err());
assert!(Triple::from_str("x86_64-linux-linux").is_err());
assert!(Triple::from_str("x86_64-x86_64-linux").is_err());
assert!(Triple::from_str("x86_64-elf-linux").is_err());
assert!(Triple::from_str("x86_64-gnu-linux").is_err());
assert!(Triple::from_str("x86_64-linux-customvendor").is_err());
assert!(Triple::from_str("customvendor").is_err());
assert!(Triple::from_str("customvendor-x86_64").is_err());
assert!(Triple::from_str("x86_64-").is_err());
assert!(Triple::from_str("x86_64--").is_err());
assert!(
Triple::from_str("x86_64-𝓬𝓾𝓼𝓽𝓸𝓶𝓿𝓮𝓷𝓭𝓸𝓻-linux").is_err(),
"unicode font hazard"
);
assert!(
Triple::from_str("x86_64-ćúśtőḿvéńdőŕ-linux").is_err(),
"diacritical mark stripping hazard"
);
assert!(
Triple::from_str("x86_64-customvendοr-linux").is_err(),
"homoglyph hazard"
);
assert!(Triple::from_str("x86_64-customvendor-linux").is_ok());
assert!(
Triple::from_str("x86_64-ffi-linux").is_err(),
"normalization hazard"
);
assert!(Triple::from_str("x86_64-ffi-linux").is_ok());
assert!(
Triple::from_str("x86_64-customvendor-linux").is_err(),
"zero-width character hazard"
);
assert!(
Triple::from_str("x86_64-customvendor-linux").is_err(),
"BOM hazard"
);
let t = Triple::from_str("x86_64-customvendor-linux")
.expect("can't parse target with custom vendor");
assert_eq!(t.architecture, Architecture::X86_64);
assert_eq!(
t.vendor,
Vendor::Custom(CustomVendor::Static("customvendor"))
);
assert_eq!(t.operating_system, OperatingSystem::Linux);
assert_eq!(t.environment, Environment::Unknown);
assert_eq!(t.binary_format, BinaryFormat::Elf);
assert_eq!(t.to_string(), "x86_64-customvendor-linux");
let t =
Triple::from_str("x86_64-customvendor").expect("can't parse target with custom vendor");
assert_eq!(t.architecture, Architecture::X86_64);
assert_eq!(
t.vendor,
Vendor::Custom(CustomVendor::Static("customvendor"))
);
assert_eq!(t.operating_system, OperatingSystem::Unknown);
assert_eq!(t.environment, Environment::Unknown);
assert_eq!(t.binary_format, BinaryFormat::Unknown);
assert_eq!(
Triple::from_str("unknown-foo"),
Ok(Triple {
architecture: Architecture::Unknown,
vendor: Vendor::Custom(CustomVendor::Static("foo")),
operating_system: OperatingSystem::Unknown,
environment: Environment::Unknown,
binary_format: BinaryFormat::Unknown,
})
);
}
}