sized 0.2.0

Sized Implementation of Unsized types
Documentation
use core::{
    marker::Unsize,
    mem::MaybeUninit,
    ops::{CoerceUnsized, Deref, DerefMut},
    ptr::{addr_of_mut, DynMetadata, Pointee, Thin},
};

pub struct SizedBox<T: ?Sized, const SIZE: usize> {
    storage: [u8; SIZE],
    /// Pointer used for CoerseUnsized. Pointer part of the fat pointer is not
    /// actually used
    _ptr: *mut T,
}

impl<T, const SIZE: usize> SizedBox<T, SIZE> {
    pub const fn new(inner: T) -> Self where {
        // Force a const context for checking the size
        const {
            if core::mem::size_of::<T>() > SIZE {
                panic!("Type is too big to fit in SizedBox")
            }
        };

        let mut s: MaybeUninit<Self> = core::mem::MaybeUninit::uninit();
        let ptr = s.as_mut_ptr();

        unsafe {
            (addr_of_mut!((*ptr).storage) as *mut T).write(inner);
            addr_of_mut!((*ptr)._ptr).write(core::ptr::null_mut());

            s.assume_init()
        }
    }
}

impl<T: ?Sized, const MAX_SIZE: usize, A: ?Sized> Deref for SizedBox<T, MAX_SIZE>
where
    T: Pointee<Metadata = DynMetadata<A>>,
{
    type Target = T;

    fn deref(&self) -> &Self::Target {
        let addr = self.storage.as_ptr() as *const ();

        // We need to create a new pointer out of the metadata in _ptr and the container
        // addr
        let meta = core::ptr::metadata(self._ptr);

        let new_ptr = core::ptr::from_raw_parts(addr, meta);

        unsafe { &*new_ptr }
    }
}

impl<T: ?Sized, const MAX_SIZE: usize, A: ?Sized> DerefMut for SizedBox<T, MAX_SIZE>
where
    T: Pointee<Metadata = DynMetadata<A>>,
{
    fn deref_mut(&mut self) -> &mut Self::Target {
        let addr = self.storage.as_mut_ptr() as *mut ();

        // We need to create a new pointer out of the metadata in _ptr and the container
        // addr
        let meta = core::ptr::metadata(self._ptr);

        let new_ptr = core::ptr::from_raw_parts_mut(addr, meta);

        unsafe { &mut *new_ptr }
    }
}

unsafe impl<T: ?Sized + Send, const SIZE: usize> Send for SizedBox<T, SIZE> {}
unsafe impl<T: ?Sized + Sync, const SIZE: usize> Sync for SizedBox<T, SIZE> {}

impl<T: ?Sized + Unsize<U>, U: ?Sized, const SIZE: usize> CoerceUnsized<SizedBox<U, SIZE>>
    for SizedBox<T, SIZE>
{
}

impl<T: ?Sized, const SIZE: usize> SizedBox<T, SIZE> {
    pub fn resize<const NEW_SIZE: usize>(self) -> SizedBox<T, NEW_SIZE> {
        const {
            if NEW_SIZE < SIZE {
                panic!("Can't reduce the size of a box")
            }
        };

        let mut s: MaybeUninit<SizedBox<T, NEW_SIZE>> = core::mem::MaybeUninit::uninit();
        let ptr = s.as_mut_ptr();

        unsafe {
            let new = addr_of_mut!((*ptr).storage) as *mut u8;
            let old = &self.storage as *const _ as *const u8;
            core::ptr::copy(old, new, SIZE);

            addr_of_mut!((*ptr)._ptr).write(self._ptr);

            s.assume_init()
        }
    }
}