| Crates.io | fn-ptr |
| lib.rs | fn-ptr |
| version | 0.9.1 |
| created_at | 2023-06-11 22:00:34.303956+00 |
| updated_at | 2026-01-12 22:27:07.831192+00 |
| description | A utility crate for introspecting and rewriting function pointer types at compile time. |
| homepage | |
| repository | https://github.com/OpenByteDev/fn-ptr |
| max_upload_size | |
| id | 887586 |
| size | 101,586 |
This is a utility crate for introspecting and rewriting function pointer types at compile time.
It implements FnPtr for all function-pointer types:
fn(T) -> Uunsafe fn(T) -> Uextern "C-unwind" fn(T)unsafe extern "sysv64" fn() -> i32FnPtr exposes metadata as associated types/consts.
use fn_ptr::{FnPtr, AbiValue};
type F = extern "C" fn(i32, i32) -> i32;
assert_eq!(<F as FnPtr>::ARITY, 2);
assert_eq!(<F as FnPtr>::IS_SAFE, true);
assert_eq!(<F as FnPtr>::IS_EXTERN, true);
assert_eq!(<F as FnPtr>::ABI, AbiValue::C { unwind: false });
Ergonomic const functions are provided as well:
const A: usize = fn_ptr::arity::<F>();
const SAFE: bool = fn_ptr::is_safe::<F>();
const EXT: bool = fn_ptr::is_extern::<F>();
const ABI: AbiValue = fn_ptr::abi::<F>();
The crate provides type-level rewriting via traits:
WithAbi / with_abi!WithSafety / with_safety! (make_safe!, make_unsafe!)WithOutput / with_output!WithArgs / with_args!The macros compute a new function-pointer type while preserving everything else.
use fn_ptr::{with_abi, with_safety, with_output, with_args};
type F = extern "C" fn(i32) -> i32;
type F1 = with_abi!("sysv64", F); // extern "sysv64" fn(i32) -> i32
type F2 = with_safety!(unsafe, F); // unsafe extern "C" fn(i32) -> i32
type F3 = with_output!(u64, F); // extern "C" fn(i32) -> u64
type F4 = with_args!((u8, u16), F); // extern "C" fn(u8, u16) -> i32
The same transformations exist at the value level via methods on FnPtr.
These casts are only transmuting and do not the actual underlying function.
use fn_ptr::{FnPtr, abi};
let f: fn(i32, i32) -> i32 = |a, b| a + b;
// safety
let u: unsafe fn(i32, i32) -> i32 = f.as_unsafe();
let f2: fn(i32, i32) -> i32 = unsafe { u.as_safe() };
// abi
let c: extern "C" fn(i32, i32) -> i32 = unsafe { f.with_abi::<abi!("C")>() };
// output
let out: fn(i32, i32) -> u64 = unsafe { f.with_output::<u64>() };
// args
let args: fn(u8, u16) -> i32 = unsafe { f.with_args::<(u8, u16)>() };
# assert_eq!(f.addr(), f2.addr());
# assert_eq!(f.addr(), c.addr());
# assert_eq!(f.addr(), out.addr());
# assert_eq!(f.addr(), args.addr());
Implementations are generated by a large macro. The rewrite macros are thin wrappers
over the traits WithAbi, WithSafety, WithOutput, WithArgs (and the corresponding *Impl helper traits).
Licensed under the MIT license, see LICENSE for details.