2 releases
Uses new Rust 2024
| 0.1.1 | Nov 9, 2025 |
|---|---|
| 0.1.0 | Aug 13, 2025 |
#1854 in Embedded development
Used in briny_ai
18KB
352 lines
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
| Type | Semantics | Use case |
|---|---|---|
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
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
use box_closure::{OpaqueFnMut, Align8};
use core::cell::Cell;
let counter = Cell::new(0);
let f = OpaqueFnMut::<_, (), Align8<32>>::new(move |_| {
counter.set(counter.get() + 1);
});
f.call(());
f.call(());
assert_eq!(counter.get(), 2);
OpaqueFnOnce
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
| Buffer Type | Alignment | Typical Size |
|---|---|---|
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
FnOnceclosures without double drop. - Designed for embedded and
no-allocenvironments.