From 562ab2de513d3a1e5ee16ae4ec15c493a1264dd4 Mon Sep 17 00:00:00 2001 From: Danilo Krummrich Date: Mon, 8 Jul 2024 19:24:30 +0200 Subject: rust: alloc: kvec: implement `truncate` and `resize` Signed-off-by: Danilo Krummrich --- rust/kernel/alloc/kvec.rs | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/rust/kernel/alloc/kvec.rs b/rust/kernel/alloc/kvec.rs index db58e764db4b..1449f967da15 100644 --- a/rust/kernel/alloc/kvec.rs +++ b/rust/kernel/alloc/kvec.rs @@ -472,6 +472,30 @@ where Ok(()) } + + /// Shortens the vector, keeping the first `len` elements and dropping + /// the rest. + pub fn truncate(&mut self, len: usize) { + // This is safe because: + // + // * the slice passed to `drop_in_place` is valid; the `len > self.len` + // case avoids creating an invalid slice, and + // * the `len` of the vector is shrunk before calling `drop_in_place`, + // such that no value will be dropped twice in case `drop_in_place` + // were to panic once (if it panics twice, the program aborts). + unsafe { + // Note: It's intentional that this is `>` and not `>=`. + // Changing it to `>=` has negative performance + // implications in some cases. See #78884 for more. + if len > self.len() { + return; + } + let remaining_len = self.len() - len; + let s = ptr::slice_from_raw_parts_mut(self.as_mut_ptr().add(len), remaining_len); + self.set_len(len); + ptr::drop_in_place(s); + } + } } impl Vec { @@ -503,6 +527,19 @@ impl Vec { Ok(v) } + + /// Resizes the `KVec` in-place so that `len` is equal to `new_len`. + pub fn resize(&mut self, new_len: usize, value: T, flags: Flags) -> Result<(), AllocError> { + let len = self.len(); + + if new_len > len { + self.extend_with(new_len - len, value, flags) + } else { + self.truncate(new_len); + + Ok(()) + } + } } impl Drop for Vec -- cgit v1.2.3-58-ga151