Skip to content

Commit fd4c8de

Browse files
committed
Update docs
1 parent dc428de commit fd4c8de

2 files changed

Lines changed: 51 additions & 56 deletions

File tree

README.md

Lines changed: 49 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -2,98 +2,93 @@
22

33
[![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)
44

5-
This is a small utility crate that provides the [`FnPtr`](https://docs.rs/fn-ptr/latest/fn_ptr/trait.FnPtr.html) trait, which is implemented for all function pointer types:
5+
This is a utility crate for **introspecting** and **rewriting** function pointer types at compile time.
6+
7+
It implements [`FnPtr`](https://docs.rs/fn-ptr/latest/fn_ptr/trait.FnPtr.html) for all function-pointer types:
68
- `fn(T) -> U`
79
- `unsafe fn(T) -> U`
8-
- `extern "C" fn(T)`
10+
- `extern "C-unwind" fn(T)`
911
- `unsafe extern "sysv64" fn() -> i32`
1012

11-
The trait provides associated types and constants to introspect function pointer types at compile time.
12-
13-
## Features
14-
15-
### 1. Function Pointer Metadata
13+
## Function pointer metadata
1614

17-
Every function pointer automatically implements [`FnPtr`](https://docs.rs/fn-ptr/latest/fn_ptr/trait.FnPtr.html) as well as a bunch of other related traits. With these you can inspect the type of function pointers at compile time:
15+
[`FnPtr`](https://docs.rs/fn-ptr/latest/fn_ptr/trait.FnPtr.html) exposes metadata as associated types/consts.
1816

1917
```rust
20-
use fn_ptr::{FnPtr, Abi};
18+
use fn_ptr::{FnPtr, AbiValue};
2119

2220
type F = extern "C" fn(i32, i32) -> i32;
23-
2421
assert_eq!(<F as FnPtr>::ARITY, 2);
2522
assert_eq!(<F as FnPtr>::IS_SAFE, true);
2623
assert_eq!(<F as FnPtr>::IS_EXTERN, true);
27-
assert_eq!(<F as FnPtr>::abi, Abi::C { unwind: false });
24+
assert_eq!(<F as FnPtr>::ABI, AbiValue::C { unwind: false });
2825
```
2926

30-
There are also some const helper functons to do so ergonomically.
27+
Ergonomic const functions are provided as well:
3128

3229
```rust
33-
const A: usize = fn_ptr::arity::<F>(); // 2
34-
const SAFE: bool = fn_ptr::is_safe::<F>(); // true
35-
const EXT: bool = fn_ptr::is_extern::<F>(); // true
36-
const abi: Abi = fn_ptr::abi::<F>(); // Abi::C
30+
const A: usize = fn_ptr::arity::<F>();
31+
const SAFE: bool = fn_ptr::is_safe::<F>();
32+
const EXT: bool = fn_ptr::is_extern::<F>();
33+
const abi: AbiValue = fn_ptr::abi::<F>();
3734
```
3835

39-
### 2. Toggle Function Pointer Safety
36+
## Rewriting function-pointer types
4037

41-
You can toggle the safety of a function pointer at the type level:
38+
The crate provides type-level rewriting via traits:
4239

43-
```rust
44-
use fn_ptr::{make_safe, make_unsafe};
40+
- **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)
41+
- **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))
42+
- **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)
43+
- **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)
4544

46-
type U = unsafe extern "C" fn(i32);
47-
type S = make_safe!(U); // extern "C" fn(i32)
45+
### Type-level transformations
4846

49-
type S2 = extern "C" fn(i32);
50-
type U2 = make_unsafe!(S2); // unsafe extern "C" fn(i32)
51-
```
52-
53-
Or at the instance level:
47+
The macros compute a new function-pointer **type** while preserving everything else.
5448

5549
```rust
56-
let safe_add: fn(i32, i32) -> i32 = |a, b| {a + b};
57-
let unsafe_add: unsafe fn(i32, i32) -> i32 = safe_add.as_unsafe();
58-
let safe_add2: fn(i32, i32) -> i32 = unsafe { unsafe_add.as_safe() };
59-
```
60-
61-
### 3. Changing ABIs
62-
63-
You can also change the abi of a function pointer at the type level:
64-
65-
```rust
66-
use fn_ptr::{with_abi, Abi};
50+
use fn_ptr::{with_abi, with_safety, with_output, with_args};
6751

6852
type F = extern "C" fn(i32) -> i32;
6953

70-
type G = with_abi!("sysv64", F);
71-
type H = with_abi!("C", extern "system" fn());
54+
type F1 = with_abi!("sysv64", F); // extern "sysv64" fn(i32) -> i32
55+
type F2 = with_safety!(unsafe, F); // unsafe extern "C" fn(i32) -> i32
56+
type F3 = with_output!(u64, F); // extern "C" fn(i32) -> u64
57+
type F4 = with_args!((u8, u16), F); // extern "C" fn(u8, u16) -> i32
7258
```
7359

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

7665
```rust
7766
use fn_ptr::{FnPtr, abi};
78-
let rust_add: fn(i32, i32) -> i32 = |a, b| {a + b};
79-
// Safety: not actually safe!
80-
let c_add: extern "C" fn(i32, i32) -> i32 = unsafe { rust_add.with_abi::<abi!("C")>() };
81-
```
8267

83-
Note that this does not change the underlying abi and should be used with caution.
68+
let f: fn(i32, i32) -> i32 = |a, b| a + b;
8469

85-
## How It Works
70+
// safety
71+
let u: unsafe fn(i32, i32) -> i32 = f.as_unsafe();
72+
let f2: fn(i32, i32) -> i32 = unsafe { u.as_safe() };
8673

87-
To implement the traits for all function pointer types, there is a large [macro](https://github.com/OpenByteDev/fn-ptr/blob/master/src/impl.rs).
88-
For the conversion macros the crate relies on two traits: [`WithAbi`](https://docs.rs/fn-ptr/latest/fn_ptr/trait.WithAbi.html) and [`WithSafety`](https://docs.rs/fn-ptr/latest/fn_ptr/trait.WithSafety.html) that can also be used directly:
74+
// abi
75+
let c: extern "C" fn(i32, i32) -> i32 = unsafe { f.with_abi::<abi!("C")>() };
8976

90-
```rust
91-
use fn_ptr::{FnPtr, WithAbi, WithSafety, marker::{SysV64, Unsafe}};
77+
// output
78+
let out: fn(i32, i32) -> u64 = unsafe { f.with_output::<u64>() };
9279

93-
type F = extern "C" fn(i32);
94-
type G = <F as WithAbi<SysV64>>::F;
95-
type U = <F as WithSafety<Unsafe>::F;
80+
// args
81+
let args: fn(u8, u16) -> i32 = unsafe { f.with_args::<(u8, u16)>() };
82+
83+
# assert_eq!(f.addr(), f2.addr());
84+
# assert_eq!(f.addr(), c.addr());
85+
# assert_eq!(f.addr(), out.addr());
86+
# assert_eq!(f.addr(), args.addr());
9687
```
88+
## How it works
89+
90+
Implementations are generated by a large [macro]((https://github.com/OpenByteDev/fn-ptr/blob/master/src/impl.rs)). The rewrite macros are thin wrappers
91+
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).
9792

9893
## License
9994

src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,8 @@
9090
//! ```
9191
//! ## How it works
9292
//!
93-
//! Implementations are generated by a macro (see `src/impl.rs` in the repo). The rewrite macros are thin wrappers
94-
//! over the traits [`WithAbi`], [`WithSafety`], [`WithOutput`], [`WithArgs`] (and the corresponding `From` helper traits).
93+
//! Implementations are generated by a large [macro](https://github.com/OpenByteDev/fn-ptr/blob/master/src/impl.rs). The rewrite macros are thin wrappers
94+
//! over the traits [`WithAbi`], [`WithSafety`], [`WithOutput`], [`WithArgs`] (and the corresponding `*Impl` helper traits).
9595
9696
/// Module containing the Abi abstraction.
9797
mod abi_value;

0 commit comments

Comments
 (0)