Skip to content

Commit 961ec3d

Browse files
committed
rust: alloc: Vec: Implement .clear()/.truncate()
Imported from https://github.com/rust-lang/rust/blob/1.82.0/library/alloc/src/vec/mod.rs Signed-off-by: Janne Grunau <j@jannau.net>
1 parent 595b1c1 commit 961ec3d

1 file changed

Lines changed: 94 additions & 0 deletions

File tree

rust/kernel/alloc/kvec.rs

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,100 @@ where
452452

453453
Ok(())
454454
}
455+
456+
/// Clears the vector, removing all values.
457+
///
458+
/// Note that this method has no effect on the allocated capacity
459+
/// of the vector.
460+
///
461+
/// # Examples
462+
///
463+
/// ```
464+
/// let mut v = vec![1, 2, 3];
465+
///
466+
/// v.clear();
467+
///
468+
/// assert!(v.is_empty());
469+
/// ```
470+
#[inline]
471+
pub fn clear(&mut self) {
472+
let elems: *mut [T] = self.as_mut_slice();
473+
474+
// SAFETY:
475+
// - `elems` comes directly from `as_mut_slice` and is therefore valid.
476+
// - Setting `self.len` before calling `drop_in_place` means that,
477+
// if an element's `Drop` impl panics, the vector's `Drop` impl will
478+
// do nothing (leaking the rest of the elements) instead of dropping
479+
// some twice.
480+
unsafe {
481+
self.len = 0;
482+
ptr::drop_in_place(elems);
483+
}
484+
}
485+
486+
/// Shortens the vector, keeping the first `len` elements and dropping
487+
/// the rest.
488+
///
489+
/// If `len` is greater or equal to the vector's current length, this has
490+
/// no effect.
491+
///
492+
/// The [`drain`] method can emulate `truncate`, but causes the excess
493+
/// elements to be returned instead of dropped.
494+
///
495+
/// Note that this method has no effect on the allocated capacity
496+
/// of the vector.
497+
///
498+
/// # Examples
499+
///
500+
/// Truncating a five element vector to two elements:
501+
///
502+
/// ```
503+
/// let mut vec = vec![1, 2, 3, 4, 5];
504+
/// vec.truncate(2);
505+
/// assert_eq!(vec, [1, 2]);
506+
/// ```
507+
///
508+
/// No truncation occurs when `len` is greater than the vector's current
509+
/// length:
510+
///
511+
/// ```
512+
/// let mut vec = vec![1, 2, 3];
513+
/// vec.truncate(8);
514+
/// assert_eq!(vec, [1, 2, 3]);
515+
/// ```
516+
///
517+
/// Truncating when `len == 0` is equivalent to calling the [`clear`]
518+
/// method.
519+
///
520+
/// ```
521+
/// let mut vec = vec![1, 2, 3];
522+
/// vec.truncate(0);
523+
/// assert_eq!(vec, []);
524+
/// ```
525+
///
526+
/// [`clear`]: Vec::clear
527+
/// [`drain`]: Vec::drain
528+
pub fn truncate(&mut self, len: usize) {
529+
// This is safe because:
530+
//
531+
// * the slice passed to `drop_in_place` is valid; the `len > self.len`
532+
// case avoids creating an invalid slice, and
533+
// * the `len` of the vector is shrunk before calling `drop_in_place`,
534+
// such that no value will be dropped twice in case `drop_in_place`
535+
// were to panic once (if it panics twice, the program aborts).
536+
unsafe {
537+
// Note: It's intentional that this is `>` and not `>=`.
538+
// Changing it to `>=` has negative performance
539+
// implications in some cases. See #78884 for more.
540+
if len > self.len {
541+
return;
542+
}
543+
let remaining_len = self.len - len;
544+
let s = ptr::slice_from_raw_parts_mut(self.as_mut_ptr().add(len), remaining_len);
545+
self.len = len;
546+
ptr::drop_in_place(s);
547+
}
548+
}
455549
}
456550

457551
impl<T: Clone, A: Allocator> Vec<T, A> {

0 commit comments

Comments
 (0)