fn-ptr 0.9.0

A utility crate for introspecting and rewriting function pointer types at compile time.
Documentation
# fn-ptr

[![CI](https://github.com/OpenByteDev/fn-ptr/actions/workflows/ci.yml/badge.svg)](https://github.com/OpenByteDev/fn-ptr/actions/workflows/ci.yml) [![crates.io](https://img.shields.io/crates/v/fn-ptr.svg)](https://crates.io/crates/fn-ptr) [![Documentation](https://docs.rs/fn-ptr/badge.svg)](https://docs.rs/fn-ptr) [![dependency status](https://deps.rs/repo/github/openbytedev/fn-ptr/status.svg)](https://deps.rs/repo/github/openbytedev/fn-ptr) [![MIT](https://img.shields.io/crates/l/fn-ptr.svg)](https://github.com/OpenByteDev/fn-ptr/blob/master/LICENSE)

This is a utility crate for **introspecting** and **rewriting** function pointer types at compile time.

It implements [`FnPtr`](https://docs.rs/fn-ptr/latest/fn_ptr/trait.FnPtr.html) for all function-pointer types:
- `fn(T) -> U`
- `unsafe fn(T) -> U`
- `extern "C-unwind" fn(T)`
- `unsafe extern "sysv64" fn() -> i32`

## Function pointer metadata

[`FnPtr`](https://docs.rs/fn-ptr/latest/fn_ptr/trait.FnPtr.html) exposes metadata as associated types/consts.

```rust
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:

```rust
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>();
```

## Rewriting function-pointer types

The crate provides type-level rewriting via traits:

- **abi:** [`WithAbi`](https://docs.rs/fn-ptr/latest/fn_ptr/trait.WithAbi.html) / [`with_abi!`](https://docs.rs/fn-ptr/latest/fn_ptr/macro.with_abi.html)
- **Safety:** [`WithSafety`](https://docs.rs/fn-ptr/latest/fn_ptr/trait.WithSafety.html) / [`with_safety!`](https://docs.rs/fn-ptr/latest/fn_ptr/macro.with_safety.html) ([`make_safe!`](https://docs.rs/fn-ptr/latest/fn_ptr/macro.make_unsafe.html), [`make_unsafe!`](https://docs.rs/fn-ptr/latest/fn_ptr/macro.make_unsafe.html))
- **Output:** [`WithOutput`](https://docs.rs/fn-ptr/latest/fn_ptr/trait.WithOutput.html) / [`with_output!`](https://docs.rs/fn-ptr/latest/fn_ptr/macro.with_output.html)
- **Args:** [`WithArgs`](https://docs.rs/fn-ptr/latest/fn_ptr/trait.WithArgs.html) / [`with_args!`](https://docs.rs/fn-ptr/latest/fn_ptr/macro.with_args.html)

### Type-level transformations

The macros compute a new function-pointer **type** while preserving everything else.

```rust
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
```

### Value-level casts

The same transformations exist at the value level via methods on [`FnPtr`](https://docs.rs/fn-ptr/latest/fn_ptr/trait.FnPtr.html).
These casts are only [`transmuting`](https://doc.rust-lang.org/std/mem/fn.transmute.html) and do **not** the actual underlying function.

```rust
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());
```
## How it works

Implementations are generated by a large [macro]((https://github.com/OpenByteDev/fn-ptr/blob/master/src/impl.rs)). The rewrite macros are thin wrappers
over the traits [`WithAbi`](https://docs.rs/fn-ptr/latest/fn_ptr/trait.WithAbi.html), [`WithSafety`](https://docs.rs/fn-ptr/latest/fn_ptr/trait.WithSafety.html), [`WithOutput`](https://docs.rs/fn-ptr/latest/fn_ptr/trait.WithOutput.html), [`WithArgs`](https://docs.rs/fn-ptr/latest/fn_ptr/trait.WithArgs.html) (and the corresponding `*Impl` helper traits).

## License

Licensed under the MIT license, see [LICENSE](https://github.com/OpenByteDev/fn-ptr/blob/master/LICENSE) for details.