fn-ptr 0.9.1

A utility crate for introspecting and rewriting function pointer types at compile time.
Documentation
#![cfg_attr(nightly_build, fn_ptr_trait)]
#![cfg_attr(has_abi_vectorcall, feature(abi_vectorcall))]
#![warn(clippy::pedantic, missing_docs)]
#![no_std]

//! `fn-ptr` is a utility crate for **introspecting** and **rewriting** function pointer types at compile time.
//!
//! It implements [`FnPtr`] 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`] 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
//! # type F = extern "C" fn(i32, i32) -> i32;
//! # use fn_ptr::{FnPtr, AbiValue};
//! 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`] / [`with_abi!`]
//! - **Safety:** [`WithSafety`] / [`with_safety!`] ([`make_safe!`], [`make_unsafe!`])
//! - **Output:** [`WithOutput`] / [`with_output!`]
//! - **Args:** [`WithArgs`] / [`with_args!`]
//!
//! ### 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`].
//! These casts are only [`transmuting`](core::mem::transmute) 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`], [`WithSafety`], [`WithOutput`], [`WithArgs`] (and the corresponding `*Impl` helper traits).

/// Module containing the Abi abstraction.
mod abi_value;
pub use abi_value::AbiValue;

mod r#impl;

/// Module containing safety related marker types and traits.
pub mod safety;
pub use safety::Safety;
/// Module containing abi related marker types and traits.
pub mod abi;
pub use abi::Abi;
/// Module containing arity related marker types and traits.
pub mod arity;
pub use arity::Arity;

/// Prelude for this crate.
pub mod prelude;

mod base;
pub use base::*;

mod build;
pub use build::*;

mod tuple;
pub use tuple::*;

mod conv;
pub use conv::*;

/// Returns the number of arguments of a function pointer type.
#[must_use]
pub const fn arity<F: FnPtr>() -> usize {
    F::ARITY
}

/// Returns `true` for safe function pointers (`fn`).
#[must_use]
pub const fn is_safe<F: FnPtr>() -> bool {
    F::IS_SAFE
}

/// Returns `true` for unsafe function pointers (`unsafe fn`).
#[must_use]
pub const fn is_unsafe<F: FnPtr>() -> bool {
    !is_safe::<F>()
}

/// Returns `true` if the function pointer uses an external abi.
#[must_use]
pub const fn is_extern<F: FnPtr>() -> bool {
    F::IS_EXTERN
}

/// Returns a runtime representation of the abi of the function pointer.
#[must_use]
pub const fn abi<F: FnPtr>() -> AbiValue {
    F::ABI
}