Crate smallbox [−] [src]
Box dynamically-sized types on stack Requires nightly rust.
Store or return trait-object and closure without heap allocation, and fallback to heap when thing goes too large.
Usage
First, add the following to your Cargo.toml
:
[dependencies]
smallbox = "0.3"
Next, add this to your crate root:
extern crate smallbox;
Currently smallbox by default links to the standard library, but if you would
instead like to use this crate in a #![no_std]
situation or crate, and want to
opt out heap dependency and SmallBox<T>
type, you can request this via:
[dependencies]
smallbox = { version = "0.3", default-features = false }
Enable heap
feature for #![no_std]
build to link alloc
crate
and bring SmallBox<T>
back.
[dependencies.smallbox]
version = "0.3"
default-features = false
features = ["heap"]
Feature Flags
The stackbox crate has the following cargo feature flags:
std
- Optional, enabled by default
- Use libstd
heap
- Optional
- Use heap fallback and include
SmallBox<T>
type, and link toalloc
crate ifstd
feature flag is opted out.
Overview
This crate delivers two core type:
StackBox<T>
: Represents a fixed-capacity allocation, and on stack stores dynamically-sized type.
The new
method on this type allows creating a instance from a concrete type,
returning Err(value)
if the instance is too large for the allocated region.
Default capacity is four words (4 * sizeof(usize)
), more details on custom capacity are at following sections.
SmallBox<T>
: Takes StackBox<T>
as an varience, and fallback to Box<T>
when type T
is too large for StackBox<T>
.
Example
The simplest usage can be trait object dynamic-dispatch
use smallbox::StackBox; let val: StackBox<PartialEq<usize>> = StackBox::new(5usize).unwrap(); assert!(*val == 5)
Any
downcasting is also quite a good use.
use std::any::Any; use smallbox::StackBox; let num: StackBox<Any> = StackBox::new(1234u32).unwrap(); if let Some(num) = num.downcast_ref::<u32>() { assert_eq!(*num, 1234); } else { unreachable!(); }
Another use case is to allow returning capturing closures without having to box them.
use smallbox::StackBox; fn make_closure(s: String) -> StackBox<Fn()->String> { StackBox::new(move || format!("Hello, {}", s)).ok().unwrap() } let closure = make_closure("world!".to_owned()); assert_eq!(closure(), "Hello, world!");
SmallBox<T>
is to eliminate heap alloction for small things, except that
the object is large enough to allocte.
In addition, the inner StackBox<T>
or Box<T>
can be moved out by explicit pattern match.
use smallbox::SmallBox; let tiny: SmallBox<[u64]> = SmallBox::new([0; 2]); let big: SmallBox<[u64]> = SmallBox::new([1; 8]); assert_eq!(tiny.len(), 2); assert_eq!(big[7], 1); match tiny { SmallBox::Stack(val) => assert_eq!(*val, [0; 2]), _ => unreachable!() } match big { SmallBox::Box(val) => assert_eq!(*val, [1; 8]), _ => unreachable!() }
Capacity
The custom capacity of SmallBox<T, Space>
and StackBox<T,Space>
is expressed by the size of type Space
,
which default to space::S4
represented as 4 words space (4 * usize).
There are some default option in smallbox::space
from S4
to S64
.
Anyway, you can defind your space type, or just use some array.
The resize()
method on StackBox<T, Space>
and SmallBox<T, Space>
is used to transforms itself to the one of bigger capacity.
use smallbox::StackBox; use smallbox::space::*; let s = StackBox::<[usize], S8>::new([0usize; 8]).unwrap(); assert!(s.resize::<S16>().is_ok());
Modules
space |
Default size type to custom stackbox capacity |
Structs
StackBox |
On-stack allocation for dynamically-sized type. |
Enums
SmallBox |
Stack allocation with heap fallback |