Skip to content

Commit c7bf5b9

Browse files
Darksonnjannau
authored andcommitted
rust: alloc: add Vec::drain_all
This is like the stdlib method drain, except that it's hard-coded to use the entire vector's range. Rust Binder uses it in the range allocator to take ownership of everything in a vector in a case where reusing the vector is desirable. Implementing `DrainAll` in terms of `slice::IterMut` lets us reuse some nice optimizations in core for the case where T is a ZST. Signed-off-by: Alice Ryhl <[email protected]> Reviewed-by: Greg Kroah-Hartman <[email protected]> Reviewed-by: Benno Lossin <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Danilo Krummrich <[email protected]>
1 parent 4218de6 commit c7bf5b9

File tree

1 file changed

+59
-0
lines changed

1 file changed

+59
-0
lines changed

rust/kernel/alloc/kvec.rs

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -589,6 +589,30 @@ where
589589
unsafe { ptr::drop_in_place(ptr) };
590590
}
591591
}
592+
593+
/// Takes ownership of all items in this vector without consuming the allocation.
594+
///
595+
/// # Examples
596+
///
597+
/// ```
598+
/// let mut v = kernel::kvec![0, 1, 2, 3]?;
599+
///
600+
/// for (i, j) in v.drain_all().enumerate() {
601+
/// assert_eq!(i, j);
602+
/// }
603+
///
604+
/// assert!(v.capacity() >= 4);
605+
/// # Ok::<(), Error>(())
606+
/// ```
607+
pub fn drain_all(&mut self) -> DrainAll<'_, T> {
608+
// SAFETY: This does not underflow the length.
609+
let elems = unsafe { self.dec_len(self.len()) };
610+
// INVARIANT: The first `len` elements of the spare capacity are valid values, and as we
611+
// just set the length to zero, we may transfer ownership to the `DrainAll` object.
612+
DrainAll {
613+
elements: elems.iter_mut(),
614+
}
615+
}
592616
}
593617

594618
impl<T: Clone, A: Allocator> Vec<T, A> {
@@ -1076,3 +1100,38 @@ where
10761100
}
10771101
}
10781102
}
1103+
1104+
/// An iterator that owns all items in a vector, but does not own its allocation.
1105+
///
1106+
/// # Invariants
1107+
///
1108+
/// Every `&mut T` returned by the iterator references a `T` that the iterator may take ownership
1109+
/// of.
1110+
pub struct DrainAll<'vec, T> {
1111+
elements: slice::IterMut<'vec, T>,
1112+
}
1113+
1114+
impl<'vec, T> Iterator for DrainAll<'vec, T> {
1115+
type Item = T;
1116+
1117+
fn next(&mut self) -> Option<T> {
1118+
let elem: *mut T = self.elements.next()?;
1119+
// SAFETY: By the type invariants, we may take ownership of this value.
1120+
Some(unsafe { elem.read() })
1121+
}
1122+
1123+
fn size_hint(&self) -> (usize, Option<usize>) {
1124+
self.elements.size_hint()
1125+
}
1126+
}
1127+
1128+
impl<'vec, T> Drop for DrainAll<'vec, T> {
1129+
fn drop(&mut self) {
1130+
if core::mem::needs_drop::<T>() {
1131+
let iter = core::mem::take(&mut self.elements);
1132+
let ptr: *mut [T] = iter.into_slice();
1133+
// SAFETY: By the type invariants, we own these values so we may destroy them.
1134+
unsafe { ptr::drop_in_place(ptr) };
1135+
}
1136+
}
1137+
}

0 commit comments

Comments
 (0)