dynode 0.0.0

A utility library for creating node-based structures that can hold dynamically sized values
Documentation
#![feature(unsize, ptr_metadata)]

use core::{fmt, marker::Unsize, ops::Deref};

use dynode::NodePtr;

#[cfg_attr(test, test)]
fn main() {
    let boxed = ThinBox::<[u8]>::new_unsize([1, 2, 3]);
    assert!([1, 2, 3].eq(&*boxed));
    println!("{boxed:?}");

    let ones: [ThinBox<dyn fmt::Debug>; 3] = [
        ThinBox::new_unsize("One"),
        ThinBox::new_unsize(1),
        ThinBox::new_unsize('1'),
    ];
    println!("{ones:?}");
}

type Node<T> = NodePtr<(), T>;
struct ThinBox<T>
where
    T: ?Sized,
{
    ptr: Node<T>,
}

impl<T> ThinBox<T>
where
    T: ?Sized,
{
    fn new_unsize<F>(value: F) -> Self
    where
        F: Unsize<T>,
    {
        let node = Node::allocate_unsize::<F>();
        unsafe { node.value_ptr().cast().write(value) };
        Self { ptr: node }
    }
}

impl<T> Deref for ThinBox<T>
where
    T: ?Sized,
{
    type Target = T;

    fn deref(&self) -> &Self::Target {
        unsafe { self.ptr.data_ptr().as_ref() }
    }
}

impl<T> Drop for ThinBox<T>
where
    T: ?Sized,
{
    fn drop(&mut self) {
        unsafe { self.ptr.data_ptr().drop_in_place() };
        unsafe { self.ptr.deallocate_global() };
    }
}

impl<T> fmt::Debug for ThinBox<T>
where
    T: ?Sized + fmt::Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        fmt::Debug::fmt(&**self, f)
    }
}