Crate sized_dst

Crate sized_dst 

Source
Expand description

§sized-dst

This crate provides Dst, an owned container for dynamically-sized types (DSTs) that’s backed by inline memory. The main use-case is owned trait objects without heap allocation. You can think of it as a stack-only version of Box<dyn Trait>.

This crate currently requires nightly, since it relies on Unsize and pointer metadata.

The layout of sized_dst::Dst consists of the DST metadata (for trait objects, this is the vtable pointer) and a fixed block of memory storing the actual object. This allows it to live entirely on the stack or even a static variable. The size and alignment of its memory block are specified by generic parameters, so a sized_dst::Dst can only store objects that fit in its memory block. If the object does not fulfill the size or alignment requirements, the constructor of sized_dst::Dst will emit a compile-time error.

use sized_dst::{Dst, max_size};

trait Draw {
    fn draw(&self);
}

struct Button {
    height: u32,
    width: u32,
    name: &'static str,
}
impl Draw for Button {
    fn draw(&self) { /* draw the button */ }
}

struct Checkbox {
    on: bool,
}
impl Draw for Checkbox {
    fn draw(&self) { /* draw the checkbox */ }
}

struct Text(&'static str);
impl Draw for Text {
    fn draw(&self) { /* draw the text */ }
}

struct Blob([u8; 100]);
impl Draw for Blob {
    fn draw(&self) { /* draw the blob */ }
}

impl Draw for u32 {
    fn draw(&self) { /* draw the u32 */ }
}

fn main() {
    // Each Dst stores a `dyn Draw` up to a fixed capacity, which is set via `max_size` to
    // the size of the biggest trait object we're using.
    let drawables: &[Dst<dyn Draw, { max_size!(Checkbox, Text, Button) }>] = &[
        Dst::new(Checkbox { on: true }),
        Dst::new(Text("lorem ipsum")),
        Dst::new(Button {
            height: 20,
            width: 20,
            name: "PANIC BUTTON",
        }),
        Dst::new(1u32),   // u32 is smaller than the fixed capacity we specified, so we can use it
        // Dst::new(Blob([0; 100]))    This would not compile, because Blob doesn't fit in Dst
    ];

    // Perform dynamic dispatch over the Draw trait
    for d in drawables {
        d.draw();
    }
}

Compared to Box<dyn Trait>, Dst requires no indirection or allocation, making it more cache-friendly and usable in environments with no allocator. In exchange, Dst can only store objects up to a fixed size, making it less flexible than Box<dyn Trait>. In a way, Dst offers a compromise between enums and boxed trait objects.

§Optional Features

  • std: Enable implementations of std traits.

If you to change the alignment requirements of your DST (for example, your type may need to be aligned to a 32-byte boundary), see DstBase, which is also where most of the documentation lives.

Macros§

max_size
Given multiple type names, return the size of the biggest type.

Structs§

A1
1-byte alignment
A2
2-byte alignment
A4
4-byte alignment
A8
8-byte alignment
A16
16-byte alignment
A32
32-byte alignment
A64
64-byte alignment
DstBase
Sized object that stores a DST object, such as a trait object, on the stack.

Traits§

Alignment
A marker trait for an alignment value.

Type Aliases§

Dst
DstBase with the alignment of usize. This is almost always what you want to use.
DstA1
DstBase storing an object with alignment of 1 byte
DstA2
DstBase storing an object with alignment of 2 bytes
DstA4
DstBase storing an object with alignment of 4 bytes
DstA8
DstBase storing an object with alignment of 8 bytes
DstA16
DstBase storing an object with alignment of 16 bytes
DstA32
DstBase storing an object with alignment of 32 bytes
DstA64
DstBase storing an object with alignment of 64 bytes
DstPtr
Dst with the size and alignment of usize. This can be used to represent both dyn pointers and dyn objects smaller than a pointer.