Skip to main content

target_tuples/
lib.rs

1#![deny(warnings, unsafe_code)]
2#![cfg_attr(not(any(doc, test)), no_std)]
3
4#[cfg(feature = "alloc")]
5extern crate alloc;
6
7pub mod pieces;
8
9use core::{ops::Deref, str::FromStr};
10
11use pieces::*;
12
13#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
14pub struct CanonicalTarget {
15    pub arch: Architecture,
16    pub vendor: Option<Vendor>,
17    pub sys: System,
18}
19
20impl CanonicalTarget {
21    pub fn guess_vendor(&self) -> Vendor {
22        if let Some(vendor) = self.vendor {
23            return vendor;
24        }
25        match (self.arch, self.sys.os()) {
26            (
27                Architecture::X86_16(_) | Architecture::X86_32(_) | Architecture::X86_64 { .. },
28                _,
29            ) => Vendor::PC,
30            (Architecture::Wc65c816, _) => Vendor::WDC,
31            _ => Vendor::Unknown,
32        }
33    }
34}
35
36impl core::str::FromStr for CanonicalTarget {
37    type Err = UnknownError;
38
39    fn from_str(s: &str) -> Result<Self, Self::Err> {
40        let (arch, rest) = s.split_once('-').ok_or(UnknownError)?;
41
42        let arch = arch.parse::<Architecture>()?;
43
44        let (vendor, sys) = if let Some((a, b)) = rest.split_once('-') {
45            if b.contains('-') {
46                // 4 component, this is vendor-os-env
47                (Some(Vendor::parse(a)), b.parse::<System>()?)
48            } else if let Ok(sys) = rest.parse::<System>() {
49                (None, sys)
50            } else {
51                (Some(Vendor::parse(a)), b.parse::<System>()?)
52            }
53        } else {
54            (None, rest.parse::<System>()?)
55        };
56
57        Ok(CanonicalTarget { arch, vendor, sys })
58    }
59}
60
61impl core::fmt::Display for CanonicalTarget {
62    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
63        self.arch.fmt(f)?;
64        f.write_str("-")?;
65
66        self.guess_vendor().fmt(f)?;
67
68        f.write_str("-")?;
69
70        self.sys.fmt(f)
71    }
72}
73
74#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
75pub struct TargetRef<'a> {
76    exact: &'a str,
77    canon: CanonicalTarget,
78}
79
80impl<'a> Deref for TargetRef<'a> {
81    type Target = CanonicalTarget;
82
83    fn deref(&self) -> &CanonicalTarget {
84        &self.canon
85    }
86}
87
88impl<'a> TargetRef<'a> {
89    pub fn try_parse(st: &'a str) -> Result<Self, UnknownError> {
90        let canon = CanonicalTarget::from_str(st)?;
91
92        Ok(TargetRef { exact: st, canon })
93    }
94
95    pub fn parse(st: &'a str) -> Self {
96        match Self::try_parse(st) {
97            Ok(targ) => targ,
98            Err(_) => panic!("Unknown target: {}", st),
99        }
100    }
101
102    pub fn exact(&self) -> &'a str {
103        self.exact
104    }
105
106    pub fn canonical(&self) -> CanonicalTarget {
107        self.canon
108    }
109}
110
111#[cfg(feature = "alloc")]
112mod feature_alloc {
113    use core::{ops::Deref, str::FromStr};
114
115    use crate::{pieces::UnknownError, CanonicalTarget, TargetRef};
116    use alloc::string::{String, ToString};
117
118    #[derive(Clone, Debug, Hash, PartialEq, Eq)]
119    pub struct OwnedTarget {
120        exact: String,
121        canon: CanonicalTarget,
122    }
123
124    impl<'a> Deref for OwnedTarget {
125        type Target = CanonicalTarget;
126
127        fn deref(&self) -> &CanonicalTarget {
128            &self.canon
129        }
130    }
131
132    impl OwnedTarget {
133        pub fn from_canonical(canon: CanonicalTarget) -> Self {
134            let exact = canon.to_string();
135
136            Self { exact, canon }
137        }
138        pub fn from_owned(st: String) -> Result<Self, UnknownError> {
139            let canon = CanonicalTarget::from_str(&st)?;
140
141            Ok(OwnedTarget { exact: st, canon })
142        }
143
144        pub fn into_exact(self) -> String {
145            self.exact
146        }
147
148        pub fn borrow<'a>(&'a self) -> TargetRef<'a> {
149            TargetRef {
150                exact: &self.exact,
151                canon: self.canon,
152            }
153        }
154    }
155
156    impl FromStr for OwnedTarget {
157        type Err = UnknownError;
158        fn from_str(s: &str) -> Result<Self, Self::Err> {
159            Self::from_owned(s.to_string())
160        }
161    }
162}
163
164#[cfg(feature = "alloc")]
165pub use feature_alloc::*;
166
167#[doc(hidden)]
168pub use core as __core;
169
170#[doc(hidden)]
171pub use target_tuples_macro::__match_targets;
172
173#[macro_export]
174macro_rules! match_targets {
175    {
176        $expr:tt {
177            $($inner:tt)*
178        }
179    } => {
180        $crate::__match_targets!([$crate] $expr {
181            $($inner)*
182        })
183    };
184}