loader/
ref_func.rs

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    /// Asserts that this is safely callable with the "C" calling convention,
18    /// and that this symbol points to the correct type, and
19    /// that it is the only pointer to its symbol.
20    /// The function may be non-reentrant.
21    pub unsafe fn assert_callable_unique(self) -> AssertUnique<Self> {
22        AssertUnique { inner: self }
23    }
24    /// Asserts that this is safely callable with the "C" calling convention,
25    /// and that this symbol points to the correct type, and
26    /// that there are no unique pointers to this symbol.
27    /// The function must be reentrant.
28    pub unsafe fn assert_callable_shared(self) -> AssertShared<Self> {
29        AssertShared { inner: self }
30    }
31    /// A reference to the library this symbol is from.
32    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                // SAFETY: self's lifetime will not end before the called function completes.
44                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                // SAFETY: self's lifetime will not end before the called function completes.
51                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                // SAFETY: self's lifetime will not end before the called function completes.
58                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                // SAFETY: self's lifetime will not end before the called function completes.
67                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                // SAFETY: self's lifetime will not end before the called function completes.
74                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                // SAFETY: self's lifetime will not end before the called function completes.
84                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                // SAFETY: self's lifetime will not end before the called function completes.
91                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                // SAFETY: self's lifetime will not end before the called function completes.
98                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                // SAFETY: self's lifetime will not end before the called function completes.
107                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                // SAFETY: self's lifetime will not end before the called function completes.
114                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);