use core::ffi::c_void;
use core::ptr::NonNull;
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
#[repr(transparent)]
pub struct FnPtr(NonNull<c_void>);
unsafe impl Send for FnPtr {}
unsafe impl Sync for FnPtr {}
impl FnPtr {
pub fn new(ptr: NonNull<c_void>) -> Self {
Self(ptr)
}
pub fn from_raw_ptr(ptr: *mut c_void) -> Option<Self> {
NonNull::new(ptr).map(Self::new)
}
pub unsafe fn from_raw_ptr_unchecked(ptr: *mut c_void) -> Self {
unsafe { Self(NonNull::new_unchecked(ptr)) }
}
pub fn as_c_void_ptr(&self) -> *mut c_void {
self.0.as_ptr()
}
pub unsafe fn into_fn<F>(self) -> F {
unsafe { core::mem::transmute_copy::<NonNull<c_void>, F>(&self.0) }
}
pub(crate) fn as_libffi_sys_ptr(self) -> Option<unsafe extern "C" fn()> {
unsafe { core::mem::transmute::<NonNull<c_void>, Option<unsafe extern "C" fn()>>(self.0) }
}
}
#[macro_export]
macro_rules! fn_ptrize {
($fn:ident) => {
$crate::FnPtr::from_raw_ptr($fn as *mut ::core::ffi::c_void).unwrap()
};
}