Skip to content

Commit 3c072a1

Browse files
authored
feat: add SoAVec::swap_remove (#36)
1 parent 46795bb commit 3c072a1

File tree

1 file changed

+46
-12
lines changed

1 file changed

+46
-12
lines changed

soavec/src/lib.rs

Lines changed: 46 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -919,14 +919,9 @@ impl<T: SoAble> SoAVec<T> {
919919
/// assert_eq!(v.len(), 2);
920920
/// ```
921921
pub fn remove(&mut self, index: u32) -> Result<T, InsertError> {
922-
#[cold]
923-
fn assert_index() -> IndexOutOfBoundsError {
924-
IndexOutOfBoundsError
925-
}
926-
927922
let len = self.len();
928923
if index >= len {
929-
return Err(assert_index().into());
924+
return Err(IndexOutOfBoundsError.into());
930925
}
931926

932927
let cap = self.buf.capacity();
@@ -984,14 +979,9 @@ impl<T: SoAble> SoAVec<T> {
984979
/// assert_eq!(vec.get(3), Some((&7, &6)));
985980
/// ```
986981
pub fn insert_mut(&mut self, index: u32, element: T) -> Result<T::Mut<'_>, InsertError> {
987-
#[cold]
988-
fn assert_index() -> IndexOutOfBoundsError {
989-
IndexOutOfBoundsError
990-
}
991-
992982
let len = self.len();
993983
if index > len {
994-
return Err(assert_index().into());
984+
return Err(IndexOutOfBoundsError.into());
995985
}
996986

997987
if len == self.capacity() {
@@ -1066,6 +1056,50 @@ impl<T: SoAble> SoAVec<T> {
10661056
unsafe { T::TupleRepr::drop_in_place(T::TupleRepr::get_pointers(ptr, 0, cap), len) };
10671057
}
10681058
}
1059+
1060+
/// Removes an element from the vector and returns it.
1061+
///
1062+
/// The removed element is replaced by the last element of the vector.
1063+
///
1064+
/// This does not preserve ordering of the remaining elements, but is *O*(n_fields).
1065+
/// If you need to preserve the element order, use [`remove`] instead.
1066+
///
1067+
/// [`remove`]: SoAVec::remove
1068+
///
1069+
/// # Examples
1070+
///
1071+
/// ```
1072+
/// use soavec::soavec;
1073+
///
1074+
/// let mut v = soavec![("foo", "foo"), ("bar", "bar"), ("baz", "baz"), ("qux", "qux")].unwrap();
1075+
///
1076+
/// assert_eq!(v.swap_remove(1).unwrap(), ("bar", "bar"));
1077+
/// assert_eq!(v, soavec![("foo", "foo"), ("qux", "qux"), ("baz", "baz")].unwrap());
1078+
///
1079+
/// assert_eq!(v.swap_remove(0).unwrap(), ("foo", "foo"));
1080+
/// assert_eq!(v, soavec![("baz", "baz"), ("qux", "qux")].unwrap());
1081+
/// ```
1082+
pub fn swap_remove(&mut self, index: u32) -> Result<T, IndexOutOfBoundsError> {
1083+
let len = self.len();
1084+
if index >= len {
1085+
return Err(IndexOutOfBoundsError);
1086+
}
1087+
1088+
let ptr = self.buf.as_mut_ptr();
1089+
let cap = self.capacity();
1090+
1091+
unsafe {
1092+
let value = T::from_tuple(T::TupleRepr::read(ptr, index, cap));
1093+
1094+
let src = T::TupleRepr::get_pointers(ptr, len - 1, cap);
1095+
let dst = T::TupleRepr::get_pointers(ptr, index, cap);
1096+
T::TupleRepr::copy(src, dst, 1);
1097+
1098+
self.buf.set_len(len - 1);
1099+
1100+
Ok(value)
1101+
}
1102+
}
10691103
}
10701104

10711105
impl<T: SoAble> Drop for SoAVec<T> {

0 commit comments

Comments
 (0)