summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHampusM <hampus@hampusmat.com>2025-03-30 16:39:16 +0200
committerHampusM <hampus@hampusmat.com>2025-03-30 16:39:16 +0200
commit5c09a140afbf1d6655323301fd89e653d924f881 (patch)
treef180799e25bd9174f13d8da0d28615da7a8e32df
parentb336988d7d5ba3790c9d19ac4befcf5d7ee5aaad (diff)
feat: add swap_remove fn
-rw-r--r--src/lib.rs117
1 files changed, 117 insertions, 0 deletions
diff --git a/src/lib.rs b/src/lib.rs
index 8fd5ee4..007cf82 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -260,6 +260,75 @@ impl MultiVec
Some(item_fields)
}
+ pub fn swap_remove(&mut self, item_index: usize) -> Option<Vec<Field<'static, '_>>>
+ {
+ if item_index >= self.length {
+ return None;
+ }
+
+ let prev_length = self.length;
+
+ self.length -= 1;
+
+ let mut item_fields = Vec::<Field<'static, '_>>::with_capacity(self.field_cnt());
+
+ for field_index in 0..self.field_cnt() {
+ let field_metadata = &self.get_field_metadata()?.get(field_index)?;
+
+ let field_arr_ptr = unsafe { self.ptr.byte_add(field_metadata.array_offset) };
+
+ let bytes = unsafe {
+ std::slice::from_raw_parts_mut(
+ field_arr_ptr.as_ptr().cast(),
+ prev_length * field_metadata.size,
+ )
+ };
+
+ let field_slice = FieldSliceMut {
+ bytes,
+ len: prev_length,
+ field_metadata,
+ };
+
+ let mut item_field_bytes = AnonUnique::new_uninit(
+ Layout::from_size_align(field_metadata.size, field_metadata.alignment)
+ .unwrap(),
+ );
+
+ item_field_bytes.as_slice_mut().copy_from_slice(
+ field_slice
+ .get_item(item_index)
+ .expect("Not possible")
+ .bytes
+ .as_a()
+ .expect("Not possible"),
+ );
+
+ let item_field = Field {
+ bytes: Either::B(item_field_bytes),
+ field_metadata,
+ };
+
+ item_fields.push(item_field);
+
+ let item_field_offset = field_slice
+ .get_item_offset(item_index)
+ .expect("Not possible");
+
+ let last_item_field_offset = field_slice
+ .get_item_offset(prev_length - 1)
+ .expect("Not possible");
+
+ field_slice.bytes.copy_within(
+ last_item_field_offset
+ ..last_item_field_offset + field_slice.field_metadata.size,
+ item_field_offset,
+ );
+ }
+
+ Some(item_fields)
+ }
+
///// Returns a field of the item with the given index.
/////
///// This function is equivalant to doing `.get_all().get(index)`
@@ -1454,6 +1523,54 @@ mod tests
}
#[test]
+ fn swap_remove_in_middle_works()
+ {
+ let mut data;
+ let mut multi_vec = multi_vec_with_data!(
+ data = &mut data,
+ {
+ _a: u32 = [u32::MAX - 3000, 901, 5560000, 123123],
+ _b: u16 = [20210u16, 7120, 1010, 9009],
+ },
+ length = 4
+ );
+
+ let removed = multi_vec.swap_remove(1).expect("Should be Some");
+
+ assert_eq!(&data._a[0..3], [u32::MAX - 3000, 123123, 5560000]);
+ assert_eq!(&data._b[0..3], [20210u16, 9009, 1010]);
+
+ assert_eq!(removed.len(), 2);
+
+ assert_eq!(*removed[0].cast::<u32>(), 901);
+ assert_eq!(*removed[1].cast::<u16>(), 7120);
+ }
+
+ #[test]
+ fn swap_remove_at_end_works()
+ {
+ let mut data;
+ let mut multi_vec = multi_vec_with_data!(
+ data = &mut data,
+ {
+ _a: u32 = [u32::MAX - 3000, 901, 5560000, 123123],
+ _b: u16 = [20210u16, 7120, 1010, 9009],
+ },
+ length = 4
+ );
+
+ let removed = multi_vec.swap_remove(3).expect("Should be Some");
+
+ assert_eq!(&data._a[0..3], [u32::MAX - 3000, 901, 5560000]);
+ assert_eq!(&data._b[0..3], [20210u16, 7120, 1010]);
+
+ assert_eq!(removed.len(), 2);
+
+ assert_eq!(*removed[0].cast::<u32>(), 123123);
+ assert_eq!(*removed[1].cast::<u16>(), 9009);
+ }
+
+ #[test]
fn fields_are_dropped()
{
static THING_DROPPED_CNT: AtomicUsize = AtomicUsize::new(0);