undo last commit, fix some wording

This commit is contained in:
missing 2022-05-13 08:43:19 -05:00 committed by missing
parent 3c00857465
commit 84332620c0

View file

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