1#[cfg(feature = "nightly")]
2use core::marker::ConstParamTy;
3use core::{
4 fmt::{Debug, Display},
5 str::FromStr,
6};
7
8use const_panic::concat_panic;
9
10#[cfg_attr(feature = "nightly", derive(ConstParamTy))]
11#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
12pub enum Abi {
14 Rust,
16 C,
18 System,
20 Win64,
22 Sysv64,
24 Aapcs,
26 Cdecl,
28 Stdcall,
30 Fastcall,
32 Vectorcall,
34}
35
36impl Abi {
37 #[must_use]
39 pub const fn to_str(&self) -> &'static str {
40 match self {
41 Abi::Rust => "Rust",
42 Abi::C => "C",
43 Abi::System => "system",
44 Abi::Win64 => "win64",
45 Abi::Sysv64 => "sysv64",
46 Abi::Aapcs => "aapcs",
47 Abi::Cdecl => "cdecl",
48 Abi::Stdcall => "stdcall",
49 Abi::Fastcall => "fastcall",
50 Abi::Vectorcall => "vectorcall",
51 }
52 }
53}
54
55impl Abi {
56 pub fn is_alias(&self) -> bool {
58 matches!(self, Abi::C | Abi::System)
59 }
60
61 pub fn is_concrete(&self) -> bool {
63 !self.is_alias()
64 }
65
66 pub fn concrete(&self) -> Abi {
68 match self {
69 Abi::C => {
70 if cfg!(target_os = "windows") && cfg!(target_arch = "x86_64") {
72 Abi::Win64
73 } else if cfg!(target_arch = "x86_64") {
74 Abi::Sysv64
75 } else if cfg!(target_arch = "x86") {
76 Abi::Cdecl
77 } else if cfg!(target_arch = "arm") || cfg!(target_arch = "aarch64") {
78 Abi::Aapcs
79 } else {
80 Abi::Cdecl }
82 }
83 Abi::System => {
84 if cfg!(target_os = "windows") && cfg!(target_arch = "x86_64") {
85 Abi::Win64
86 } else if cfg!(target_os = "windows") && cfg!(target_arch = "x86") {
87 Abi::Stdcall
88 } else if cfg!(target_arch = "x86_64") {
89 Abi::Sysv64
90 } else if cfg!(target_arch = "x86") {
91 Abi::Cdecl
92 } else if cfg!(target_arch = "arm") || cfg!(target_arch = "aarch64") {
93 Abi::Aapcs
94 } else {
95 Abi::Cdecl }
97 }
98 other => *other,
99 }
100 }
101}
102
103impl FromStr for Abi {
104 type Err = ();
105
106 fn from_str(s: &str) -> Result<Self, Self::Err> {
107 match s {
108 "" | "Rust" => Ok(Abi::Rust),
109 "C" => Ok(Abi::C),
110 "system" => Ok(Abi::System),
111 "win64" => Ok(Abi::Win64),
112 "sysv64" => Ok(Abi::Sysv64),
113 "aapcs" => Ok(Abi::Aapcs),
114 "cdecl" => Ok(Abi::Cdecl),
115 "stdcall" => Ok(Abi::Stdcall),
116 "fastcall" => Ok(Abi::Fastcall),
117 "vectorcall" => Ok(Abi::Vectorcall),
118 _ => Err(()),
119 }
120 }
121}
122
123impl Display for Abi {
124 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
125 write!(f, "{}", self.to_str())
126 }
127}
128
129#[must_use]
131pub const fn parse(conv: &'static str) -> Option<Abi> {
132 if konst::eq_str(conv, "") || konst::eq_str(conv, "Rust") {
133 Some(Abi::Rust)
134 } else if konst::eq_str(conv, "C") {
135 Some(Abi::C)
136 } else if konst::eq_str(conv, "system") {
137 Some(Abi::System)
138 } else if konst::eq_str(conv, "win64") {
139 Some(Abi::Win64)
140 } else if konst::eq_str(conv, "sysv64") {
141 Some(Abi::Sysv64)
142 } else if konst::eq_str(conv, "aapcs") {
143 Some(Abi::Aapcs)
144 } else if konst::eq_str(conv, "cdecl") {
145 Some(Abi::Cdecl)
146 } else if konst::eq_str(conv, "stdcall") {
147 Some(Abi::Stdcall)
148 } else if konst::eq_str(conv, "fastcall") {
149 Some(Abi::Fastcall)
150 } else if konst::eq_str(conv, "vectorcall") {
151 Some(Abi::Vectorcall)
152 } else {
153 None
154 }
155}
156
157#[must_use]
159pub const fn parse_or_fail(conv: &'static str) -> Abi {
160 match parse(conv) {
161 Some(c) => c,
162 None => concat_panic!("invalid or unknown abi", conv),
163 }
164}