dyn_vec 0.1.0

A Vec<T: ?Sized>
Documentation
use std::{
    alloc::{alloc, Layout},
    mem::size_of_val,
};

#[cfg(not(feature = "unstable"))]
use std::ptr::addr_of_mut;

use self::__priv::Sealed;

mod __priv {
    pub trait Sealed {}

    impl<T: ?Sized> Sealed for *const T {}
    impl<T: ?Sized> Sealed for *mut T {}
}

pub trait PtrExt: Sealed {
    type Pointee: ?Sized;

    fn addr(self) -> usize;

    fn align_up(self, align: usize) -> Self;

    fn with_addr_from<U: ?Sized>(self, addr: *const U) -> Self;

    fn with_addr(self, addr: usize) -> Self;

    unsafe fn get_end(self) -> Self;

    fn add_bytes(self, offset: usize) -> Self;

    fn sub_bytes(self, offset: usize) -> Self;

    unsafe fn copy_bytes_to<U: ?Sized>(self, dest: *mut U, count: usize);

    unsafe fn copy_val_to<U: ?Sized>(self, dest: *mut U);

    unsafe fn read_to_box(self) -> Box<Self::Pointee>;
}

impl<T: ?Sized> PtrExt for *const T {
    type Pointee = T;

    fn addr(self) -> usize {
        self.data_ptr() as usize
    }

    fn align_up(self, align: usize) -> Self {
        self.with_addr((self.addr() + align - 1) & !(align - 1))
    }

    fn with_addr_from<U: ?Sized>(self, addr: *const U) -> Self {
        self.with_addr(addr.addr())
    }

    fn with_addr(self, addr: usize) -> Self {
        #[cfg(feature = "unstable")]
        {
            self.wrapping_byte_sub(self.addr()).wrapping_byte_add(addr)
        }
        #[cfg(not(feature = "unstable"))]
        {
            let mut this = self;
            unsafe { *addr_of_mut!(this).cast() = addr }
            this
        }
    }

    unsafe fn get_end(self) -> Self {
        // TODO: _raw
        self.add_bytes(size_of_val(&*self))
    }

    fn add_bytes(self, offset: usize) -> Self {
        self.with_addr_from(self.cast::<u8>().wrapping_add(offset))
    }

    fn sub_bytes(self, offset: usize) -> Self {
        self.with_addr_from(self.cast::<u8>().wrapping_sub(offset))
    }

    unsafe fn copy_bytes_to<U: ?Sized>(self, dest: *mut U, count: usize) {
        self.cast::<u8>().copy_to(dest.cast(), count);
    }

    unsafe fn copy_val_to<U: ?Sized>(self, dest: *mut U) {
        // TODO: _raw
        self.copy_bytes_to(dest, size_of_val(&*self));
    }

    unsafe fn read_to_box(self) -> Box<Self::Pointee> {
        // TODO: _raw
        let alloc = alloc(Layout::for_value(&*self));
        self.copy_val_to(alloc);
        Box::from_raw(alloc.with_meta_from(self))
    }
}

impl<T: ?Sized> PtrExt for *mut T {
    type Pointee = T;

    fn addr(self) -> usize {
        self.data_ptr() as usize
    }

    fn align_up(self, align: usize) -> Self {
        self.with_addr((self.addr() + align - 1) & !(align - 1))
    }

    fn with_addr_from<U: ?Sized>(self, addr: *const U) -> Self {
        self.with_addr(addr.addr())
    }

    fn with_addr(self, addr: usize) -> Self {
        #[cfg(feature = "unstable")]
        {
            self.wrapping_byte_sub(self.addr()).wrapping_byte_add(addr)
        }
        #[cfg(not(feature = "unstable"))]
        {
            let mut this = self;
            unsafe { *addr_of_mut!(this).cast() = addr }
            this
        }
    }

    unsafe fn get_end(self) -> Self {
        // TODO: _raw
        self.add_bytes(size_of_val(&*self))
    }

    fn add_bytes(self, offset: usize) -> Self {
        self.with_addr_from(self.cast::<u8>().wrapping_add(offset))
    }

    fn sub_bytes(self, offset: usize) -> Self {
        self.with_addr_from(self.cast::<u8>().wrapping_sub(offset))
    }

    unsafe fn copy_bytes_to<U: ?Sized>(self, dest: *mut U, count: usize) {
        self.cast::<u8>().copy_to(dest.cast(), count);
    }

    unsafe fn copy_val_to<U: ?Sized>(self, dest: *mut U) {
        // TODO: _raw
        self.copy_bytes_to(dest, size_of_val(&*self));
    }

    unsafe fn read_to_box(self) -> Box<Self::Pointee> {
        // TODO: _raw
        let alloc = alloc(Layout::for_value(&*self));
        self.copy_val_to(alloc);
        Box::from_raw(alloc.with_meta_from(self))
    }
}

#[allow(clippy::module_name_repetitions)]
pub trait ConstPtrExt: Sealed {
    fn data_ptr(self) -> *const ();

    fn with_meta_from<U: ?Sized>(self, ptr: *const U) -> *const U;
}

impl<T: ?Sized> ConstPtrExt for *const T {
    fn data_ptr(self) -> *const () {
        self.cast()
    }

    // fn with_meta<U: ?Sized>(self, meta: <U as Pointee>::Metadata) -> *const U {
    //     ptr::from_raw_parts(self.data_ptr(), meta)
    // }

    fn with_meta_from<U: ?Sized>(self, ptr: *const U) -> *const U {
        #[cfg(feature = "unstable")]
        {
            self.with_metadata_of(ptr)
        }
        #[cfg(not(feature = "unstable"))]
        {
            ptr.with_addr_from(self)
        }
    }
}

#[allow(clippy::module_name_repetitions)]
pub trait MutPtrExt: Sealed {
    fn data_ptr(self) -> *mut ();

    // fn with_meta<U: ?Sized>(self, meta: <U as Pointee>::Metadata) -> *mut U;

    fn with_meta_from<U: ?Sized>(self, ptr: *const U) -> *mut U;
}

impl<T: ?Sized> MutPtrExt for *mut T {
    fn data_ptr(self) -> *mut () {
        self.cast()
    }

    // fn with_meta<U: ?Sized>(self, meta: <U as Pointee>::Metadata) -> *mut U {
    //     ptr::from_raw_parts_mut(self.data_ptr(), meta)
    // }

    fn with_meta_from<U: ?Sized>(self, ptr: *const U) -> *mut U {
        #[cfg(feature = "unstable")]
        {
            self.with_metadata_of(ptr as _)
        }
        #[cfg(not(feature = "unstable"))]
        {
            ptr.with_addr_from(self) as _
        }
    }
}