# `box_closure`
`box_closure` provides opaque wrappers over Rust closures (`Fn`, `FnMut`, `FnOnce`) for no-alloc environments.
Rust treats closures as unique types, even when their behavior is identical. This can cause compiler errors when passing closures in generic contexts. Normally, `Box<dyn Fn>` solves this by heap-allocating the closure, but heap allocation isn’t always available—especially in embedded systems.
`box_closure` offers `OpaqueFn`, `OpaqueFnMut`, and `OpaqueFnOnce`:
- Hide the concrete type of the closure from the compiler.
- Allow stack-only storage in a fixed-size, aligned buffer.
- Provide safe dispatch without heap allocation.
- Prevent opaque type mismatch compiler errors.
## Closure Wrappers
| `OpaqueFn` | Immutable closure (`Fn`) | Shared access, stateless or read-only captures |
| `OpaqueFnMut` | Mutable closure (`FnMut`) | Closures that mutate captured state |
| `OpaqueFnOnce` | Single-use closure (`FnOnce`) | Closures that consume captured state |
## Quick Reference
### Closures
#### `OpaqueFn`
```rust
use box_closure::{OpaqueFn, Align8};
let y = 10;
let f = OpaqueFn::<_, u32, Align8<32>>::new(|x: u32| x + y);
assert_eq!(f.call(5), 15);
```
#### `OpaqueFnMut`
```rust
use box_closure::{OpaqueFnMut, Align8};
use core::cell::Cell;
let counter = Cell::new(0);
});
f.call(());
f.call(());
assert_eq!(counter.get(), 2);
```
#### `OpaqueFnOnce`
```rust
use box_closure::{OpaqueFnOnce, Align16};
let s = String::from("hello");
let f = OpaqueFnOnce::<_, usize, Align16<64>>::new(move |x: usize| {
x + s.len()
});
assert_eq!(f.call(5), 10); // consumes closure
```
### Buffer Alignment
| `Align1<N>` | 1 byte | `N` bytes |
| `Align2<N>` | 2 bytes | `N` bytes |
| `Align4<N>` | 4 bytes | `N` bytes |
| `Align8<N>` | 8 bytes | `N` bytes |
| `Align16<N>` | 16 bytes | `N` bytes |
| `Align32<N>` | 32 bytes | `N` bytes |
| `Align64<N>` | 64 bytes | `N` bytes |
## Benefits
- No heap allocation: everything fits in a fixed buffer.
- Opaque types prevent generic mismatch errors.
- Safe consumption of `FnOnce` closures without double drop.
- Designed for embedded and `no-alloc` environments.