about summary refs log tree commit diff
path: root/library/alloc/src
diff options
context:
space:
mode:
authorYuki Okushi <huyuumi.dev@gmail.com>2021-02-10 12:24:22 +0900
committerGitHub <noreply@github.com>2021-02-10 12:24:22 +0900
commite2765f8cbdfce02816aff7bce4c4d41bfea2c5d4 (patch)
tree7b2316579f8ac1d42dfc83b36fc71542217a1cbe /library/alloc/src
parent3f09418cbe0cc598e8b0567626c2c800a09cc9cc (diff)
parent8ff7b75c016af8bebf995f12e7e5b246ad849470 (diff)
downloadrust-e2765f8cbdfce02816aff7bce4c4d41bfea2c5d4.tar.gz
rust-e2765f8cbdfce02816aff7bce4c4d41bfea2c5d4.zip
Rollup merge of #81687 - WaffleLapkin:split_at_spare, r=KodrAus
Make Vec::split_at_spare_mut public

This PR introduces a new method to the public API, under
`vec_split_at_spare` feature gate:

```rust
impl<T, A: Allocator> impl Vec<T, A> {
    pub fn split_at_spare_mut(&mut self) -> (&mut [T], &mut [MaybeUninit<T>]);
}
```

The method returns 2 slices, one slice references the content of the vector,
and the other references the remaining spare capacity.

The method was previously implemented while adding `Vec::extend_from_within` in #79015,
and used to implement `Vec::spare_capacity_mut` (as the later is just a
subset of former one).

See also previous [discussion in `Vec::spare_capacity_mut` tracking issue](https://github.com/rust-lang/rust/issues/75017#issuecomment-770381335).

## Unresolved questions

- [ ] Should we consider changing the name? `split_at_spare_mut` doesn't seem like an intuitive name
- [ ] Should we deprecate `Vec::spare_capacity_mut`? Any usecase of `Vec::spare_capacity_mut` can be replaced with `Vec::split_at_spare_mut` (but not vise-versa)

r? `@KodrAus`
Diffstat (limited to 'library/alloc/src')
-rw-r--r--library/alloc/src/vec/mod.rs54
1 files changed, 53 insertions, 1 deletions
diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs
index ede1601fa33..c7b4c98041b 100644
--- a/library/alloc/src/vec/mod.rs
+++ b/library/alloc/src/vec/mod.rs
@@ -1828,8 +1828,60 @@ impl<T, A: Allocator> Vec<T, A> {
         self.split_at_spare_mut().1
     }
 
+    /// Returns vector content as a slice of `T`, along with the remaining spare
+    /// capacity of the vector as a slice of `MaybeUninit<T>`.
+    ///
+    /// The returned spare capacity slice can be used to fill the vector with data
+    /// (e.g. by reading from a file) before marking the data as initialized using
+    /// the [`set_len`] method.
+    ///
+    /// [`set_len`]: Vec::set_len
+    ///
+    /// Note that this is a low-level API, which should be used with care for
+    /// optimization purposes. If you need to append data to a `Vec`
+    /// you can use [`push`], [`extend`], [`extend_from_slice`],
+    /// [`extend_from_within`], [`insert`], [`append`], [`resize`] or
+    /// [`resize_with`], depending on your exact needs.
+    ///
+    /// [`push`]: Vec::push
+    /// [`extend`]: Vec::extend
+    /// [`extend_from_slice`]: Vec::extend_from_slice
+    /// [`extend_from_within`]: Vec::extend_from_within
+    /// [`insert`]: Vec::insert
+    /// [`append`]: Vec::append
+    /// [`resize`]: Vec::resize
+    /// [`resize_with`]: Vec::resize_with
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(vec_split_at_spare, maybe_uninit_extra)]
+    ///
+    /// let mut v = vec![1, 1, 2];
+    ///
+    /// // Reserve additional space big enough for 10 elements.
+    /// v.reserve(10);
+    ///
+    /// let (init, uninit) = v.split_at_spare_mut();
+    /// let sum = init.iter().copied().sum::<u32>();
+    ///
+    /// // Fill in the next 4 elements.
+    /// uninit[0].write(sum);
+    /// uninit[1].write(sum * 2);
+    /// uninit[2].write(sum * 3);
+    /// uninit[3].write(sum * 4);
+    ///
+    /// // Mark the 4 elements of the vector as being initialized.
+    /// unsafe {
+    ///     let len = v.len();
+    ///     v.set_len(len + 4);
+    /// }
+    ///
+    /// assert_eq!(&v, &[1, 1, 2, 4, 8, 12, 16]);
+    /// ```
+    #[unstable(feature = "vec_split_at_spare", issue = "81944")]
     #[inline]
-    fn split_at_spare_mut(&mut self) -> (&mut [T], &mut [MaybeUninit<T>]) {
+    pub fn split_at_spare_mut(&mut self) -> (&mut [T], &mut [MaybeUninit<T>]) {
         let ptr = self.as_mut_ptr();
 
         // Safety: