fn_ptr/
marker.rs

1/// Type-level marker trait for function arity, from [`A0`] to [`A12`].
2pub trait Arity {
3    /// Number of parameters for this arity.
4    const N: usize;
5}
6macro_rules! define_arity_marker {
7    ($(($name:ident, $n:expr)),+ $(,)?) => {
8        $(
9            #[doc = "Type-level marker for functions with exactly "]
10            #[doc = stringify!($n)]
11            #[doc = " parameters."]
12            #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
13            pub struct $name;
14
15            impl Arity for $name {
16                const N: usize = $n;
17            }
18        )+
19    };
20}
21define_arity_marker!(
22    (A0, 0),
23    (A1, 1),
24    (A2, 2),
25    (A3, 3),
26    (A4, 4),
27    (A5, 5),
28    (A6, 6),
29    (A7, 7),
30    (A8, 8),
31    (A9, 9),
32    (A10, 10),
33    (A11, 11),
34    (A12, 12),
35);
36
37/// Type-level marker trait for function safety, either [`Safe`] or [`Unsafe`].
38pub trait Safety {
39    /// `true` for safe functions, `false` for unsafe ones.
40    const IS_SAFE: bool;
41}
42
43/// Marker type for safe functions.
44#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
45pub struct Safe;
46/// Marker type for unsafe functions.
47#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
48pub struct Unsafe;
49
50impl Safety for Safe {
51    const IS_SAFE: bool = true;
52}
53impl Safety for Unsafe {
54    const IS_SAFE: bool = false;
55}
56
57/// Type-level marker trait for function ABI.
58///
59/// Types implementing this trait represent a specific `extern "..."` ABI.
60///
61/// See [`Abi`] for the runtime representation.
62pub trait Abi {
63    /// The exact ABI string used in `extern "..."`.
64    const STR: &'static str;
65
66    /// The runtime [`Abi`] that represent this marker type.
67    const VALUE: crate::Abi;
68}
69
70/// Helper macro to implement [`Abi`].
71macro_rules! define_abi_marker {
72    ($name:ident, $lit:literal) => {
73        #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
74        #[doc = "Type-level marker for the `"]
75        #[doc = $lit]
76        #[doc = "` ABI."]
77        pub struct $name;
78
79        impl Abi for $name {
80            const STR: &'static str = $lit;
81            const VALUE: $crate::Abi = $crate::Abi::from_str_const($lit).unwrap();
82        }
83    };
84}
85
86// Universal
87define_abi_marker!(C, "C");
88define_abi_marker!(CUnwind, "C-unwind");
89define_abi_marker!(System, "system");
90define_abi_marker!(SystemUnwind, "system-unwind");
91
92// Rust
93define_abi_marker!(Rust, "Rust");
94
95// ARM
96define_abi_marker!(Aapcs, "aapcs");
97define_abi_marker!(AapcsUnwind, "aapcs-unwind");
98
99// x86
100define_abi_marker!(Cdecl, "cdecl");
101define_abi_marker!(CdeclUnwind, "cdecl-unwind");
102define_abi_marker!(Stdcall, "stdcall");
103define_abi_marker!(StdcallUnwind, "stdcall-unwind");
104define_abi_marker!(Fastcall, "fastcall");
105define_abi_marker!(FastcallUnwind, "fastcall-unwind");
106define_abi_marker!(Thiscall, "thiscall");
107define_abi_marker!(ThiscallUnwind, "thiscall-unwind");
108define_abi_marker!(Vectorcall, "vectorcall");
109define_abi_marker!(VectorcallUnwind, "vectorcall-unwind");
110
111// x86_64
112define_abi_marker!(SysV64, "sysv64");
113define_abi_marker!(SysV64Unwind, "sysv64-unwind");
114define_abi_marker!(Win64, "win64");
115define_abi_marker!(Win64Unwind, "win64-unwind");
116
117/// Macro to convert an integral number to the corresponding [`Arity`] marker type.
118#[macro_export]
119macro_rules! arity {
120    (0) => {
121        $crate::marker::A0
122    };
123    (1) => {
124        $crate::marker::A1
125    };
126    (2) => {
127        $crate::marker::A2
128    };
129    (3) => {
130        $crate::marker::A3
131    };
132    (4) => {
133        $crate::marker::A4
134    };
135    (5) => {
136        $crate::marker::A5
137    };
138    (6) => {
139        $crate::marker::A6
140    };
141    (7) => {
142        $crate::marker::A7
143    };
144    (8) => {
145        $crate::marker::A8
146    };
147    (9) => {
148        $crate::marker::A9
149    };
150    (10) => {
151        $crate::marker::A10
152    };
153    (11) => {
154        $crate::marker::A11
155    };
156    (12) => {
157        $crate::marker::A12
158    };
159}
160
161/// Macro to convert an ABI string to the corrsponding [`Abi`] marker type.
162#[macro_export]
163macro_rules! abi {
164    // Common
165    ("Rust") => {
166        $crate::marker::Rust
167    };
168    ("C") => {
169        $crate::marker::C
170    };
171    ("C-unwind") => {
172        $crate::marker::CUnwind
173    };
174    ("system") => {
175        $crate::marker::System
176    };
177    ("system-unwind") => {
178        $crate::marker::SystemUnwind
179    };
180
181    // ARM
182    ("aapcs") => {
183        $crate::marker::Aapcs
184    };
185    ("aapcs-unwind") => {
186        $crate::marker::AapcsUnwind
187    };
188
189    // x86
190    ("cdecl") => {
191        $crate::marker::Cdecl
192    };
193    ("cdecl-unwind") => {
194        $crate::marker::CdeclUnwind
195    };
196    ("stdcall") => {
197        $crate::marker::Stdcall
198    };
199    ("stdcall-unwind") => {
200        $crate::marker::StdcallUnwind
201    };
202    ("fastcall") => {
203        $crate::marker::Fastcall
204    };
205    ("fastcall-unwind") => {
206        $crate::marker::FastcallUnwind
207    };
208    ("thiscall") => {
209        $crate::marker::Thiscall
210    };
211    ("thiscall-unwind") => {
212        $crate::marker::ThiscallUnwind
213    };
214    ("vectorcall") => {
215        $crate::marker::Vectorcall
216    };
217    ("vectorcall-unwind") => {
218        $crate::marker::VectorcallUnwind
219    };
220
221    // x86_64
222    ("sysv64") => {
223        $crate::marker::SysV64
224    };
225    ("sysv64-unwind") => {
226        $crate::marker::SysV64Unwind
227    };
228    ("win64") => {
229        $crate::marker::Win64
230    };
231    ("win64-unwind") => {
232        $crate::marker::Win64Unwind
233    };
234}
235
236/// Macro to convert a safety token (`safe` or `unsafe`) or a boolean literal to the corrsponding [`Safety`] marker type.
237#[macro_export]
238macro_rules! safety {
239    (safe) => {
240        $crate::marker::Safe
241    };
242    (unsafe) => {
243        $crate::marker::Unsafe
244    };
245    (true) => {
246        $crate::marker::Safe
247    };
248    (false) => {
249        $crate::marker::Unsafe
250    };
251}