1use 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#[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 Pulley32be,
37 Pulley64be,
38 Powerpc,
39 Powerpc64,
40 Powerpc64le,
41 Riscv32(Riscv32Architecture),
42 Riscv64(Riscv64Architecture),
43 S390x,
44 Sparc,
45 Sparc64,
46 Sparcv9,
47 Wasm32,
48 Wasm64,
49 X86_64,
50 X86_64h,
52 XTensa,
53 Clever(CleverArchitecture),
54 #[cfg(feature = "arch_zkasm")]
58 ZkAsm,
59 #[cfg(feature = "arch_z80")]
60 Z80(Z80Architecture),
61}
62
63#[cfg_attr(feature = "rust_1_40", non_exhaustive)]
64#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
65#[allow(missing_docs)]
66pub enum ArmArchitecture {
67 Arm, Armeb,
69 Armv4,
70 Armv4t,
71 Armv5t,
72 Armv5te,
73 Armv5tej,
74 Armv6,
75 Armv6j,
76 Armv6k,
77 Armv6z,
78 Armv6kz,
79 Armv6t2,
80 Armv6m,
81 Armv7,
82 Armv7a,
83 Armv7k,
84 Armv7ve,
85 Armv7m,
86 Armv7r,
87 Armv7s,
88 Armv8,
89 Armv8a,
90 Armv8_1a,
91 Armv8_2a,
92 Armv8_3a,
93 Armv8_4a,
94 Armv8_5a,
95 Armv8mBase,
96 Armv8mMain,
97 Armv8r,
98
99 Armebv7r,
100
101 Thumbeb,
102 Thumbv4t,
103 Thumbv5te,
104 Thumbv6m,
105 Thumbv7a,
106 Thumbv7em,
107 Thumbv7m,
108 Thumbv7neon,
109 Thumbv8mBase,
110 Thumbv8mMain,
111}
112
113#[cfg_attr(feature = "rust_1_40", non_exhaustive)]
114#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
115#[allow(missing_docs)]
116pub enum Aarch64Architecture {
117 Aarch64,
118 Aarch64be,
119}
120
121impl ArmArchitecture {
145 #[rustfmt::skip]
147 pub fn is_thumb(self) -> bool {
148 use ArmArchitecture::*;
149
150 match self {
151 Arm
152 | Armeb
153 | Armv4
154 | Armv4t
155 | Armv5t
156 | Armv5te
157 | Armv5tej
158 | Armv6
159 | Armv6j
160 | Armv6k
161 | Armv6z
162 | Armv6kz
163 | Armv6t2
164 | Armv6m
165 | Armv7
166 | Armv7a
167 | Armv7k
168 | Armv7ve
169 | Armv7m
170 | Armv7r
171 | Armv7s
172 | Armv8
173 | Armv8a
174 | Armv8_1a
175 | Armv8_2a
176 | Armv8_3a
177 | Armv8_4a
178 | Armv8_5a
179 | Armv8mBase
180 | Armv8mMain
181 | Armv8r
182 | Armebv7r => false,
183 Thumbeb
184 | Thumbv4t
185 | Thumbv5te
186 | Thumbv6m
187 | Thumbv7a
188 | Thumbv7em
189 | Thumbv7m
190 | Thumbv7neon
191 | Thumbv8mBase
192 | Thumbv8mMain => true,
193 }
194 }
195
196 #[rustfmt::skip]
202 pub fn pointer_width(self) -> PointerWidth {
203 use ArmArchitecture::*;
204
205 match self {
206 Arm
207 | Armeb
208 | Armv4
209 | Armv4t
210 | Armv5t
211 | Armv5te
212 | Armv5tej
213 | Armv6
214 | Armv6j
215 | Armv6k
216 | Armv6z
217 | Armv6kz
218 | Armv6t2
219 | Armv6m
220 | Armv7
221 | Armv7a
222 | Armv7k
223 | Armv7ve
224 | Armv7m
225 | Armv7r
226 | Armv7s
227 | Armv8
228 | Armv8a
229 | Armv8_1a
230 | Armv8_2a
231 | Armv8_3a
232 | Armv8_4a
233 | Armv8_5a
234 | Armv8mBase
235 | Armv8mMain
236 | Armv8r
237 | Armebv7r
238 | Thumbeb
239 | Thumbv4t
240 | Thumbv5te
241 | Thumbv6m
242 | Thumbv7a
243 | Thumbv7em
244 | Thumbv7m
245 | Thumbv7neon
246 | Thumbv8mBase
247 | Thumbv8mMain => PointerWidth::U32,
248 }
249 }
250
251 #[rustfmt::skip]
253 pub fn endianness(self) -> Endianness {
254 use ArmArchitecture::*;
255
256 match self {
257 Arm
258 | Armv4
259 | Armv4t
260 | Armv5t
261 | Armv5te
262 | Armv5tej
263 | Armv6
264 | Armv6j
265 | Armv6k
266 | Armv6z
267 | Armv6kz
268 | Armv6t2
269 | Armv6m
270 | Armv7
271 | Armv7a
272 | Armv7k
273 | Armv7ve
274 | Armv7m
275 | Armv7r
276 | Armv7s
277 | Armv8
278 | Armv8a
279 | Armv8_1a
280 | Armv8_2a
281 | Armv8_3a
282 | Armv8_4a
283 | Armv8_5a
284 | Armv8mBase
285 | Armv8mMain
286 | Armv8r
287 | Thumbv4t
288 | Thumbv5te
289 | Thumbv6m
290 | Thumbv7a
291 | Thumbv7em
292 | Thumbv7m
293 | Thumbv7neon
294 | Thumbv8mBase
295 | Thumbv8mMain => Endianness::Little,
296 Armeb | Armebv7r | Thumbeb => Endianness::Big,
297 }
298 }
299
300 pub fn into_str(self) -> Cow<'static, str> {
302 use ArmArchitecture::*;
303
304 match self {
305 Arm => Cow::Borrowed("arm"),
306 Armeb => Cow::Borrowed("armeb"),
307 Armv4 => Cow::Borrowed("armv4"),
308 Armv4t => Cow::Borrowed("armv4t"),
309 Armv5t => Cow::Borrowed("armv5t"),
310 Armv5te => Cow::Borrowed("armv5te"),
311 Armv5tej => Cow::Borrowed("armv5tej"),
312 Armv6 => Cow::Borrowed("armv6"),
313 Armv6j => Cow::Borrowed("armv6j"),
314 Armv6k => Cow::Borrowed("armv6k"),
315 Armv6z => Cow::Borrowed("armv6z"),
316 Armv6kz => Cow::Borrowed("armv6kz"),
317 Armv6t2 => Cow::Borrowed("armv6t2"),
318 Armv6m => Cow::Borrowed("armv6m"),
319 Armv7 => Cow::Borrowed("armv7"),
320 Armv7a => Cow::Borrowed("armv7a"),
321 Armv7k => Cow::Borrowed("armv7k"),
322 Armv7ve => Cow::Borrowed("armv7ve"),
323 Armv7m => Cow::Borrowed("armv7m"),
324 Armv7r => Cow::Borrowed("armv7r"),
325 Armv7s => Cow::Borrowed("armv7s"),
326 Armv8 => Cow::Borrowed("armv8"),
327 Armv8a => Cow::Borrowed("armv8a"),
328 Armv8_1a => Cow::Borrowed("armv8.1a"),
329 Armv8_2a => Cow::Borrowed("armv8.2a"),
330 Armv8_3a => Cow::Borrowed("armv8.3a"),
331 Armv8_4a => Cow::Borrowed("armv8.4a"),
332 Armv8_5a => Cow::Borrowed("armv8.5a"),
333 Armv8mBase => Cow::Borrowed("armv8m.base"),
334 Armv8mMain => Cow::Borrowed("armv8m.main"),
335 Armv8r => Cow::Borrowed("armv8r"),
336 Thumbeb => Cow::Borrowed("thumbeb"),
337 Thumbv4t => Cow::Borrowed("thumbv4t"),
338 Thumbv5te => Cow::Borrowed("thumbv5te"),
339 Thumbv6m => Cow::Borrowed("thumbv6m"),
340 Thumbv7a => Cow::Borrowed("thumbv7a"),
341 Thumbv7em => Cow::Borrowed("thumbv7em"),
342 Thumbv7m => Cow::Borrowed("thumbv7m"),
343 Thumbv7neon => Cow::Borrowed("thumbv7neon"),
344 Thumbv8mBase => Cow::Borrowed("thumbv8m.base"),
345 Thumbv8mMain => Cow::Borrowed("thumbv8m.main"),
346 Armebv7r => Cow::Borrowed("armebv7r"),
347 }
348 }
349}
350
351impl Aarch64Architecture {
352 pub fn is_thumb(self) -> bool {
354 match self {
355 Aarch64Architecture::Aarch64 | Aarch64Architecture::Aarch64be => false,
356 }
357 }
358
359 pub fn pointer_width(self) -> PointerWidth {
368 match self {
369 Aarch64Architecture::Aarch64 | Aarch64Architecture::Aarch64be => PointerWidth::U64,
370 }
371 }
372
373 pub fn endianness(self) -> Endianness {
375 match self {
376 Aarch64Architecture::Aarch64 => Endianness::Little,
377 Aarch64Architecture::Aarch64be => Endianness::Big,
378 }
379 }
380
381 pub fn into_str(self) -> Cow<'static, str> {
383 use Aarch64Architecture::*;
384
385 match self {
386 Aarch64 => Cow::Borrowed("aarch64"),
387 Aarch64be => Cow::Borrowed("aarch64_be"),
388 }
389 }
390}
391
392#[cfg_attr(feature = "rust_1_40", non_exhaustive)]
393#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
394#[allow(missing_docs)]
395pub enum CleverArchitecture {
396 Clever,
397 Clever1_0,
398}
399
400impl CleverArchitecture {
401 pub fn into_str(self) -> Cow<'static, str> {
403 use CleverArchitecture::*;
404
405 match self {
406 Clever => Cow::Borrowed("clever"),
407 Clever1_0 => Cow::Borrowed("clever1.0"),
408 }
409 }
410}
411
412#[cfg_attr(feature = "rust_1_40", non_exhaustive)]
414#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
415#[allow(missing_docs)]
416pub enum Riscv32Architecture {
417 Riscv32,
418 Riscv32gc,
419 Riscv32i,
420 Riscv32im,
421 Riscv32ima,
422 Riscv32imac,
423 Riscv32imafc,
424 Riscv32imc,
425}
426
427impl Riscv32Architecture {
428 pub fn into_str(self) -> Cow<'static, str> {
430 use Riscv32Architecture::*;
431
432 match self {
433 Riscv32 => Cow::Borrowed("riscv32"),
434 Riscv32gc => Cow::Borrowed("riscv32gc"),
435 Riscv32i => Cow::Borrowed("riscv32i"),
436 Riscv32im => Cow::Borrowed("riscv32im"),
437 Riscv32ima => Cow::Borrowed("riscv32ima"),
438 Riscv32imac => Cow::Borrowed("riscv32imac"),
439 Riscv32imafc => Cow::Borrowed("riscv32imafc"),
440 Riscv32imc => Cow::Borrowed("riscv32imc"),
441 }
442 }
443}
444
445#[cfg_attr(feature = "rust_1_40", non_exhaustive)]
447#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
448#[allow(missing_docs)]
449pub enum Riscv64Architecture {
450 Riscv64,
451 Riscv64gc,
452 Riscv64imac,
453 Riscv64a23,
454}
455
456impl Riscv64Architecture {
457 pub fn into_str(self) -> Cow<'static, str> {
459 use Riscv64Architecture::*;
460
461 match self {
462 Riscv64 => Cow::Borrowed("riscv64"),
463 Riscv64gc => Cow::Borrowed("riscv64gc"),
464 Riscv64imac => Cow::Borrowed("riscv64imac"),
465 Riscv64a23 => Cow::Borrowed("riscv64a23"),
466 }
467 }
468}
469
470#[cfg_attr(feature = "rust_1_40", non_exhaustive)]
472#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
473#[allow(missing_docs)]
474pub enum X86_32Architecture {
475 I386,
476 I586,
477 I686,
478}
479
480impl X86_32Architecture {
481 pub fn into_str(self) -> Cow<'static, str> {
483 use X86_32Architecture::*;
484
485 match self {
486 I386 => Cow::Borrowed("i386"),
487 I586 => Cow::Borrowed("i586"),
488 I686 => Cow::Borrowed("i686"),
489 }
490 }
491}
492
493#[cfg_attr(feature = "rust_1_40", non_exhaustive)]
495#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
496#[allow(missing_docs)]
497pub enum Mips32Architecture {
498 Mips,
499 Mipsel,
500 Mipsisa32r6,
501 Mipsisa32r6el,
502}
503
504impl Mips32Architecture {
505 pub fn into_str(self) -> Cow<'static, str> {
507 use Mips32Architecture::*;
508
509 match self {
510 Mips => Cow::Borrowed("mips"),
511 Mipsel => Cow::Borrowed("mipsel"),
512 Mipsisa32r6 => Cow::Borrowed("mipsisa32r6"),
513 Mipsisa32r6el => Cow::Borrowed("mipsisa32r6el"),
514 }
515 }
516}
517
518#[cfg_attr(feature = "rust_1_40", non_exhaustive)]
520#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
521#[allow(missing_docs)]
522pub enum Mips64Architecture {
523 Mips64,
524 Mips64el,
525 Mipsisa64r6,
526 Mipsisa64r6el,
527}
528
529impl Mips64Architecture {
530 pub fn into_str(self) -> Cow<'static, str> {
532 use Mips64Architecture::*;
533
534 match self {
535 Mips64 => Cow::Borrowed("mips64"),
536 Mips64el => Cow::Borrowed("mips64el"),
537 Mipsisa64r6 => Cow::Borrowed("mipsisa64r6"),
538 Mipsisa64r6el => Cow::Borrowed("mipsisa64r6el"),
539 }
540 }
541}
542
543#[cfg(feature = "arch_z80")]
544#[cfg_attr(feature = "rust_1_40", non_exhaustive)]
545#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
546#[allow(missing_docs)]
547pub enum Z80Architecture {
548 Z80,
549 Z180,
550 Ez80,
551 Sm83,
552 Rabbit2000,
553 Rabbit2000A,
554 Rabbit3000,
555 Rabbit3000A,
556 Tlcs90,
557 R800,
558}
559
560#[cfg(feature = "arch_z80")]
561impl Z80Architecture {
562 pub fn into_str(self) -> Cow<'static, str> {
563 use Z80Architecture::*;
564
565 match self {
566 Z80 => Cow::Borrowed("z80"),
567 Z180 => Cow::Borrowed("z180"),
568 Ez80 => Cow::Borrowed("ez80"),
569 Sm83 => Cow::Borrowed("sm83"),
570 Rabbit2000 => Cow::Borrowed("rabbit2000"),
571 Rabbit2000A => Cow::Borrowed("rabbit2000a"),
572 Rabbit3000 => Cow::Borrowed("rabbit3000"),
573 Rabbit3000A => Cow::Borrowed("rabbit3000a"),
574 Tlcs90 => Cow::Borrowed("tlcs90"),
575 R800 => Cow::Borrowed("r800"),
576 }
577 }
578}
579
580#[derive(Clone, Debug, Eq)]
583pub enum CustomVendor {
584 Owned(Box<String>),
586 Static(&'static str),
589}
590
591impl CustomVendor {
592 pub fn as_str(&self) -> &str {
594 match self {
595 CustomVendor::Owned(s) => s,
596 CustomVendor::Static(s) => s,
597 }
598 }
599}
600
601impl PartialEq for CustomVendor {
602 fn eq(&self, other: &Self) -> bool {
603 self.as_str() == other.as_str()
604 }
605}
606
607impl Hash for CustomVendor {
608 fn hash<H: Hasher>(&self, state: &mut H) {
609 self.as_str().hash(state)
610 }
611}
612
613#[cfg_attr(feature = "rust_1_40", non_exhaustive)]
616#[derive(Clone, Debug, PartialEq, Eq, Hash)]
617#[allow(missing_docs)]
618pub enum Vendor {
619 Unknown,
620 Amd,
621 Apple,
622 Espressif,
623 Experimental,
624 Fortanix,
625 Ibm,
626 Kmc,
627 Nintendo,
628 Nvidia,
629 Pc,
630 Rumprun,
631 Sun,
632 Uwp,
633 Wrs,
634
635 Custom(CustomVendor),
643}
644
645impl Vendor {
646 pub fn as_str(&self) -> &str {
648 use Vendor::*;
649
650 match self {
651 Unknown => "unknown",
652 Amd => "amd",
653 Apple => "apple",
654 Espressif => "espressif",
655 Experimental => "experimental",
656 Fortanix => "fortanix",
657 Ibm => "ibm",
658 Kmc => "kmc",
659 Nintendo => "nintendo",
660 Nvidia => "nvidia",
661 Pc => "pc",
662 Rumprun => "rumprun",
663 Sun => "sun",
664 Uwp => "uwp",
665 Wrs => "wrs",
666 Custom(name) => name.as_str(),
667 }
668 }
669}
670
671#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
677#[allow(missing_docs)]
678pub struct DeploymentTarget {
679 pub major: u16,
680 pub minor: u8,
681 pub patch: u8,
682}
683
684#[cfg_attr(feature = "rust_1_40", non_exhaustive)]
691#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
692#[allow(missing_docs)]
693pub enum OperatingSystem {
694 Unknown,
695 Aix,
696 AmdHsa,
697 Bitrig,
698 Cloudabi,
699 Cuda,
700 Cygwin,
701 Darwin(Option<DeploymentTarget>),
712 Dragonfly,
713 Emscripten,
714 Espidf,
715 Freebsd,
716 Fuchsia,
717 Haiku,
718 Hermit,
719 Horizon,
720 Hurd,
721 Illumos,
722 IOS(Option<DeploymentTarget>),
723 L4re,
724 Linux,
725 MacOSX(Option<DeploymentTarget>),
730 Nebulet,
731 Netbsd,
732 None_,
733 Openbsd,
734 Psp,
735 Redox,
736 Solaris,
737 SolidAsp3,
738 TvOS(Option<DeploymentTarget>),
739 Uefi,
740 VisionOS(Option<DeploymentTarget>),
741 VxWorks,
742 Wasi,
743 WasiP1,
744 WasiP2,
745 WatchOS(Option<DeploymentTarget>),
746 Windows,
747 XROS(Option<DeploymentTarget>),
749}
750
751impl OperatingSystem {
752 pub fn into_str(self) -> Cow<'static, str> {
754 use OperatingSystem::*;
755
756 let darwin_version = |name, deployment_target| {
757 if let Some(DeploymentTarget {
758 major,
759 minor,
760 patch,
761 }) = deployment_target
762 {
763 Cow::Owned(format!("{}{}.{}.{}", name, major, minor, patch))
764 } else {
765 Cow::Borrowed(name)
766 }
767 };
768
769 match self {
770 Unknown => Cow::Borrowed("unknown"),
771 Aix => Cow::Borrowed("aix"),
772 AmdHsa => Cow::Borrowed("amdhsa"),
773 Bitrig => Cow::Borrowed("bitrig"),
774 Cloudabi => Cow::Borrowed("cloudabi"),
775 Cuda => Cow::Borrowed("cuda"),
776 Cygwin => Cow::Borrowed("cygwin"),
777 Darwin(deployment_target) => darwin_version("darwin", deployment_target),
778 Dragonfly => Cow::Borrowed("dragonfly"),
779 Emscripten => Cow::Borrowed("emscripten"),
780 Espidf => Cow::Borrowed("espidf"),
781 Freebsd => Cow::Borrowed("freebsd"),
782 Fuchsia => Cow::Borrowed("fuchsia"),
783 Haiku => Cow::Borrowed("haiku"),
784 Hermit => Cow::Borrowed("hermit"),
785 Horizon => Cow::Borrowed("horizon"),
786 Hurd => Cow::Borrowed("hurd"),
787 Illumos => Cow::Borrowed("illumos"),
788 IOS(deployment_target) => darwin_version("ios", deployment_target),
789 L4re => Cow::Borrowed("l4re"),
790 Linux => Cow::Borrowed("linux"),
791 MacOSX(deployment_target) => darwin_version("macosx", deployment_target),
792 Nebulet => Cow::Borrowed("nebulet"),
793 Netbsd => Cow::Borrowed("netbsd"),
794 None_ => Cow::Borrowed("none"),
795 Openbsd => Cow::Borrowed("openbsd"),
796 Psp => Cow::Borrowed("psp"),
797 Redox => Cow::Borrowed("redox"),
798 Solaris => Cow::Borrowed("solaris"),
799 SolidAsp3 => Cow::Borrowed("solid_asp3"),
800 TvOS(deployment_target) => darwin_version("tvos", deployment_target),
801 Uefi => Cow::Borrowed("uefi"),
802 VxWorks => Cow::Borrowed("vxworks"),
803 VisionOS(deployment_target) => darwin_version("visionos", deployment_target),
804 Wasi => Cow::Borrowed("wasi"),
805 WasiP1 => Cow::Borrowed("wasip1"),
806 WasiP2 => Cow::Borrowed("wasip2"),
807 WatchOS(deployment_target) => darwin_version("watchos", deployment_target),
808 Windows => Cow::Borrowed("windows"),
809 XROS(deployment_target) => darwin_version("xros", deployment_target),
810 }
811 }
812
813 pub fn is_like_darwin(&self) -> bool {
824 use OperatingSystem::*;
825
826 match self {
827 Darwin(_) | IOS(_) | MacOSX(_) | TvOS(_) | VisionOS(_) | WatchOS(_) | XROS(_) => true,
828 _ => false,
829 }
830 }
831}
832
833#[cfg_attr(feature = "rust_1_40", non_exhaustive)]
837#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
838#[allow(missing_docs)]
839pub enum Environment {
840 Unknown,
841 AmdGiz,
842 Android,
843 Androideabi,
844 Eabi,
845 Eabihf,
846 Gnu,
847 Gnuabi64,
848 Gnueabi,
849 Gnueabihf,
850 Gnuspe,
851 Gnux32,
852 GnuIlp32,
853 GnuLlvm,
854 HermitKernel,
855 HurdKernel,
856 LinuxKernel,
857 Macabi,
858 Musl,
859 Musleabi,
860 Musleabihf,
861 Muslabi64,
862 Msvc,
863 Newlib,
864 None,
865 Kernel,
866 Uclibc,
867 Uclibceabi,
868 Uclibceabihf,
869 Sgx,
870 Sim,
871 Softfloat,
872 Spe,
873 Threads,
874 Ohos,
875}
876
877impl Environment {
878 pub fn into_str(self) -> Cow<'static, str> {
880 use Environment::*;
881
882 match self {
883 Unknown => Cow::Borrowed("unknown"),
884 AmdGiz => Cow::Borrowed("amdgiz"),
885 Android => Cow::Borrowed("android"),
886 Androideabi => Cow::Borrowed("androideabi"),
887 Eabi => Cow::Borrowed("eabi"),
888 Eabihf => Cow::Borrowed("eabihf"),
889 Gnu => Cow::Borrowed("gnu"),
890 Gnuabi64 => Cow::Borrowed("gnuabi64"),
891 Gnueabi => Cow::Borrowed("gnueabi"),
892 Gnueabihf => Cow::Borrowed("gnueabihf"),
893 Gnuspe => Cow::Borrowed("gnuspe"),
894 Gnux32 => Cow::Borrowed("gnux32"),
895 GnuIlp32 => Cow::Borrowed("gnu_ilp32"),
896 GnuLlvm => Cow::Borrowed("gnullvm"),
897 HermitKernel => Cow::Borrowed("hermitkernel"),
898 HurdKernel => Cow::Borrowed("hurdkernel"),
899 LinuxKernel => Cow::Borrowed("linuxkernel"),
900 Macabi => Cow::Borrowed("macabi"),
901 Musl => Cow::Borrowed("musl"),
902 Musleabi => Cow::Borrowed("musleabi"),
903 Musleabihf => Cow::Borrowed("musleabihf"),
904 Muslabi64 => Cow::Borrowed("muslabi64"),
905 Msvc => Cow::Borrowed("msvc"),
906 Newlib => Cow::Borrowed("newlib"),
907 None => Cow::Borrowed("none"),
908 Kernel => Cow::Borrowed("kernel"),
909 Uclibc => Cow::Borrowed("uclibc"),
910 Uclibceabi => Cow::Borrowed("uclibceabi"),
911 Uclibceabihf => Cow::Borrowed("uclibceabihf"),
912 Sgx => Cow::Borrowed("sgx"),
913 Sim => Cow::Borrowed("sim"),
914 Softfloat => Cow::Borrowed("softfloat"),
915 Spe => Cow::Borrowed("spe"),
916 Threads => Cow::Borrowed("threads"),
917 Ohos => Cow::Borrowed("ohos"),
918 }
919 }
920}
921
922#[cfg_attr(feature = "rust_1_40", non_exhaustive)]
925#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
926#[allow(missing_docs)]
927pub enum BinaryFormat {
928 Unknown,
929 Elf,
930 Coff,
931 Macho,
932 Wasm,
933 Xcoff,
934}
935
936impl BinaryFormat {
937 pub fn into_str(self) -> Cow<'static, str> {
939 use BinaryFormat::*;
940
941 match self {
942 Unknown => Cow::Borrowed("unknown"),
943 Elf => Cow::Borrowed("elf"),
944 Coff => Cow::Borrowed("coff"),
945 Macho => Cow::Borrowed("macho"),
946 Wasm => Cow::Borrowed("wasm"),
947 Xcoff => Cow::Borrowed("xcoff"),
948 }
949 }
950}
951
952impl Architecture {
953 #[rustfmt::skip]
955 pub fn endianness(self) -> Result<Endianness, ()> {
956 use Architecture::*;
957
958 match self {
959 Unknown => Err(()),
960 Arm(arm) => Ok(arm.endianness()),
961 Aarch64(aarch) => Ok(aarch.endianness()),
962 AmdGcn
963 | Asmjs
964 | Avr
965 | Bpfel
966 | Hexagon
967 | X86_32(_)
968 | LoongArch64
969 | Mips64(Mips64Architecture::Mips64el)
970 | Mips32(Mips32Architecture::Mipsel)
971 | Mips32(Mips32Architecture::Mipsisa32r6el)
972 | Mips64(Mips64Architecture::Mipsisa64r6el)
973 | Msp430
974 | Nvptx64
975 | Pulley32
976 | Pulley64
977 | Powerpc64le
978 | Riscv32(_)
979 | Riscv64(_)
980 | Wasm32
981 | Wasm64
982 | X86_64
983 | X86_64h
984 | XTensa
985 | Clever(_) => Ok(Endianness::Little),
986 Bpfeb
987 | M68k
988 | Mips32(Mips32Architecture::Mips)
989 | Mips64(Mips64Architecture::Mips64)
990 | Mips32(Mips32Architecture::Mipsisa32r6)
991 | Mips64(Mips64Architecture::Mipsisa64r6)
992 | Powerpc
993 | Powerpc64
994 | Pulley32be
995 | Pulley64be
996 | S390x
997 | Sparc
998 | Sparc64
999 | Sparcv9 => Ok(Endianness::Big),
1000 #[cfg(feature="arch_zkasm")]
1001 ZkAsm => Ok(Endianness::Big),
1002 #[cfg(feature = "arch_z80")]
1003 Z80(_) => Ok(Endianness::Little),
1004 }
1005 }
1006
1007 #[rustfmt::skip]
1012 pub fn pointer_width(self) -> Result<PointerWidth, ()> {
1013 use Architecture::*;
1014
1015 match self {
1016 Unknown => Err(()),
1017 Avr | Msp430 => Ok(PointerWidth::U16),
1018 Arm(arm) => Ok(arm.pointer_width()),
1019 Aarch64(aarch) => Ok(aarch.pointer_width()),
1020 Asmjs
1021 | Hexagon
1022 | X86_32(_)
1023 | Riscv32(_)
1024 | Sparc
1025 | Wasm32
1026 | M68k
1027 | Mips32(_)
1028 | Pulley32
1029 | Pulley32be
1030 | Powerpc
1031 | XTensa => Ok(PointerWidth::U32),
1032 AmdGcn
1033 | Bpfeb
1034 | Bpfel
1035 | Powerpc64le
1036 | Riscv64(_)
1037 | X86_64
1038 | X86_64h
1039 | Mips64(_)
1040 | Nvptx64
1041 | Pulley64
1042 | Pulley64be
1043 | Powerpc64
1044 | S390x
1045 | Sparc64
1046 | Sparcv9
1047 | LoongArch64
1048 | Wasm64
1049 | Clever(_) => Ok(PointerWidth::U64),
1050 #[cfg(feature="arch_zkasm")]
1051 ZkAsm => Ok(PointerWidth::U64),
1052 #[cfg(feature = "arch_z80")]
1053 Z80(_) => Ok(PointerWidth::U16),
1054 }
1055 }
1056
1057 pub fn is_clever(&self) -> bool {
1059 match self {
1060 Architecture::Clever(_) => true,
1061 _ => false,
1062 }
1063 }
1064
1065 pub fn into_str(self) -> Cow<'static, str> {
1067 use Architecture::*;
1068
1069 match self {
1070 Arm(arm) => arm.into_str(),
1071 Aarch64(aarch) => aarch.into_str(),
1072 Unknown => Cow::Borrowed("unknown"),
1073 AmdGcn => Cow::Borrowed("amdgcn"),
1074 Asmjs => Cow::Borrowed("asmjs"),
1075 Avr => Cow::Borrowed("avr"),
1076 Bpfeb => Cow::Borrowed("bpfeb"),
1077 Bpfel => Cow::Borrowed("bpfel"),
1078 Hexagon => Cow::Borrowed("hexagon"),
1079 X86_32(x86_32) => x86_32.into_str(),
1080 LoongArch64 => Cow::Borrowed("loongarch64"),
1081 M68k => Cow::Borrowed("m68k"),
1082 Mips32(mips32) => mips32.into_str(),
1083 Mips64(mips64) => mips64.into_str(),
1084 Msp430 => Cow::Borrowed("msp430"),
1085 Nvptx64 => Cow::Borrowed("nvptx64"),
1086 Pulley32 => Cow::Borrowed("pulley32"),
1087 Pulley64 => Cow::Borrowed("pulley64"),
1088 Pulley32be => Cow::Borrowed("pulley32be"),
1089 Pulley64be => Cow::Borrowed("pulley64be"),
1090 Powerpc => Cow::Borrowed("powerpc"),
1091 Powerpc64 => Cow::Borrowed("powerpc64"),
1092 Powerpc64le => Cow::Borrowed("powerpc64le"),
1093 Riscv32(riscv32) => riscv32.into_str(),
1094 Riscv64(riscv64) => riscv64.into_str(),
1095 S390x => Cow::Borrowed("s390x"),
1096 Sparc => Cow::Borrowed("sparc"),
1097 Sparc64 => Cow::Borrowed("sparc64"),
1098 Sparcv9 => Cow::Borrowed("sparcv9"),
1099 Wasm32 => Cow::Borrowed("wasm32"),
1100 Wasm64 => Cow::Borrowed("wasm64"),
1101 X86_64 => Cow::Borrowed("x86_64"),
1102 X86_64h => Cow::Borrowed("x86_64h"),
1103 XTensa => Cow::Borrowed("xtensa"),
1104 Clever(ver) => ver.into_str(),
1105 #[cfg(feature = "arch_zkasm")]
1106 ZkAsm => Cow::Borrowed("zkasm"),
1107 #[cfg(feature = "arch_z80")]
1108 Z80(z80) => z80.into_str(),
1109 }
1110 }
1111}
1112
1113pub(crate) fn default_binary_format(triple: &Triple) -> BinaryFormat {
1116 match triple.operating_system {
1117 OperatingSystem::None_ => match triple.environment {
1118 Environment::Eabi | Environment::Eabihf => BinaryFormat::Elf,
1119 _ => BinaryFormat::Unknown,
1120 },
1121 OperatingSystem::Aix => BinaryFormat::Xcoff,
1122 os if os.is_like_darwin() => BinaryFormat::Macho,
1123 OperatingSystem::Windows => BinaryFormat::Coff,
1124 OperatingSystem::Nebulet
1125 | OperatingSystem::Emscripten
1126 | OperatingSystem::VxWorks
1127 | OperatingSystem::Wasi
1128 | OperatingSystem::Unknown => match triple.architecture {
1129 Architecture::Wasm32 | Architecture::Wasm64 => BinaryFormat::Wasm,
1130 Architecture::Unknown => BinaryFormat::Unknown,
1131 _ => BinaryFormat::Elf,
1133 },
1134 _ => BinaryFormat::Elf,
1135 }
1136}
1137
1138impl fmt::Display for ArmArchitecture {
1139 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1140 f.write_str(&self.into_str())
1141 }
1142}
1143
1144impl fmt::Display for Aarch64Architecture {
1145 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1146 f.write_str(&self.into_str())
1147 }
1148}
1149
1150impl fmt::Display for CleverArchitecture {
1151 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1152 f.write_str(&self.into_str())
1153 }
1154}
1155
1156impl fmt::Display for Riscv32Architecture {
1157 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1158 f.write_str(&self.into_str())
1159 }
1160}
1161
1162impl fmt::Display for Riscv64Architecture {
1163 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1164 f.write_str(&self.into_str())
1165 }
1166}
1167
1168impl fmt::Display for X86_32Architecture {
1169 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1170 f.write_str(&self.into_str())
1171 }
1172}
1173
1174impl fmt::Display for Mips32Architecture {
1175 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1176 f.write_str(&self.into_str())
1177 }
1178}
1179
1180impl fmt::Display for Mips64Architecture {
1181 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1182 f.write_str(&self.into_str())
1183 }
1184}
1185
1186#[cfg(feature = "arch_z80")]
1187impl fmt::Display for Z80Architecture {
1188 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1189 f.write_str(&self.into_str())
1190 }
1191}
1192
1193impl fmt::Display for Architecture {
1194 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1195 f.write_str(&self.into_str())
1196 }
1197}
1198
1199impl FromStr for ArmArchitecture {
1200 type Err = ();
1201
1202 fn from_str(s: &str) -> Result<Self, ()> {
1203 use ArmArchitecture::*;
1204
1205 Ok(match s {
1206 "arm" => Arm,
1207 "armeb" => Armeb,
1208 "armv4" => Armv4,
1209 "armv4t" => Armv4t,
1210 "armv5t" => Armv5t,
1211 "armv5te" => Armv5te,
1212 "armv5tej" => Armv5tej,
1213 "armv6" => Armv6,
1214 "armv6j" => Armv6j,
1215 "armv6k" => Armv6k,
1216 "armv6z" => Armv6z,
1217 "armv6kz" => Armv6kz,
1218 "armv6t2" => Armv6t2,
1219 "armv6m" => Armv6m,
1220 "armv7" => Armv7,
1221 "armv7a" => Armv7a,
1222 "armv7k" => Armv7k,
1223 "armv7ve" => Armv7ve,
1224 "armv7m" => Armv7m,
1225 "armv7r" => Armv7r,
1226 "armv7s" => Armv7s,
1227 "armv8" => Armv8,
1228 "armv8a" => Armv8a,
1229 "armv8.1a" => Armv8_1a,
1230 "armv8.2a" => Armv8_2a,
1231 "armv8.3a" => Armv8_3a,
1232 "armv8.4a" => Armv8_4a,
1233 "armv8.5a" => Armv8_5a,
1234 "armv8m.base" => Armv8mBase,
1235 "armv8m.main" => Armv8mMain,
1236 "armv8r" => Armv8r,
1237 "thumbeb" => Thumbeb,
1238 "thumbv4t" => Thumbv4t,
1239 "thumbv5te" => Thumbv5te,
1240 "thumbv6m" => Thumbv6m,
1241 "thumbv7a" => Thumbv7a,
1242 "thumbv7em" => Thumbv7em,
1243 "thumbv7m" => Thumbv7m,
1244 "thumbv7neon" => Thumbv7neon,
1245 "thumbv8m.base" => Thumbv8mBase,
1246 "thumbv8m.main" => Thumbv8mMain,
1247 "armebv7r" => Armebv7r,
1248 _ => return Err(()),
1249 })
1250 }
1251}
1252
1253impl FromStr for Aarch64Architecture {
1254 type Err = ();
1255
1256 fn from_str(s: &str) -> Result<Self, ()> {
1257 use Aarch64Architecture::*;
1258
1259 Ok(match s {
1260 "aarch64" => Aarch64,
1261 "arm64" => Aarch64,
1262 "aarch64_be" => Aarch64be,
1263 _ => return Err(()),
1264 })
1265 }
1266}
1267
1268impl FromStr for CleverArchitecture {
1269 type Err = ();
1270 fn from_str(s: &str) -> Result<Self, ()> {
1271 match s {
1272 "clever" => Ok(CleverArchitecture::Clever),
1273 "clever1.0" => Ok(CleverArchitecture::Clever1_0),
1274 _ => Err(()),
1275 }
1276 }
1277}
1278
1279impl FromStr for Riscv32Architecture {
1280 type Err = ();
1281
1282 fn from_str(s: &str) -> Result<Self, ()> {
1283 use Riscv32Architecture::*;
1284
1285 Ok(match s {
1286 "riscv32" => Riscv32,
1287 "riscv32gc" => Riscv32gc,
1288 "riscv32i" => Riscv32i,
1289 "riscv32im" => Riscv32im,
1290 "riscv32ima" => Riscv32ima,
1291 "riscv32imac" => Riscv32imac,
1292 "riscv32imafc" => Riscv32imafc,
1293 "riscv32imc" => Riscv32imc,
1294 _ => return Err(()),
1295 })
1296 }
1297}
1298
1299impl FromStr for Riscv64Architecture {
1300 type Err = ();
1301
1302 fn from_str(s: &str) -> Result<Self, ()> {
1303 use Riscv64Architecture::*;
1304
1305 Ok(match s {
1306 "riscv64" => Riscv64,
1307 "riscv64gc" => Riscv64gc,
1308 "riscv64imac" => Riscv64imac,
1309 "riscv64a23" => Riscv64a23,
1310 _ => return Err(()),
1311 })
1312 }
1313}
1314
1315impl FromStr for X86_32Architecture {
1316 type Err = ();
1317
1318 fn from_str(s: &str) -> Result<Self, ()> {
1319 use X86_32Architecture::*;
1320
1321 Ok(match s {
1322 "i386" => I386,
1323 "i586" => I586,
1324 "i686" => I686,
1325 _ => return Err(()),
1326 })
1327 }
1328}
1329
1330impl FromStr for Mips32Architecture {
1331 type Err = ();
1332
1333 fn from_str(s: &str) -> Result<Self, ()> {
1334 use Mips32Architecture::*;
1335
1336 Ok(match s {
1337 "mips" => Mips,
1338 "mipsel" => Mipsel,
1339 "mipsisa32r6" => Mipsisa32r6,
1340 "mipsisa32r6el" => Mipsisa32r6el,
1341 _ => return Err(()),
1342 })
1343 }
1344}
1345
1346impl FromStr for Mips64Architecture {
1347 type Err = ();
1348
1349 fn from_str(s: &str) -> Result<Self, ()> {
1350 use Mips64Architecture::*;
1351
1352 Ok(match s {
1353 "mips64" => Mips64,
1354 "mips64el" => Mips64el,
1355 "mipsisa64r6" => Mipsisa64r6,
1356 "mipsisa64r6el" => Mipsisa64r6el,
1357 _ => return Err(()),
1358 })
1359 }
1360}
1361
1362#[cfg(feature = "arch_z80")]
1363impl FromStr for Z80Architecture {
1364 type Err = ();
1365
1366 fn from_str(s: &str) -> Result<Self, ()> {
1367 use Z80Architecture::*;
1368
1369 Ok(match s {
1370 "z80" => Z80,
1371 "z180" => Z180,
1372 "ez80" => Ez80,
1373 "sm83" => Sm83,
1374 "rabbit2000" => Rabbit2000,
1375 "rabbit2000a" => Rabbit2000A,
1376 "rabbit3000" => Rabbit3000,
1377 "rabbit3000a" => Rabbit3000A,
1378 "tlcs90" => Tlcs90,
1379 "r800" => R800,
1380 _ => return Err(()),
1381 })
1382 }
1383}
1384
1385impl FromStr for Architecture {
1386 type Err = ();
1387
1388 fn from_str(s: &str) -> Result<Self, ()> {
1389 use Architecture::*;
1390
1391 Ok(match s {
1392 "unknown" => Unknown,
1393 "amdgcn" => AmdGcn,
1394 "asmjs" => Asmjs,
1395 "avr" => Avr,
1396 "bpfeb" => Bpfeb,
1397 "bpfel" => Bpfel,
1398 "hexagon" => Hexagon,
1399 "loongarch64" => LoongArch64,
1400 "m68k" => M68k,
1401 "msp430" => Msp430,
1402 "nvptx64" => Nvptx64,
1403 "pulley32" => Pulley32,
1404 "pulley64" => Pulley64,
1405 "pulley32be" => Pulley32be,
1406 "pulley64be" => Pulley64be,
1407 "powerpc" => Powerpc,
1408 "powerpc64" => Powerpc64,
1409 "powerpc64le" => Powerpc64le,
1410 "s390x" => S390x,
1411 "sparc" => Sparc,
1412 "sparc64" => Sparc64,
1413 "sparcv9" => Sparcv9,
1414 "wasm32" => Wasm32,
1415 "wasm64" => Wasm64,
1416 "x86_64" => X86_64,
1417 "x86_64h" => X86_64h,
1418 "xtensa" => XTensa,
1419 #[cfg(feature = "arch_zkasm")]
1420 "zkasm" => ZkAsm,
1421 _ => {
1422 if let Ok(arm) = ArmArchitecture::from_str(s) {
1423 Arm(arm)
1424 } else if let Ok(aarch64) = Aarch64Architecture::from_str(s) {
1425 Aarch64(aarch64)
1426 } else if let Ok(riscv32) = Riscv32Architecture::from_str(s) {
1427 Riscv32(riscv32)
1428 } else if let Ok(riscv64) = Riscv64Architecture::from_str(s) {
1429 Riscv64(riscv64)
1430 } else if let Ok(x86_32) = X86_32Architecture::from_str(s) {
1431 X86_32(x86_32)
1432 } else if let Ok(mips32) = Mips32Architecture::from_str(s) {
1433 Mips32(mips32)
1434 } else if let Ok(mips64) = Mips64Architecture::from_str(s) {
1435 Mips64(mips64)
1436 } else if let Ok(clever) = CleverArchitecture::from_str(s) {
1437 Clever(clever)
1438 } else {
1439 #[cfg(feature = "arch_z80")]
1440 {
1441 if let Ok(z80) = Z80Architecture::from_str(s) {
1442 return Ok(Architecture::Z80(z80));
1443 }
1444 }
1445 return Err(());
1446 }
1447 }
1448 })
1449 }
1450}
1451
1452impl fmt::Display for Vendor {
1453 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1454 f.write_str(self.as_str())
1455 }
1456}
1457
1458impl FromStr for Vendor {
1459 type Err = ();
1460
1461 fn from_str(s: &str) -> Result<Self, ()> {
1462 use Vendor::*;
1463
1464 Ok(match s {
1465 "unknown" => Unknown,
1466 "amd" => Amd,
1467 "apple" => Apple,
1468 "espressif" => Espressif,
1469 "experimental" => Experimental,
1470 "fortanix" => Fortanix,
1471 "ibm" => Ibm,
1472 "kmc" => Kmc,
1473 "nintendo" => Nintendo,
1474 "nvidia" => Nvidia,
1475 "pc" => Pc,
1476 "rumprun" => Rumprun,
1477 "sun" => Sun,
1478 "uwp" => Uwp,
1479 "wrs" => Wrs,
1480 custom => {
1481 #[cfg(not(feature = "std"))]
1482 use alloc::borrow::ToOwned;
1483
1484 if custom.is_empty() {
1491 return Err(());
1492 }
1493
1494 if Architecture::from_str(custom).is_ok()
1497 || OperatingSystem::from_str(custom).is_ok()
1498 || Environment::from_str(custom).is_ok()
1499 || BinaryFormat::from_str(custom).is_ok()
1500 {
1501 return Err(());
1502 }
1503
1504 if !custom.chars().next().unwrap().is_ascii_lowercase() {
1506 return Err(());
1507 }
1508
1509 let has_restricted = custom.chars().any(|c: char| {
1511 !(c.is_ascii_lowercase() || c.is_ascii_digit() || c == '_' || c == '.')
1512 });
1513
1514 if has_restricted {
1515 return Err(());
1516 }
1517
1518 Custom(CustomVendor::Owned(Box::new(custom.to_owned())))
1519 }
1520 })
1521 }
1522}
1523
1524impl fmt::Display for OperatingSystem {
1525 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1526 use OperatingSystem::*;
1527
1528 let mut with_version = |name, deployment_target| {
1529 if let Some(DeploymentTarget {
1530 major,
1531 minor,
1532 patch,
1533 }) = deployment_target
1534 {
1535 write!(f, "{}{}.{}.{}", name, major, minor, patch)
1536 } else {
1537 write!(f, "{}", name)
1538 }
1539 };
1540
1541 match *self {
1542 Darwin(deployment_target) => with_version("darwin", deployment_target),
1543 IOS(deployment_target) => with_version("ios", deployment_target),
1544 MacOSX(deployment_target) => with_version("macosx", deployment_target),
1545 TvOS(deployment_target) => with_version("tvos", deployment_target),
1546 VisionOS(deployment_target) => with_version("visionos", deployment_target),
1547 WatchOS(deployment_target) => with_version("watchos", deployment_target),
1548 XROS(deployment_target) => with_version("xros", deployment_target),
1549 os => f.write_str(&os.into_str()),
1550 }
1551 }
1552}
1553
1554impl FromStr for OperatingSystem {
1555 type Err = ();
1556
1557 fn from_str(s: &str) -> Result<Self, ()> {
1558 use OperatingSystem::*;
1559
1560 let parse_darwin = |name: &str| {
1561 let s = &s[name.len()..];
1562 let mut parts = s.split('.');
1563
1564 if s.is_empty() {
1565 return Ok(None);
1567 }
1568
1569 let major = if let Some(part) = parts.next() {
1570 part.parse().map_err(|_| ())?
1571 } else {
1572 return Err(());
1575 };
1576 let minor = if let Some(part) = parts.next() {
1577 part.parse().map_err(|_| ())?
1578 } else {
1579 0
1581 };
1582 let patch = if let Some(part) = parts.next() {
1583 part.parse().map_err(|_| ())?
1584 } else {
1585 0
1587 };
1588
1589 if parts.next().is_some() {
1590 return Err(());
1592 }
1593
1594 Ok(Some(DeploymentTarget {
1595 major,
1596 minor,
1597 patch,
1598 }))
1599 };
1600
1601 if s.starts_with("darwin") {
1603 return Ok(Darwin(parse_darwin("darwin")?));
1604 }
1605 if s.starts_with("ios") {
1606 return Ok(IOS(parse_darwin("ios")?));
1607 }
1608 if s.starts_with("macosx") {
1609 return Ok(MacOSX(parse_darwin("macosx")?));
1610 }
1611 if s.starts_with("tvos") {
1612 return Ok(TvOS(parse_darwin("tvos")?));
1613 }
1614 if s.starts_with("visionos") {
1615 return Ok(VisionOS(parse_darwin("visionos")?));
1616 }
1617 if s.starts_with("watchos") {
1618 return Ok(WatchOS(parse_darwin("watchos")?));
1619 }
1620 if s.starts_with("xros") {
1621 return Ok(XROS(parse_darwin("xros")?));
1622 }
1623
1624 Ok(match s {
1625 "unknown" => Unknown,
1626 "aix" => Aix,
1627 "amdhsa" => AmdHsa,
1628 "bitrig" => Bitrig,
1629 "cloudabi" => Cloudabi,
1630 "cuda" => Cuda,
1631 "cygwin" => Cygwin,
1632 "dragonfly" => Dragonfly,
1633 "emscripten" => Emscripten,
1634 "freebsd" => Freebsd,
1635 "fuchsia" => Fuchsia,
1636 "haiku" => Haiku,
1637 "hermit" => Hermit,
1638 "horizon" => Horizon,
1639 "hurd" => Hurd,
1640 "illumos" => Illumos,
1641 "l4re" => L4re,
1642 "linux" => Linux,
1643 "nebulet" => Nebulet,
1644 "netbsd" => Netbsd,
1645 "none" => None_,
1646 "openbsd" => Openbsd,
1647 "psp" => Psp,
1648 "redox" => Redox,
1649 "solaris" => Solaris,
1650 "solid_asp3" => SolidAsp3,
1651 "uefi" => Uefi,
1652 "vxworks" => VxWorks,
1653 "wasi" => Wasi,
1654 "wasip1" => WasiP1,
1655 "wasip2" => WasiP2,
1656 "windows" => Windows,
1657 "espidf" => Espidf,
1658 _ => return Err(()),
1659 })
1660 }
1661}
1662
1663impl fmt::Display for Environment {
1664 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1665 f.write_str(&self.into_str())
1666 }
1667}
1668
1669impl FromStr for Environment {
1670 type Err = ();
1671
1672 fn from_str(s: &str) -> Result<Self, ()> {
1673 use Environment::*;
1674
1675 Ok(match s {
1676 "unknown" => Unknown,
1677 "amdgiz" => AmdGiz,
1678 "android" => Android,
1679 "androideabi" => Androideabi,
1680 "eabi" => Eabi,
1681 "eabihf" => Eabihf,
1682 "gnu" => Gnu,
1683 "gnuabi64" => Gnuabi64,
1684 "gnueabi" => Gnueabi,
1685 "gnueabihf" => Gnueabihf,
1686 "gnuspe" => Gnuspe,
1687 "gnux32" => Gnux32,
1688 "gnu_ilp32" => GnuIlp32,
1689 "gnullvm" => GnuLlvm,
1690 "hermitkernel" => HermitKernel,
1691 "hurdkernel" => HurdKernel,
1692 "linuxkernel" => LinuxKernel,
1693 "macabi" => Macabi,
1694 "musl" => Musl,
1695 "musleabi" => Musleabi,
1696 "musleabihf" => Musleabihf,
1697 "muslabi64" => Muslabi64,
1698 "msvc" => Msvc,
1699 "newlib" => Newlib,
1700 "none" => None,
1701 "kernel" => Kernel,
1702 "uclibc" => Uclibc,
1703 "uclibceabi" => Uclibceabi,
1704 "uclibceabihf" => Uclibceabihf,
1705 "sgx" => Sgx,
1706 "sim" => Sim,
1707 "softfloat" => Softfloat,
1708 "spe" => Spe,
1709 "threads" => Threads,
1710 "ohos" => Ohos,
1711 _ => return Err(()),
1712 })
1713 }
1714}
1715
1716impl fmt::Display for BinaryFormat {
1717 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1718 f.write_str(&self.into_str())
1719 }
1720}
1721
1722impl FromStr for BinaryFormat {
1723 type Err = ();
1724
1725 fn from_str(s: &str) -> Result<Self, ()> {
1726 use BinaryFormat::*;
1727
1728 Ok(match s {
1729 "unknown" => Unknown,
1730 "elf" => Elf,
1731 "coff" => Coff,
1732 "macho" => Macho,
1733 "wasm" => Wasm,
1734 "xcoff" => Xcoff,
1735 _ => return Err(()),
1736 })
1737 }
1738}
1739
1740#[cfg(test)]
1741mod tests {
1742 use super::*;
1743 use alloc::string::ToString;
1744
1745 #[test]
1746 fn roundtrip_known_triples() {
1747 let targets = [
1752 "aarch64-apple-darwin",
1753 "aarch64-apple-ios",
1754 "aarch64-apple-ios-macabi",
1755 "aarch64-apple-ios-sim",
1756 "aarch64-apple-tvos",
1757 "aarch64-apple-tvos-sim",
1758 "aarch64-apple-visionos",
1759 "aarch64-apple-visionos-sim",
1760 "aarch64-apple-watchos",
1761 "aarch64-apple-watchos-sim",
1762 "aarch64_be-unknown-linux-gnu",
1763 "aarch64_be-unknown-linux-gnu_ilp32",
1764 "aarch64_be-unknown-netbsd",
1765 "aarch64-kmc-solid_asp3",
1766 "aarch64-linux-android",
1767 "aarch64-pc-windows-gnullvm",
1769 "aarch64-pc-windows-msvc",
1770 "aarch64-unknown-cloudabi",
1771 "aarch64-unknown-freebsd",
1772 "aarch64-unknown-fuchsia",
1773 "aarch64-unknown-hermit",
1774 "aarch64-unknown-illumos",
1775 "aarch64-unknown-linux-gnu",
1776 "aarch64-unknown-linux-gnu_ilp32",
1777 "aarch64-unknown-linux-musl",
1778 "aarch64-unknown-linux-ohos",
1779 "aarch64-unknown-netbsd",
1780 "aarch64-unknown-none",
1781 "aarch64-unknown-none-softfloat",
1782 "aarch64-unknown-openbsd",
1784 "aarch64-unknown-redox",
1785 "aarch64-unknown-uefi",
1787 "aarch64-uwp-windows-msvc",
1788 "aarch64-wrs-vxworks",
1789 "amdgcn-amd-amdhsa",
1792 "amdgcn-amd-amdhsa-amdgiz",
1793 "armeb-unknown-linux-gnueabi",
1796 "armebv7r-none-eabi",
1797 "armebv7r-none-eabihf",
1798 "arm-linux-androideabi",
1799 "arm-unknown-linux-gnueabi",
1800 "arm-unknown-linux-gnueabihf",
1801 "arm-unknown-linux-musleabi",
1802 "arm-unknown-linux-musleabihf",
1803 "armv4t-none-eabi",
1804 "armv4t-unknown-linux-gnueabi",
1805 "armv5te-none-eabi",
1806 "armv5te-unknown-linux-gnueabi",
1807 "armv5te-unknown-linux-musleabi",
1808 "armv5te-unknown-linux-uclibceabi",
1809 "armv6k-nintendo-3ds",
1810 "armv6-unknown-freebsd",
1811 "armv6-unknown-netbsd-eabihf",
1812 "armv7a-kmc-solid_asp3-eabi",
1813 "armv7a-kmc-solid_asp3-eabihf",
1814 "armv7a-none-eabi",
1815 "armv7a-none-eabihf",
1816 "armv7-apple-ios",
1817 "armv7k-apple-watchos",
1818 "armv7-linux-androideabi",
1819 "armv7r-none-eabi",
1820 "armv7r-none-eabihf",
1821 "armv7s-apple-ios",
1822 "armv7-unknown-cloudabi-eabihf",
1823 "armv7-unknown-freebsd",
1825 "armv7-unknown-linux-gnueabi",
1826 "armv7-unknown-linux-gnueabihf",
1827 "armv7-unknown-linux-musleabi",
1828 "armv7-unknown-linux-musleabihf",
1829 "armv7-unknown-linux-ohos",
1830 "armv7-unknown-linux-uclibceabi",
1831 "armv7-unknown-linux-uclibceabihf",
1832 "armv7-unknown-netbsd-eabihf",
1833 "armv7-wrs-vxworks-eabihf",
1834 "asmjs-unknown-emscripten",
1835 "armv8r-none-eabihf",
1836 "avr-unknown-unknown",
1838 "bpfeb-unknown-none",
1839 "bpfel-unknown-none",
1840 "hexagon-unknown-linux-musl",
1843 "hexagon-unknown-none-elf",
1844 "i386-apple-ios",
1845 "i586-pc-windows-msvc",
1847 "i586-unknown-linux-gnu",
1848 "i586-unknown-linux-musl",
1849 "i586-unknown-netbsd",
1850 "i686-apple-darwin",
1851 "i686-linux-android",
1852 "i686-apple-macosx10.7.0",
1853 "i686-pc-windows-gnu",
1854 "i686-pc-windows-gnullvm",
1855 "i686-pc-windows-msvc",
1856 "i686-unknown-cloudabi",
1857 "i686-unknown-dragonfly",
1858 "i686-unknown-freebsd",
1859 "i686-unknown-haiku",
1860 "i686-unknown-hurd-gnu",
1861 "i686-unknown-linux-gnu",
1862 "i686-unknown-linux-musl",
1863 "i686-unknown-netbsd",
1864 "i686-unknown-openbsd",
1865 "i686-unknown-redox",
1866 "i686-unknown-uefi",
1867 "i686-uwp-windows-gnu",
1868 "i686-uwp-windows-msvc",
1869 "i686-win7-windows-msvc",
1870 "i686-wrs-vxworks",
1871 "loongarch64-unknown-linux-gnu",
1872 "loongarch64-unknown-linux-musl",
1873 "loongarch64-unknown-none",
1874 "loongarch64-unknown-none-softfloat",
1875 "m68k-unknown-linux-gnu",
1876 "mips64el-unknown-linux-gnuabi64",
1877 "mips64el-unknown-linux-muslabi64",
1878 "mips64-openwrt-linux-musl",
1879 "mips64-unknown-linux-gnuabi64",
1880 "mips64-unknown-linux-muslabi64",
1881 "mipsel-sony-psp",
1882 "mipsel-unknown-linux-gnu",
1884 "mipsel-unknown-linux-musl",
1885 "mipsel-unknown-linux-uclibc",
1886 "mipsel-unknown-netbsd",
1887 "mipsel-unknown-none",
1888 "mipsisa32r6el-unknown-linux-gnu",
1889 "mipsisa32r6-unknown-linux-gnu",
1890 "mipsisa64r6el-unknown-linux-gnuabi64",
1891 "mipsisa64r6-unknown-linux-gnuabi64",
1892 "mips-unknown-linux-gnu",
1893 "mips-unknown-linux-musl",
1894 "mips-unknown-linux-uclibc",
1895 "msp430-none-elf",
1896 "nvptx64-nvidia-cuda",
1897 "powerpc64-ibm-aix",
1898 "powerpc64le-unknown-freebsd",
1899 "powerpc64le-unknown-linux-gnu",
1900 "powerpc64le-unknown-linux-musl",
1901 "powerpc64-unknown-freebsd",
1902 "powerpc64-unknown-linux-gnu",
1903 "powerpc64-unknown-linux-musl",
1904 "powerpc64-unknown-openbsd",
1905 "powerpc64-wrs-vxworks",
1906 "powerpc-ibm-aix",
1907 "powerpc-unknown-freebsd",
1908 "powerpc-unknown-linux-gnu",
1909 "powerpc-unknown-linux-gnuspe",
1910 "powerpc-unknown-linux-musl",
1911 "powerpc-unknown-netbsd",
1912 "powerpc-unknown-openbsd",
1913 "powerpc-wrs-vxworks",
1914 "powerpc-wrs-vxworks-spe",
1915 "riscv32gc-unknown-linux-gnu",
1916 "riscv32gc-unknown-linux-musl",
1917 "riscv32imac-esp-espidf",
1918 "riscv32imac-unknown-none-elf",
1919 "riscv32imafc-esp-espidf",
1921 "riscv32imafc-unknown-none-elf",
1922 "riscv32ima-unknown-none-elf",
1923 "riscv32imc-esp-espidf",
1924 "riscv32imc-unknown-none-elf",
1925 "riscv32im-unknown-none-elf",
1927 "riscv32i-unknown-none-elf",
1928 "riscv64gc-unknown-freebsd",
1929 "riscv64gc-unknown-fuchsia",
1930 "riscv64gc-unknown-hermit",
1931 "riscv64gc-unknown-linux-gnu",
1932 "riscv64a23-unknown-linux-gnu",
1933 "riscv64gc-unknown-linux-musl",
1934 "riscv64gc-unknown-netbsd",
1935 "riscv64gc-unknown-none-elf",
1936 "riscv64gc-unknown-openbsd",
1937 "riscv64imac-unknown-none-elf",
1938 "riscv64-linux-android",
1939 "s390x-unknown-linux-gnu",
1940 "s390x-unknown-linux-musl",
1941 "sparc64-unknown-linux-gnu",
1942 "sparc64-unknown-netbsd",
1943 "sparc64-unknown-openbsd",
1944 "sparc-unknown-linux-gnu",
1945 "sparc-unknown-none-elf",
1946 "sparcv9-sun-solaris",
1947 "thumbv4t-none-eabi",
1948 "thumbv5te-none-eabi",
1949 "thumbv6m-none-eabi",
1950 "thumbv7a-pc-windows-msvc",
1951 "thumbv7a-uwp-windows-msvc",
1952 "thumbv7em-none-eabi",
1953 "thumbv7em-none-eabihf",
1954 "thumbv7m-none-eabi",
1955 "thumbv7neon-linux-androideabi",
1956 "thumbv7neon-unknown-linux-gnueabihf",
1957 "thumbv7neon-unknown-linux-musleabihf",
1958 "thumbv8m.base-none-eabi",
1959 "thumbv8m.main-none-eabi",
1960 "thumbv8m.main-none-eabihf",
1961 "wasm32-experimental-emscripten",
1962 "wasm32-unknown-emscripten",
1963 "wasm32-unknown-unknown",
1964 "wasm32-wasi",
1965 "wasm32-wasip1",
1966 "wasm32-wasip1-threads",
1967 "wasm32-wasip2",
1968 "wasm64-unknown-unknown",
1969 "wasm64-wasi",
1970 "x86_64-apple-darwin",
1971 "x86_64-apple-darwin23.6.0",
1972 "x86_64-apple-ios",
1973 "x86_64-apple-ios-macabi",
1974 "x86_64-apple-tvos",
1975 "x86_64-apple-watchos-sim",
1976 "x86_64-fortanix-unknown-sgx",
1977 "x86_64h-apple-darwin",
1978 "x86_64-linux-android",
1979 "x86_64-linux-kernel", "x86_64-apple-macosx",
1982 "x86_64-apple-macosx10.7.0",
1983 "x86_64-pc-cygwin",
1984 "x86_64-pc-solaris",
1985 "x86_64-pc-windows-gnu",
1986 "x86_64-pc-windows-gnullvm",
1987 "x86_64-pc-windows-msvc",
1988 "x86_64-rumprun-netbsd", "x86_64-sun-solaris",
1990 "x86_64-unknown-bitrig",
1991 "x86_64-unknown-cloudabi",
1992 "x86_64-unikraft-linux-musl",
1993 "x86_64-unknown-dragonfly",
1994 "x86_64-unknown-freebsd",
1995 "x86_64-unknown-fuchsia",
1996 "x86_64-unknown-haiku",
1997 "x86_64-unknown-hermit-kernel", "x86_64-unknown-hermit",
1999 "x86_64-unknown-illumos",
2000 "x86_64-unknown-l4re-uclibc",
2001 "x86_64-unknown-linux-gnu",
2002 "x86_64-unknown-linux-gnux32",
2003 "x86_64-unknown-linux-musl",
2004 "x86_64-unknown-linux-none",
2005 "x86_64-unknown-linux-ohos",
2006 "x86_64-unknown-netbsd",
2007 "x86_64-unknown-none",
2008 "x86_64-unknown-none-hermitkernel",
2009 "x86_64-unknown-none-linuxkernel",
2010 "x86_64-unknown-openbsd",
2011 "x86_64-unknown-redox",
2012 "x86_64-unknown-uefi",
2013 "x86_64-uwp-windows-gnu",
2014 "x86_64-uwp-windows-msvc",
2015 "x86_64-win7-windows-msvc",
2016 "x86_64-wrs-vxworks",
2017 "xtensa-esp32-espidf",
2018 "clever-unknown-elf",
2019 "xtensa-esp32-none-elf",
2020 "xtensa-esp32s2-espidf",
2021 "xtensa-esp32s2-none-elf",
2022 "xtensa-esp32s3-espidf",
2023 "xtensa-esp32s3-none-elf",
2024 #[cfg(feature = "arch_zkasm")]
2025 "zkasm-unknown-unknown",
2026 #[cfg(feature = "arch_z80")]
2027 "z80-zilog-none",
2028 #[cfg(feature = "arch_z80")]
2029 "sm83-nintendo-none",
2030 #[cfg(feature = "arch_z80")]
2031 "tlcs90-toshiba-none",
2032 ];
2033
2034 for target in targets.iter() {
2035 let t = Triple::from_str(target).expect("can't parse target");
2036 assert_ne!(t.architecture, Architecture::Unknown);
2037 assert_eq!(t.to_string(), *target, "{:#?}", t);
2038 }
2039 }
2040
2041 #[test]
2042 fn default_format_to_elf() {
2043 let t = Triple::from_str("riscv64").expect("can't parse target");
2044 assert_eq!(
2045 t.architecture,
2046 Architecture::Riscv64(Riscv64Architecture::Riscv64),
2047 );
2048 assert_eq!(t.vendor, Vendor::Unknown);
2049 assert_eq!(t.operating_system, OperatingSystem::Unknown);
2050 assert_eq!(t.environment, Environment::Unknown);
2051 assert_eq!(t.binary_format, BinaryFormat::Elf);
2052 }
2053
2054 #[test]
2055 fn thumbv7em_none_eabihf() {
2056 let t = Triple::from_str("thumbv7em-none-eabihf").expect("can't parse target");
2057 assert_eq!(
2058 t.architecture,
2059 Architecture::Arm(ArmArchitecture::Thumbv7em)
2060 );
2061 assert_eq!(t.vendor, Vendor::Unknown);
2062 assert_eq!(t.operating_system, OperatingSystem::None_);
2063 assert_eq!(t.environment, Environment::Eabihf);
2064 assert_eq!(t.binary_format, BinaryFormat::Elf);
2065 }
2066
2067 #[test]
2068 fn fuchsia_rename() {
2069 assert_eq!(
2071 Triple::from_str("aarch64-fuchsia"),
2072 Triple::from_str("aarch64-unknown-fuchsia")
2073 );
2074 assert_eq!(
2075 Triple::from_str("x86_64-fuchsia"),
2076 Triple::from_str("x86_64-unknown-fuchsia")
2077 );
2078 }
2079
2080 #[test]
2081 fn custom_vendors() {
2082 assert!(Triple::from_str("x86_64--linux").is_err());
2084 assert!(Triple::from_str("x86_64-42-linux").is_err());
2085 assert!(Triple::from_str("x86_64-__customvendor__-linux").is_err());
2086 assert!(Triple::from_str("x86_64-^-linux").is_err());
2087 assert!(Triple::from_str("x86_64- -linux").is_err());
2088 assert!(Triple::from_str("x86_64-CustomVendor-linux").is_err());
2089 assert!(Triple::from_str("x86_64-linux-linux").is_err());
2090 assert!(Triple::from_str("x86_64-x86_64-linux").is_err());
2091 assert!(Triple::from_str("x86_64-elf-linux").is_err());
2092 assert!(Triple::from_str("x86_64-gnu-linux").is_err());
2093 assert!(Triple::from_str("x86_64-linux-customvendor").is_err());
2094 assert!(Triple::from_str("customvendor").is_err());
2095 assert!(Triple::from_str("customvendor-x86_64").is_err());
2096 assert!(Triple::from_str("x86_64-").is_err());
2097 assert!(Triple::from_str("x86_64--").is_err());
2098
2099 assert!(
2101 Triple::from_str("x86_64-𝓬𝓾𝓼𝓽𝓸𝓶𝓿𝓮𝓷𝓭𝓸𝓻-linux").is_err(),
2102 "unicode font hazard"
2103 );
2104 assert!(
2105 Triple::from_str("x86_64-ćúśtőḿvéńdőŕ-linux").is_err(),
2106 "diacritical mark stripping hazard"
2107 );
2108 assert!(
2109 Triple::from_str("x86_64-customvendοr-linux").is_err(),
2110 "homoglyph hazard"
2111 );
2112 assert!(Triple::from_str("x86_64-customvendor-linux").is_ok());
2113 assert!(
2114 Triple::from_str("x86_64-ffi-linux").is_err(),
2115 "normalization hazard"
2116 );
2117 assert!(Triple::from_str("x86_64-ffi-linux").is_ok());
2118 assert!(
2119 Triple::from_str("x86_64-customvendor-linux").is_err(),
2120 "zero-width character hazard"
2121 );
2122 assert!(
2123 Triple::from_str("x86_64-customvendor-linux").is_err(),
2124 "BOM hazard"
2125 );
2126
2127 let t = Triple::from_str("x86_64-customvendor-linux")
2129 .expect("can't parse target with custom vendor");
2130 assert_eq!(t.architecture, Architecture::X86_64);
2131 assert_eq!(
2132 t.vendor,
2133 Vendor::Custom(CustomVendor::Static("customvendor"))
2134 );
2135 assert_eq!(t.operating_system, OperatingSystem::Linux);
2136 assert_eq!(t.environment, Environment::Unknown);
2137 assert_eq!(t.binary_format, BinaryFormat::Elf);
2138 assert_eq!(t.to_string(), "x86_64-customvendor-linux");
2139
2140 let t =
2141 Triple::from_str("x86_64-customvendor").expect("can't parse target with custom vendor");
2142 assert_eq!(t.architecture, Architecture::X86_64);
2143 assert_eq!(
2144 t.vendor,
2145 Vendor::Custom(CustomVendor::Static("customvendor"))
2146 );
2147 assert_eq!(t.operating_system, OperatingSystem::Unknown);
2148 assert_eq!(t.environment, Environment::Unknown);
2149 assert_eq!(t.binary_format, BinaryFormat::Elf);
2150
2151 assert_eq!(
2152 Triple::from_str("unknown-foo"),
2153 Ok(Triple {
2154 architecture: Architecture::Unknown,
2155 vendor: Vendor::Custom(CustomVendor::Static("foo")),
2156 operating_system: OperatingSystem::Unknown,
2157 environment: Environment::Unknown,
2158 binary_format: BinaryFormat::Unknown,
2159 })
2160 );
2161 }
2162
2163 #[test]
2164 fn deployment_version_parsing() {
2165 assert_eq!(
2166 Triple::from_str("aarch64-apple-macosx"),
2167 Ok(Triple {
2168 architecture: Architecture::Aarch64(Aarch64Architecture::Aarch64),
2169 vendor: Vendor::Apple,
2170 operating_system: OperatingSystem::MacOSX(None),
2171 environment: Environment::Unknown,
2172 binary_format: BinaryFormat::Macho,
2173 })
2174 );
2175
2176 assert_eq!(
2177 Triple::from_str("aarch64-apple-macosx10.14.6"),
2178 Ok(Triple {
2179 architecture: Architecture::Aarch64(Aarch64Architecture::Aarch64),
2180 vendor: Vendor::Apple,
2181 operating_system: OperatingSystem::MacOSX(Some(DeploymentTarget {
2182 major: 10,
2183 minor: 14,
2184 patch: 6,
2185 })),
2186 environment: Environment::Unknown,
2187 binary_format: BinaryFormat::Macho,
2188 })
2189 );
2190
2191 let expected = Triple {
2192 architecture: Architecture::X86_64,
2193 vendor: Vendor::Apple,
2194 operating_system: OperatingSystem::Darwin(Some(DeploymentTarget {
2195 major: 23,
2196 minor: 0,
2197 patch: 0,
2198 })),
2199 environment: Environment::Unknown,
2200 binary_format: BinaryFormat::Macho,
2201 };
2202 assert_eq!(
2203 Triple::from_str("x86_64-apple-darwin23"),
2204 Ok(expected.clone())
2205 );
2206 assert_eq!(
2207 Triple::from_str("x86_64-apple-darwin23.0"),
2208 Ok(expected.clone())
2209 );
2210 assert_eq!(Triple::from_str("x86_64-apple-darwin23.0.0"), Ok(expected));
2211
2212 assert!(Triple::from_str("x86_64-apple-darwin.").is_err());
2213 assert!(Triple::from_str("x86_64-apple-darwin23.0.0.0").is_err());
2214 }
2215}