Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/kixiron/tagged-box
A no_std, zero-dependency crate for the creation and management of NaN-boxed types with Box-like semantics, tagged pointers and a macro interface to safely create NaN-boxed enums.
https://github.com/kixiron/tagged-box
Last synced: about 13 hours ago
JSON representation
A no_std, zero-dependency crate for the creation and management of NaN-boxed types with Box-like semantics, tagged pointers and a macro interface to safely create NaN-boxed enums.
- Host: GitHub
- URL: https://github.com/kixiron/tagged-box
- Owner: Kixiron
- License: other
- Created: 2020-03-06T12:33:56.000Z (over 4 years ago)
- Default Branch: master
- Last Pushed: 2020-04-17T17:49:01.000Z (over 4 years ago)
- Last Synced: 2024-11-16T04:47:44.422Z (1 day ago)
- Language: Rust
- Homepage:
- Size: 146 KB
- Stars: 19
- Watchers: 3
- Forks: 3
- Open Issues: 3
-
Metadata Files:
- Readme: README.md
- Changelog: Changelog.md
- License: LICENSE
Awesome Lists containing this project
README
# Tagged-box
[![Crates.io](https://img.shields.io/crates/v/tagged-box?style=flat)](https://crates.io/crates/tagged-box)
[![Docs.rs](https://docs.rs/tagged-box/badge.svg)](https://docs.rs/tagged-box)
[![GitHub](https://img.shields.io/github/languages/top/Kixiron/tagged-box)](https://github.com/Kixiron/tagged-box)
[![LOC](https://tokei.rs/b1/github/Kixiron/tagged-box)](https://github.com/Kixiron/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 [settings] section)
```toml
tagged_box = "0.1.1"
```Next, for using the macro, add the following to the top of your file
```rust
use tagged_box::{tagged_box, TaggableContainer, TaggableInner};
```Then you can use the macro as follows
```rust
tagged_box! {
#[derive(Debug, Clone, PartialEq)]
pub struct Container, pub enum Item {
String(String),
Numbers(i32, f32),
Nothing,
Struct {
float: f32,
boolean: bool,
},
}
}let container = Container::from(String::from("Hello from tagged-box!"));
assert_eq!(
container.into_inner(),
Item::String(String::from("Hello from tagged-box!")),
);// For tuple structs with more than 1 variant, `From<(values)>` is derived
let container = Container::from((10i32, 10.0));assert_eq!(
container.into_inner(),
Item::Numbers(10i32, 10.0),
);// Note: `From` is not implemented for unit and orphan struct variants
```For working with NaN-boxes, simply add
```rust
use tagged_box::TaggedBox;
```And for tagged pointers use
```rust
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 [settings] enabled. For explanation's sake,
I'll be using the `48bits` feature to explain, as it leads to the cleanest examples.
The pointers this applies to are 64 bits long, looking something like this```text
0000 0000 0000 0000
```However, not all of these bits are used for the actual addressing of memory, so most pointers look like this
```text
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 settings that change the number of free and reserved bits, this can be changed by setting `TAGGED_BOX_RESERVED_WIDTH`:
- `48bits`: 48 bits of reserved pointer, 16 bits for data
- `49bits`: 49 bits of reserved pointer, 15 bits for data
- `50bits`: 50 bits of reserved pointer, 14 bits for data
- `51bits`: 51 bits of reserved pointer, 13 bits for data
- `52bits`: 52 bits of reserved pointer, 12 bits for data
- `53bits`: 53 bits of reserved pointer, 11 bits for data
- `54bits`: 54 bits of reserved pointer, 10 bits for data
- `55bits`: 55 bits of reserved pointer, 9 bits for data
- `56bits`: 56 bits of reserved pointer, 8 bits for data
- `57bits`: 57 bits of reserved pointer, 7 bits for data
- `58bits`: 58 bits of reserved pointer, 6 bits for data
- `59bits`: 59 bits of reserved pointer, 5 bits for data
- `60bits` (On by default): 60 bits of reserved pointer, 4 bits for data
- `61bits`: 61 bits of reserved pointer, 3 bits for data
- `62bits`: 62 bits of reserved pointer, 2 bits for data
- `63bits`: 63 bits of reserved pointer, 1 bit for dataHowever, only one of these may be active at a time, otherwise a `compile_error` will be emitted.
[`Box`]: (https://doc.rust-lang.org/std/boxed/struct.Box.html)
[settings]: #crate-settings
[NaN-Boxing]: https://wingolog.org/archives/2011/05/18/value-representation-in-javascript-implementations
[Tagged Pointers]: https://en.wikipedia.org/wiki/Tagged_pointer
[unused bits of pointers]: https://en.wikipedia.org/wiki/X86-64#Virtual_address_space_details
[enum discriminant]: https://doc.rust-lang.org/reference/items/enumerations.html