diff options
author | HampusM <hampus@hampusmat.com> | 2024-08-26 19:29:25 +0200 |
---|---|---|
committer | HampusM <hampus@hampusmat.com> | 2024-08-26 19:29:25 +0200 |
commit | 0f51ae2df6b8101297fce8540cdc51166c34482b (patch) | |
tree | cfda3e8195c46f01211977604166ccaf5ea7c6ef /src | |
parent | 472215a06849919287b1d3f122c64c8e72532d41 (diff) |
feat: add support for containing more than 1 item
Diffstat (limited to 'src')
-rw-r--r-- | src/lib.rs | 98 |
1 files changed, 66 insertions, 32 deletions
@@ -1,4 +1,4 @@ -use std::alloc::{alloc, handle_alloc_error, Layout}; +use std::alloc::{alloc, handle_alloc_error, realloc, Layout}; use std::marker::PhantomData; use std::mem::{forget, needs_drop}; use std::ptr::NonNull; @@ -55,15 +55,13 @@ where pub fn push(&mut self, item: ItemT) { if self.length != 0 { - todo!(); - } + self.reallocate_for_more(1); - let (ptr, fields_arr_byte_offsets, layout) = Self::do_first_alloc(); + self.write_item(self.length - 1, item); + return; + } - self.ptr = ptr; - self.length = 1; - self.field_arr_byte_offsets = fields_arr_byte_offsets; - self.layout = Some(layout); + self.do_first_alloc(); self.write_item(0, item); } @@ -93,7 +91,48 @@ where unsafe { field_ptr.cast().as_ref() } } - fn do_first_alloc() -> (NonNull<u8>, Vec<usize>, Layout) + fn reallocate_for_more(&mut self, item_cnt_inc: usize) + { + let new_length = self.length + item_cnt_inc; + + let layout = &self.layout.unwrap(); + + let (new_layout, new_field_arr_byte_offsets) = Self::create_layout(new_length); + + let Some(new_ptr) = NonNull::new(unsafe { + realloc(self.ptr.as_ptr(), *layout, new_layout.size()) + }) else { + handle_alloc_error(new_layout); + }; + + for (field_index, field_metadata) in + ItemT::iter_field_metadata().enumerate().rev() + { + let old_field_arr_byte_offset = self.field_arr_byte_offsets[field_index]; + let new_field_arr_byte_offset = new_field_arr_byte_offsets[field_index]; + + let old_field_arr_ptr = + unsafe { new_ptr.byte_add(old_field_arr_byte_offset) }; + + let new_field_arr_ptr = + unsafe { new_ptr.byte_add(new_field_arr_byte_offset) }; + + unsafe { + std::ptr::copy( + old_field_arr_ptr.as_ptr(), + new_field_arr_ptr.as_ptr(), + field_metadata.size * self.length, + ); + } + } + + self.ptr = new_ptr; + self.layout = Some(new_layout); + self.length = new_length; + self.field_arr_byte_offsets = new_field_arr_byte_offsets; + } + + fn do_first_alloc(&mut self) { let (layout, field_arr_byte_offsets) = Self::create_layout(1); @@ -101,7 +140,10 @@ where handle_alloc_error(layout); }; - (ptr, field_arr_byte_offsets, layout) + self.ptr = ptr; + self.length = 1; + self.field_arr_byte_offsets = field_arr_byte_offsets; + self.layout = Some(layout); } fn create_layout(length: usize) -> (Layout, Vec<usize>) @@ -110,9 +152,12 @@ where let first_field_metadata = field_metadata_iter.next().unwrap(); - let mut layout = - array_layout(first_field_metadata.size, first_field_metadata.alignment, 1) - .unwrap(); + let mut layout = array_layout( + first_field_metadata.size, + first_field_metadata.alignment, + length, + ) + .unwrap(); let mut field_arr_byte_offsets = Vec::with_capacity(ItemT::FIELD_CNT); @@ -197,7 +242,9 @@ where /// correctly represents fields of the implementor type. pub unsafe trait Item { - type FieldMetadataIter<'a>: Iterator<Item = &'a ItemFieldMetadata>; + type FieldMetadataIter<'a>: Iterator<Item = &'a ItemFieldMetadata> + + DoubleEndedIterator + + ExactSizeIterator; const FIELD_CNT: usize; @@ -322,21 +369,6 @@ mod tests } } - struct FooFieldMetadataIter<'a> - { - iter: std::slice::Iter<'a, ItemFieldMetadata>, - } - - impl<'a> Iterator for FooFieldMetadataIter<'a> - { - type Item = &'a ItemFieldMetadata; - - fn next(&mut self) -> Option<Self::Item> - { - self.iter.next() - } - } - static FOO_FIELD_METADATA: [ItemFieldMetadata; 2] = [ ItemFieldMetadata { offset: offset_of!(Foo, num_a), @@ -352,13 +384,13 @@ mod tests unsafe impl Item for Foo { - type FieldMetadataIter<'a> = FooFieldMetadataIter<'a>; + type FieldMetadataIter<'a> = std::slice::Iter<'a, ItemFieldMetadata>; const FIELD_CNT: usize = 2; fn iter_field_metadata() -> Self::FieldMetadataIter<'static> { - FooFieldMetadataIter { iter: FOO_FIELD_METADATA.iter() } + FOO_FIELD_METADATA.iter() } unsafe fn drop_field_inplace(field_index: usize, field_ptr: *mut u8) @@ -378,7 +410,9 @@ mod tests multi_vec.push(Foo { num_a: 123, num_b: 654 }); - let item = multi_vec.get::<FooFieldNumB>(0); + multi_vec.push(Foo { num_a: 12338, num_b: 191 }); + + let item = multi_vec.get::<FooFieldNumA>(1); println!("yay: {}", *item); } |