diff options
author | HampusM <hampus@hampusmat.com> | 2025-03-30 16:39:16 +0200 |
---|---|---|
committer | HampusM <hampus@hampusmat.com> | 2025-03-30 16:39:16 +0200 |
commit | 5c09a140afbf1d6655323301fd89e653d924f881 (patch) | |
tree | f180799e25bd9174f13d8da0d28615da7a8e32df | |
parent | b336988d7d5ba3790c9d19ac4befcf5d7ee5aaad (diff) |
feat: add swap_remove fn
-rw-r--r-- | src/lib.rs | 117 |
1 files changed, 117 insertions, 0 deletions
@@ -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); |