dynstack 0.4.0

A stack for trait objects that minimizes allocations
Documentation
use std::mem;

#[path = "src/fatptr.rs"]
mod fatptr;

fn main() {
    // This build script sanity checks the memory layout of
    // trait objects/fat pointers. So if the Rust compiler ever change
    // layout of these, this crate should hopefully fail to compile
    // instead of producing programs that has undefined behavior.

    assert_eq!(
        mem::size_of::<&dyn TestTrait>(),
        mem::size_of::<[usize; 2]>(),
        "Trait objects does not have the expected size"
    );

    let instance1 = Implementer1(1);
    let instance2 = Implementer2(2);
    let [data1, vtable1] = unsafe { fatptr::decomp(&instance1 as &dyn TestTrait) };
    let [data2, vtable2] = unsafe { fatptr::decomp(&instance2 as &dyn TestTrait) };

    assert_eq!(
        data1, &instance1 as *const Implementer1 as usize,
        "First part of the fat pointer does not point to the data"
    );

    let data1_vtable2: &dyn TestTrait = unsafe { &*fatptr::recomp([data1, vtable2]) };
    let data2_vtable1: &dyn TestTrait = unsafe { &*fatptr::recomp([data2, vtable1]) };
    assert_eq!(
        data1_vtable2.calc(),
        1 + 20,
        "Recombining fat pointer from parts yielded unexpected result"
    );
    assert_eq!(
        data2_vtable1.calc(),
        2 + 10,
        "Recombining fat pointer from parts yielded unexpected result"
    );
}

trait TestTrait {
    fn calc(&self) -> u8;
}

struct Implementer1(u8);
impl TestTrait for Implementer1 {
    fn calc(&self) -> u8 {
        self.0 + 10
    }
}

struct Implementer2(u8);
impl TestTrait for Implementer2 {
    fn calc(&self) -> u8 {
        self.0 + 20
    }
}