target_lexicon/
targets.rs

1// This file defines all the identifier enums and target-aware logic.
2
3use crate::triple::{Endianness, PointerWidth, Triple};
4use alloc::borrow::Cow;
5use alloc::boxed::Box;
6use alloc::format;
7use alloc::string::String;
8use core::fmt;
9use core::hash::{Hash, Hasher};
10use core::str::FromStr;
11
12/// The "architecture" field, which in some cases also specifies a specific
13/// subarchitecture.
14#[cfg_attr(feature = "rust_1_40", non_exhaustive)]
15#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
16#[allow(missing_docs)]
17pub enum Architecture {
18    Unknown,
19    Arm(ArmArchitecture),
20    AmdGcn,
21    Aarch64(Aarch64Architecture),
22    Asmjs,
23    Avr,
24    Bpfeb,
25    Bpfel,
26    Hexagon,
27    X86_32(X86_32Architecture),
28    M68k,
29    LoongArch64,
30    Mips32(Mips32Architecture),
31    Mips64(Mips64Architecture),
32    Msp430,
33    Nvptx64,
34    Pulley32,
35    Pulley64,
36    Powerpc,
37    Powerpc64,
38    Powerpc64le,
39    Riscv32(Riscv32Architecture),
40    Riscv64(Riscv64Architecture),
41    S390x,
42    Sparc,
43    Sparc64,
44    Sparcv9,
45    Wasm32,
46    Wasm64,
47    X86_64,
48    /// x86_64 target that only supports Haswell-compatible Intel chips.
49    X86_64h,
50    XTensa,
51    Clever(CleverArchitecture),
52    /// A software machine that produces zero-knowledge proofs of the execution.
53    ///
54    /// See https://wiki.polygon.technology/docs/category/zk-assembly/
55    #[cfg(feature = "arch_zkasm")]
56    ZkAsm,
57}
58
59#[cfg_attr(feature = "rust_1_40", non_exhaustive)]
60#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
61#[allow(missing_docs)]
62pub enum ArmArchitecture {
63    Arm, // Generic arm
64    Armeb,
65    Armv4,
66    Armv4t,
67    Armv5t,
68    Armv5te,
69    Armv5tej,
70    Armv6,
71    Armv6j,
72    Armv6k,
73    Armv6z,
74    Armv6kz,
75    Armv6t2,
76    Armv6m,
77    Armv7,
78    Armv7a,
79    Armv7k,
80    Armv7ve,
81    Armv7m,
82    Armv7r,
83    Armv7s,
84    Armv8,
85    Armv8a,
86    Armv8_1a,
87    Armv8_2a,
88    Armv8_3a,
89    Armv8_4a,
90    Armv8_5a,
91    Armv8mBase,
92    Armv8mMain,
93    Armv8r,
94
95    Armebv7r,
96
97    Thumbeb,
98    Thumbv4t,
99    Thumbv5te,
100    Thumbv6m,
101    Thumbv7a,
102    Thumbv7em,
103    Thumbv7m,
104    Thumbv7neon,
105    Thumbv8mBase,
106    Thumbv8mMain,
107}
108
109#[cfg_attr(feature = "rust_1_40", non_exhaustive)]
110#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
111#[allow(missing_docs)]
112pub enum Aarch64Architecture {
113    Aarch64,
114    Aarch64be,
115}
116
117// #[cfg_attr(feature = "rust_1_40", non_exhaustive)]
118// #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
119// #[allow(missing_docs)]
120// pub enum ArmFpu {
121//     Vfp,
122//     Vfpv2,
123//     Vfpv3,
124//     Vfpv3Fp16,
125//     Vfpv3Xd,
126//     Vfpv3XdFp16,
127//     Neon,
128//     NeonVfpv3,
129//     NeonVfpv4,
130//     Vfpv4,
131//     Vfpv4D16,
132//     Fpv4SpD16,
133//     Fpv5SpD16,
134//     Fpv5D16,
135//     FpArmv8,
136//     NeonFpArmv8,
137//     CryptoNeonFpArmv8,
138// }
139
140impl ArmArchitecture {
141    /// Test if this architecture uses the Thumb instruction set.
142    #[rustfmt::skip]
143    pub fn is_thumb(self) -> bool {
144        use ArmArchitecture::*;
145
146        match self {
147            Arm
148            | Armeb
149            | Armv4
150            | Armv4t
151            | Armv5t
152            | Armv5te
153            | Armv5tej
154            | Armv6
155            | Armv6j
156            | Armv6k
157            | Armv6z
158            | Armv6kz
159            | Armv6t2
160            | Armv6m
161            | Armv7
162            | Armv7a
163            | Armv7k
164            | Armv7ve
165            | Armv7m
166            | Armv7r
167            | Armv7s
168            | Armv8
169            | Armv8a
170            | Armv8_1a
171            | Armv8_2a
172            | Armv8_3a
173            | Armv8_4a
174            | Armv8_5a
175            | Armv8mBase
176            | Armv8mMain
177            | Armv8r
178            | Armebv7r => false,
179            Thumbeb
180            | Thumbv4t
181            | Thumbv5te
182            | Thumbv6m
183            | Thumbv7a
184            | Thumbv7em
185            | Thumbv7m
186            | Thumbv7neon
187            | Thumbv8mBase
188            | Thumbv8mMain => true,
189        }
190    }
191
192    // pub fn has_fpu(self) -> Result<&'static [ArmFpu], ()> {
193
194    // }
195
196    /// Return the pointer bit width of this target's architecture.
197    #[rustfmt::skip]
198    pub fn pointer_width(self) -> PointerWidth {
199        use ArmArchitecture::*;
200
201        match self {
202            Arm
203            | Armeb
204            | Armv4
205            | Armv4t
206            | Armv5t
207            | Armv5te
208            | Armv5tej
209            | Armv6
210            | Armv6j
211            | Armv6k
212            | Armv6z
213            | Armv6kz
214            | Armv6t2
215            | Armv6m
216            | Armv7
217            | Armv7a
218            | Armv7k
219            | Armv7ve
220            | Armv7m
221            | Armv7r
222            | Armv7s
223            | Armv8
224            | Armv8a
225            | Armv8_1a
226            | Armv8_2a
227            | Armv8_3a
228            | Armv8_4a
229            | Armv8_5a
230            | Armv8mBase
231            | Armv8mMain
232            | Armv8r
233            | Armebv7r
234            | Thumbeb
235            | Thumbv4t
236            | Thumbv5te
237            | Thumbv6m
238            | Thumbv7a
239            | Thumbv7em
240            | Thumbv7m
241            | Thumbv7neon
242            | Thumbv8mBase
243            | Thumbv8mMain => PointerWidth::U32,
244        }
245    }
246
247    /// Return the endianness of this architecture.
248    #[rustfmt::skip]
249    pub fn endianness(self) -> Endianness {
250        use ArmArchitecture::*;
251
252        match self {
253            Arm
254            | Armv4
255            | Armv4t
256            | Armv5t
257            | Armv5te
258            | Armv5tej
259            | Armv6
260            | Armv6j
261            | Armv6k
262            | Armv6z
263            | Armv6kz
264            | Armv6t2
265            | Armv6m
266            | Armv7
267            | Armv7a
268            | Armv7k
269            | Armv7ve
270            | Armv7m
271            | Armv7r
272            | Armv7s
273            | Armv8
274            | Armv8a
275            | Armv8_1a
276            | Armv8_2a
277            | Armv8_3a
278            | Armv8_4a
279            | Armv8_5a
280            | Armv8mBase
281            | Armv8mMain
282            | Armv8r
283            | Thumbv4t
284            | Thumbv5te
285            | Thumbv6m
286            | Thumbv7a
287            | Thumbv7em
288            | Thumbv7m
289            | Thumbv7neon
290            | Thumbv8mBase
291            | Thumbv8mMain => Endianness::Little,
292            Armeb | Armebv7r | Thumbeb => Endianness::Big,
293        }
294    }
295
296    /// Convert into a string
297    pub fn into_str(self) -> Cow<'static, str> {
298        use ArmArchitecture::*;
299
300        match self {
301            Arm => Cow::Borrowed("arm"),
302            Armeb => Cow::Borrowed("armeb"),
303            Armv4 => Cow::Borrowed("armv4"),
304            Armv4t => Cow::Borrowed("armv4t"),
305            Armv5t => Cow::Borrowed("armv5t"),
306            Armv5te => Cow::Borrowed("armv5te"),
307            Armv5tej => Cow::Borrowed("armv5tej"),
308            Armv6 => Cow::Borrowed("armv6"),
309            Armv6j => Cow::Borrowed("armv6j"),
310            Armv6k => Cow::Borrowed("armv6k"),
311            Armv6z => Cow::Borrowed("armv6z"),
312            Armv6kz => Cow::Borrowed("armv6kz"),
313            Armv6t2 => Cow::Borrowed("armv6t2"),
314            Armv6m => Cow::Borrowed("armv6m"),
315            Armv7 => Cow::Borrowed("armv7"),
316            Armv7a => Cow::Borrowed("armv7a"),
317            Armv7k => Cow::Borrowed("armv7k"),
318            Armv7ve => Cow::Borrowed("armv7ve"),
319            Armv7m => Cow::Borrowed("armv7m"),
320            Armv7r => Cow::Borrowed("armv7r"),
321            Armv7s => Cow::Borrowed("armv7s"),
322            Armv8 => Cow::Borrowed("armv8"),
323            Armv8a => Cow::Borrowed("armv8a"),
324            Armv8_1a => Cow::Borrowed("armv8.1a"),
325            Armv8_2a => Cow::Borrowed("armv8.2a"),
326            Armv8_3a => Cow::Borrowed("armv8.3a"),
327            Armv8_4a => Cow::Borrowed("armv8.4a"),
328            Armv8_5a => Cow::Borrowed("armv8.5a"),
329            Armv8mBase => Cow::Borrowed("armv8m.base"),
330            Armv8mMain => Cow::Borrowed("armv8m.main"),
331            Armv8r => Cow::Borrowed("armv8r"),
332            Thumbeb => Cow::Borrowed("thumbeb"),
333            Thumbv4t => Cow::Borrowed("thumbv4t"),
334            Thumbv5te => Cow::Borrowed("thumbv5te"),
335            Thumbv6m => Cow::Borrowed("thumbv6m"),
336            Thumbv7a => Cow::Borrowed("thumbv7a"),
337            Thumbv7em => Cow::Borrowed("thumbv7em"),
338            Thumbv7m => Cow::Borrowed("thumbv7m"),
339            Thumbv7neon => Cow::Borrowed("thumbv7neon"),
340            Thumbv8mBase => Cow::Borrowed("thumbv8m.base"),
341            Thumbv8mMain => Cow::Borrowed("thumbv8m.main"),
342            Armebv7r => Cow::Borrowed("armebv7r"),
343        }
344    }
345}
346
347impl Aarch64Architecture {
348    /// Test if this architecture uses the Thumb instruction set.
349    pub fn is_thumb(self) -> bool {
350        match self {
351            Aarch64Architecture::Aarch64 | Aarch64Architecture::Aarch64be => false,
352        }
353    }
354
355    // pub fn has_fpu(self) -> Result<&'static [ArmFpu], ()> {
356
357    // }
358
359    /// Return the pointer bit width of this target's architecture.
360    ///
361    /// This function is only aware of the CPU architecture so it is not aware
362    /// of ilp32 ABIs.
363    pub fn pointer_width(self) -> PointerWidth {
364        match self {
365            Aarch64Architecture::Aarch64 | Aarch64Architecture::Aarch64be => PointerWidth::U64,
366        }
367    }
368
369    /// Return the endianness of this architecture.
370    pub fn endianness(self) -> Endianness {
371        match self {
372            Aarch64Architecture::Aarch64 => Endianness::Little,
373            Aarch64Architecture::Aarch64be => Endianness::Big,
374        }
375    }
376
377    /// Convert into a string
378    pub fn into_str(self) -> Cow<'static, str> {
379        use Aarch64Architecture::*;
380
381        match self {
382            Aarch64 => Cow::Borrowed("aarch64"),
383            Aarch64be => Cow::Borrowed("aarch64_be"),
384        }
385    }
386}
387
388#[cfg_attr(feature = "rust_1_40", non_exhaustive)]
389#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
390#[allow(missing_docs)]
391pub enum CleverArchitecture {
392    Clever,
393    Clever1_0,
394}
395
396impl CleverArchitecture {
397    /// Convert into a string
398    pub fn into_str(self) -> Cow<'static, str> {
399        use CleverArchitecture::*;
400
401        match self {
402            Clever => Cow::Borrowed("clever"),
403            Clever1_0 => Cow::Borrowed("clever1.0"),
404        }
405    }
406}
407
408/// An enum for all 32-bit RISC-V architectures.
409#[cfg_attr(feature = "rust_1_40", non_exhaustive)]
410#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
411#[allow(missing_docs)]
412pub enum Riscv32Architecture {
413    Riscv32,
414    Riscv32gc,
415    Riscv32i,
416    Riscv32im,
417    Riscv32ima,
418    Riscv32imac,
419    Riscv32imafc,
420    Riscv32imc,
421}
422
423impl Riscv32Architecture {
424    /// Convert into a string
425    pub fn into_str(self) -> Cow<'static, str> {
426        use Riscv32Architecture::*;
427
428        match self {
429            Riscv32 => Cow::Borrowed("riscv32"),
430            Riscv32gc => Cow::Borrowed("riscv32gc"),
431            Riscv32i => Cow::Borrowed("riscv32i"),
432            Riscv32im => Cow::Borrowed("riscv32im"),
433            Riscv32ima => Cow::Borrowed("riscv32ima"),
434            Riscv32imac => Cow::Borrowed("riscv32imac"),
435            Riscv32imafc => Cow::Borrowed("riscv32imafc"),
436            Riscv32imc => Cow::Borrowed("riscv32imc"),
437        }
438    }
439}
440
441/// An enum for all 64-bit RISC-V architectures.
442#[cfg_attr(feature = "rust_1_40", non_exhaustive)]
443#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
444#[allow(missing_docs)]
445pub enum Riscv64Architecture {
446    Riscv64,
447    Riscv64gc,
448    Riscv64imac,
449}
450
451impl Riscv64Architecture {
452    /// Convert into a string
453    pub fn into_str(self) -> Cow<'static, str> {
454        use Riscv64Architecture::*;
455
456        match self {
457            Riscv64 => Cow::Borrowed("riscv64"),
458            Riscv64gc => Cow::Borrowed("riscv64gc"),
459            Riscv64imac => Cow::Borrowed("riscv64imac"),
460        }
461    }
462}
463
464/// An enum for all 32-bit x86 architectures.
465#[cfg_attr(feature = "rust_1_40", non_exhaustive)]
466#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
467#[allow(missing_docs)]
468pub enum X86_32Architecture {
469    I386,
470    I586,
471    I686,
472}
473
474impl X86_32Architecture {
475    /// Convert into a string
476    pub fn into_str(self) -> Cow<'static, str> {
477        use X86_32Architecture::*;
478
479        match self {
480            I386 => Cow::Borrowed("i386"),
481            I586 => Cow::Borrowed("i586"),
482            I686 => Cow::Borrowed("i686"),
483        }
484    }
485}
486
487/// An enum for all 32-bit MIPS architectures (not just "MIPS32").
488#[cfg_attr(feature = "rust_1_40", non_exhaustive)]
489#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
490#[allow(missing_docs)]
491pub enum Mips32Architecture {
492    Mips,
493    Mipsel,
494    Mipsisa32r6,
495    Mipsisa32r6el,
496}
497
498impl Mips32Architecture {
499    /// Convert into a string
500    pub fn into_str(self) -> Cow<'static, str> {
501        use Mips32Architecture::*;
502
503        match self {
504            Mips => Cow::Borrowed("mips"),
505            Mipsel => Cow::Borrowed("mipsel"),
506            Mipsisa32r6 => Cow::Borrowed("mipsisa32r6"),
507            Mipsisa32r6el => Cow::Borrowed("mipsisa32r6el"),
508        }
509    }
510}
511
512/// An enum for all 64-bit MIPS architectures (not just "MIPS64").
513#[cfg_attr(feature = "rust_1_40", non_exhaustive)]
514#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
515#[allow(missing_docs)]
516pub enum Mips64Architecture {
517    Mips64,
518    Mips64el,
519    Mipsisa64r6,
520    Mipsisa64r6el,
521}
522
523impl Mips64Architecture {
524    /// Convert into a string
525    pub fn into_str(self) -> Cow<'static, str> {
526        use Mips64Architecture::*;
527
528        match self {
529            Mips64 => Cow::Borrowed("mips64"),
530            Mips64el => Cow::Borrowed("mips64el"),
531            Mipsisa64r6 => Cow::Borrowed("mipsisa64r6"),
532            Mipsisa64r6el => Cow::Borrowed("mipsisa64r6el"),
533        }
534    }
535}
536
537/// A string for a `Vendor::Custom` that can either be used in `const`
538/// contexts or hold dynamic strings.
539#[derive(Clone, Debug, Eq)]
540pub enum CustomVendor {
541    /// An owned `String`. This supports the general case.
542    Owned(Box<String>),
543    /// A static `str`, so that `CustomVendor` can be constructed in `const`
544    /// contexts.
545    Static(&'static str),
546}
547
548impl CustomVendor {
549    /// Extracts a string slice.
550    pub fn as_str(&self) -> &str {
551        match self {
552            CustomVendor::Owned(s) => s,
553            CustomVendor::Static(s) => s,
554        }
555    }
556}
557
558impl PartialEq for CustomVendor {
559    fn eq(&self, other: &Self) -> bool {
560        self.as_str() == other.as_str()
561    }
562}
563
564impl Hash for CustomVendor {
565    fn hash<H: Hasher>(&self, state: &mut H) {
566        self.as_str().hash(state)
567    }
568}
569
570/// The "vendor" field, which in practice is little more than an arbitrary
571/// modifier.
572#[cfg_attr(feature = "rust_1_40", non_exhaustive)]
573#[derive(Clone, Debug, PartialEq, Eq, Hash)]
574#[allow(missing_docs)]
575pub enum Vendor {
576    Unknown,
577    Amd,
578    Apple,
579    Espressif,
580    Experimental,
581    Fortanix,
582    Ibm,
583    Kmc,
584    Nintendo,
585    Nvidia,
586    Pc,
587    Rumprun,
588    Sun,
589    Uwp,
590    Wrs,
591
592    /// A custom vendor. "Custom" in this context means that the vendor is
593    /// not specifically recognized by upstream Autotools, LLVM, Rust, or other
594    /// relevant authorities on triple naming. It's useful for people building
595    /// and using locally patched toolchains.
596    ///
597    /// Outside of such patched environments, users of `target-lexicon` should
598    /// treat `Custom` the same as `Unknown` and ignore the string.
599    Custom(CustomVendor),
600}
601
602impl Vendor {
603    /// Extracts a string slice.
604    pub fn as_str(&self) -> &str {
605        use Vendor::*;
606
607        match self {
608            Unknown => "unknown",
609            Amd => "amd",
610            Apple => "apple",
611            Espressif => "espressif",
612            Experimental => "experimental",
613            Fortanix => "fortanix",
614            Ibm => "ibm",
615            Kmc => "kmc",
616            Nintendo => "nintendo",
617            Nvidia => "nvidia",
618            Pc => "pc",
619            Rumprun => "rumprun",
620            Sun => "sun",
621            Uwp => "uwp",
622            Wrs => "wrs",
623            Custom(name) => name.as_str(),
624        }
625    }
626}
627
628/// The "operating system" field, which sometimes implies an environment, and
629/// sometimes isn't an actual operating system.
630#[cfg_attr(feature = "rust_1_40", non_exhaustive)]
631#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
632#[allow(missing_docs)]
633pub enum OperatingSystem {
634    Unknown,
635    Aix,
636    AmdHsa,
637    Bitrig,
638    Cloudabi,
639    Cuda,
640    Darwin,
641    Dragonfly,
642    Emscripten,
643    Espidf,
644    Freebsd,
645    Fuchsia,
646    Haiku,
647    Hermit,
648    Horizon,
649    Hurd,
650    Illumos,
651    Ios,
652    L4re,
653    Linux,
654    MacOSX { major: u16, minor: u16, patch: u16 },
655    Nebulet,
656    Netbsd,
657    None_,
658    Openbsd,
659    Psp,
660    Redox,
661    Solaris,
662    SolidAsp3,
663    Tvos,
664    Uefi,
665    Visionos,
666    VxWorks,
667    Wasi,
668    WasiP1,
669    WasiP2,
670    Watchos,
671    Windows,
672}
673
674impl OperatingSystem {
675    /// Convert into a string
676    pub fn into_str(self) -> Cow<'static, str> {
677        use OperatingSystem::*;
678
679        match self {
680            Unknown => Cow::Borrowed("unknown"),
681            Aix => Cow::Borrowed("aix"),
682            AmdHsa => Cow::Borrowed("amdhsa"),
683            Bitrig => Cow::Borrowed("bitrig"),
684            Cloudabi => Cow::Borrowed("cloudabi"),
685            Cuda => Cow::Borrowed("cuda"),
686            Darwin => Cow::Borrowed("darwin"),
687            Dragonfly => Cow::Borrowed("dragonfly"),
688            Emscripten => Cow::Borrowed("emscripten"),
689            Espidf => Cow::Borrowed("espidf"),
690            Freebsd => Cow::Borrowed("freebsd"),
691            Fuchsia => Cow::Borrowed("fuchsia"),
692            Haiku => Cow::Borrowed("haiku"),
693            Hermit => Cow::Borrowed("hermit"),
694            Horizon => Cow::Borrowed("horizon"),
695            Hurd => Cow::Borrowed("hurd"),
696            Illumos => Cow::Borrowed("illumos"),
697            Ios => Cow::Borrowed("ios"),
698            L4re => Cow::Borrowed("l4re"),
699            Linux => Cow::Borrowed("linux"),
700            MacOSX {
701                major,
702                minor,
703                patch,
704            } => Cow::Owned(format!("macosx{}.{}.{}", major, minor, patch)),
705            Nebulet => Cow::Borrowed("nebulet"),
706            Netbsd => Cow::Borrowed("netbsd"),
707            None_ => Cow::Borrowed("none"),
708            Openbsd => Cow::Borrowed("openbsd"),
709            Psp => Cow::Borrowed("psp"),
710            Redox => Cow::Borrowed("redox"),
711            Solaris => Cow::Borrowed("solaris"),
712            SolidAsp3 => Cow::Borrowed("solid_asp3"),
713            Tvos => Cow::Borrowed("tvos"),
714            Uefi => Cow::Borrowed("uefi"),
715            VxWorks => Cow::Borrowed("vxworks"),
716            Visionos => Cow::Borrowed("visionos"),
717            Wasi => Cow::Borrowed("wasi"),
718            WasiP1 => Cow::Borrowed("wasip1"),
719            WasiP2 => Cow::Borrowed("wasip2"),
720            Watchos => Cow::Borrowed("watchos"),
721            Windows => Cow::Borrowed("windows"),
722        }
723    }
724}
725
726/// The "environment" field, which specifies an ABI environment on top of the
727/// operating system. In many configurations, this field is omitted, and the
728/// environment is implied by the operating system.
729#[cfg_attr(feature = "rust_1_40", non_exhaustive)]
730#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
731#[allow(missing_docs)]
732pub enum Environment {
733    Unknown,
734    AmdGiz,
735    Android,
736    Androideabi,
737    Eabi,
738    Eabihf,
739    Gnu,
740    Gnuabi64,
741    Gnueabi,
742    Gnueabihf,
743    Gnuspe,
744    Gnux32,
745    GnuIlp32,
746    GnuLlvm,
747    HermitKernel,
748    HurdKernel,
749    LinuxKernel,
750    Macabi,
751    Musl,
752    Musleabi,
753    Musleabihf,
754    Muslabi64,
755    Msvc,
756    Newlib,
757    None,
758    Kernel,
759    Uclibc,
760    Uclibceabi,
761    Uclibceabihf,
762    Sgx,
763    Sim,
764    Softfloat,
765    Spe,
766    Threads,
767    Ohos,
768}
769
770impl Environment {
771    /// Convert into a string
772    pub fn into_str(self) -> Cow<'static, str> {
773        use Environment::*;
774
775        match self {
776            Unknown => Cow::Borrowed("unknown"),
777            AmdGiz => Cow::Borrowed("amdgiz"),
778            Android => Cow::Borrowed("android"),
779            Androideabi => Cow::Borrowed("androideabi"),
780            Eabi => Cow::Borrowed("eabi"),
781            Eabihf => Cow::Borrowed("eabihf"),
782            Gnu => Cow::Borrowed("gnu"),
783            Gnuabi64 => Cow::Borrowed("gnuabi64"),
784            Gnueabi => Cow::Borrowed("gnueabi"),
785            Gnueabihf => Cow::Borrowed("gnueabihf"),
786            Gnuspe => Cow::Borrowed("gnuspe"),
787            Gnux32 => Cow::Borrowed("gnux32"),
788            GnuIlp32 => Cow::Borrowed("gnu_ilp32"),
789            GnuLlvm => Cow::Borrowed("gnullvm"),
790            HermitKernel => Cow::Borrowed("hermitkernel"),
791            HurdKernel => Cow::Borrowed("hurdkernel"),
792            LinuxKernel => Cow::Borrowed("linuxkernel"),
793            Macabi => Cow::Borrowed("macabi"),
794            Musl => Cow::Borrowed("musl"),
795            Musleabi => Cow::Borrowed("musleabi"),
796            Musleabihf => Cow::Borrowed("musleabihf"),
797            Muslabi64 => Cow::Borrowed("muslabi64"),
798            Msvc => Cow::Borrowed("msvc"),
799            Newlib => Cow::Borrowed("newlib"),
800            None => Cow::Borrowed("none"),
801            Kernel => Cow::Borrowed("kernel"),
802            Uclibc => Cow::Borrowed("uclibc"),
803            Uclibceabi => Cow::Borrowed("uclibceabi"),
804            Uclibceabihf => Cow::Borrowed("uclibceabihf"),
805            Sgx => Cow::Borrowed("sgx"),
806            Sim => Cow::Borrowed("sim"),
807            Softfloat => Cow::Borrowed("softfloat"),
808            Spe => Cow::Borrowed("spe"),
809            Threads => Cow::Borrowed("threads"),
810            Ohos => Cow::Borrowed("ohos"),
811        }
812    }
813}
814
815/// The "binary format" field, which is usually omitted, and the binary format
816/// is implied by the other fields.
817#[cfg_attr(feature = "rust_1_40", non_exhaustive)]
818#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
819#[allow(missing_docs)]
820pub enum BinaryFormat {
821    Unknown,
822    Elf,
823    Coff,
824    Macho,
825    Wasm,
826    Xcoff,
827}
828
829impl BinaryFormat {
830    /// Convert into a string
831    pub fn into_str(self) -> Cow<'static, str> {
832        use BinaryFormat::*;
833
834        match self {
835            Unknown => Cow::Borrowed("unknown"),
836            Elf => Cow::Borrowed("elf"),
837            Coff => Cow::Borrowed("coff"),
838            Macho => Cow::Borrowed("macho"),
839            Wasm => Cow::Borrowed("wasm"),
840            Xcoff => Cow::Borrowed("xcoff"),
841        }
842    }
843}
844
845impl Architecture {
846    /// Return the endianness of this architecture.
847    #[rustfmt::skip]
848    pub fn endianness(self) -> Result<Endianness, ()> {
849        use Architecture::*;
850
851        match self {
852            Unknown => Err(()),
853            Arm(arm) => Ok(arm.endianness()),
854            Aarch64(aarch) => Ok(aarch.endianness()),
855            AmdGcn
856            | Asmjs
857            | Avr
858            | Bpfel
859            | Hexagon
860            | X86_32(_)
861            | LoongArch64
862            | Mips64(Mips64Architecture::Mips64el)
863            | Mips32(Mips32Architecture::Mipsel)
864            | Mips32(Mips32Architecture::Mipsisa32r6el)
865            | Mips64(Mips64Architecture::Mipsisa64r6el)
866            | Msp430
867            | Nvptx64
868            | Pulley32
869            | Pulley64
870            | Powerpc64le
871            | Riscv32(_)
872            | Riscv64(_)
873            | Wasm32
874            | Wasm64
875            | X86_64
876            | X86_64h
877            | XTensa
878            | Clever(_) => Ok(Endianness::Little),
879            Bpfeb
880            | M68k
881            | Mips32(Mips32Architecture::Mips)
882            | Mips64(Mips64Architecture::Mips64)
883            | Mips32(Mips32Architecture::Mipsisa32r6)
884            | Mips64(Mips64Architecture::Mipsisa64r6)
885            | Powerpc
886            | Powerpc64
887            | S390x
888            | Sparc
889            | Sparc64
890            | Sparcv9 => Ok(Endianness::Big),
891            #[cfg(feature="arch_zkasm")]
892            ZkAsm => Ok(Endianness::Big),
893        }
894    }
895
896    /// Return the pointer bit width of this target's architecture.
897    ///
898    /// This function is only aware of the CPU architecture so it is not aware
899    /// of ilp32 and x32 ABIs.
900    #[rustfmt::skip]
901    pub fn pointer_width(self) -> Result<PointerWidth, ()> {
902        use Architecture::*;
903
904        match self {
905            Unknown => Err(()),
906            Avr | Msp430 => Ok(PointerWidth::U16),
907            Arm(arm) => Ok(arm.pointer_width()),
908            Aarch64(aarch) => Ok(aarch.pointer_width()),
909            Asmjs
910            | Hexagon
911            | X86_32(_)
912            | Riscv32(_)
913            | Sparc
914            | Wasm32
915            | M68k
916            | Mips32(_)
917            | Pulley32
918            | Powerpc
919            | XTensa => Ok(PointerWidth::U32),
920            AmdGcn
921            | Bpfeb
922            | Bpfel
923            | Powerpc64le
924            | Riscv64(_)
925            | X86_64
926            | X86_64h
927            | Mips64(_)
928            | Nvptx64
929            | Pulley64
930            | Powerpc64
931            | S390x
932            | Sparc64
933            | Sparcv9
934            | LoongArch64
935            | Wasm64
936            | Clever(_) => Ok(PointerWidth::U64),
937            #[cfg(feature="arch_zkasm")]
938            ZkAsm => Ok(PointerWidth::U64),
939        }
940    }
941
942    /// Checks if this Architecture is some variant of Clever-ISA
943    pub fn is_clever(&self) -> bool {
944        match self {
945            Architecture::Clever(_) => true,
946            _ => false,
947        }
948    }
949
950    /// Convert into a string
951    pub fn into_str(self) -> Cow<'static, str> {
952        use Architecture::*;
953
954        match self {
955            Arm(arm) => arm.into_str(),
956            Aarch64(aarch) => aarch.into_str(),
957            Unknown => Cow::Borrowed("unknown"),
958            AmdGcn => Cow::Borrowed("amdgcn"),
959            Asmjs => Cow::Borrowed("asmjs"),
960            Avr => Cow::Borrowed("avr"),
961            Bpfeb => Cow::Borrowed("bpfeb"),
962            Bpfel => Cow::Borrowed("bpfel"),
963            Hexagon => Cow::Borrowed("hexagon"),
964            X86_32(x86_32) => x86_32.into_str(),
965            LoongArch64 => Cow::Borrowed("loongarch64"),
966            M68k => Cow::Borrowed("m68k"),
967            Mips32(mips32) => mips32.into_str(),
968            Mips64(mips64) => mips64.into_str(),
969            Msp430 => Cow::Borrowed("msp430"),
970            Nvptx64 => Cow::Borrowed("nvptx64"),
971            Pulley32 => Cow::Borrowed("pulley32"),
972            Pulley64 => Cow::Borrowed("pulley64"),
973            Powerpc => Cow::Borrowed("powerpc"),
974            Powerpc64 => Cow::Borrowed("powerpc64"),
975            Powerpc64le => Cow::Borrowed("powerpc64le"),
976            Riscv32(riscv32) => riscv32.into_str(),
977            Riscv64(riscv64) => riscv64.into_str(),
978            S390x => Cow::Borrowed("s390x"),
979            Sparc => Cow::Borrowed("sparc"),
980            Sparc64 => Cow::Borrowed("sparc64"),
981            Sparcv9 => Cow::Borrowed("sparcv9"),
982            Wasm32 => Cow::Borrowed("wasm32"),
983            Wasm64 => Cow::Borrowed("wasm64"),
984            X86_64 => Cow::Borrowed("x86_64"),
985            X86_64h => Cow::Borrowed("x86_64h"),
986            XTensa => Cow::Borrowed("xtensa"),
987            Clever(ver) => ver.into_str(),
988            #[cfg(feature = "arch_zkasm")]
989            ZkAsm => Cow::Borrowed("zkasm"),
990        }
991    }
992}
993
994/// Return the binary format implied by this target triple, ignoring its
995/// `binary_format` field.
996pub(crate) fn default_binary_format(triple: &Triple) -> BinaryFormat {
997    match triple.operating_system {
998        OperatingSystem::None_ => match triple.environment {
999            Environment::Eabi | Environment::Eabihf => BinaryFormat::Elf,
1000            _ => BinaryFormat::Unknown,
1001        },
1002        OperatingSystem::Aix => BinaryFormat::Xcoff,
1003        OperatingSystem::Darwin
1004        | OperatingSystem::Ios
1005        | OperatingSystem::MacOSX { .. }
1006        | OperatingSystem::Visionos
1007        | OperatingSystem::Watchos
1008        | OperatingSystem::Tvos => BinaryFormat::Macho,
1009        OperatingSystem::Windows => BinaryFormat::Coff,
1010        OperatingSystem::Nebulet
1011        | OperatingSystem::Emscripten
1012        | OperatingSystem::VxWorks
1013        | OperatingSystem::Wasi
1014        | OperatingSystem::Unknown => match triple.architecture {
1015            Architecture::Wasm32 | Architecture::Wasm64 => BinaryFormat::Wasm,
1016            Architecture::Unknown => BinaryFormat::Unknown,
1017            // Default to ELF, following `getDefaultFormat` in LLVM.
1018            _ => BinaryFormat::Elf,
1019        },
1020        _ => BinaryFormat::Elf,
1021    }
1022}
1023
1024impl fmt::Display for ArmArchitecture {
1025    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1026        f.write_str(&self.into_str())
1027    }
1028}
1029
1030impl fmt::Display for Aarch64Architecture {
1031    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1032        f.write_str(&self.into_str())
1033    }
1034}
1035
1036impl fmt::Display for CleverArchitecture {
1037    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1038        f.write_str(&self.into_str())
1039    }
1040}
1041
1042impl fmt::Display for Riscv32Architecture {
1043    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1044        f.write_str(&self.into_str())
1045    }
1046}
1047
1048impl fmt::Display for Riscv64Architecture {
1049    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1050        f.write_str(&self.into_str())
1051    }
1052}
1053
1054impl fmt::Display for X86_32Architecture {
1055    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1056        f.write_str(&self.into_str())
1057    }
1058}
1059
1060impl fmt::Display for Mips32Architecture {
1061    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1062        f.write_str(&self.into_str())
1063    }
1064}
1065
1066impl fmt::Display for Mips64Architecture {
1067    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1068        f.write_str(&self.into_str())
1069    }
1070}
1071
1072impl fmt::Display for Architecture {
1073    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1074        f.write_str(&self.into_str())
1075    }
1076}
1077
1078impl FromStr for ArmArchitecture {
1079    type Err = ();
1080
1081    fn from_str(s: &str) -> Result<Self, ()> {
1082        use ArmArchitecture::*;
1083
1084        Ok(match s {
1085            "arm" => Arm,
1086            "armeb" => Armeb,
1087            "armv4" => Armv4,
1088            "armv4t" => Armv4t,
1089            "armv5t" => Armv5t,
1090            "armv5te" => Armv5te,
1091            "armv5tej" => Armv5tej,
1092            "armv6" => Armv6,
1093            "armv6j" => Armv6j,
1094            "armv6k" => Armv6k,
1095            "armv6z" => Armv6z,
1096            "armv6kz" => Armv6kz,
1097            "armv6t2" => Armv6t2,
1098            "armv6m" => Armv6m,
1099            "armv7" => Armv7,
1100            "armv7a" => Armv7a,
1101            "armv7k" => Armv7k,
1102            "armv7ve" => Armv7ve,
1103            "armv7m" => Armv7m,
1104            "armv7r" => Armv7r,
1105            "armv7s" => Armv7s,
1106            "armv8" => Armv8,
1107            "armv8a" => Armv8a,
1108            "armv8.1a" => Armv8_1a,
1109            "armv8.2a" => Armv8_2a,
1110            "armv8.3a" => Armv8_3a,
1111            "armv8.4a" => Armv8_4a,
1112            "armv8.5a" => Armv8_5a,
1113            "armv8m.base" => Armv8mBase,
1114            "armv8m.main" => Armv8mMain,
1115            "armv8r" => Armv8r,
1116            "thumbeb" => Thumbeb,
1117            "thumbv4t" => Thumbv4t,
1118            "thumbv5te" => Thumbv5te,
1119            "thumbv6m" => Thumbv6m,
1120            "thumbv7a" => Thumbv7a,
1121            "thumbv7em" => Thumbv7em,
1122            "thumbv7m" => Thumbv7m,
1123            "thumbv7neon" => Thumbv7neon,
1124            "thumbv8m.base" => Thumbv8mBase,
1125            "thumbv8m.main" => Thumbv8mMain,
1126            "armebv7r" => Armebv7r,
1127            _ => return Err(()),
1128        })
1129    }
1130}
1131
1132impl FromStr for Aarch64Architecture {
1133    type Err = ();
1134
1135    fn from_str(s: &str) -> Result<Self, ()> {
1136        use Aarch64Architecture::*;
1137
1138        Ok(match s {
1139            "aarch64" => Aarch64,
1140            "arm64" => Aarch64,
1141            "aarch64_be" => Aarch64be,
1142            _ => return Err(()),
1143        })
1144    }
1145}
1146
1147impl FromStr for CleverArchitecture {
1148    type Err = ();
1149    fn from_str(s: &str) -> Result<Self, ()> {
1150        match s {
1151            "clever" => Ok(CleverArchitecture::Clever),
1152            "clever1.0" => Ok(CleverArchitecture::Clever1_0),
1153            _ => Err(()),
1154        }
1155    }
1156}
1157
1158impl FromStr for Riscv32Architecture {
1159    type Err = ();
1160
1161    fn from_str(s: &str) -> Result<Self, ()> {
1162        use Riscv32Architecture::*;
1163
1164        Ok(match s {
1165            "riscv32" => Riscv32,
1166            "riscv32gc" => Riscv32gc,
1167            "riscv32i" => Riscv32i,
1168            "riscv32im" => Riscv32im,
1169            "riscv32ima" => Riscv32ima,
1170            "riscv32imac" => Riscv32imac,
1171            "riscv32imafc" => Riscv32imafc,
1172            "riscv32imc" => Riscv32imc,
1173            _ => return Err(()),
1174        })
1175    }
1176}
1177
1178impl FromStr for Riscv64Architecture {
1179    type Err = ();
1180
1181    fn from_str(s: &str) -> Result<Self, ()> {
1182        use Riscv64Architecture::*;
1183
1184        Ok(match s {
1185            "riscv64" => Riscv64,
1186            "riscv64gc" => Riscv64gc,
1187            "riscv64imac" => Riscv64imac,
1188            _ => return Err(()),
1189        })
1190    }
1191}
1192
1193impl FromStr for X86_32Architecture {
1194    type Err = ();
1195
1196    fn from_str(s: &str) -> Result<Self, ()> {
1197        use X86_32Architecture::*;
1198
1199        Ok(match s {
1200            "i386" => I386,
1201            "i586" => I586,
1202            "i686" => I686,
1203            _ => return Err(()),
1204        })
1205    }
1206}
1207
1208impl FromStr for Mips32Architecture {
1209    type Err = ();
1210
1211    fn from_str(s: &str) -> Result<Self, ()> {
1212        use Mips32Architecture::*;
1213
1214        Ok(match s {
1215            "mips" => Mips,
1216            "mipsel" => Mipsel,
1217            "mipsisa32r6" => Mipsisa32r6,
1218            "mipsisa32r6el" => Mipsisa32r6el,
1219            _ => return Err(()),
1220        })
1221    }
1222}
1223
1224impl FromStr for Mips64Architecture {
1225    type Err = ();
1226
1227    fn from_str(s: &str) -> Result<Self, ()> {
1228        use Mips64Architecture::*;
1229
1230        Ok(match s {
1231            "mips64" => Mips64,
1232            "mips64el" => Mips64el,
1233            "mipsisa64r6" => Mipsisa64r6,
1234            "mipsisa64r6el" => Mipsisa64r6el,
1235            _ => return Err(()),
1236        })
1237    }
1238}
1239
1240impl FromStr for Architecture {
1241    type Err = ();
1242
1243    fn from_str(s: &str) -> Result<Self, ()> {
1244        use Architecture::*;
1245
1246        Ok(match s {
1247            "unknown" => Unknown,
1248            "amdgcn" => AmdGcn,
1249            "asmjs" => Asmjs,
1250            "avr" => Avr,
1251            "bpfeb" => Bpfeb,
1252            "bpfel" => Bpfel,
1253            "hexagon" => Hexagon,
1254            "loongarch64" => LoongArch64,
1255            "m68k" => M68k,
1256            "msp430" => Msp430,
1257            "nvptx64" => Nvptx64,
1258            "pulley32" => Pulley32,
1259            "pulley64" => Pulley64,
1260            "powerpc" => Powerpc,
1261            "powerpc64" => Powerpc64,
1262            "powerpc64le" => Powerpc64le,
1263            "s390x" => S390x,
1264            "sparc" => Sparc,
1265            "sparc64" => Sparc64,
1266            "sparcv9" => Sparcv9,
1267            "wasm32" => Wasm32,
1268            "wasm64" => Wasm64,
1269            "x86_64" => X86_64,
1270            "x86_64h" => X86_64h,
1271            "xtensa" => XTensa,
1272            #[cfg(feature = "arch_zkasm")]
1273            "zkasm" => ZkAsm,
1274            _ => {
1275                if let Ok(arm) = ArmArchitecture::from_str(s) {
1276                    Arm(arm)
1277                } else if let Ok(aarch64) = Aarch64Architecture::from_str(s) {
1278                    Aarch64(aarch64)
1279                } else if let Ok(riscv32) = Riscv32Architecture::from_str(s) {
1280                    Riscv32(riscv32)
1281                } else if let Ok(riscv64) = Riscv64Architecture::from_str(s) {
1282                    Riscv64(riscv64)
1283                } else if let Ok(x86_32) = X86_32Architecture::from_str(s) {
1284                    X86_32(x86_32)
1285                } else if let Ok(mips32) = Mips32Architecture::from_str(s) {
1286                    Mips32(mips32)
1287                } else if let Ok(mips64) = Mips64Architecture::from_str(s) {
1288                    Mips64(mips64)
1289                } else if let Ok(clever) = CleverArchitecture::from_str(s) {
1290                    Clever(clever)
1291                } else {
1292                    return Err(());
1293                }
1294            }
1295        })
1296    }
1297}
1298
1299impl fmt::Display for Vendor {
1300    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1301        f.write_str(self.as_str())
1302    }
1303}
1304
1305impl FromStr for Vendor {
1306    type Err = ();
1307
1308    fn from_str(s: &str) -> Result<Self, ()> {
1309        use Vendor::*;
1310
1311        Ok(match s {
1312            "unknown" => Unknown,
1313            "amd" => Amd,
1314            "apple" => Apple,
1315            "espressif" => Espressif,
1316            "experimental" => Experimental,
1317            "fortanix" => Fortanix,
1318            "ibm" => Ibm,
1319            "kmc" => Kmc,
1320            "nintendo" => Nintendo,
1321            "nvidia" => Nvidia,
1322            "pc" => Pc,
1323            "rumprun" => Rumprun,
1324            "sun" => Sun,
1325            "uwp" => Uwp,
1326            "wrs" => Wrs,
1327            custom => {
1328                #[cfg(not(feature = "std"))]
1329                use alloc::borrow::ToOwned;
1330
1331                // A custom vendor. Since triple syntax is so loosely defined,
1332                // be as conservative as we can to avoid potential ambiguities.
1333                // We err on the side of being too strict here, as we can
1334                // always relax it if needed.
1335
1336                // Don't allow empty string names.
1337                if custom.is_empty() {
1338                    return Err(());
1339                }
1340
1341                // Don't allow any other recognized name as a custom vendor,
1342                // since vendors can be omitted in some contexts.
1343                if Architecture::from_str(custom).is_ok()
1344                    || OperatingSystem::from_str(custom).is_ok()
1345                    || Environment::from_str(custom).is_ok()
1346                    || BinaryFormat::from_str(custom).is_ok()
1347                {
1348                    return Err(());
1349                }
1350
1351                // Require the first character to be an ascii lowercase.
1352                if !custom.chars().next().unwrap().is_ascii_lowercase() {
1353                    return Err(());
1354                }
1355
1356                // Restrict the set of characters permitted in a custom vendor.
1357                let has_restricted = custom.chars().any(|c: char| {
1358                    !(c.is_ascii_lowercase() || c.is_ascii_digit() || c == '_' || c == '.')
1359                });
1360
1361                if has_restricted {
1362                    return Err(());
1363                }
1364
1365                Custom(CustomVendor::Owned(Box::new(custom.to_owned())))
1366            }
1367        })
1368    }
1369}
1370
1371impl fmt::Display for OperatingSystem {
1372    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1373        use OperatingSystem::*;
1374
1375        match *self {
1376            MacOSX {
1377                major,
1378                minor,
1379                patch,
1380            } => write!(f, "macosx{}.{}.{}", major, minor, patch),
1381            os => f.write_str(&os.into_str()),
1382        }
1383    }
1384}
1385
1386impl FromStr for OperatingSystem {
1387    type Err = ();
1388
1389    fn from_str(s: &str) -> Result<Self, ()> {
1390        use OperatingSystem::*;
1391
1392        // TODO also parse version number for darwin and ios OSes
1393        if s.starts_with("macosx") {
1394            // Parse operating system names like `macosx10.7.0`.
1395            let s = &s["macosx".len()..];
1396            let mut parts = s.split('.').map(|num| num.parse::<u16>());
1397
1398            macro_rules! get_part {
1399                () => {
1400                    if let Some(Ok(part)) = parts.next() {
1401                        part
1402                    } else {
1403                        return Err(());
1404                    }
1405                };
1406            }
1407
1408            let major = get_part!();
1409            let minor = get_part!();
1410            let patch = get_part!();
1411
1412            if parts.next().is_some() {
1413                return Err(());
1414            }
1415
1416            return Ok(MacOSX {
1417                major,
1418                minor,
1419                patch,
1420            });
1421        }
1422
1423        Ok(match s {
1424            "unknown" => Unknown,
1425            "aix" => Aix,
1426            "amdhsa" => AmdHsa,
1427            "bitrig" => Bitrig,
1428            "cloudabi" => Cloudabi,
1429            "cuda" => Cuda,
1430            "darwin" => Darwin,
1431            "dragonfly" => Dragonfly,
1432            "emscripten" => Emscripten,
1433            "freebsd" => Freebsd,
1434            "fuchsia" => Fuchsia,
1435            "haiku" => Haiku,
1436            "hermit" => Hermit,
1437            "horizon" => Horizon,
1438            "hurd" => Hurd,
1439            "illumos" => Illumos,
1440            "ios" => Ios,
1441            "l4re" => L4re,
1442            "linux" => Linux,
1443            "nebulet" => Nebulet,
1444            "netbsd" => Netbsd,
1445            "none" => None_,
1446            "openbsd" => Openbsd,
1447            "psp" => Psp,
1448            "redox" => Redox,
1449            "solaris" => Solaris,
1450            "solid_asp3" => SolidAsp3,
1451            "tvos" => Tvos,
1452            "uefi" => Uefi,
1453            "visionos" => Visionos,
1454            "vxworks" => VxWorks,
1455            "wasi" => Wasi,
1456            "wasip1" => WasiP1,
1457            "wasip2" => WasiP2,
1458            "watchos" => Watchos,
1459            "windows" => Windows,
1460            "espidf" => Espidf,
1461            _ => return Err(()),
1462        })
1463    }
1464}
1465
1466impl fmt::Display for Environment {
1467    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1468        f.write_str(&self.into_str())
1469    }
1470}
1471
1472impl FromStr for Environment {
1473    type Err = ();
1474
1475    fn from_str(s: &str) -> Result<Self, ()> {
1476        use Environment::*;
1477
1478        Ok(match s {
1479            "unknown" => Unknown,
1480            "amdgiz" => AmdGiz,
1481            "android" => Android,
1482            "androideabi" => Androideabi,
1483            "eabi" => Eabi,
1484            "eabihf" => Eabihf,
1485            "gnu" => Gnu,
1486            "gnuabi64" => Gnuabi64,
1487            "gnueabi" => Gnueabi,
1488            "gnueabihf" => Gnueabihf,
1489            "gnuspe" => Gnuspe,
1490            "gnux32" => Gnux32,
1491            "gnu_ilp32" => GnuIlp32,
1492            "gnullvm" => GnuLlvm,
1493            "hermitkernel" => HermitKernel,
1494            "hurdkernel" => HurdKernel,
1495            "linuxkernel" => LinuxKernel,
1496            "macabi" => Macabi,
1497            "musl" => Musl,
1498            "musleabi" => Musleabi,
1499            "musleabihf" => Musleabihf,
1500            "muslabi64" => Muslabi64,
1501            "msvc" => Msvc,
1502            "newlib" => Newlib,
1503            "none" => None,
1504            "kernel" => Kernel,
1505            "uclibc" => Uclibc,
1506            "uclibceabi" => Uclibceabi,
1507            "uclibceabihf" => Uclibceabihf,
1508            "sgx" => Sgx,
1509            "sim" => Sim,
1510            "softfloat" => Softfloat,
1511            "spe" => Spe,
1512            "threads" => Threads,
1513            "ohos" => Ohos,
1514            _ => return Err(()),
1515        })
1516    }
1517}
1518
1519impl fmt::Display for BinaryFormat {
1520    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1521        f.write_str(&self.into_str())
1522    }
1523}
1524
1525impl FromStr for BinaryFormat {
1526    type Err = ();
1527
1528    fn from_str(s: &str) -> Result<Self, ()> {
1529        use BinaryFormat::*;
1530
1531        Ok(match s {
1532            "unknown" => Unknown,
1533            "elf" => Elf,
1534            "coff" => Coff,
1535            "macho" => Macho,
1536            "wasm" => Wasm,
1537            "xcoff" => Xcoff,
1538            _ => return Err(()),
1539        })
1540    }
1541}
1542
1543#[cfg(test)]
1544mod tests {
1545    use super::*;
1546    use alloc::string::ToString;
1547
1548    #[test]
1549    fn roundtrip_known_triples() {
1550        // This list is constructed from:
1551        //  - targets emitted by "rustup target list"
1552        //  - targets emitted by "rustc +nightly --print target-list"
1553        //  - targets contributors have added
1554        let targets = [
1555            "aarch64-apple-darwin",
1556            "aarch64-apple-ios",
1557            "aarch64-apple-ios-macabi",
1558            "aarch64-apple-ios-sim",
1559            "aarch64-apple-tvos",
1560            "aarch64-apple-tvos-sim",
1561            "aarch64-apple-visionos",
1562            "aarch64-apple-visionos-sim",
1563            "aarch64-apple-watchos",
1564            "aarch64-apple-watchos-sim",
1565            "aarch64_be-unknown-linux-gnu",
1566            "aarch64_be-unknown-linux-gnu_ilp32",
1567            "aarch64_be-unknown-netbsd",
1568            "aarch64-kmc-solid_asp3",
1569            "aarch64-linux-android",
1570            //"aarch64-nintendo-switch-freestanding", // TODO
1571            "aarch64-pc-windows-gnullvm",
1572            "aarch64-pc-windows-msvc",
1573            "aarch64-unknown-cloudabi",
1574            "aarch64-unknown-freebsd",
1575            "aarch64-unknown-fuchsia",
1576            "aarch64-unknown-hermit",
1577            "aarch64-unknown-illumos",
1578            "aarch64-unknown-linux-gnu",
1579            "aarch64-unknown-linux-gnu_ilp32",
1580            "aarch64-unknown-linux-musl",
1581            "aarch64-unknown-linux-ohos",
1582            "aarch64-unknown-netbsd",
1583            "aarch64-unknown-none",
1584            "aarch64-unknown-none-softfloat",
1585            //"aarch64-unknown-nto-qnx710", // TODO
1586            "aarch64-unknown-openbsd",
1587            "aarch64-unknown-redox",
1588            //"aarch64-unknown-teeos", // TODO
1589            "aarch64-unknown-uefi",
1590            "aarch64-uwp-windows-msvc",
1591            "aarch64-wrs-vxworks",
1592            //"arm64_32-apple-watchos", // TODO
1593            //"arm64e-apple-darwin", // TODO
1594            "amdgcn-amd-amdhsa",
1595            "amdgcn-amd-amdhsa-amdgiz",
1596            //"arm64e-apple-ios", // TODO
1597            //"arm64ec-pc-windows-msvc", // TODO
1598            "armeb-unknown-linux-gnueabi",
1599            "armebv7r-none-eabi",
1600            "armebv7r-none-eabihf",
1601            "arm-linux-androideabi",
1602            "arm-unknown-linux-gnueabi",
1603            "arm-unknown-linux-gnueabihf",
1604            "arm-unknown-linux-musleabi",
1605            "arm-unknown-linux-musleabihf",
1606            "armv4t-none-eabi",
1607            "armv4t-unknown-linux-gnueabi",
1608            "armv5te-none-eabi",
1609            "armv5te-unknown-linux-gnueabi",
1610            "armv5te-unknown-linux-musleabi",
1611            "armv5te-unknown-linux-uclibceabi",
1612            "armv6k-nintendo-3ds",
1613            "armv6-unknown-freebsd",
1614            "armv6-unknown-netbsd-eabihf",
1615            "armv7a-kmc-solid_asp3-eabi",
1616            "armv7a-kmc-solid_asp3-eabihf",
1617            "armv7a-none-eabi",
1618            "armv7a-none-eabihf",
1619            "armv7-apple-ios",
1620            "armv7k-apple-watchos",
1621            "armv7-linux-androideabi",
1622            "armv7r-none-eabi",
1623            "armv7r-none-eabihf",
1624            "armv7s-apple-ios",
1625            "armv7-unknown-cloudabi-eabihf",
1626            //"armv7-sony-vita-newlibeabihf", // TODO
1627            "armv7-unknown-freebsd",
1628            "armv7-unknown-linux-gnueabi",
1629            "armv7-unknown-linux-gnueabihf",
1630            "armv7-unknown-linux-musleabi",
1631            "armv7-unknown-linux-musleabihf",
1632            "armv7-unknown-linux-ohos",
1633            "armv7-unknown-linux-uclibceabi",
1634            "armv7-unknown-linux-uclibceabihf",
1635            "armv7-unknown-netbsd-eabihf",
1636            "armv7-wrs-vxworks-eabihf",
1637            "asmjs-unknown-emscripten",
1638            "armv8r-none-eabihf",
1639            //"avr-unknown-gnu-atmega328", // TODO
1640            "avr-unknown-unknown",
1641            "bpfeb-unknown-none",
1642            "bpfel-unknown-none",
1643            //"csky-unknown-linux-gnuabiv2", // TODO
1644            //"csky-unknown-linux-gnuabiv2hf", // TODO
1645            "hexagon-unknown-linux-musl",
1646            "hexagon-unknown-none-elf",
1647            "i386-apple-ios",
1648            //"i586-pc-nto-qnx700", // TODO
1649            "i586-pc-windows-msvc",
1650            "i586-unknown-linux-gnu",
1651            "i586-unknown-linux-musl",
1652            "i586-unknown-netbsd",
1653            "i686-apple-darwin",
1654            "i686-linux-android",
1655            "i686-apple-macosx10.7.0",
1656            "i686-pc-windows-gnu",
1657            "i686-pc-windows-gnullvm",
1658            "i686-pc-windows-msvc",
1659            "i686-unknown-cloudabi",
1660            "i686-unknown-dragonfly",
1661            "i686-unknown-freebsd",
1662            "i686-unknown-haiku",
1663            "i686-unknown-hurd-gnu",
1664            "i686-unknown-linux-gnu",
1665            "i686-unknown-linux-musl",
1666            "i686-unknown-netbsd",
1667            "i686-unknown-openbsd",
1668            "i686-unknown-redox",
1669            "i686-unknown-uefi",
1670            "i686-uwp-windows-gnu",
1671            "i686-uwp-windows-msvc",
1672            "i686-win7-windows-msvc",
1673            "i686-wrs-vxworks",
1674            "loongarch64-unknown-linux-gnu",
1675            "loongarch64-unknown-linux-musl",
1676            "loongarch64-unknown-none",
1677            "loongarch64-unknown-none-softfloat",
1678            "m68k-unknown-linux-gnu",
1679            "mips64el-unknown-linux-gnuabi64",
1680            "mips64el-unknown-linux-muslabi64",
1681            "mips64-openwrt-linux-musl",
1682            "mips64-unknown-linux-gnuabi64",
1683            "mips64-unknown-linux-muslabi64",
1684            "mipsel-sony-psp",
1685            //"mipsel-sony-psx", // TODO
1686            "mipsel-unknown-linux-gnu",
1687            "mipsel-unknown-linux-musl",
1688            "mipsel-unknown-linux-uclibc",
1689            "mipsel-unknown-netbsd",
1690            "mipsel-unknown-none",
1691            "mipsisa32r6el-unknown-linux-gnu",
1692            "mipsisa32r6-unknown-linux-gnu",
1693            "mipsisa64r6el-unknown-linux-gnuabi64",
1694            "mipsisa64r6-unknown-linux-gnuabi64",
1695            "mips-unknown-linux-gnu",
1696            "mips-unknown-linux-musl",
1697            "mips-unknown-linux-uclibc",
1698            "msp430-none-elf",
1699            "nvptx64-nvidia-cuda",
1700            "powerpc64-ibm-aix",
1701            "powerpc64le-unknown-freebsd",
1702            "powerpc64le-unknown-linux-gnu",
1703            "powerpc64le-unknown-linux-musl",
1704            "powerpc64-unknown-freebsd",
1705            "powerpc64-unknown-linux-gnu",
1706            "powerpc64-unknown-linux-musl",
1707            "powerpc64-unknown-openbsd",
1708            "powerpc64-wrs-vxworks",
1709            "powerpc-ibm-aix",
1710            "powerpc-unknown-freebsd",
1711            "powerpc-unknown-linux-gnu",
1712            "powerpc-unknown-linux-gnuspe",
1713            "powerpc-unknown-linux-musl",
1714            "powerpc-unknown-netbsd",
1715            "powerpc-unknown-openbsd",
1716            "powerpc-wrs-vxworks",
1717            "powerpc-wrs-vxworks-spe",
1718            "riscv32gc-unknown-linux-gnu",
1719            "riscv32gc-unknown-linux-musl",
1720            "riscv32imac-esp-espidf",
1721            "riscv32imac-unknown-none-elf",
1722            //"riscv32imac-unknown-xous-elf", // TODO
1723            "riscv32imafc-esp-espidf",
1724            "riscv32imafc-unknown-none-elf",
1725            "riscv32ima-unknown-none-elf",
1726            "riscv32imc-esp-espidf",
1727            "riscv32imc-unknown-none-elf",
1728            //"riscv32im-risc0-zkvm-elf", // TODO
1729            "riscv32im-unknown-none-elf",
1730            "riscv32i-unknown-none-elf",
1731            "riscv64gc-unknown-freebsd",
1732            "riscv64gc-unknown-fuchsia",
1733            "riscv64gc-unknown-hermit",
1734            "riscv64gc-unknown-linux-gnu",
1735            "riscv64gc-unknown-linux-musl",
1736            "riscv64gc-unknown-netbsd",
1737            "riscv64gc-unknown-none-elf",
1738            "riscv64gc-unknown-openbsd",
1739            "riscv64imac-unknown-none-elf",
1740            "riscv64-linux-android",
1741            "s390x-unknown-linux-gnu",
1742            "s390x-unknown-linux-musl",
1743            "sparc64-unknown-linux-gnu",
1744            "sparc64-unknown-netbsd",
1745            "sparc64-unknown-openbsd",
1746            "sparc-unknown-linux-gnu",
1747            "sparc-unknown-none-elf",
1748            "sparcv9-sun-solaris",
1749            "thumbv4t-none-eabi",
1750            "thumbv5te-none-eabi",
1751            "thumbv6m-none-eabi",
1752            "thumbv7a-pc-windows-msvc",
1753            "thumbv7a-uwp-windows-msvc",
1754            "thumbv7em-none-eabi",
1755            "thumbv7em-none-eabihf",
1756            "thumbv7m-none-eabi",
1757            "thumbv7neon-linux-androideabi",
1758            "thumbv7neon-unknown-linux-gnueabihf",
1759            "thumbv7neon-unknown-linux-musleabihf",
1760            "thumbv8m.base-none-eabi",
1761            "thumbv8m.main-none-eabi",
1762            "thumbv8m.main-none-eabihf",
1763            "wasm32-experimental-emscripten",
1764            "wasm32-unknown-emscripten",
1765            "wasm32-unknown-unknown",
1766            "wasm32-wasi",
1767            "wasm32-wasip1",
1768            "wasm32-wasip1-threads",
1769            "wasm32-wasip2",
1770            "wasm64-unknown-unknown",
1771            "wasm64-wasi",
1772            "x86_64-apple-darwin",
1773            "x86_64-apple-ios",
1774            "x86_64-apple-ios-macabi",
1775            "x86_64-apple-tvos",
1776            "x86_64-apple-watchos-sim",
1777            "x86_64-fortanix-unknown-sgx",
1778            "x86_64h-apple-darwin",
1779            "x86_64-linux-android",
1780            //"x86_64-pc-nto-qnx710", // TODO
1781            "x86_64-linux-kernel", // Changed to x86_64-unknown-none-linuxkernel in 1.53.0
1782            "x86_64-apple-macosx10.7.0",
1783            "x86_64-pc-solaris",
1784            "x86_64-pc-windows-gnu",
1785            "x86_64-pc-windows-gnullvm",
1786            "x86_64-pc-windows-msvc",
1787            "x86_64-rumprun-netbsd", // Removed in 1.53.0
1788            "x86_64-sun-solaris",
1789            "x86_64-unknown-bitrig",
1790            "x86_64-unknown-cloudabi",
1791            "x86_64-unikraft-linux-musl",
1792            "x86_64-unknown-dragonfly",
1793            "x86_64-unknown-freebsd",
1794            "x86_64-unknown-fuchsia",
1795            "x86_64-unknown-haiku",
1796            "x86_64-unknown-hermit-kernel", // Changed to x86_64-unknown-none-hermitkernel in 1.53.0
1797            "x86_64-unknown-hermit",
1798            "x86_64-unknown-illumos",
1799            "x86_64-unknown-l4re-uclibc",
1800            "x86_64-unknown-linux-gnu",
1801            "x86_64-unknown-linux-gnux32",
1802            "x86_64-unknown-linux-musl",
1803            "x86_64-unknown-linux-none",
1804            "x86_64-unknown-linux-ohos",
1805            "x86_64-unknown-netbsd",
1806            "x86_64-unknown-none",
1807            "x86_64-unknown-none-hermitkernel",
1808            "x86_64-unknown-none-linuxkernel",
1809            "x86_64-unknown-openbsd",
1810            "x86_64-unknown-redox",
1811            "x86_64-unknown-uefi",
1812            "x86_64-uwp-windows-gnu",
1813            "x86_64-uwp-windows-msvc",
1814            "x86_64-win7-windows-msvc",
1815            "x86_64-wrs-vxworks",
1816            "xtensa-esp32-espidf",
1817            "clever-unknown-elf",
1818            "xtensa-esp32-none-elf",
1819            "xtensa-esp32s2-espidf",
1820            "xtensa-esp32s2-none-elf",
1821            "xtensa-esp32s3-espidf",
1822            "xtensa-esp32s3-none-elf",
1823            #[cfg(feature = "arch_zkasm")]
1824            "zkasm-unknown-unknown",
1825        ];
1826
1827        for target in targets.iter() {
1828            let t = Triple::from_str(target).expect("can't parse target");
1829            assert_ne!(t.architecture, Architecture::Unknown);
1830            assert_eq!(t.to_string(), *target, "{:#?}", t);
1831        }
1832    }
1833
1834    #[test]
1835    fn default_format_to_elf() {
1836        let t = Triple::from_str("riscv64").expect("can't parse target");
1837        assert_eq!(
1838            t.architecture,
1839            Architecture::Riscv64(Riscv64Architecture::Riscv64),
1840        );
1841        assert_eq!(t.vendor, Vendor::Unknown);
1842        assert_eq!(t.operating_system, OperatingSystem::Unknown);
1843        assert_eq!(t.environment, Environment::Unknown);
1844        assert_eq!(t.binary_format, BinaryFormat::Elf);
1845    }
1846
1847    #[test]
1848    fn thumbv7em_none_eabihf() {
1849        let t = Triple::from_str("thumbv7em-none-eabihf").expect("can't parse target");
1850        assert_eq!(
1851            t.architecture,
1852            Architecture::Arm(ArmArchitecture::Thumbv7em)
1853        );
1854        assert_eq!(t.vendor, Vendor::Unknown);
1855        assert_eq!(t.operating_system, OperatingSystem::None_);
1856        assert_eq!(t.environment, Environment::Eabihf);
1857        assert_eq!(t.binary_format, BinaryFormat::Elf);
1858    }
1859
1860    #[test]
1861    fn fuchsia_rename() {
1862        // Fuchsia targets were renamed to add the `unknown`.
1863        assert_eq!(
1864            Triple::from_str("aarch64-fuchsia"),
1865            Triple::from_str("aarch64-unknown-fuchsia")
1866        );
1867        assert_eq!(
1868            Triple::from_str("x86_64-fuchsia"),
1869            Triple::from_str("x86_64-unknown-fuchsia")
1870        );
1871    }
1872
1873    #[test]
1874    fn custom_vendors() {
1875        // Test various invalid cases.
1876        assert!(Triple::from_str("x86_64--linux").is_err());
1877        assert!(Triple::from_str("x86_64-42-linux").is_err());
1878        assert!(Triple::from_str("x86_64-__customvendor__-linux").is_err());
1879        assert!(Triple::from_str("x86_64-^-linux").is_err());
1880        assert!(Triple::from_str("x86_64- -linux").is_err());
1881        assert!(Triple::from_str("x86_64-CustomVendor-linux").is_err());
1882        assert!(Triple::from_str("x86_64-linux-linux").is_err());
1883        assert!(Triple::from_str("x86_64-x86_64-linux").is_err());
1884        assert!(Triple::from_str("x86_64-elf-linux").is_err());
1885        assert!(Triple::from_str("x86_64-gnu-linux").is_err());
1886        assert!(Triple::from_str("x86_64-linux-customvendor").is_err());
1887        assert!(Triple::from_str("customvendor").is_err());
1888        assert!(Triple::from_str("customvendor-x86_64").is_err());
1889        assert!(Triple::from_str("x86_64-").is_err());
1890        assert!(Triple::from_str("x86_64--").is_err());
1891
1892        // Test various Unicode things.
1893        assert!(
1894            Triple::from_str("x86_64-𝓬𝓾𝓼𝓽𝓸𝓶𝓿𝓮𝓷𝓭𝓸𝓻-linux").is_err(),
1895            "unicode font hazard"
1896        );
1897        assert!(
1898            Triple::from_str("x86_64-ćúśtőḿvéńdőŕ-linux").is_err(),
1899            "diacritical mark stripping hazard"
1900        );
1901        assert!(
1902            Triple::from_str("x86_64-customvendοr-linux").is_err(),
1903            "homoglyph hazard"
1904        );
1905        assert!(Triple::from_str("x86_64-customvendor-linux").is_ok());
1906        assert!(
1907            Triple::from_str("x86_64-ffi-linux").is_err(),
1908            "normalization hazard"
1909        );
1910        assert!(Triple::from_str("x86_64-ffi-linux").is_ok());
1911        assert!(
1912            Triple::from_str("x86_64-custom‍vendor-linux").is_err(),
1913            "zero-width character hazard"
1914        );
1915        assert!(
1916            Triple::from_str("x86_64-customvendor-linux").is_err(),
1917            "BOM hazard"
1918        );
1919
1920        // Test some valid cases.
1921        let t = Triple::from_str("x86_64-customvendor-linux")
1922            .expect("can't parse target with custom vendor");
1923        assert_eq!(t.architecture, Architecture::X86_64);
1924        assert_eq!(
1925            t.vendor,
1926            Vendor::Custom(CustomVendor::Static("customvendor"))
1927        );
1928        assert_eq!(t.operating_system, OperatingSystem::Linux);
1929        assert_eq!(t.environment, Environment::Unknown);
1930        assert_eq!(t.binary_format, BinaryFormat::Elf);
1931        assert_eq!(t.to_string(), "x86_64-customvendor-linux");
1932
1933        let t =
1934            Triple::from_str("x86_64-customvendor").expect("can't parse target with custom vendor");
1935        assert_eq!(t.architecture, Architecture::X86_64);
1936        assert_eq!(
1937            t.vendor,
1938            Vendor::Custom(CustomVendor::Static("customvendor"))
1939        );
1940        assert_eq!(t.operating_system, OperatingSystem::Unknown);
1941        assert_eq!(t.environment, Environment::Unknown);
1942        assert_eq!(t.binary_format, BinaryFormat::Elf);
1943
1944        assert_eq!(
1945            Triple::from_str("unknown-foo"),
1946            Ok(Triple {
1947                architecture: Architecture::Unknown,
1948                vendor: Vendor::Custom(CustomVendor::Static("foo")),
1949                operating_system: OperatingSystem::Unknown,
1950                environment: Environment::Unknown,
1951                binary_format: BinaryFormat::Unknown,
1952            })
1953        );
1954    }
1955}