1macro_rules! impl_fn {
4 (@recurse () ($($nm:ident : $ty:ident),*)) => {
5 impl_fn!(@impl_all ($($nm : $ty),*));
6 };
7 (@recurse ($hd_nm:ident : $hd_ty:ident $(, $tl_nm:ident : $tl_ty:ident)*) ($($nm:ident : $ty:ident),*)) => {
8 impl_fn!(@impl_all ($($nm : $ty),*));
9 impl_fn!(@recurse ($($tl_nm : $tl_ty),*) ($($nm : $ty,)* $hd_nm : $hd_ty));
10 };
11
12 (@impl_all ($($nm:ident : $ty:ident),*)) => {
13 impl_fn!(@impl_u_and_s ($($nm : $ty),*), Rust, "Rust");
14 impl_fn!(@impl_u_and_s ($($nm : $ty),*), C, "C");
15 impl_fn!(@impl_u_and_s ($($nm : $ty),*), System, "system");
16 #[cfg(has_abi_cdecl)]
17 impl_fn!(@impl_u_and_s ($($nm : $ty),*), Cdecl, "cdecl");
18 #[cfg(has_abi_stdcall)]
19 impl_fn!(@impl_u_and_s ($($nm : $ty),*), Stdcall, "stdcall");
20 #[cfg(has_abi_fastcall)]
21 impl_fn!(@impl_u_and_s ($($nm : $ty),*), Fastcall, "fastcall");
22 #[cfg(has_abi_win64)]
23 impl_fn!(@impl_u_and_s ($($nm : $ty),*), Win64, "win64");
24 #[cfg(has_abi_sysv64)]
25 impl_fn!(@impl_u_and_s ($($nm : $ty),*), Sysv64, "sysv64");
26 #[cfg(has_abi_aapcs)]
27 impl_fn!(@impl_u_and_s ($($nm : $ty),*), Aapcs, "aapcs");
28 };
29
30 (@impl_u_and_s ($($nm:ident : $ty:ident),*), $abi_ident:ident, $abi_str:expr) => {
31 impl_fn!(@impl_core ($($nm : $ty),*), extern $abi_str fn($($ty),*) -> Ret, true, $abi_ident, $abi_str);
32 impl_fn!(@impl_core ($($nm : $ty),*), unsafe extern $abi_str fn($($ty),*) -> Ret, false, $abi_ident, $abi_str);
33 };
34
35 (@impl_core ($($nm:ident : $ty:ident),*), $fn_type:ty, $safety:tt, $abi_ident:ident, $call_conv:expr) => {
36 #[automatically_derived]
37 impl<Ret: 'static, $($ty: 'static),*> $crate::FnPtr for $fn_type {
38 type Args = ($($ty,)*);
39 type Output = Ret;
40
41 const ARITY: ::core::primitive::usize = impl_fn!(@count ($($ty)*));
42 const IS_SAFE: ::core::primitive::bool = $safety;
43 const IS_EXTERN: ::core::primitive::bool = !matches!($crate::Abi::$abi_ident, $crate::Abi::Rust);
44 const ABI: $crate::Abi = $crate::Abi::$abi_ident;
45
46 fn as_ptr(&self) -> $crate::UntypedFnPtr {
47 *self as $crate::UntypedFnPtr
48 }
49 unsafe fn from_ptr(ptr: $crate::UntypedFnPtr) -> Self {
50 ::core::assert!(!ptr.is_null());
51 unsafe { ::core::mem::transmute::<$crate::UntypedFnPtr, Self>(ptr) }
52 }
53 }
54 impl_fn!(@impl_safe_fn_type ($($nm : $ty),*), $fn_type, $safety);
55
56 #[automatically_derived]
58 impl<Ret: 'static, $($ty: 'static),*> $crate::WithSafety<{true}> for $fn_type {
59 type F = extern $call_conv fn($($ty),*) -> Ret;
60 }
61 #[automatically_derived]
62 impl<Ret: 'static, $($ty: 'static),*> $crate::WithSafety<{false}> for $fn_type {
63 type F = unsafe extern $call_conv fn($($ty),*) -> Ret;
64 }
65
66 #[automatically_derived]
68 impl<Ret: 'static, $($ty: 'static),*> $crate::HasAbi<{$crate::abi!($call_conv)}> for $fn_type {}
69
70 #[automatically_derived]
72 impl<Ret: 'static, $($ty: 'static),*> $crate::WithAbi<{$crate::abi!("Rust")}> for $fn_type {
73 type F = impl_fn!(@make_unsafe extern "Rust" fn($($ty),*) -> Ret, $safety);
74 }
75 #[automatically_derived]
76 impl<Ret: 'static, $($ty: 'static),*> $crate::WithAbi<{$crate::abi!("C")}> for $fn_type {
77 type F = impl_fn!(@make_unsafe extern "C" fn($($ty),*) -> Ret, $safety);
78 }
79 #[automatically_derived]
80 impl<Ret: 'static, $($ty: 'static),*> $crate::WithAbi<{$crate::abi!("system")}> for $fn_type {
81 type F = impl_fn!(@make_unsafe extern "system" fn($($ty),*) -> Ret, $safety);
82 }
83 #[cfg(has_abi_cdecl)]
84 #[automatically_derived]
85 impl<Ret: 'static, $($ty: 'static),*> $crate::WithAbi<{$crate::abi!("cdecl")}> for $fn_type {
86 type F = impl_fn!(@make_unsafe extern "cdecl" fn($($ty),*) -> Ret, $safety);
87 }
88 #[cfg(has_abi_stdcall)]
89 #[automatically_derived]
90 impl<Ret: 'static, $($ty: 'static),*> $crate::WithAbi<{$crate::abi!("stdcall")}> for $fn_type {
91 type F = impl_fn!(@make_unsafe extern "stdcall" fn($($ty),*) -> Ret, $safety);
92 }
93 #[cfg(has_abi_fastcall)]
94 #[automatically_derived]
95 impl<Ret: 'static, $($ty: 'static),*> $crate::WithAbi<{$crate::abi!("fastcall")}> for $fn_type {
96 type F = impl_fn!(@make_unsafe extern "fastcall" fn($($ty),*) -> Ret, $safety);
97 }
98 #[cfg(has_abi_win64)]
99 #[automatically_derived]
100 impl<Ret: 'static, $($ty: 'static),*> $crate::WithAbi<{$crate::abi!("win64")}> for $fn_type {
101 type F = impl_fn!(@make_unsafe extern "win64" fn($($ty),*) -> Ret, $safety);
102 }
103 #[cfg(has_abi_sysv64)]
104 #[automatically_derived]
105 impl<Ret: 'static, $($ty: 'static),*> $crate::WithAbi<{$crate::abi!("sysv64")}> for $fn_type {
106 type F = impl_fn!(@make_unsafe extern "sysv64" fn($($ty),*) -> Ret, $safety);
107 }
108 #[cfg(has_abi_aapcs)]
109 #[automatically_derived]
110 impl<Ret: 'static, $($ty: 'static),*> $crate::WithAbi<{$crate::abi!("aapcs")}> for $fn_type {
111 type F = impl_fn!(@make_unsafe extern "aapcs" fn($($ty),*) -> Ret, $safety);
112 }
113 };
114
115 (@count ()) => {
116 0
117 };
118 (@count ($hd:tt $($tl:tt)*)) => {
119 1 + impl_fn!(@count ($($tl)*))
120 };
121
122 (@make_unsafe $fn_type:ty, true) => {
123 $fn_type
124 };
125 (@make_unsafe extern $abi:literal fn($($args:ty),*) -> $ret:ty, false) => {
126 unsafe extern $abi fn($($args),*) -> $ret
127 };
128
129 (@impl_safe_fn_type ($($nm:ident : $ty:ident),*), $fn_type:ty, true) => {
130 #[automatically_derived]
131 impl<Ret: 'static, $($ty: 'static),*> $crate::SafeFnPtr for $fn_type {
132 fn invoke(&self, impl_fn!(@call_args ($($nm),*)): Self::Args) -> Self::Output {
133 (*self)($($nm),*)
134 }
135 }
136 };
137 (@impl_safe_fn_type ($($nm:ident : $ty:ident),*), $fn_type:ty, false) => {
138 #[automatically_derived]
139 impl<Ret: 'static, $($ty: 'static),*> $crate::UnsafeFnPtr for $fn_type {
140 unsafe fn invoke(&self, impl_fn!(@call_args ($($nm),*)): Self::Args) -> Self::Output {
141 unsafe { (*self)($($nm),*) }
142 }
143 }
144 };
145
146 (@call_args ($single:ident)) => {
147 ($single,)
148 };
149 (@call_args ($($args:ident),*)) => {
150 ($($args),*)
151 };
152
153 ($($nm:ident : $ty:ident),*) => {
154 impl_fn!(@recurse ($($nm : $ty),*) ());
155 };
156}
157
158#[cfg(not(feature = "max-arity-12"))]
160impl_fn! {
161 __arg_0: A, __arg_1: B, __arg_2: C, __arg_3: D, __arg_4: E, __arg_5: F
162}
163
164#[cfg(feature = "max-arity-12")]
166impl_fn! {
167 __arg_0: A, __arg_1: B, __arg_2: C, __arg_3: D, __arg_4: E, __arg_5: F, __arg_6: G,
168 __arg_7: H, __arg_8: I, __arg_9: J, __arg_10: K, __arg_11: L
169}