about summary refs log tree commit diff
diff options
context:
space:
mode:
authorThe8472 <git@infinite-source.de>2021-08-05 00:23:19 +0200
committerThe8472 <git@infinite-source.de>2021-08-05 00:23:19 +0200
commitde91157389c4cf63ee6805e8490d0872fe2a7b33 (patch)
treef60762dee327f1ac1778c801088836c6847b8731
parent6fe0886723c9e08b800c9951f1c6f6a57b2bf22c (diff)
downloadrust-de91157389c4cf63ee6805e8490d0872fe2a7b33.tar.gz
rust-de91157389c4cf63ee6805e8490d0872fe2a7b33.zip
add Box::try_new_zeroed_slice()
Currently there is no API that allows fallible zero-allocation of a Vec.
Vec.try_reserve is not appropriate for this job since it doesn't know
whether it should zero or arbitrary uninitialized memory is fine.

Since Box currently holds most of the zeroing/uninit/slice allocation APIs
it's the best place to add yet another entry into this feature matrix.
-rw-r--r--library/alloc/src/boxed.rs32
1 files changed, 32 insertions, 0 deletions
diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs
index 53bfe02d0e7..e09cc227105 100644
--- a/library/alloc/src/boxed.rs
+++ b/library/alloc/src/boxed.rs
@@ -589,6 +589,38 @@ impl<T> Box<[T]> {
     pub fn new_zeroed_slice(len: usize) -> Box<[mem::MaybeUninit<T>]> {
         unsafe { RawVec::with_capacity_zeroed(len).into_box(len) }
     }
+
+    /// Constructs a new boxed slice with uninitialized contents, with the memory
+    /// being filled with `0` bytes. Returns an error if the allocation fails
+    ///
+    /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and incorrect usage
+    /// of this method.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(allocator_api, new_uninit)]
+    ///
+    /// let values = Box::<[u32]>::try_new_zeroed_slice(3)?;
+    /// let values = unsafe { values.assume_init() };
+    ///
+    /// assert_eq!(*values, [0, 0, 0]);
+    /// # Ok::<(), std::alloc::AllocError>(())
+    /// ```
+    ///
+    /// [zeroed]: mem::MaybeUninit::zeroed
+    #[unstable(feature = "allocator_api", issue = "32838")]
+    #[inline]
+    pub fn try_new_zeroed_slice(len: usize) -> Result<Box<[mem::MaybeUninit<T>]>, AllocError> {
+        unsafe {
+            let layout = match Layout::array::<mem::MaybeUninit<T>>(len) {
+                Ok(l) => l,
+                Err(_) => return Err(AllocError),
+            };
+            let ptr = Global.allocate_zeroed(layout)?;
+            Ok(RawVec::from_raw_parts_in(ptr.as_mut_ptr() as *mut _, len, Global).into_box(len))
+        }
+    }
 }
 
 impl<T, A: Allocator> Box<[T], A> {