// SPDX-License-Identifier: GPL-2.0 //! Extensions to [`Vec`] for fallible allocations. use super::{AllocError, Flags}; use alloc::vec::Vec; /// Extensions to [`Vec`]. pub trait VecExt: Sized { /// Creates a new [`Vec`] instance with at least the given capacity. /// /// # Examples /// /// ``` /// let v = Vec::::with_capacity(20, GFP_KERNEL)?; /// /// assert!(v.capacity() >= 20); /// # Ok::<(), Error>(()) /// ``` fn with_capacity(capacity: usize, flags: Flags) -> Result; /// Appends an element to the back of the [`Vec`] instance. /// /// # Examples /// /// ``` /// let mut v = Vec::new(); /// v.push(1, GFP_KERNEL)?; /// assert_eq!(&v, &[1]); /// /// v.push(2, GFP_KERNEL)?; /// assert_eq!(&v, &[1, 2]); /// # Ok::<(), Error>(()) /// ``` fn push(&mut self, v: T, flags: Flags) -> Result<(), AllocError>; /// Pushes clones of the elements of slice into the [`Vec`] instance. /// /// # Examples /// /// ``` /// let mut v = Vec::new(); /// v.push(1, GFP_KERNEL)?; /// /// v.extend_from_slice(&[20, 30, 40], GFP_KERNEL)?; /// assert_eq!(&v, &[1, 20, 30, 40]); /// /// v.extend_from_slice(&[50, 60], GFP_KERNEL)?; /// assert_eq!(&v, &[1, 20, 30, 40, 50, 60]); /// # Ok::<(), Error>(()) /// ``` fn extend_from_slice(&mut self, other: &[T], flags: Flags) -> Result<(), AllocError> where T: Clone; /// Ensures that the capacity exceeds the length by at least `additional` elements. /// /// # Examples /// /// ``` /// let mut v = Vec::new(); /// v.push(1, GFP_KERNEL)?; /// /// v.reserve(10, GFP_KERNEL)?; /// let cap = v.capacity(); /// assert!(cap >= 10); /// /// v.reserve(10, GFP_KERNEL)?; /// let new_cap = v.capacity(); /// assert_eq!(new_cap, cap); /// /// # Ok::<(), Error>(()) /// ``` fn reserve(&mut self, additional: usize, flags: Flags) -> Result<(), AllocError>; } impl VecExt for Vec { fn with_capacity(capacity: usize, flags: Flags) -> Result { let mut v = Vec::new(); >::reserve(&mut v, capacity, flags)?; Ok(v) } fn push(&mut self, v: T, flags: Flags) -> Result<(), AllocError> { >::reserve(self, 1, flags)?; let s = self.spare_capacity_mut(); s[0].write(v); // SAFETY: We just initialised the first spare entry, so it is safe to increase the length // by 1. We also know that the new length is <= capacity because of the previous call to // `reserve` above. unsafe { self.set_len(self.len() + 1) }; Ok(()) } fn extend_from_slice(&mut self, other: &[T], flags: Flags) -> Result<(), AllocError> where T: Clone, { >::reserve(self, other.len(), flags)?; for (slot, item) in core::iter::zip(self.spare_capacity_mut(), other) { slot.write(item.clone()); } // SAFETY: We just initialised the `other.len()` spare entries, so it is safe to increase // the length by the same amount. We also know that the new length is <= capacity because // of the previous call to `reserve` above. unsafe { self.set_len(self.len() + other.len()) }; Ok(()) } #[cfg(any(test, testlib))] fn reserve(&mut self, additional: usize, _flags: Flags) -> Result<(), AllocError> { Vec::reserve(self, additional); Ok(()) } #[cfg(not(any(test, testlib)))] fn reserve(&mut self, additional: usize, flags: Flags) -> Result<(), AllocError> { let len = self.len(); let cap = self.capacity(); if cap - len >= additional { return Ok(()); } if core::mem::size_of::() == 0 { // The capacity is already `usize::MAX` for SZTs, we can't go higher. return Err(AllocError); } // We know cap is <= `isize::MAX` because `Layout::array` fails if the resulting byte size // is greater than `isize::MAX`. So the multiplication by two won't overflow. let new_cap = core::cmp::max(cap * 2, len.checked_add(additional).ok_or(AllocError)?); let layout = core::alloc::Layout::array::(new_cap).map_err(|_| AllocError)?; let (old_ptr, len, cap) = destructure(self); // We need to make sure that `ptr` is either NULL or comes from a previous call to // `krealloc_aligned`. A `Vec`'s `ptr` value is not guaranteed to be NULL and might be // dangling after being created with `Vec::new`. Instead, we can rely on `Vec`'s capacity // to be zero if no memory has been allocated yet. let ptr = if cap == 0 { core::ptr::null_mut() } else { old_ptr }; // SAFETY: `ptr` is valid because it's either NULL or comes from a previous call to // `krealloc_aligned`. We also verified that the type is not a ZST. let new_ptr = unsafe { super::allocator::krealloc_aligned(ptr.cast(), layout, flags) }; if new_ptr.is_null() { // SAFETY: We are just rebuilding the existing `Vec` with no changes. unsafe { rebuild(self, old_ptr, len, cap) }; Err(AllocError) } else { // SAFETY: `ptr` has been reallocated with the layout for `new_cap` elements. New cap // is greater than `cap`, so it continues to be >= `len`. unsafe { rebuild(self, new_ptr.cast::(), len, new_cap) }; Ok(()) } } } #[cfg(not(any(test, testlib)))] fn destructure(v: &mut Vec) -> (*mut T, usize, usize) { let mut tmp = Vec::new(); core::mem::swap(&mut tmp, v); let mut tmp = core::mem::ManuallyDrop::new(tmp); let len = tmp.len(); let cap = tmp.capacity(); (tmp.as_mut_ptr(), len, cap) } /// Rebuilds a `Vec` from a pointer, length, and capacity. /// /// # Safety /// /// The same as [`Vec::from_raw_parts`]. #[cfg(not(any(test, testlib)))] unsafe fn rebuild(v: &mut Vec, ptr: *mut T, len: usize, cap: usize) { // SAFETY: The safety requirements from this function satisfy those of `from_raw_parts`. let mut tmp = unsafe { Vec::from_raw_parts(ptr, len, cap) }; core::mem::swap(&mut tmp, v); }