[PATCH 1/6] rust: alloc: add Vec::push_init
Eliot Courtney <[email protected]>
| Newsgroups | dev.linux.lists.nova-gpu,org.freedesktop.lists.dri-devel,org.kernel.vger.linux-kernel,org.kernel.vger.rust-for-linux |
|---|---|
| Message-ID | <[email protected]> |
Add `Vec::push_init` which initializes a new element in place. We can't modify the existing `Vec::push` signature to take an `impl Init<T, E>` without changing its Error type. Signed-off-by: Eliot Courtney <[email protected]> --- rust/kernel/alloc/kvec.rs | 42 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/rust/kernel/alloc/kvec.rs b/rust/kernel/alloc/kvec.rs index c7546b9da4fa..9f6f25d7e218 100644 --- a/rust/kernel/alloc/kvec.rs +++ b/rust/kernel/alloc/kvec.rs @@ -52,7 +52,10 @@ }, // }; -use pin_init::Zeroable; +use pin_init::{ + Init, + Zeroable, // +}; mod errors; pub use self::errors::{InsertError, PushError, RemoveError}; @@ -359,6 +362,43 @@ pub fn push(&mut self, v: T, flags: Flags) -> Result<(), AllocError> { Ok(()) } + /// Appends an element to the back of the [`Vec`] instance by initializing it in place. + /// + /// # Examples + /// + /// ``` + /// struct Element { + /// buf: KVec<u8>, + /// } + /// + /// impl Element { + /// fn new() -> impl Init<Self, Error> { + /// try_init!(Element { + /// buf: KVec::with_capacity(16, GFP_KERNEL)?, + /// }? Error) + /// } + /// } + /// + /// let mut v: KVec<Element> = KVec::new(); + /// v.push_init(Element::new(), GFP_KERNEL)?; + /// assert!(v[0].buf.is_empty()); + /// # Ok::<(), Error>(()) + /// ``` + pub fn push_init<E>(&mut self, init: impl Init<T, E>, flags: Flags) -> Result<(), E> + where + E: From<AllocError>, + { + self.reserve(1, flags)?; + // SAFETY: The call to `reserve` was successful, so there is at least one spare slot; the + // pointer therefore refers to allocated, aligned memory valid for a write of one `T`. + unsafe { init.__init(self.spare_capacity_mut().as_mut_ptr().cast::<T>())? }; + // SAFETY: The call to `__init` returned `Ok`, so the first spare slot now holds an + // initialized `T`. The new length does not exceed the capacity because `reserve` ensured + // the capacity is greater than the length by at least one. + unsafe { self.inc_len(1) }; + Ok(()) + } + /// Appends an element to the back of the [`Vec`] instance without reallocating. /// /// Fails if the vector does not have capacity for the new element. -- 2.55.0