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;
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[allow(missing_docs)]
pub enum Architecture {
Unknown,
Arm(ArmArchitecture),
AmdGcn,
Aarch64(Aarch64Architecture),
Asmjs,
Hexagon,
I386,
I586,
I686,
Mips,
Mips64,
Mips64el,
Mipsel,
Mipsisa32r6,
Mipsisa32r6el,
Mipsisa64r6,
Mipsisa64r6el,
Msp430,
Nvptx64,
Powerpc,
Powerpc64,
Powerpc64le,
Riscv32,
Riscv32i,
Riscv32imac,
Riscv32imc,
Riscv64,
Riscv64gc,
Riscv64imac,
S390x,
Sparc,
Sparc64,
Sparcv9,
Wasm32,
X86_64,
}
#[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,
}
#[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 {
ArmArchitecture::Arm
| ArmArchitecture::Armeb
| ArmArchitecture::Armv4
| ArmArchitecture::Armv4t
| ArmArchitecture::Armv5t
| ArmArchitecture::Armv5te
| ArmArchitecture::Armv5tej
| ArmArchitecture::Armv6
| ArmArchitecture::Armv6j
| ArmArchitecture::Armv6k
| ArmArchitecture::Armv6z
| ArmArchitecture::Armv6kz
| ArmArchitecture::Armv6t2
| ArmArchitecture::Armv6m
| ArmArchitecture::Armv7
| ArmArchitecture::Armv7a
| ArmArchitecture::Armv7ve
| ArmArchitecture::Armv7m
| ArmArchitecture::Armv7r
| ArmArchitecture::Armv7s
| ArmArchitecture::Armv8
| ArmArchitecture::Armv8a
| ArmArchitecture::Armv8_1a
| ArmArchitecture::Armv8_2a
| ArmArchitecture::Armv8_3a
| ArmArchitecture::Armv8_4a
| ArmArchitecture::Armv8_5a
| ArmArchitecture::Armv8mBase
| ArmArchitecture::Armv8mMain
| ArmArchitecture::Armv8r
| ArmArchitecture::Armebv7r => false,
ArmArchitecture::Thumbeb
| ArmArchitecture::Thumbv6m
| ArmArchitecture::Thumbv7a
| ArmArchitecture::Thumbv7em
| ArmArchitecture::Thumbv7m
| ArmArchitecture::Thumbv7neon
| ArmArchitecture::Thumbv8mBase
| ArmArchitecture::Thumbv8mMain => true,
}
}
pub fn pointer_width(self) -> PointerWidth {
match self {
ArmArchitecture::Arm
| ArmArchitecture::Armeb
| ArmArchitecture::Armv4
| ArmArchitecture::Armv4t
| ArmArchitecture::Armv5t
| ArmArchitecture::Armv5te
| ArmArchitecture::Armv5tej
| ArmArchitecture::Armv6
| ArmArchitecture::Armv6j
| ArmArchitecture::Armv6k
| ArmArchitecture::Armv6z
| ArmArchitecture::Armv6kz
| ArmArchitecture::Armv6t2
| ArmArchitecture::Armv6m
| ArmArchitecture::Armv7
| ArmArchitecture::Armv7a
| ArmArchitecture::Armv7ve
| ArmArchitecture::Armv7m
| ArmArchitecture::Armv7r
| ArmArchitecture::Armv7s
| ArmArchitecture::Armv8
| ArmArchitecture::Armv8a
| ArmArchitecture::Armv8_1a
| ArmArchitecture::Armv8_2a
| ArmArchitecture::Armv8_3a
| ArmArchitecture::Armv8_4a
| ArmArchitecture::Armv8_5a
| ArmArchitecture::Armv8mBase
| ArmArchitecture::Armv8mMain
| ArmArchitecture::Armv8r
| ArmArchitecture::Armebv7r
| ArmArchitecture::Thumbeb
| ArmArchitecture::Thumbv6m
| ArmArchitecture::Thumbv7a
| ArmArchitecture::Thumbv7em
| ArmArchitecture::Thumbv7m
| ArmArchitecture::Thumbv7neon
| ArmArchitecture::Thumbv8mBase
| ArmArchitecture::Thumbv8mMain => PointerWidth::U32,
}
}
pub fn endianness(self) -> Endianness {
match self {
ArmArchitecture::Arm
| ArmArchitecture::Armv4
| ArmArchitecture::Armv4t
| ArmArchitecture::Armv5t
| ArmArchitecture::Armv5te
| ArmArchitecture::Armv5tej
| ArmArchitecture::Armv6
| ArmArchitecture::Armv6j
| ArmArchitecture::Armv6k
| ArmArchitecture::Armv6z
| ArmArchitecture::Armv6kz
| ArmArchitecture::Armv6t2
| ArmArchitecture::Armv6m
| ArmArchitecture::Armv7
| ArmArchitecture::Armv7a
| ArmArchitecture::Armv7ve
| ArmArchitecture::Armv7m
| ArmArchitecture::Armv7r
| ArmArchitecture::Armv7s
| ArmArchitecture::Armv8
| ArmArchitecture::Armv8a
| ArmArchitecture::Armv8_1a
| ArmArchitecture::Armv8_2a
| ArmArchitecture::Armv8_3a
| ArmArchitecture::Armv8_4a
| ArmArchitecture::Armv8_5a
| ArmArchitecture::Armv8mBase
| ArmArchitecture::Armv8mMain
| ArmArchitecture::Armv8r
| ArmArchitecture::Thumbv6m
| ArmArchitecture::Thumbv7a
| ArmArchitecture::Thumbv7em
| ArmArchitecture::Thumbv7m
| ArmArchitecture::Thumbv7neon
| ArmArchitecture::Thumbv8mBase
| ArmArchitecture::Thumbv8mMain => Endianness::Little,
ArmArchitecture::Armeb | ArmArchitecture::Armebv7r | ArmArchitecture::Thumbeb => {
Endianness::Big
}
}
}
}
impl Aarch64Architecture {
pub fn is_thumb(self) -> bool {
match self {
Aarch64Architecture::Aarch64 | Aarch64Architecture::Aarch64be => false,
}
}
pub fn pointer_width(self) -> PointerWidth {
match self {
Aarch64Architecture::Aarch64 | Aarch64Architecture::Aarch64be => PointerWidth::U64,
}
}
pub fn endianness(self) -> Endianness {
match self {
Aarch64Architecture::Aarch64 => Endianness::Little,
Aarch64Architecture::Aarch64be => Endianness::Big,
}
}
}
#[derive(Clone, Debug, Eq)]
pub enum CustomVendor {
Owned(Box<String>),
Static(&'static str),
}
impl CustomVendor {
pub fn as_str(&self) -> &str {
match self {
CustomVendor::Owned(s) => s,
CustomVendor::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)
}
}
#[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),
}
#[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,
Ios,
L4re,
Linux,
MacOSX { major: u16, minor: u16, patch: u16 },
Nebulet,
Netbsd,
None_,
Openbsd,
Redox,
Solaris,
Uefi,
VxWorks,
Wasi,
Windows,
}
#[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,
Musl,
Musleabi,
Musleabihf,
Muslabi64,
Msvc,
Kernel,
Uclibc,
Sgx,
Softfloat,
Spe,
}
#[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 {
Architecture::Unknown => Err(()),
Architecture::Arm(arm) => Ok(arm.endianness()),
Architecture::Aarch64(aarch) => Ok(aarch.endianness()),
Architecture::AmdGcn
| Architecture::Asmjs
| Architecture::Hexagon
| Architecture::I386
| Architecture::I586
| Architecture::I686
| Architecture::Mips64el
| Architecture::Mipsel
| Architecture::Mipsisa32r6el
| Architecture::Mipsisa64r6el
| Architecture::Msp430
| Architecture::Nvptx64
| Architecture::Powerpc64le
| Architecture::Riscv32
| Architecture::Riscv32i
| Architecture::Riscv32imac
| Architecture::Riscv32imc
| Architecture::Riscv64
| Architecture::Riscv64gc
| Architecture::Riscv64imac
| Architecture::Wasm32
| Architecture::X86_64 => Ok(Endianness::Little),
Architecture::Mips
| Architecture::Mips64
| Architecture::Mipsisa32r6
| Architecture::Mipsisa64r6
| Architecture::Powerpc
| Architecture::Powerpc64
| Architecture::S390x
| Architecture::Sparc
| Architecture::Sparc64
| Architecture::Sparcv9 => Ok(Endianness::Big),
}
}
pub fn pointer_width(self) -> Result<PointerWidth, ()> {
match self {
Architecture::Unknown => Err(()),
Architecture::Msp430 => Ok(PointerWidth::U16),
Architecture::Arm(arm) => Ok(arm.pointer_width()),
Architecture::Aarch64(aarch) => Ok(aarch.pointer_width()),
Architecture::Asmjs
| Architecture::Hexagon
| Architecture::I386
| Architecture::I586
| Architecture::I686
| Architecture::Mipsel
| Architecture::Mipsisa32r6
| Architecture::Mipsisa32r6el
| Architecture::Riscv32
| Architecture::Riscv32i
| Architecture::Riscv32imac
| Architecture::Riscv32imc
| Architecture::Sparc
| Architecture::Wasm32
| Architecture::Mips
| Architecture::Powerpc => Ok(PointerWidth::U32),
Architecture::AmdGcn
| Architecture::Mips64el
| Architecture::Mipsisa64r6
| Architecture::Mipsisa64r6el
| Architecture::Powerpc64le
| Architecture::Riscv64
| Architecture::Riscv64gc
| Architecture::Riscv64imac
| Architecture::X86_64
| Architecture::Mips64
| Architecture::Nvptx64
| Architecture::Powerpc64
| Architecture::S390x
| Architecture::Sparc64
| Architecture::Sparcv9 => 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 => BinaryFormat::Wasm,
_ => BinaryFormat::Unknown,
},
_ => BinaryFormat::Elf,
}
}
impl fmt::Display for ArmArchitecture {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let s = match *self {
ArmArchitecture::Arm => "arm",
ArmArchitecture::Armeb => "armeb",
ArmArchitecture::Armv4 => "armv4",
ArmArchitecture::Armv4t => "armv4t",
ArmArchitecture::Armv5t => "armv5t",
ArmArchitecture::Armv5te => "armv5te",
ArmArchitecture::Armv5tej => "armv5tej",
ArmArchitecture::Armv6 => "armv6",
ArmArchitecture::Armv6j => "armv6j",
ArmArchitecture::Armv6k => "armv6k",
ArmArchitecture::Armv6z => "armv6z",
ArmArchitecture::Armv6kz => "armv6kz",
ArmArchitecture::Armv6t2 => "armv6t2",
ArmArchitecture::Armv6m => "armv6m",
ArmArchitecture::Armv7 => "armv7",
ArmArchitecture::Armv7a => "armv7a",
ArmArchitecture::Armv7ve => "armv7ve",
ArmArchitecture::Armv7m => "armv7m",
ArmArchitecture::Armv7r => "armv7r",
ArmArchitecture::Armv7s => "armv7s",
ArmArchitecture::Armv8 => "armv8",
ArmArchitecture::Armv8a => "armv8a",
ArmArchitecture::Armv8_1a => "armv8.1a",
ArmArchitecture::Armv8_2a => "armv8.2a",
ArmArchitecture::Armv8_3a => "armv8.3a",
ArmArchitecture::Armv8_4a => "armv8.4a",
ArmArchitecture::Armv8_5a => "armv8.5a",
ArmArchitecture::Armv8mBase => "armv8m.base",
ArmArchitecture::Armv8mMain => "armv8m.main",
ArmArchitecture::Armv8r => "armv8r",
ArmArchitecture::Thumbeb => "thumbeb",
ArmArchitecture::Thumbv6m => "thumbv6m",
ArmArchitecture::Thumbv7a => "thumbv7a",
ArmArchitecture::Thumbv7em => "thumbv7em",
ArmArchitecture::Thumbv7m => "thumbv7m",
ArmArchitecture::Thumbv7neon => "thumbv7neon",
ArmArchitecture::Thumbv8mBase => "thumbv8m.base",
ArmArchitecture::Thumbv8mMain => "thumbv8m.main",
ArmArchitecture::Armebv7r => "armebv7r",
};
f.write_str(s)
}
}
impl fmt::Display for Aarch64Architecture {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let s = match *self {
Aarch64Architecture::Aarch64 => "aarch64",
Aarch64Architecture::Aarch64be => "aarch64be",
};
f.write_str(s)
}
}
impl fmt::Display for Architecture {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Architecture::Arm(arm) => arm.fmt(f),
Architecture::Aarch64(aarch) => aarch.fmt(f),
Architecture::Unknown => f.write_str("unknown"),
Architecture::AmdGcn => f.write_str("amdgcn"),
Architecture::Asmjs => f.write_str("asmjs"),
Architecture::Hexagon => f.write_str("hexagon"),
Architecture::I386 => f.write_str("i386"),
Architecture::I586 => f.write_str("i586"),
Architecture::I686 => f.write_str("i686"),
Architecture::Mips => f.write_str("mips"),
Architecture::Mips64 => f.write_str("mips64"),
Architecture::Mips64el => f.write_str("mips64el"),
Architecture::Mipsel => f.write_str("mipsel"),
Architecture::Mipsisa32r6 => f.write_str("mipsisa32r6"),
Architecture::Mipsisa32r6el => f.write_str("mipsisa32r6el"),
Architecture::Mipsisa64r6 => f.write_str("mipsisa64r6"),
Architecture::Mipsisa64r6el => f.write_str("mipsisa64r6el"),
Architecture::Msp430 => f.write_str("msp430"),
Architecture::Nvptx64 => f.write_str("nvptx64"),
Architecture::Powerpc => f.write_str("powerpc"),
Architecture::Powerpc64 => f.write_str("powerpc64"),
Architecture::Powerpc64le => f.write_str("powerpc64le"),
Architecture::Riscv32 => f.write_str("riscv32"),
Architecture::Riscv32i => f.write_str("riscv32i"),
Architecture::Riscv32imac => f.write_str("riscv32imac"),
Architecture::Riscv32imc => f.write_str("riscv32imc"),
Architecture::Riscv64 => f.write_str("riscv64"),
Architecture::Riscv64gc => f.write_str("riscv64gc"),
Architecture::Riscv64imac => f.write_str("riscv64imac"),
Architecture::S390x => f.write_str("s390x"),
Architecture::Sparc => f.write_str("sparc"),
Architecture::Sparc64 => f.write_str("sparc64"),
Architecture::Sparcv9 => f.write_str("sparcv9"),
Architecture::Wasm32 => f.write_str("wasm32"),
Architecture::X86_64 => f.write_str("x86_64"),
}
}
}
impl FromStr for ArmArchitecture {
type Err = ();
fn from_str(s: &str) -> Result<Self, ()> {
Ok(match s {
"arm" => ArmArchitecture::Arm,
"armeb" => ArmArchitecture::Armeb,
"armv4" => ArmArchitecture::Armv4,
"armv4t" => ArmArchitecture::Armv4t,
"armv5t" => ArmArchitecture::Armv5t,
"armv5te" => ArmArchitecture::Armv5te,
"armv5tej" => ArmArchitecture::Armv5tej,
"armv6" => ArmArchitecture::Armv6,
"armv6j" => ArmArchitecture::Armv6j,
"armv6k" => ArmArchitecture::Armv6k,
"armv6z" => ArmArchitecture::Armv6z,
"armv6kz" => ArmArchitecture::Armv6kz,
"armv6t2" => ArmArchitecture::Armv6t2,
"armv6m" => ArmArchitecture::Armv6m,
"armv7" => ArmArchitecture::Armv7,
"armv7a" => ArmArchitecture::Armv7a,
"armv7ve" => ArmArchitecture::Armv7ve,
"armv7m" => ArmArchitecture::Armv7m,
"armv7r" => ArmArchitecture::Armv7r,
"armv7s" => ArmArchitecture::Armv7s,
"armv8" => ArmArchitecture::Armv8,
"armv8a" => ArmArchitecture::Armv8a,
"armv8.1a" => ArmArchitecture::Armv8_1a,
"armv8.2a" => ArmArchitecture::Armv8_2a,
"armv8.3a" => ArmArchitecture::Armv8_3a,
"armv8.4a" => ArmArchitecture::Armv8_4a,
"armv8.5a" => ArmArchitecture::Armv8_5a,
"armv8m.base" => ArmArchitecture::Armv8mBase,
"armv8m.main" => ArmArchitecture::Armv8mMain,
"armv8r" => ArmArchitecture::Armv8r,
"thumbeb" => ArmArchitecture::Thumbeb,
"thumbv6m" => ArmArchitecture::Thumbv6m,
"thumbv7a" => ArmArchitecture::Thumbv7a,
"thumbv7em" => ArmArchitecture::Thumbv7em,
"thumbv7m" => ArmArchitecture::Thumbv7m,
"thumbv7neon" => ArmArchitecture::Thumbv7neon,
"thumbv8m.base" => ArmArchitecture::Thumbv8mBase,
"thumbv8m.main" => ArmArchitecture::Thumbv8mMain,
"armebv7r" => ArmArchitecture::Armebv7r,
_ => return Err(()),
})
}
}
impl FromStr for Aarch64Architecture {
type Err = ();
fn from_str(s: &str) -> Result<Self, ()> {
Ok(match s {
"aarch64" => Aarch64Architecture::Aarch64,
"arm64" => Aarch64Architecture::Aarch64,
"aarch64be" => Aarch64Architecture::Aarch64be,
_ => return Err(()),
})
}
}
impl FromStr for Architecture {
type Err = ();
fn from_str(s: &str) -> Result<Self, ()> {
Ok(match s {
"unknown" => Architecture::Unknown,
"amdgcn" => Architecture::AmdGcn,
"asmjs" => Architecture::Asmjs,
"hexagon" => Architecture::Hexagon,
"i386" => Architecture::I386,
"i586" => Architecture::I586,
"i686" => Architecture::I686,
"mips" => Architecture::Mips,
"mips64" => Architecture::Mips64,
"mips64el" => Architecture::Mips64el,
"mipsel" => Architecture::Mipsel,
"mipsisa32r6" => Architecture::Mipsisa32r6,
"mipsisa32r6el" => Architecture::Mipsisa32r6el,
"mipsisa64r6" => Architecture::Mipsisa64r6,
"mipsisa64r6el" => Architecture::Mipsisa64r6el,
"msp430" => Architecture::Msp430,
"nvptx64" => Architecture::Nvptx64,
"powerpc" => Architecture::Powerpc,
"powerpc64" => Architecture::Powerpc64,
"powerpc64le" => Architecture::Powerpc64le,
"riscv32" => Architecture::Riscv32,
"riscv32i" => Architecture::Riscv32i,
"riscv32imac" => Architecture::Riscv32imac,
"riscv32imc" => Architecture::Riscv32imc,
"riscv64" => Architecture::Riscv64,
"riscv64gc" => Architecture::Riscv64gc,
"riscv64imac" => Architecture::Riscv64imac,
"s390x" => Architecture::S390x,
"sparc" => Architecture::Sparc,
"sparc64" => Architecture::Sparc64,
"sparcv9" => Architecture::Sparcv9,
"wasm32" => Architecture::Wasm32,
"x86_64" => Architecture::X86_64,
_ => {
if let Ok(arm) = ArmArchitecture::from_str(s) {
Architecture::Arm(arm)
} else if let Ok(aarch64) = Aarch64Architecture::from_str(s) {
Architecture::Aarch64(aarch64)
} else {
return Err(());
}
}
})
}
}
impl fmt::Display for Vendor {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let s = match *self {
Vendor::Unknown => "unknown",
Vendor::Amd => "amd",
Vendor::Apple => "apple",
Vendor::Experimental => "experimental",
Vendor::Fortanix => "fortanix",
Vendor::Nvidia => "nvidia",
Vendor::Pc => "pc",
Vendor::Rumprun => "rumprun",
Vendor::Sun => "sun",
Vendor::Uwp => "uwp",
Vendor::Wrs => "wrs",
Vendor::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" => Vendor::Unknown,
"amd" => Vendor::Amd,
"apple" => Vendor::Apple,
"experimental" => Vendor::Experimental,
"fortanix" => Vendor::Fortanix,
"nvidia" => Vendor::Nvidia,
"pc" => Vendor::Pc,
"rumprun" => Vendor::Rumprun,
"sun" => Vendor::Sun,
"uwp" => Vendor::Uwp,
"wrs" => Vendor::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().nth(0).unwrap().is_ascii_lowercase() {
return Err(());
}
if custom.chars().any(|c: char| {
!(c.is_ascii_lowercase() || c.is_ascii_digit() || c == '_' || c == '.')
}) {
return Err(());
}
Vendor::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 {
OperatingSystem::Unknown => "unknown",
OperatingSystem::AmdHsa => "amdhsa",
OperatingSystem::Bitrig => "bitrig",
OperatingSystem::Cloudabi => "cloudabi",
OperatingSystem::Cuda => "cuda",
OperatingSystem::Darwin => "darwin",
OperatingSystem::Dragonfly => "dragonfly",
OperatingSystem::Emscripten => "emscripten",
OperatingSystem::Freebsd => "freebsd",
OperatingSystem::Fuchsia => "fuchsia",
OperatingSystem::Haiku => "haiku",
OperatingSystem::Hermit => "hermit",
OperatingSystem::Ios => "ios",
OperatingSystem::L4re => "l4re",
OperatingSystem::Linux => "linux",
OperatingSystem::MacOSX {
major,
minor,
patch,
} => {
return write!(f, "macosx{}.{}.{}", major, minor, patch);
}
OperatingSystem::Nebulet => "nebulet",
OperatingSystem::Netbsd => "netbsd",
OperatingSystem::None_ => "none",
OperatingSystem::Openbsd => "openbsd",
OperatingSystem::Redox => "redox",
OperatingSystem::Solaris => "solaris",
OperatingSystem::Uefi => "uefi",
OperatingSystem::VxWorks => "vxworks",
OperatingSystem::Wasi => "wasi",
OperatingSystem::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(OperatingSystem::MacOSX {
major,
minor,
patch,
});
}
Ok(match s {
"unknown" => OperatingSystem::Unknown,
"amdhsa" => OperatingSystem::AmdHsa,
"bitrig" => OperatingSystem::Bitrig,
"cloudabi" => OperatingSystem::Cloudabi,
"cuda" => OperatingSystem::Cuda,
"darwin" => OperatingSystem::Darwin,
"dragonfly" => OperatingSystem::Dragonfly,
"emscripten" => OperatingSystem::Emscripten,
"freebsd" => OperatingSystem::Freebsd,
"fuchsia" => OperatingSystem::Fuchsia,
"haiku" => OperatingSystem::Haiku,
"hermit" => OperatingSystem::Hermit,
"ios" => OperatingSystem::Ios,
"l4re" => OperatingSystem::L4re,
"linux" => OperatingSystem::Linux,
"nebulet" => OperatingSystem::Nebulet,
"netbsd" => OperatingSystem::Netbsd,
"none" => OperatingSystem::None_,
"openbsd" => OperatingSystem::Openbsd,
"redox" => OperatingSystem::Redox,
"solaris" => OperatingSystem::Solaris,
"uefi" => OperatingSystem::Uefi,
"vxworks" => OperatingSystem::VxWorks,
"wasi" => OperatingSystem::Wasi,
"windows" => OperatingSystem::Windows,
_ => return Err(()),
})
}
}
impl fmt::Display for Environment {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let s = match *self {
Environment::Unknown => "unknown",
Environment::AmdGiz => "amdgiz",
Environment::Android => "android",
Environment::Androideabi => "androideabi",
Environment::Eabi => "eabi",
Environment::Eabihf => "eabihf",
Environment::Gnu => "gnu",
Environment::Gnuabi64 => "gnuabi64",
Environment::Gnueabi => "gnueabi",
Environment::Gnueabihf => "gnueabihf",
Environment::Gnuspe => "gnuspe",
Environment::Gnux32 => "gnux32",
Environment::Musl => "musl",
Environment::Musleabi => "musleabi",
Environment::Musleabihf => "musleabihf",
Environment::Muslabi64 => "muslabi64",
Environment::Msvc => "msvc",
Environment::Kernel => "kernel",
Environment::Uclibc => "uclibc",
Environment::Sgx => "sgx",
Environment::Softfloat => "softfloat",
Environment::Spe => "spe",
};
f.write_str(s)
}
}
impl FromStr for Environment {
type Err = ();
fn from_str(s: &str) -> Result<Self, ()> {
Ok(match s {
"unknown" => Environment::Unknown,
"amdgiz" => Environment::AmdGiz,
"android" => Environment::Android,
"androideabi" => Environment::Androideabi,
"eabi" => Environment::Eabi,
"eabihf" => Environment::Eabihf,
"gnu" => Environment::Gnu,
"gnuabi64" => Environment::Gnuabi64,
"gnueabi" => Environment::Gnueabi,
"gnueabihf" => Environment::Gnueabihf,
"gnuspe" => Environment::Gnuspe,
"gnux32" => Environment::Gnux32,
"musl" => Environment::Musl,
"musleabi" => Environment::Musleabi,
"musleabihf" => Environment::Musleabihf,
"muslabi64" => Environment::Muslabi64,
"msvc" => Environment::Msvc,
"kernel" => Environment::Kernel,
"uclibc" => Environment::Uclibc,
"sgx" => Environment::Sgx,
"softfloat" => Environment::Softfloat,
"spe" => Environment::Spe,
_ => return Err(()),
})
}
}
impl fmt::Display for BinaryFormat {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let s = match *self {
BinaryFormat::Unknown => "unknown",
BinaryFormat::Elf => "elf",
BinaryFormat::Coff => "coff",
BinaryFormat::Macho => "macho",
BinaryFormat::Wasm => "wasm",
};
f.write_str(s)
}
}
impl FromStr for BinaryFormat {
type Err = ();
fn from_str(s: &str) -> Result<Self, ()> {
Ok(match s {
"unknown" => BinaryFormat::Unknown,
"elf" => BinaryFormat::Elf,
"coff" => BinaryFormat::Coff,
"macho" => BinaryFormat::Macho,
"wasm" => BinaryFormat::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",
"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-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-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",
"thumbv7em-none-eabi",
"thumbv7em-none-eabihf",
"thumbv7m-none-eabi",
"thumbv7neon-linux-androideabi",
"thumbv7neon-unknown-linux-gnueabihf",
"thumbv8m.base-none-eabi",
"thumbv8m.main-none-eabi",
"thumbv8m.main-none-eabihf",
"wasm32-experimental-emscripten",
"wasm32-unknown-emscripten",
"wasm32-unknown-unknown",
"wasm32-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-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,
})
);
}
}