mirror of
https://github.com/Noratrieb/vechonk.git
synced 2026-01-14 16:45:10 +01:00
also store index lol
This commit is contained in:
parent
796c41f2b4
commit
290d3de45c
2 changed files with 34 additions and 18 deletions
48
src/lib.rs
48
src/lib.rs
|
|
@ -41,6 +41,7 @@ use alloc::boxed::Box;
|
||||||
use core::alloc::Layout;
|
use core::alloc::Layout;
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
use core::num::NonZeroUsize;
|
use core::num::NonZeroUsize;
|
||||||
|
use core::ops::Index;
|
||||||
use core::ptr::{NonNull, Pointee};
|
use core::ptr::{NonNull, Pointee};
|
||||||
use core::{mem, ptr};
|
use core::{mem, ptr};
|
||||||
|
|
||||||
|
|
@ -81,9 +82,9 @@ impl<T: ?Sized> Vechonk<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new Vechonk that allocates `capacity` bytes. `capacity` gets shrunken down
|
/// Create a new Vechonk that allocates `capacity` bytes. `capacity` gets shrunken down
|
||||||
/// to the next multiple of the alignment of the metadata of `T`
|
/// to the next multiple of the alignment of usize + metadata of `T`
|
||||||
pub fn with_capacity(capacity: usize) -> Self {
|
pub fn with_capacity(capacity: usize) -> Self {
|
||||||
let capacity = capacity - (capacity % Self::meta_align());
|
let capacity = capacity - (capacity % Self::data_align());
|
||||||
|
|
||||||
let mut vechonk = Self::new();
|
let mut vechonk = Self::new();
|
||||||
|
|
||||||
|
|
@ -98,16 +99,19 @@ impl<T: ?Sized> Vechonk<T> {
|
||||||
vechonk
|
vechonk
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Pushes a new element into the [`Vechonk`]. Does panic (for now) if there is no more capacity
|
||||||
pub fn push(&mut self, element: Box<T>) {
|
pub fn push(&mut self, element: Box<T>) {
|
||||||
let element_size = mem::size_of_val(element.as_ref());
|
let element_size = mem::size_of_val(element.as_ref());
|
||||||
|
|
||||||
let ptr = element.as_ref();
|
let ptr = element.as_ref();
|
||||||
let meta = ptr::metadata(ptr);
|
let meta = ptr::metadata(ptr);
|
||||||
|
|
||||||
let meta_size = Self::meta_size();
|
let data_size = Self::data_size();
|
||||||
|
|
||||||
// just panic here instead of a proper realloc
|
// just panic here instead of a proper realloc
|
||||||
assert!(!self.needs_grow(element_size + meta_size));
|
assert!(!self.needs_grow(element_size + data_size));
|
||||||
|
|
||||||
|
let data: PtrData<T> = (self.len, meta);
|
||||||
|
|
||||||
// SAFETY: none for now
|
// SAFETY: none for now
|
||||||
unsafe {
|
unsafe {
|
||||||
|
|
@ -117,12 +121,12 @@ impl<T: ?Sized> Vechonk<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// SAFETY: none for now
|
// SAFETY: none for now
|
||||||
let meta_ptr = unsafe { self.ptr.as_ptr().add(self.cap - meta_size) };
|
let data_ptr = unsafe { self.ptr.as_ptr().add(self.cap - data_size) };
|
||||||
let meta_ptr = meta_ptr as *mut _;
|
let data_ptr = data_ptr as *mut _;
|
||||||
|
|
||||||
// SAFETY: none for now
|
// SAFETY: none for now
|
||||||
unsafe {
|
unsafe {
|
||||||
*meta_ptr = meta;
|
*data_ptr = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.elem_size += element_size;
|
self.elem_size += element_size;
|
||||||
|
|
@ -136,7 +140,7 @@ impl<T: ?Sized> Vechonk<T> {
|
||||||
/// The caller must either set the `len` to zero, or copy the elements to the new allocation by saving
|
/// The caller must either set the `len` to zero, or copy the elements to the new allocation by saving
|
||||||
/// `self.ptr` before calling this function.
|
/// `self.ptr` before calling this function.
|
||||||
unsafe fn grow_to(&mut self, size: NonZeroUsize) {
|
unsafe fn grow_to(&mut self, size: NonZeroUsize) {
|
||||||
let layout = Layout::from_size_align(size.get(), Self::meta_align()).unwrap();
|
let layout = Layout::from_size_align(size.get(), Self::data_align()).unwrap();
|
||||||
|
|
||||||
// SAFETY: layout is guaranteed to have a non-zero size
|
// SAFETY: layout is guaranteed to have a non-zero size
|
||||||
let alloced_ptr = unsafe { alloc::alloc::alloc(layout) };
|
let alloced_ptr = unsafe { alloc::alloc::alloc(layout) };
|
||||||
|
|
@ -148,23 +152,31 @@ impl<T: ?Sized> Vechonk<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn needs_grow(&self, additional_size: usize) -> bool {
|
fn needs_grow(&self, additional_size: usize) -> bool {
|
||||||
additional_size > self.cap - (self.elem_size + self.meta_section_size())
|
additional_size > self.cap - (self.elem_size + self.data_section_size())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn meta_section_size(&self) -> usize {
|
fn data_section_size(&self) -> usize {
|
||||||
self.len * mem::size_of::<Meta<T>>()
|
self.len * mem::size_of::<PtrData<T>>()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn meta_align() -> usize {
|
fn data_align() -> usize {
|
||||||
mem::align_of::<Meta<T>>()
|
mem::align_of::<PtrData<T>>()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn meta_size() -> usize {
|
fn data_size() -> usize {
|
||||||
mem::size_of::<Meta<T>>()
|
mem::size_of::<PtrData<T>>()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// we can only drop copy for now because destructors 🤮
|
impl<T: ?Sized> Index<usize> for Vechonk<T> {
|
||||||
|
type Output = T;
|
||||||
|
|
||||||
|
fn index(&self, _index: usize) -> &Self::Output {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// don't bother with destructors for now
|
||||||
impl<T: ?Sized> Drop for Vechonk<T> {
|
impl<T: ?Sized> Drop for Vechonk<T> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
if self.cap == 0 {
|
if self.cap == 0 {
|
||||||
|
|
@ -172,7 +184,7 @@ impl<T: ?Sized> Drop for Vechonk<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// SAFETY: 1 is not 0 and a power of two. `size > usize::MAX` must always be true
|
// SAFETY: 1 is not 0 and a power of two. `size > usize::MAX` must always be true
|
||||||
let layout = Layout::from_size_align(self.cap, mem::align_of::<Meta<T>>()).unwrap();
|
let layout = Layout::from_size_align(self.cap, mem::align_of::<PtrData<T>>()).unwrap();
|
||||||
|
|
||||||
unsafe { alloc::alloc::dealloc(self.ptr.as_ptr(), layout) };
|
unsafe { alloc::alloc::dealloc(self.ptr.as_ptr(), layout) };
|
||||||
}
|
}
|
||||||
|
|
@ -184,4 +196,4 @@ impl<T: ?Sized> Default for Vechonk<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type Meta<T> = <T as Pointee>::Metadata;
|
type PtrData<T> = (usize, <T as Pointee>::Metadata);
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,8 @@ fn push_two_sized_elem() {
|
||||||
chonk.push(Box::new(2));
|
chonk.push(Box::new(2));
|
||||||
|
|
||||||
assert_eq!(chonk.len(), 2);
|
assert_eq!(chonk.len(), 2);
|
||||||
|
assert_eq!(chonk.elem_size, 2);
|
||||||
|
assert_eq!(chonk.data_section_size(), 16); // two indecies
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
@ -60,4 +62,6 @@ fn push_two_unsized_elem() {
|
||||||
chonk.push("uwu".into());
|
chonk.push("uwu".into());
|
||||||
|
|
||||||
assert_eq!(chonk.len(), 2);
|
assert_eq!(chonk.len(), 2);
|
||||||
|
assert_eq!(chonk.elem_size, 8);
|
||||||
|
assert_eq!(chonk.data_section_size(), 32); // two indecies + lengths
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue