2 releases
0.1.1 | Mar 8, 2020 |
---|---|
0.1.0 | Mar 8, 2020 |
#464 in Embedded development
135 downloads per month
Used in 12 crates
(via litl)
72KB
964 lines
Tagged-box
A no_std
, zero-dependency crate for the creation and management of NaN-boxed types with
Box
-like semantics and tagged pointers, tagged pointers and a macro interface to safely
create NaN-boxed enums.
Quickstart
First, add the crate to your Cargo.lock
(Note: for variable reserved widths, see the features section)
tagged_box = "0.1.0"
Next, for using the macro, add the following to the top of your file
use tagged_box::{tagged_box, TaggableContainer, TaggableInner};
Then you can use the macro as follows
tagged_box! {
#[derive(Debug, Clone, PartialEq)]
struct Container, enum Item {
Integer(i32),
Boolean(bool),
String(String),
}
}
let container = Container::from(String::from("Hello from tagged-box!"));
assert_eq!(
container.into_inner(),
Item::String(String::from("Hello from tagged-box!"))
);
For working with NaN-boxes, simply add
use tagged_box::TaggedBox;
And for tagged pointers use
use tagged_box::TaggedPointer;
What this crate does
This crate implements NaN-Boxing and Tagged Pointers, which are a way to store extra data in the unused bits of pointers.
While the two differ in implementation, they are semantically the same. In this crate, the TaggedBox
type allows you to store
anywhere from 7 to 16 bits of arbitrary data in your pointer, depending on the features enabled. For explanation's sake,
I'll be using the 48bits
feature to explain, as it's the default and leads to the cleanest examples.
The pointers this applies to are 64 bits long, looking something like this
0000 0000 0000 0000
However, not all of these bits are used for the actual addressing of memory, so most pointers look like this
0000 FFFF FFFF FFFF
^^^^
Free Data!
Those first 16 bits are free data, just begging to be used, and that's what TaggedPointer
does. TaggedPointer
simply
manages the pointer and the data (referred to as a 'discriminant' throughout this crate), making sure you get a pointer when you
need it and data when you need it, and not mixing those two up.
TaggedBox
goes one layer higher, storing an enum discriminant (Indicated by the type parameter) and directly storing the enum variant's inner value to the heap. In short, TaggedBox
is like a Box
and an enum rolled into one.
Ramping the abstraction up one more notch, we have the tagged_box!
macro, which creates a container-type struct and an associated TaggedBox
-backed enum that can be seamlessly transferred between.
Cargo Features
This crate has a few features that change the number of free and reserved bits:
48bits
(On by default): 48 bits of reserved pointer, 16 bits for data49bits
: 49 bits of reserved pointer, 15 bits for data50bits
: 50 bits of reserved pointer, 14 bits for data51bits
: 51 bits of reserved pointer, 13 bits for data52bits
: 52 bits of reserved pointer, 12 bits for data53bits
: 53 bits of reserved pointer, 11 bits for data54bits
: 54 bits of reserved pointer, 10 bits for data55bits
: 55 bits of reserved pointer, 9 bits for data56bits
: 56 bits of reserved pointer, 8 bits for data57bits
: 57 bits of reserved pointer, 7 bits for data
However, only one of these may be active at a time, otherwise a compile_error
will be emitted.
To select a feature, put the following in your Cargo.toml
[dependencies.tagged_box]
version = "0.1.0"
default-features = false
features = ["50bits"] # Select your feature here