From 2d64dd0e562642877377d97a8b75db8f6224a607 Mon Sep 17 00:00:00 2001 From: The8472 Date: Mon, 20 Sep 2021 20:22:14 +0200 Subject: [PATCH 1/2] add Vec::push_within_capacity - fallible, does not allocate --- alloc/src/vec/mod.rs | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/alloc/src/vec/mod.rs b/alloc/src/vec/mod.rs index fa9f2131c..1dccb053f 100644 --- a/alloc/src/vec/mod.rs +++ b/alloc/src/vec/mod.rs @@ -1773,6 +1773,50 @@ impl Vec { } } + /// Appends an element if there is sufficient spare capacity, otherwise the element is returned. + /// + /// Unlike [`push`] method will not reallocate when there's insufficient capacity. + /// The caller should use [`reserve`] or [`try_reserve`] to ensure that there is enough capacity. + /// + /// [`push`]: Vec::push + /// [`reserve`]: Vec::reserve + /// [`try_reserve`]: Vec::try_reserve + /// + /// # Examples + /// + /// A manual, panic-free alternative to FromIterator + /// + /// ``` + /// #![feature(vec_push_within_capacity, try_reserve)] + /// + /// use std::collections::TryReserveError; + /// fn from_iter(iter: impl Iterator) -> Result, TryReserveError> { + /// let mut vec = Vec::new(); + /// for value in iter { + /// if let Err(value) = vec.push_within_capacity(value) { + /// vec.try_reserve(1)?; + /// // this cannot fail, the previous line either returned or added at least 1 free slot + /// let _ = vec.push_within_capacity(value); + /// } + /// } + /// Ok(vec) + /// } + /// # from_iter(0..100).expect("please insert more memory"); + /// ``` + #[inline] + #[unstable(feature = "vec_push_within_capacity", issue = "none")] + pub fn push_within_capacity(&mut self, value: T) -> Result<(), T> { + if self.len == self.buf.capacity() { + return Err(value); + } + unsafe { + let end = self.as_mut_ptr().add(self.len); + ptr::write(end, value); + self.len += 1; + } + Ok(()) + } + /// Removes the last element from a vector and returns it, or [`None`] if it /// is empty. /// From c110dabc49a163cecbdbc5070c3086c7f7be3109 Mon Sep 17 00:00:00 2001 From: The 8472 Date: Sat, 13 Aug 2022 12:58:17 +0200 Subject: [PATCH 2/2] address review comments, add tracking issue --- alloc/src/vec/mod.rs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/alloc/src/vec/mod.rs b/alloc/src/vec/mod.rs index 1dccb053f..f36dfbf30 100644 --- a/alloc/src/vec/mod.rs +++ b/alloc/src/vec/mod.rs @@ -1773,9 +1773,10 @@ impl Vec { } } - /// Appends an element if there is sufficient spare capacity, otherwise the element is returned. + /// Appends an element if there is sufficient spare capacity, otherwise an error is returned + /// with the element. /// - /// Unlike [`push`] method will not reallocate when there's insufficient capacity. + /// Unlike [`push`] this method will not reallocate when there's insufficient capacity. /// The caller should use [`reserve`] or [`try_reserve`] to ensure that there is enough capacity. /// /// [`push`]: Vec::push @@ -1784,13 +1785,13 @@ impl Vec { /// /// # Examples /// - /// A manual, panic-free alternative to FromIterator + /// A manual, panic-free alternative to [`FromIterator`]: /// /// ``` - /// #![feature(vec_push_within_capacity, try_reserve)] + /// #![feature(vec_push_within_capacity)] /// /// use std::collections::TryReserveError; - /// fn from_iter(iter: impl Iterator) -> Result, TryReserveError> { + /// fn from_iter_fallible(iter: impl Iterator) -> Result, TryReserveError> { /// let mut vec = Vec::new(); /// for value in iter { /// if let Err(value) = vec.push_within_capacity(value) { @@ -1801,10 +1802,10 @@ impl Vec { /// } /// Ok(vec) /// } - /// # from_iter(0..100).expect("please insert more memory"); + /// assert_eq!(from_iter_fallible(0..100), Ok(Vec::from_iter(0..100))); /// ``` #[inline] - #[unstable(feature = "vec_push_within_capacity", issue = "none")] + #[unstable(feature = "vec_push_within_capacity", issue = "100486")] pub fn push_within_capacity(&mut self, value: T) -> Result<(), T> { if self.len == self.buf.capacity() { return Err(value);