fn_ptr/
abi.rs

1use core::{
2    fmt::{Debug, Display},
3    str::FromStr,
4};
5
6use const_panic::concat_panic;
7
8#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
9/// The abi or calling convention of a function pointer.
10pub enum Abi {
11    /// The default ABI when you write a normal `fn foo()` in any Rust code.
12    Rust,
13    /// This is the same as `extern fn foo()`; whatever the default your C compiler supports.
14    C,
15    /// Usually the same as [`extern "C"`](Abi::C), except on Win32, in which case it's [`"stdcall"`](Abi::Stdcall), or what you should use to link to the Windows API itself.
16    System,
17    /// The default for C code on x86_64 Windows.
18    Win64,
19    /// The default for C code on non-Windows x86_64.
20    Sysv64,
21    /// The default for ARM.
22    Aapcs,
23    /// The default for x86_32 C code.
24    Cdecl,
25    /// The default for the Win32 API on x86_32.
26    Stdcall,
27    /// The `fastcall` ABI -- corresponds to MSVC's `__fastcall` and GCC and clang's `__attribute__((fastcall))`
28    Fastcall,
29    /// The `vectorcall` ABI -- corresponds to MSVC's `__vectorcall` and GCC and clang's `__attribute__((vectorcall))`
30    Vectorcall,
31}
32
33impl Abi {
34    /// Returns the string representation of this ABI.
35    #[must_use]
36    pub const fn to_str(&self) -> &'static str {
37        match self {
38            Abi::Rust => "Rust",
39            Abi::C => "C",
40            Abi::System => "System",
41            Abi::Win64 => "Win64",
42            Abi::Sysv64 => "Sysv64",
43            Abi::Aapcs => "Aapcs",
44            Abi::Cdecl => "Cdecl",
45            Abi::Stdcall => "Stdcall",
46            Abi::Fastcall => "Fastcall",
47            Abi::Vectorcall => "Vectorcall",
48        }
49    }
50}
51
52impl FromStr for Abi {
53    type Err = ();
54
55    fn from_str(s: &str) -> Result<Self, Self::Err> {
56        match s {
57            "" | "Rust" => Ok(Abi::C),
58            "C" => Ok(Abi::C),
59            "system" => Ok(Abi::System),
60            "win64" => Ok(Abi::Win64),
61            "sysv64" => Ok(Abi::Sysv64),
62            "aapcs" => Ok(Abi::Aapcs),
63            "cdecl" => Ok(Abi::Cdecl),
64            "stdcall" => Ok(Abi::Stdcall),
65            "fastcall" => Ok(Abi::Fastcall),
66            "vectorcall" => Ok(Abi::Vectorcall),
67            _ => Err(()),
68        }
69    }
70}
71
72impl Display for Abi {
73    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
74        write!(f, "{}", self.to_str())
75    }
76}
77
78#[must_use]
79pub const fn parse(conv: &'static str) -> Option<Abi> {
80    if konst::eq_str(conv, "") || konst::eq_str(conv, "Rust") {
81        Some(Abi::Rust)
82    } else if konst::eq_str(conv, "C") {
83        Some(Abi::C)
84    } else if konst::eq_str(conv, "system") {
85        Some(Abi::System)
86    } else if konst::eq_str(conv, "win64") {
87        Some(Abi::Win64)
88    } else if konst::eq_str(conv, "sysv64") {
89        Some(Abi::Sysv64)
90    } else if konst::eq_str(conv, "aapcs") {
91        Some(Abi::Aapcs)
92    } else if konst::eq_str(conv, "cdecl") {
93        Some(Abi::Cdecl)
94    } else if konst::eq_str(conv, "stdcall") {
95        Some(Abi::Stdcall)
96    } else if konst::eq_str(conv, "fastcall") {
97        Some(Abi::Fastcall)
98    } else if konst::eq_str(conv, "vectorcall") {
99        Some(Abi::Vectorcall)
100    } else {
101        None
102    }
103}
104
105#[must_use]
106pub const fn parse_or_fail(conv: &'static str) -> Abi {
107    match parse(conv) {
108        Some(c) => c,
109        None => concat_panic!("invalid or unknown abi", conv),
110    }
111}