summaryrefslogtreecommitdiff
path: root/src/lib.rs
diff options
context:
space:
mode:
authorHampusM <hampus@hampusmat.com>2024-08-26 19:29:25 +0200
committerHampusM <hampus@hampusmat.com>2024-08-26 19:29:25 +0200
commit0f51ae2df6b8101297fce8540cdc51166c34482b (patch)
treecfda3e8195c46f01211977604166ccaf5ea7c6ef /src/lib.rs
parent472215a06849919287b1d3f122c64c8e72532d41 (diff)
feat: add support for containing more than 1 item
Diffstat (limited to 'src/lib.rs')
-rw-r--r--src/lib.rs98
1 files changed, 66 insertions, 32 deletions
diff --git a/src/lib.rs b/src/lib.rs
index 998da2e..098d726 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -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);
}