1use crate::{AsPtr, AssertShared, AssertUnique, Library};
2
3#[derive(Debug, Clone, Copy)]
4pub struct LibraryFunc<'a, F> {
5 pub(crate) ptr: F,
6 pub(crate) _library: &'a Library,
7}
8
9impl<'a, F: Copy> AsPtr for LibraryFunc<'a, F> {
10 type Pointer = F;
11 unsafe fn as_ptr(&self) -> Self::Pointer {
12 self.ptr
13 }
14}
15
16impl<'a, F> LibraryFunc<'a, F> {
17 pub unsafe fn assert_callable_unique(self) -> AssertUnique<Self> {
22 AssertUnique { inner: self }
23 }
24 pub unsafe fn assert_callable_shared(self) -> AssertShared<Self> {
29 AssertShared { inner: self }
30 }
31 pub fn library(&self) -> &'a Library {
33 self._library
34 }
35}
36
37#[cfg(feature = "fn_traits")]
38macro_rules! make_fn_impls {
39 ($($var:ident: $ty:ident),*) => {
40 impl<'a, $($ty ,)* R> FnOnce<($($ty,)*)> for AssertShared<LibraryFunc<'a, unsafe extern "C" fn($($ty,)*) -> R>> {
41 type Output = R;
42 extern "rust-call" fn call_once(self, ($($var,)*): ($($ty,)*)) -> Self::Output {
43 let f = unsafe { self.as_ptr() };
45 unsafe { f($($var,)*) }
46 }
47 }
48 impl<'a, $($ty ,)* R> FnMut<($($ty,)*)> for AssertShared<LibraryFunc<'a, unsafe extern "C" fn($($ty,)*) -> R>> {
49 extern "rust-call" fn call_mut(&mut self, ($($var,)*): ($($ty,)*)) -> Self::Output {
50 let f = unsafe { self.as_ptr() };
52 unsafe { f($($var,)*) }
53 }
54 }
55 impl<'a, $($ty ,)* R> Fn<($($ty,)*)> for AssertShared<LibraryFunc<'a, unsafe extern "C" fn($($ty,)*) -> R>> {
56 extern "rust-call" fn call(&self, ($($var,)*): ($($ty,)*)) -> Self::Output {
57 let f = unsafe { self.as_ptr() };
59 unsafe { f($($var,)*) }
60 }
61 }
62
63 impl<'a, $($ty ,)* R> FnOnce<($($ty,)*)> for AssertUnique<LibraryFunc<'a, unsafe extern "C" fn($($ty,)*) -> R>> {
64 type Output = R;
65 extern "rust-call" fn call_once(self, ($($var,)*): ($($ty,)*)) -> Self::Output {
66 let f = unsafe { self.as_ptr() };
68 unsafe { f($($var,)*) }
69 }
70 }
71 impl<'a, $($ty ,)* R> FnMut<($($ty,)*)> for AssertUnique<LibraryFunc<'a, unsafe extern "C" fn($($ty,)*) -> R>> {
72 extern "rust-call" fn call_mut(&mut self, ($($var,)*): ($($ty,)*)) -> Self::Output {
73 let f = unsafe { self.as_ptr() };
75 unsafe { f($($var,)*) }
76 }
77 }
78
79
80 impl<'a, $($ty ,)* R> FnOnce<($($ty,)*)> for AssertShared<LibraryFunc<'a, extern "C" fn($($ty,)*) -> R>> {
81 type Output = R;
82 extern "rust-call" fn call_once(self, ($($var,)*): ($($ty,)*)) -> Self::Output {
83 let f = unsafe { self.as_ptr() };
85 { f($($var,)*) }
86 }
87 }
88 impl<'a, $($ty ,)* R> FnMut<($($ty,)*)> for AssertShared<LibraryFunc<'a, extern "C" fn($($ty,)*) -> R>> {
89 extern "rust-call" fn call_mut(&mut self, ($($var,)*): ($($ty,)*)) -> Self::Output {
90 let f = unsafe { self.as_ptr() };
92 { f($($var,)*) }
93 }
94 }
95 impl<'a, $($ty ,)* R> Fn<($($ty,)*)> for AssertShared<LibraryFunc<'a, extern "C" fn($($ty,)*) -> R>> {
96 extern "rust-call" fn call(&self, ($($var,)*): ($($ty,)*)) -> Self::Output {
97 let f = unsafe { self.as_ptr() };
99 { f($($var,)*) }
100 }
101 }
102
103 impl<'a, $($ty ,)* R> FnOnce<($($ty,)*)> for AssertUnique<LibraryFunc<'a, extern "C" fn($($ty,)*) -> R>> {
104 type Output = R;
105 extern "rust-call" fn call_once(self, ($($var,)*): ($($ty,)*)) -> Self::Output {
106 let f = unsafe { self.as_ptr() };
108 { f($($var,)*) }
109 }
110 }
111 impl<'a, $($ty ,)* R> FnMut<($($ty,)*)> for AssertUnique<LibraryFunc<'a, extern "C" fn($($ty,)*) -> R>> {
112 extern "rust-call" fn call_mut(&mut self, ($($var,)*): ($($ty,)*)) -> Self::Output {
113 let f = unsafe { self.as_ptr() };
115 { f($($var,)*) }
116 }
117 }
118 };
119}
120
121#[cfg(not(feature = "fn_traits"))]
122macro_rules! make_fn_impls {
123 ($($_:tt)*) => {};
124}
125
126make_fn_impls!();
127make_fn_impls!(a: A);
128make_fn_impls!(a: A, b: B);
129make_fn_impls!(a: A, b: B, c: C);
130make_fn_impls!(a: A, b: B, c: C, d: D);
131make_fn_impls!(a: A, b: B, c: C, d: D, e: E);
132make_fn_impls!(a: A, b: B, c: C, d: D, e: E, f: F);
133make_fn_impls!(a: A, b: B, c: C, d: D, e: E, f: F, g: G);
134make_fn_impls!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H);
135make_fn_impls!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I);
136make_fn_impls!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J);