diff --git a/src/lib.rs b/src/lib.rs index c42c850..de3ad91 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,15 +8,12 @@ mod test; pub mod prelude; use core::panic; -#[cfg(feature = "only_store_meta")] -use std::{ptr::Pointee, mem::align_of_val_raw}; use std::{ - ptr::{NonNull, self, drop_in_place, metadata, Pointee}, + ptr::{NonNull, self, drop_in_place, metadata}, marker::PhantomData, alloc::{alloc, Layout}, - mem::{size_of, size_of_val, align_of_val, self, size_of_val_raw, align_of_val_raw}, + mem::{size_of, size_of_val, align_of_val, self, size_of_val_raw}, slice, - fmt::Debug, ops::{CoerceUnsized, Index, IndexMut} }; @@ -44,75 +41,15 @@ fn align_up_mut(ptr: *mut T, align: usize) -> *mut T { align_up(ptr as _, align) as _ } -trait Strategy: Sized { - type Metadata: Copy; - - unsafe fn get_ptr(vec: &Vec, index: usize) -> *const T; - - unsafe fn next(vec: &Vec, prev: *const T, index: usize) -> *const T; - - fn create_meta_from_ptr(vec: &Vec, ptr: *const T) -> Self::Metadata; -} - -struct StorePtr; - -impl Strategy for StorePtr { - type Metadata = *const T; - - unsafe fn get_ptr(vec: &Vec, index: usize) -> *const T { - vec.get_ptr_to_meta(index + 1).cast::<*const T>().read() - } - - unsafe fn next(vec: &Vec, _prev: *const T, index: usize) -> *const T { - Self::get_ptr(vec, index) - } - - fn create_meta_from_ptr(_vec: &Vec, ptr: *const T) -> Self::Metadata { - ptr - } -} - -struct OnlyStoreMeta; - -impl Strategy for OnlyStoreMeta { - type Metadata = ::Metadata; - - unsafe fn get_ptr(vec: &Vec, index: usize) -> *const T { - let meta = vec.get_ptr_to_meta(1).cast::<::Metadata>().read(); - let fake = ptr::from_raw_parts::(0 as _, meta); - let ptr = align_up(vec.ptr.as_ptr(), align_of_val_raw(fake)); - let mut ptr = ptr::from_raw_parts(ptr.cast(), meta); - - for index in 1..=index { - ptr = Self::next(vec, ptr, index); - } - - ptr - } - - unsafe fn next(vec: &Vec, prev: *const T, index: usize) -> *const T { - let ptr = prev.cast::().wrapping_add(size_of_val_raw(prev)); - - let meta = vec.get_ptr_to_meta(index + 1).cast::<::Metadata>().read(); - let fake = ptr::from_raw_parts::(0 as _, meta); - let ptr = align_up(ptr, align_of_val_raw(fake)); - ptr::from_raw_parts(ptr.cast(), meta) - } - - fn create_meta_from_ptr(_vec: &Vec, ptr: *const T) -> Self::Metadata { - metadata(ptr) - } -} - /// A heap allocated, dynamically sized collection of `?Sized` elements. /// /// See [`::alloc::vec::Vec`] (the standard library `Vec` type) for more information. -struct Vec> { +pub struct Vec { ptr: NonNull, len: usize, capacity: usize, end_ptr: NonNull, - _phantom: PhantomData<(*mut S, T)> + _phantom: PhantomData } // keeps this file cleaner @@ -120,23 +57,10 @@ mod impls; mod iter; pub use iter::*; -/// The data stored as metadata at the end of the allocation. -#[cfg(feature = "only_store_meta")] -type Meta = ::Metadata; -#[cfg(not(feature = "only_store_meta"))] -type Meta = *const T; +/// The extra data stored at the end of the allocation. +type Extra = *const T; -#[cfg(feature = "only_store_meta")] -unsafe fn size_of_val_meta(meta: Meta) -> usize { - size_of_val_raw(ptr::from_raw_parts::(0 as *const (), meta)) -} - -#[cfg(feature = "only_store_meta")] -unsafe fn align_of_val_meta(meta: Meta) -> usize { - align_of_val_raw(ptr::from_raw_parts::(0 as *const (), meta)) -} - -impl> Vec { +impl Vec { /// Creates a new, empty `Vec`. pub fn new() -> Self { let ptr = NonNull::dangling(); @@ -182,7 +106,7 @@ impl> Vec { // make sure we have enough space for a new element, but also space for future elements // this bit is tricky, we must make sure we have enough space for padding too, so its probably UB somehow // FIXME: ^^^ - let new_alloc_size = self.capacity * 2 + size * 2 + size_of::(); + let new_alloc_size = self.capacity * 2 + size * 2 + size_of::>(); self.realloc(new_alloc_size); } @@ -201,7 +125,7 @@ impl> Vec { /// Checks if a given element will fill in the `Vec` without reallocations. pub fn will_fit(&self, v: &T) -> bool { let remaining_space = self.get_ptr_to_meta(self.len) as usize - self.end_ptr.as_ptr() as usize; - let needed_space = size_of_val(v) + size_of::(); + let needed_space = size_of_val(v) + size_of::>(); remaining_space >= needed_space } @@ -252,7 +176,7 @@ impl> Vec { let meta_len = current_alloc_end as usize - meta_src as usize; new_alloc_end.wrapping_sub(meta_len) }; - let meta_size = self.len * size_of::>(); + let meta_size = self.len * size_of::>(); memcpy(meta_src.cast(), meta_dst, meta_size); dealloc(self.ptr.as_ptr(), Layout::from_size_align_unchecked(self.capacity, 8)); @@ -266,24 +190,19 @@ impl> Vec { /// for internal use /// /// NOTE: 1-indexed, to allow getting a pointer to the end of the alloc easily - fn get_ptr_to_meta(&self, index: usize) -> *mut S::Metadata { + fn get_ptr_to_meta(&self, index: usize) -> *mut Extra { self.ptr.as_ptr() .wrapping_add(self.capacity) - .cast::() + .cast::>() .wrapping_sub(index) } - /// for internal use - unsafe fn get_meta(&self, index: usize) -> S::Metadata { - *self.get_ptr_to_meta(index + 1) - } - unsafe fn set_meta_from_ptr(&self, index: usize, ptr: *const T) { - self.get_ptr_to_meta(index + 1).write(S::create_meta_from_ptr(self, ptr)); + self.get_ptr_to_meta(index + 1).write(ptr); } unsafe fn get_ptr(&self, index: usize) -> *const T { - S::get_ptr(self, index) + *self.get_ptr_to_meta(index + 1) } pub fn get(&self, index: usize) -> Option<&T> { @@ -341,7 +260,7 @@ impl> Vec { } /// Converts a `Vec` into a `Vec`, given that `T` can be `CoerceUnsized` into `U`. - pub fn unsize(self) -> Vec where for<'a> &'a T: CoerceUnsized<&'a U>, S: Strategy { + pub fn unsize(self) -> Vec where for<'a> &'a T: CoerceUnsized<&'a U> { let new_vec = Vec:: { ptr: self.ptr, len: self.len, @@ -350,15 +269,15 @@ impl> Vec { _phantom: PhantomData, }; - if size_of::<>::Metadata>() > size_of::<>::Metadata>() { - // new meta larger than old meta, must go from back to front + if size_of::>() > size_of::>() { + // new extra larger than old extra, must go from back to front for i in (0..self.len).rev() { let current = unsafe { &*self.get_ptr(i) }; unsafe { new_vec.set_meta_from_ptr(i, current as &U) } } } else { - // new meta smaller or same size as old meta, must go from front to back + // new extra smaller or same size as old extra, must go from front to back for i in 0..self.len { let current = unsafe { &*self.get_ptr(i) };