Skip to content

Commit 2f07f8e

Browse files
committed
feat: add insert api
1 parent 8a4c8a0 commit 2f07f8e

1 file changed

Lines changed: 111 additions & 0 deletions

File tree

‎soavec/src/lib.rs‎

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -807,6 +807,82 @@ impl<T: SoAble> SoAVec<T> {
807807
}
808808
}
809809

810+
/// Inserts an element at position `index` within the vector, shifting all
811+
/// elements after it to the right.
812+
///
813+
/// # Panics
814+
///
815+
/// Panics if `index > len`.
816+
///
817+
/// # Examples
818+
///
819+
/// ```
820+
/// use soavec::soavec;
821+
///
822+
/// let mut vec = soavec![('a', 'b'), ('c', 'd')].unwrap();
823+
/// vec.insert(1, ('x', 'y')).unwrap();
824+
/// assert_eq!(vec.len(), 3);
825+
/// ```
826+
pub fn insert(&mut self, index: u32, element: T) -> Result<(), AllocError> {
827+
let _ = self.insert_mut(index, element)?;
828+
829+
Ok(())
830+
}
831+
832+
/// Inserts an element at position `index` within the vector, shifting all
833+
/// elements after it to the right, and returning a reference to the new
834+
/// element.
835+
///
836+
/// # Panics
837+
///
838+
/// Panics if `index > len`.
839+
///
840+
/// # Examples
841+
///
842+
/// ```
843+
/// use soavec::soavec;
844+
///
845+
/// let mut vec = soavec![(1, 1), (3, 3), (5, 5), (7, 7), (9, 9)].unwrap();
846+
/// let (mut x1, _) = vec.insert_mut(3, (6, 6)).unwrap();
847+
/// *x1 += 1;
848+
/// assert_eq!(vec.len(), 6);
849+
/// assert_eq!(vec.get(3), Some((&7, &6)));
850+
/// ```
851+
pub fn insert_mut(&mut self, index: u32, element: T) -> Result<T::Mut<'_>, AllocError> {
852+
let len = self.len();
853+
854+
if index > len {
855+
panic!("insertion index (is {index}) should be <= len (is {len})");
856+
}
857+
858+
if len == self.capacity() {
859+
// Make sure we have space to one more element.
860+
self.buf.reserve(1)?;
861+
}
862+
863+
let ptr = self.buf.as_mut_ptr();
864+
let cap = self.capacity();
865+
866+
unsafe {
867+
if index < len {
868+
// Shift elements to the right.
869+
let src = T::TupleRepr::get_pointers(ptr, index, cap);
870+
let dst = T::TupleRepr::get_pointers(ptr, (index) + 1, cap);
871+
T::TupleRepr::copy(src, dst, len - (index));
872+
}
873+
874+
// Write the new element.
875+
let src = T::into_tuple(element);
876+
T::TupleRepr::write(ptr, src, index, cap);
877+
878+
// Update length.
879+
self.buf.set_len(self.len().unchecked_add(1));
880+
881+
let ptrs = T::TupleRepr::get_pointers(ptr, index, cap);
882+
Ok(T::as_mut(PhantomData, ptrs))
883+
}
884+
}
885+
810886
/// Clears the vector, removing all values.
811887
///
812888
/// Note that this method has no effect on the allocated capacity
@@ -1239,6 +1315,41 @@ mod tests {
12391315
assert_eq!(first.a, &0);
12401316
}
12411317

1318+
#[test]
1319+
fn insert_and_insert_mut() {
1320+
let mut vec = SoAVec::<(u32, u32)>::new();
1321+
vec.push((1, 10)).unwrap();
1322+
vec.push((3, 30)).unwrap();
1323+
1324+
let (first, second) = vec.insert_mut(1, (2, 20)).unwrap();
1325+
*first += 10;
1326+
*second += 5;
1327+
1328+
vec.insert(0, (0, 0)).unwrap();
1329+
1330+
let slice = vec.as_slice();
1331+
assert_eq!(slice.0, &[0, 1, 12, 3]);
1332+
assert_eq!(slice.1, &[0, 10, 25, 30]);
1333+
}
1334+
1335+
#[test]
1336+
fn insert_grows_capacity() {
1337+
let mut vec = SoAVec::<(u32, u32)>::with_capacity(2).unwrap();
1338+
assert_eq!(vec.capacity(), 2);
1339+
1340+
vec.push((1, 10)).unwrap();
1341+
vec.push((2, 20)).unwrap();
1342+
assert_eq!(vec.capacity(), 2);
1343+
1344+
// Should grow capacity.
1345+
vec.insert(1, (3, 30)).unwrap();
1346+
assert!(vec.capacity() >= 3);
1347+
1348+
let slice = vec.as_slice();
1349+
assert_eq!(slice.0, &[1, 3, 2]);
1350+
assert_eq!(slice.1, &[10, 30, 20]);
1351+
}
1352+
12421353
#[test]
12431354
fn basic_usage_with_zst() {
12441355
use soavec_derive::SoAble;

0 commit comments

Comments
 (0)