use crate::error::Reason;
use std::borrow::Cow;
mod builtins;
pub use builtins::ALL_BUILTINS;
#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct Triple(pub Cow<'static, str>);
#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct Arch(pub Cow<'static, str>);
#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct Vendor(pub Cow<'static, str>);
#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct Os(pub Cow<'static, str>);
#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct Family(pub Cow<'static, str>);
#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct Env(pub Cow<'static, str>);
macro_rules! field_impls {
($kind:ident) => {
impl $kind {
#[inline]
pub fn new(val: impl Into<Cow<'static, str>>) -> Self {
Self(val.into())
}
#[inline]
pub const fn new_const(val: &'static str) -> Self {
Self(Cow::Borrowed(val))
}
#[inline]
pub fn as_str(&self) -> &str {
&*self.0
}
}
impl AsRef<str> for $kind {
#[inline]
fn as_ref(&self) -> &str {
&*self.0
}
}
impl std::fmt::Display for $kind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(self.as_str())
}
}
};
}
field_impls!(Triple);
field_impls!(Arch);
field_impls!(Vendor);
field_impls!(Os);
field_impls!(Family);
field_impls!(Env);
macro_rules! target_enum {
(
$(#[$outer:meta])*
pub enum $kind:ident {
$(
$(#[$inner:ident $($args:tt)*])*
$name:ident $(= $value:expr)?,
)+
}
) => {
$(#[$outer])*
#[allow(non_camel_case_types)]
pub enum $kind {
$(
$(#[$inner $($args)*])*
$name $(= $value)?,
)+
}
impl_from_str! {
$kind {
$(
$(#[$inner $($args)*])*
$name $(= $value)?,
)+
}
}
};
}
macro_rules! impl_from_str {
(
$kind:ident {
$(
$(#[$attr:ident $($args:tt)*])*
$name:ident $(= $value:expr)?,
)+
}
) => {
impl std::str::FromStr for $kind {
type Err = Reason;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
$(stringify!($name) => Ok(Self::$name),)+
_ => Err(Reason::Unexpected(&[$(stringify!($name),)+])),
}
}
}
};
}
target_enum! {
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub enum Endian {
big,
little,
}
}
#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct TargetInfo {
pub triple: Triple,
pub os: Option<Os>,
pub arch: Arch,
pub env: Option<Env>,
pub vendor: Option<Vendor>,
pub family: Option<Family>,
pub pointer_width: u8,
pub endian: Endian,
}
pub fn get_builtin_target_by_triple(triple: &str) -> Option<&'static TargetInfo> {
ALL_BUILTINS
.binary_search_by(|ti| ti.triple.as_ref().cmp(triple))
.map(|i| &ALL_BUILTINS[i])
.ok()
}
pub fn rustc_version() -> &'static str {
builtins::RUSTC_VERSION
}
#[cfg(test)]
mod test {
use crate::targets::get_builtin_target_by_triple;
use std::collections::{BTreeSet, HashSet};
#[test]
fn targets_are_sorted() {
for window in super::ALL_BUILTINS.windows(2) {
assert!(window[0].triple < window[1].triple);
}
}
#[test]
fn has_ios() {
assert_eq!(
8,
super::ALL_BUILTINS
.iter()
.filter(|ti| ti.os == Some(super::Os::ios))
.count()
);
}
#[test]
fn set_map_key() {
let target_info =
get_builtin_target_by_triple("x86_64-unknown-linux-gnu").expect("known target");
let mut btree_set = BTreeSet::new();
btree_set.insert(target_info);
let mut hash_set = HashSet::new();
hash_set.insert(target_info);
}
}