mirror of
https://github.com/Noratrieb/vechonk.git
synced 2026-01-14 08:35:10 +01:00
push several elements
This commit is contained in:
parent
dfd35624a1
commit
796c41f2b4
2 changed files with 47 additions and 10 deletions
37
src/lib.rs
37
src/lib.rs
|
|
@ -54,8 +54,8 @@ pub struct Vechonk<T: ?Sized> {
|
||||||
len: usize,
|
len: usize,
|
||||||
/// How much memory the Vechonk owns
|
/// How much memory the Vechonk owns
|
||||||
cap: usize,
|
cap: usize,
|
||||||
/// How much memory has been used already for elements + meta
|
/// How much memory has been used by the elements
|
||||||
filled: usize,
|
elem_size: usize,
|
||||||
_marker: PhantomData<T>,
|
_marker: PhantomData<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -75,7 +75,7 @@ impl<T: ?Sized> Vechonk<T> {
|
||||||
ptr: unsafe { NonNull::new_unchecked(1 as *mut u8) },
|
ptr: unsafe { NonNull::new_unchecked(1 as *mut u8) },
|
||||||
len: 0,
|
len: 0,
|
||||||
cap: 0,
|
cap: 0,
|
||||||
filled: 0,
|
elem_size: 0,
|
||||||
_marker: PhantomData,
|
_marker: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -83,7 +83,7 @@ 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 the metadata of `T`
|
||||||
pub fn with_capacity(capacity: usize) -> Self {
|
pub fn with_capacity(capacity: usize) -> Self {
|
||||||
let capacity = capacity - (capacity % mem::align_of::<Meta<T>>());
|
let capacity = capacity - (capacity % Self::meta_align());
|
||||||
|
|
||||||
let mut vechonk = Self::new();
|
let mut vechonk = Self::new();
|
||||||
|
|
||||||
|
|
@ -99,21 +99,21 @@ impl<T: ?Sized> Vechonk<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn push(&mut self, element: Box<T>) {
|
pub fn push(&mut self, element: Box<T>) {
|
||||||
assert_eq!(self.len, 0, "we only support a single element for now :)");
|
|
||||||
|
|
||||||
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 = mem::size_of::<Meta<T>>();
|
let meta_size = Self::meta_size();
|
||||||
|
|
||||||
// just panic here instead of a proper realloc
|
// just panic here instead of a proper realloc
|
||||||
assert!(element_size + meta_size < self.cap - self.filled);
|
assert!(!self.needs_grow(element_size + meta_size));
|
||||||
|
|
||||||
// SAFETY: none for now
|
// SAFETY: none for now
|
||||||
unsafe {
|
unsafe {
|
||||||
ptr::copy_nonoverlapping(ptr as *const T as *mut u8, self.ptr.as_ptr(), element_size);
|
let target_ptr = self.ptr.as_ptr().add(self.elem_size);
|
||||||
|
|
||||||
|
ptr::copy_nonoverlapping(ptr as *const T as _, target_ptr, element_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
// SAFETY: none for now
|
// SAFETY: none for now
|
||||||
|
|
@ -125,6 +125,7 @@ impl<T: ?Sized> Vechonk<T> {
|
||||||
*meta_ptr = meta;
|
*meta_ptr = meta;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.elem_size += element_size;
|
||||||
self.len += 1;
|
self.len += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -135,7 +136,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(), mem::align_of::<Meta<T>>()).unwrap();
|
let layout = Layout::from_size_align(size.get(), Self::meta_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) };
|
||||||
|
|
@ -145,6 +146,22 @@ impl<T: ?Sized> Vechonk<T> {
|
||||||
|
|
||||||
self.cap = size.get();
|
self.cap = size.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn needs_grow(&self, additional_size: usize) -> bool {
|
||||||
|
additional_size > self.cap - (self.elem_size + self.meta_section_size())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn meta_section_size(&self) -> usize {
|
||||||
|
self.len * mem::size_of::<Meta<T>>()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn meta_align() -> usize {
|
||||||
|
mem::align_of::<Meta<T>>()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn meta_size() -> usize {
|
||||||
|
mem::size_of::<Meta<T>>()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// we can only drop copy for now because destructors 🤮
|
// we can only drop copy for now because destructors 🤮
|
||||||
|
|
|
||||||
20
src/test.rs
20
src/test.rs
|
|
@ -41,3 +41,23 @@ fn push_single_unsized_elem() {
|
||||||
|
|
||||||
assert_eq!(chonk.len(), 1);
|
assert_eq!(chonk.len(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn push_two_sized_elem() {
|
||||||
|
let mut chonk = Vechonk::<u8>::with_capacity(100);
|
||||||
|
|
||||||
|
chonk.push(Box::new(1));
|
||||||
|
chonk.push(Box::new(2));
|
||||||
|
|
||||||
|
assert_eq!(chonk.len(), 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn push_two_unsized_elem() {
|
||||||
|
let mut chonk = Vechonk::<str>::with_capacity(100);
|
||||||
|
|
||||||
|
chonk.push("hello".into());
|
||||||
|
chonk.push("uwu".into());
|
||||||
|
|
||||||
|
assert_eq!(chonk.len(), 2);
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue