macro_rules! wrap_fn_ptr {
($vis:vis unsafe extern "C" fn $name:ident(
$($arg_name:ident: $arg_ty:ty),*$(,)?
) -> $return_ty:ty) => {
$vis mod $name {
use $crate::src::enum_map::DefaultValue;
#[allow(unused_imports)]
use super::*;
#[cfg(asm_fn_ptrs)]
pub type FnPtr = unsafe extern "C" fn($($arg_name: $arg_ty),*) -> $return_ty;
#[cfg(asm_fn_ptrs)]
#[derive(Clone, Copy, PartialEq, Eq)]
#[repr(transparent)]
pub struct Fn(FnPtr);
#[cfg(asm_fn_ptrs)]
impl Fn {
pub(super) const fn new(fn_ptr: FnPtr) -> Self {
Self(fn_ptr)
}
pub(super) const fn get(&self) -> &FnPtr {
&self.0
}
}
#[cfg(asm_fn_ptrs)]
impl DefaultValue for Fn {
const DEFAULT: Self = {
extern "C" fn default_unimplemented(
$($arg_name: $arg_ty,)*
) -> $return_ty {
$(let _ = $arg_name;)*
unimplemented!()
}
Self::new(default_unimplemented)
};
}
#[cfg(not(asm_fn_ptrs))]
#[derive(Clone, Copy, PartialEq, Eq)]
pub struct Fn(());
#[cfg(not(asm_fn_ptrs))]
impl Fn {
#[allow(dead_code)]
pub(super) const fn new(
_fn_ptr: unsafe extern "C" fn($($arg_name: $arg_ty),*) -> $return_ty
) -> Self {
Fn(())
}
}
#[cfg(not(asm_fn_ptrs))]
impl DefaultValue for Fn {
const DEFAULT: Self = Fn(());
}
#[cfg(asm_fn_ptrs)]
#[allow(unused_macros)]
macro_rules! decl_fn {
(fn $fn_name:ident) => {{
unsafe extern "C" {
fn $fn_name($($arg_name: $arg_ty,)*) -> $return_ty;
}
self::$name::Fn::new($fn_name)
}};
}
#[cfg(asm_fn_ptrs)]
#[allow(unused_imports)]
pub(crate) use decl_fn;
#[cfg(not(asm_fn_ptrs))]
#[allow(unused_macros)]
macro_rules! decl_fn_safe {
($fn_path:path) => {{
self::$name::Fn::new($fn_path)
}};
}
#[cfg(not(asm_fn_ptrs))]
#[allow(unused_imports)]
pub(crate) use decl_fn_safe;
}
};
}
pub(crate) use wrap_fn_ptr;