fn_ptr/
impl.rs

1macro_rules! impl_fn {
2    (@recurse () ($($nm:ident : $ty:ident),*)) => {
3        impl_fn!(@impl_all ($($nm : $ty),*));
4    };
5    (@recurse ($hd_nm:ident : $hd_ty:ident $(, $tl_nm:ident : $tl_ty:ident)*) ($($nm:ident : $ty:ident),*)) => {
6        impl_fn!(@impl_all ($($nm : $ty),*));
7        impl_fn!(@recurse ($($tl_nm : $tl_ty),*) ($($nm : $ty,)* $hd_nm : $hd_ty));
8    };
9
10    (@impl_all ($($nm:ident : $ty:ident),*)) => {
11        impl_fn!(@impl_core ($($nm : $ty),*), fn($($ty),*) -> Ret, true, false, "Rust");
12        impl_fn!(@impl_core ($($nm : $ty),*), unsafe fn($($ty),*) -> Ret, false, false, "Rust");
13
14        // Universal conventions
15        impl_fn!(@impl_u_and_s ($($nm : $ty),*), "C");
16        impl_fn!(@impl_u_and_s ($($nm : $ty),*), "system");
17
18        // x86-specific conventions
19        #[cfg(target_arch = "x86")]
20        impl_fn!(@impl_u_and_s ($($nm : $ty),*), "cdecl");
21        #[cfg(target_arch = "x86")]
22        impl_fn!(@impl_u_and_s ($($nm : $ty),*), "stdcall");
23        #[cfg(target_arch = "x86")]
24        impl_fn!(@impl_u_and_s ($($nm : $ty),*), "fastcall");
25
26        // x86_64 Windows
27        #[cfg(all(target_arch = "x86_64", target_os = "windows"))]
28        impl_fn!(@impl_u_and_s ($($nm : $ty),*), "win64");
29
30        // x86_64 System V (Linux/macOS)
31        #[cfg(all(target_arch = "x86_64", not(target_os = "windows")))]
32        impl_fn!(@impl_u_and_s ($($nm : $ty),*), "sysv64");
33
34        // ARM conventions
35        #[cfg(any(target_arch = "arm"))]
36        impl_fn!(@impl_u_and_s ($($nm : $ty),*), "aapcs");
37    };
38
39    (@impl_u_and_s ($($nm:ident : $ty:ident),*), $abi:expr) => {
40        impl_fn!(@impl_core ($($nm : $ty),*), extern $abi fn($($ty),*) -> Ret, true, true, $abi);
41        impl_fn!(@impl_core ($($nm : $ty),*), unsafe extern $abi fn($($ty),*) -> Ret, false, true, $abi);
42    };
43
44    (@impl_core ($($nm:ident : $ty:ident),*), $fn_type:ty, $is_safe:expr, $is_extern:expr, $call_conv:expr) => {
45        unsafe impl<Ret: 'static, $($ty: 'static),*> crate::FunctionPtr for $fn_type {
46            type Args = ($($ty,)*);
47            type Output = Ret;
48
49            const ARITY: ::core::primitive::usize = impl_fn!(@count ($($ty)*));
50            const SAFE: ::core::primitive::bool = $is_safe;
51            const EXTERN: ::core::primitive::bool = $is_extern;
52            const ABI: crate::Abi = crate::abi::parse_or_fail($call_conv);
53        }
54    };
55
56    (@count ()) => {
57        0
58    };
59    (@count ($hd:tt $($tl:tt)*)) => {
60        1 + impl_fn!(@count ($($tl)*))
61    };
62
63    ($($nm:ident : $ty:ident),*) => {
64        impl_fn!(@recurse ($($nm : $ty),*) ());
65    };
66}
67
68impl_fn! {
69    __arg_0:  A, __arg_1:  B, __arg_2:  C, __arg_3:  D, __arg_4:  E, __arg_5:  F, __arg_6:  G,
70    __arg_7:  H, __arg_8:  I, __arg_9:  J, __arg_10: K, __arg_11: L
71}