1macro_rules! cfg_all {
4 ($meta:meta { $($items:item)* }) => {
5 $(#[cfg($meta)] $items)*
6 };
7}
8
9macro_rules! impl_fn {
10 (@recurse () ($($nm:ident : $ty:ident),*)) => {
11 impl_fn!(@impl_all ($($nm : $ty),*));
12 };
13 (@recurse ($hd_nm:ident : $hd_ty:ident $(, $tl_nm:ident : $tl_ty:ident)*) ($($nm:ident : $ty:ident),*)) => {
14 impl_fn!(@impl_all ($($nm : $ty),*));
15 impl_fn!(@recurse ($($tl_nm : $tl_ty),*) ($($nm : $ty,)* $hd_nm : $hd_ty));
16 };
17
18 (@impl_all ($($nm:ident : $ty:ident),*)) => {
19 impl_fn!(@impl_u_and_s ($($nm : $ty),*), Rust, "Rust");
20 impl_fn!(@impl_u_and_s ($($nm : $ty),*), C, "C");
21 impl_fn!(@impl_u_and_s ($($nm : $ty),*), System, "system");
22 #[cfg(has_abi_cdecl)]
23 impl_fn!(@impl_u_and_s ($($nm : $ty),*), Cdecl, "cdecl");
24 #[cfg(has_abi_stdcall)]
25 impl_fn!(@impl_u_and_s ($($nm : $ty),*), Stdcall, "stdcall");
26 #[cfg(has_abi_fastcall)]
27 impl_fn!(@impl_u_and_s ($($nm : $ty),*), Fastcall, "fastcall");
28 #[cfg(has_abi_win64)]
29 impl_fn!(@impl_u_and_s ($($nm : $ty),*), Win64, "win64");
30 #[cfg(has_abi_sysv64)]
31 impl_fn!(@impl_u_and_s ($($nm : $ty),*), Sysv64, "sysv64");
32 #[cfg(has_abi_aapcs)]
33 impl_fn!(@impl_u_and_s ($($nm : $ty),*), Aapcs, "aapcs");
34 };
35
36 (@impl_u_and_s ($($nm:ident : $ty:ident),*), $abi_ident:ident, $abi_str:expr) => {
37 impl_fn!(@impl_core ($($nm : $ty),*), extern $abi_str fn($($ty),*) -> Ret, true, $abi_ident, $abi_str);
38 impl_fn!(@impl_core ($($nm : $ty),*), unsafe extern $abi_str fn($($ty),*) -> Ret, false, $abi_ident, $abi_str);
39 };
40
41 (@impl_core ($($nm:ident : $ty:ident),*), $fn_type:ty, true, $abi_ident:ident, $call_conv:expr) => {
42 impl<Ret: 'static, $($ty: 'static),*> $crate::FnPtr for $fn_type {
43 type Args = ($($ty,)*);
44 type Output = Ret;
45
46 const ARITY: ::core::primitive::usize = impl_fn!(@count ($($ty)*));
47 const IS_SAFE: ::core::primitive::bool = true;
48 const IS_EXTERN: ::core::primitive::bool = !matches!($crate::Abi::$abi_ident, $crate::Abi::Rust);
49 const ABI: $crate::Abi = $crate::Abi::$abi_ident;
50 }
51 impl<Ret: 'static, $($ty: 'static),*> $crate::SafeFnPtr for $fn_type {}
52
53 impl<Ret: 'static, $($ty: 'static),*> $crate::WithSafety<{true}, $fn_type> for $fn_type { type F = $fn_type; }
55 impl<Ret: 'static, $($ty: 'static),*> $crate::WithSafety<{false}, $fn_type> for $fn_type { type F = unsafe extern $call_conv fn($($ty),*) -> Ret; }
56
57 cfg_all!(feature = "nightly" {
58 impl<Ret: 'static, $($ty: 'static),*> $crate::HasAbi<{$crate::Abi::$abi_ident}> for $fn_type {}
60
61 impl<Ret: 'static, $($ty: 'static),*> $crate::WithAbi<{$crate::Abi::Rust}, $fn_type> for $fn_type { type F = extern "Rust" fn($($ty),*) -> Ret; }
63 impl<Ret: 'static, $($ty: 'static),*> $crate::WithAbi<{$crate::Abi::C}, $fn_type> for $fn_type { type F = extern "C" fn($($ty),*) -> Ret; }
64 impl<Ret: 'static, $($ty: 'static),*> $crate::WithAbi<{$crate::Abi::System}, $fn_type> for $fn_type { type F = extern "system" fn($($ty),*) -> Ret; }
65 #[cfg(has_abi_cdecl)]
66 impl<Ret: 'static, $($ty: 'static),*> $crate::WithAbi<{$crate::Abi::Cdecl}, $fn_type> for $fn_type { type F = extern "cdecl" fn($($ty),*) -> Ret; }
67 #[cfg(has_abi_stdcall)]
68 impl<Ret: 'static, $($ty: 'static),*> $crate::WithAbi<{$crate::Abi::Stdcall}, $fn_type> for $fn_type { type F = extern "stdcall" fn($($ty),*) -> Ret; }
69 #[cfg(has_abi_fastcall)]
70 impl<Ret: 'static, $($ty: 'static),*> $crate::WithAbi<{$crate::Abi::Fastcall}, $fn_type> for $fn_type { type F = extern "fastcall" fn($($ty),*) -> Ret; }
71 #[cfg(has_abi_win64)]
72 impl<Ret: 'static, $($ty: 'static),*> $crate::WithAbi<{$crate::Abi::Win64}, $fn_type> for $fn_type { type F = extern "win64" fn($($ty),*) -> Ret; }
73 #[cfg(has_abi_sysv64)]
74 impl<Ret: 'static, $($ty: 'static),*> $crate::WithAbi<{$crate::Abi::Sysv64}, $fn_type> for $fn_type { type F = extern "sysv64" fn($($ty),*) -> Ret; }
75 #[cfg(has_abi_aapcs)]
76 impl<Ret: 'static, $($ty: 'static),*> $crate::WithAbi<{$crate::Abi::Aapcs}, $fn_type> for $fn_type { type F = extern "aapcs" fn($($ty),*) -> Ret; }
77 });
78 };
79
80 (@impl_core ($($nm:ident : $ty:ident),*), $fn_type:ty, false, $abi_ident:ident, $call_conv:expr) => {
81 impl<Ret: 'static, $($ty: 'static),*> $crate::FnPtr for $fn_type {
82 type Args = ($($ty,)*);
83 type Output = Ret;
84
85 const ARITY: ::core::primitive::usize = impl_fn!(@count ($($ty)*));
86 const IS_SAFE: ::core::primitive::bool = false;
87 const IS_EXTERN: ::core::primitive::bool = !matches!($crate::Abi::$abi_ident, $crate::Abi::Rust);
88 const ABI: $crate::Abi = $crate::Abi::$abi_ident;
89 }
90 impl<Ret: 'static, $($ty: 'static),*> $crate::UnsafeFnPtr for $fn_type {}
91
92 impl<Ret: 'static, $($ty: 'static),*> $crate::WithSafety<{true}, $fn_type> for $fn_type { type F = extern $call_conv fn($($ty),*) -> Ret; }
94 impl<Ret: 'static, $($ty: 'static),*> $crate::WithSafety<{false}, $fn_type> for $fn_type { type F = $fn_type; }
95
96 cfg_all!(feature = "nightly" {
97 impl<Ret: 'static, $($ty: 'static),*> $crate::HasAbi<{$crate::Abi::$abi_ident}> for $fn_type {}
99
100 impl<Ret: 'static, $($ty: 'static),*> $crate::WithAbi<{$crate::Abi::Rust}, $fn_type> for $fn_type { type F = unsafe extern "Rust" fn($($ty),*) -> Ret; }
102 impl<Ret: 'static, $($ty: 'static),*> $crate::WithAbi<{$crate::Abi::C}, $fn_type> for $fn_type { type F = unsafe extern "C" fn($($ty),*) -> Ret; }
103 impl<Ret: 'static, $($ty: 'static),*> $crate::WithAbi<{$crate::Abi::System}, $fn_type> for $fn_type { type F = unsafe extern "system" fn($($ty),*) -> Ret; }
104 #[cfg(has_abi_cdecl)]
105 impl<Ret: 'static, $($ty: 'static),*> $crate::WithAbi<{$crate::Abi::Cdecl}, $fn_type> for $fn_type { type F = unsafe extern "cdecl" fn($($ty),*) -> Ret; }
106 #[cfg(has_abi_stdcall)]
107 impl<Ret: 'static, $($ty: 'static),*> $crate::WithAbi<{$crate::Abi::Stdcall}, $fn_type> for $fn_type { type F = unsafe extern "stdcall" fn($($ty),*) -> Ret; }
108 #[cfg(has_abi_fastcall)]
109 impl<Ret: 'static, $($ty: 'static),*> $crate::WithAbi<{$crate::Abi::Fastcall}, $fn_type> for $fn_type { type F = unsafe extern "fastcall" fn($($ty),*) -> Ret; }
110 #[cfg(has_abi_win64)]
111 impl<Ret: 'static, $($ty: 'static),*> $crate::WithAbi<{$crate::Abi::Win64}, $fn_type> for $fn_type { type F = unsafe extern "win64" fn($($ty),*) -> Ret; }
112 #[cfg(has_abi_sysv64)]
113 impl<Ret: 'static, $($ty: 'static),*> $crate::WithAbi<{$crate::Abi::Sysv64}, $fn_type> for $fn_type { type F = unsafe extern "sysv64" fn($($ty),*) -> Ret; }
114 #[cfg(has_abi_aapcs)]
115 impl<Ret: 'static, $($ty: 'static),*> $crate::WithAbi<{$crate::Abi::Aapcs}, $fn_type> for $fn_type { type F = unsafe extern "aapcs" fn($($ty),*) -> Ret; }
116 });
117 };
118
119 (@count ()) => {
120 0
121 };
122 (@count ($hd:tt $($tl:tt)*)) => {
123 1 + impl_fn!(@count ($($tl)*))
124 };
125
126 ($($nm:ident : $ty:ident),*) => {
127 impl_fn!(@recurse ($($nm : $ty),*) ());
128 };
129}
130
131#[cfg(not(feature = "max-arity-12"))]
133impl_fn! {
134 __arg_0: A, __arg_1: B, __arg_2: C, __arg_3: D, __arg_4: E, __arg_5: F
135}
136
137#[cfg(feature = "max-arity-12")]
139impl_fn! {
140 __arg_0: A, __arg_1: B, __arg_2: C, __arg_3: D, __arg_4: E, __arg_5: F, __arg_6: G,
141 __arg_7: H, __arg_8: I, __arg_9: J, __arg_10: K, __arg_11: L
142}