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;
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<T: ?Sized>(ptr: *mut T, align: usize) -> *mut T {
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.
///
/// 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>,
len: usize,
capacity: usize,
end_ptr: NonNull<u8>,
_phantom: PhantomData<(*mut S, T)>
_phantom: PhantomData<T>
}
// 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<T> = <T as Pointee>::Metadata;
#[cfg(not(feature = "only_store_meta"))]
type Meta<T> = *const T;
/// The extra data stored at the end of the allocation.
type Extra<T> = *const T;
#[cfg(feature = "only_store_meta")]
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> {
impl<T: ?Sized> Vec<T> {
/// Creates a new, empty `Vec`.
pub fn new() -> Self {
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
// 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::<S::Metadata>();
let new_alloc_size = self.capacity * 2 + size * 2 + size_of::<Extra<T>>();
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.
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::<S::Metadata>();
let needed_space = size_of_val(v) + size_of::<Extra<T>>();
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;
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);
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
///
/// 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()
.wrapping_add(self.capacity)
.cast::<S::Metadata>()
.cast::<Extra<T>>()
.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<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`.
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> {
ptr: self.ptr,
len: self.len,
@ -350,15 +269,15 @@ impl<T: ?Sized, S: Strategy<T>> Vec<T, S> {
_phantom: PhantomData,
};
if size_of::<<S as Strategy<U>>::Metadata>() > size_of::<<S as Strategy<T>>::Metadata>() {
// new meta larger than old meta, must go from back to front
if size_of::<Extra<U>>() > size_of::<Extra<T>>() {
// 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) };