undo last commit, fix some wording
This commit is contained in:
parent
3c00857465
commit
84332620c0
117
src/lib.rs
117
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<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) };
|
||||
|
|
Loading…
Reference in a new issue