Skip to content

Commit e4e945e

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 93f54c2 commit e4e945e

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
@@ -455,6 +455,100 @@ where
455455

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

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

0 commit comments

Comments
 (0)