Skip to content

Instantly share code, notes, and snippets.

@agrif
Created June 14, 2024 02:41
Show Gist options
  • Save agrif/c85c4031d065d61ce2e2787a65191a7b to your computer and use it in GitHub Desktop.
Save agrif/c85c4031d065d61ce2e2787a65191a7b to your computer and use it in GitHub Desktop.
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct HeaderFn<F>(*const core::marker::PhantomData<F>);
impl<F> HeaderFn<F> {
pub const fn from_addr(addr: usize) -> Self {
Self(addr as *const core::marker::PhantomData<F>)
}
pub fn as_addr(&self) -> usize {
self.0 as usize
}
}
macro_rules! fn_impl {
(<$($var:ident),+>, $from_fn:ident, $fn:ty) => {
#[cfg(all(target_arch = "arm", target_os = "none"))]
impl<$($var),+> HeaderFn<$fn> {
pub const fn $from_fn(f: $fn) -> Self {
Self(f as *const core::marker::PhantomData<$fn>)
}
pub unsafe fn as_fn(&self, offset: usize) -> $fn {
core::mem::transmute::<*const (), $fn>(
(offset + self.as_addr()) as *const (),
)
}
}
}
}
fn_impl!(<R>, from_fn0, extern "C" fn () -> R);
fn_impl!(<A, R>, from_fn1, extern "C" fn(A) -> R);
fn_impl!(<A, B, R>, from_fn2, extern "C" fn(A, B) -> R);
fn_impl!(<A, B, C, R>, from_fn3, extern "C" fn(A, B, C) -> R);
fn_impl!(<A, B, C, D, R>, from_fn4, extern "C" fn(A, B, C, D) -> R);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment