use crate::{AsPtr, AssertShared, AssertUnique, Library};
#[derive(Debug, Clone, Copy)]
pub struct LibraryFunc<'a, F> {
pub(crate) ptr: F,
pub(crate) _library: &'a Library,
}
impl<'a, F: Copy> AsPtr for LibraryFunc<'a, F> {
type Pointer = F;
unsafe fn as_ptr(&self) -> Self::Pointer {
self.ptr
}
}
impl<'a, F> LibraryFunc<'a, F> {
pub unsafe fn assert_callable_unique(self) -> AssertUnique<Self> {
AssertUnique { inner: self }
}
pub unsafe fn assert_callable_shared(self) -> AssertShared<Self> {
AssertShared { inner: self }
}
pub fn library(&self) -> &'a Library {
self._library
}
}
#[cfg(feature = "fn_traits")]
macro_rules! make_fn_impls {
($($var:ident: $ty:ident),*) => {
impl<'a, $($ty ,)* R> FnOnce<($($ty,)*)> for AssertShared<LibraryFunc<'a, unsafe extern "C" fn($($ty,)*) -> R>> {
type Output = R;
extern "rust-call" fn call_once(self, ($($var,)*): ($($ty,)*)) -> Self::Output {
let f = unsafe { self.as_ptr() };
unsafe { f($($var,)*) }
}
}
impl<'a, $($ty ,)* R> FnMut<($($ty,)*)> for AssertShared<LibraryFunc<'a, unsafe extern "C" fn($($ty,)*) -> R>> {
extern "rust-call" fn call_mut(&mut self, ($($var,)*): ($($ty,)*)) -> Self::Output {
let f = unsafe { self.as_ptr() };
unsafe { f($($var,)*) }
}
}
impl<'a, $($ty ,)* R> Fn<($($ty,)*)> for AssertShared<LibraryFunc<'a, unsafe extern "C" fn($($ty,)*) -> R>> {
extern "rust-call" fn call(&self, ($($var,)*): ($($ty,)*)) -> Self::Output {
let f = unsafe { self.as_ptr() };
unsafe { f($($var,)*) }
}
}
impl<'a, $($ty ,)* R> FnOnce<($($ty,)*)> for AssertUnique<LibraryFunc<'a, unsafe extern "C" fn($($ty,)*) -> R>> {
type Output = R;
extern "rust-call" fn call_once(self, ($($var,)*): ($($ty,)*)) -> Self::Output {
let f = unsafe { self.as_ptr() };
unsafe { f($($var,)*) }
}
}
impl<'a, $($ty ,)* R> FnMut<($($ty,)*)> for AssertUnique<LibraryFunc<'a, unsafe extern "C" fn($($ty,)*) -> R>> {
extern "rust-call" fn call_mut(&mut self, ($($var,)*): ($($ty,)*)) -> Self::Output {
let f = unsafe { self.as_ptr() };
unsafe { f($($var,)*) }
}
}
impl<'a, $($ty ,)* R> FnOnce<($($ty,)*)> for AssertShared<LibraryFunc<'a, extern "C" fn($($ty,)*) -> R>> {
type Output = R;
extern "rust-call" fn call_once(self, ($($var,)*): ($($ty,)*)) -> Self::Output {
let f = unsafe { self.as_ptr() };
{ f($($var,)*) }
}
}
impl<'a, $($ty ,)* R> FnMut<($($ty,)*)> for AssertShared<LibraryFunc<'a, extern "C" fn($($ty,)*) -> R>> {
extern "rust-call" fn call_mut(&mut self, ($($var,)*): ($($ty,)*)) -> Self::Output {
let f = unsafe { self.as_ptr() };
{ f($($var,)*) }
}
}
impl<'a, $($ty ,)* R> Fn<($($ty,)*)> for AssertShared<LibraryFunc<'a, extern "C" fn($($ty,)*) -> R>> {
extern "rust-call" fn call(&self, ($($var,)*): ($($ty,)*)) -> Self::Output {
let f = unsafe { self.as_ptr() };
{ f($($var,)*) }
}
}
impl<'a, $($ty ,)* R> FnOnce<($($ty,)*)> for AssertUnique<LibraryFunc<'a, extern "C" fn($($ty,)*) -> R>> {
type Output = R;
extern "rust-call" fn call_once(self, ($($var,)*): ($($ty,)*)) -> Self::Output {
let f = unsafe { self.as_ptr() };
{ f($($var,)*) }
}
}
impl<'a, $($ty ,)* R> FnMut<($($ty,)*)> for AssertUnique<LibraryFunc<'a, extern "C" fn($($ty,)*) -> R>> {
extern "rust-call" fn call_mut(&mut self, ($($var,)*): ($($ty,)*)) -> Self::Output {
let f = unsafe { self.as_ptr() };
{ f($($var,)*) }
}
}
};
}
#[cfg(not(feature = "fn_traits"))]
macro_rules! make_fn_impls {
($($_:tt)*) => {};
}
make_fn_impls!();
make_fn_impls!(a: A);
make_fn_impls!(a: A, b: B);
make_fn_impls!(a: A, b: B, c: C);
make_fn_impls!(a: A, b: B, c: C, d: D);
make_fn_impls!(a: A, b: B, c: C, d: D, e: E);
make_fn_impls!(a: A, b: B, c: C, d: D, e: E, f: F);
make_fn_impls!(a: A, b: B, c: C, d: D, e: E, f: F, g: G);
make_fn_impls!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H);
make_fn_impls!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I);
make_fn_impls!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J);