From c2c0641444bac053188ff792eaa21c6ce8b2a690 Mon Sep 17 00:00:00 2001 From: Clar Charr Date: Fri, 5 May 2017 14:42:39 -0400 Subject: [PATCH] Add Vec::resize_default. --- src/doc/unstable-book/src/SUMMARY.md | 1 + .../library-features/vec-resize-default.md | 7 + src/libcollections/vec.rs | 128 +++++++++++++----- 3 files changed, 103 insertions(+), 33 deletions(-) create mode 100644 src/doc/unstable-book/src/library-features/vec-resize-default.md diff --git a/src/doc/unstable-book/src/SUMMARY.md b/src/doc/unstable-book/src/SUMMARY.md index 3d9e7c7fd860d..b978ce6b22be3 100644 --- a/src/doc/unstable-book/src/SUMMARY.md +++ b/src/doc/unstable-book/src/SUMMARY.md @@ -217,6 +217,7 @@ - [unique](library-features/unique.md) - [unsize](library-features/unsize.md) - [utf8_error_error_len](library-features/utf8-error-error-len.md) + - [vec_resize_default](library-features/vec-resize-default.md) - [vec_remove_item](library-features/vec-remove-item.md) - [windows_c](library-features/windows-c.md) - [windows_handle](library-features/windows-handle.md) diff --git a/src/doc/unstable-book/src/library-features/vec-resize-default.md b/src/doc/unstable-book/src/library-features/vec-resize-default.md new file mode 100644 index 0000000000000..5803d3215a54b --- /dev/null +++ b/src/doc/unstable-book/src/library-features/vec-resize-default.md @@ -0,0 +1,7 @@ +# `vec_resize_default` + +The tracking issue for this feature is: [#41758] + +[#41758]: https://github.com/rust-lang/rust/issues/41758 + +------------------------ diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index 7ec5c29de6b4b..1cf713290d8e8 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -1220,11 +1220,14 @@ impl Vec { } impl Vec { - /// Resizes the `Vec` in-place so that `len()` is equal to `new_len`. + /// Resizes the `Vec` in-place so that `len` is equal to `new_len`. /// - /// If `new_len` is greater than `len()`, the `Vec` is extended by the + /// If `new_len` is greater than `len`, the `Vec` is extended by the /// difference, with each additional slot filled with `value`. - /// If `new_len` is less than `len()`, the `Vec` is simply truncated. + /// If `new_len` is less than `len`, the `Vec` is simply truncated. + /// + /// This method requires `Clone` to clone the passed value. If you'd + /// rather create a value with `Default` instead, see [`resize_default`]. /// /// # Examples /// @@ -1237,19 +1240,100 @@ impl Vec { /// vec.resize(2, 0); /// assert_eq!(vec, [1, 2]); /// ``` + /// + /// [`resize_default`]: #method.resize_default #[stable(feature = "vec_resize", since = "1.5.0")] pub fn resize(&mut self, new_len: usize, value: T) { let len = self.len(); if new_len > len { - self.extend_with_element(new_len - len, value); + self.extend_with(new_len - len, ExtendElement(value)) + } else { + self.truncate(new_len); + } + } + + /// Clones and appends all elements in a slice to the `Vec`. + /// + /// Iterates over the slice `other`, clones each element, and then appends + /// it to this `Vec`. The `other` vector is traversed in-order. + /// + /// Note that this function is same as `extend` except that it is + /// specialized to work with slices instead. If and when Rust gets + /// specialization this function will likely be deprecated (but still + /// available). + /// + /// # Examples + /// + /// ``` + /// let mut vec = vec![1]; + /// vec.extend_from_slice(&[2, 3, 4]); + /// assert_eq!(vec, [1, 2, 3, 4]); + /// ``` + #[stable(feature = "vec_extend_from_slice", since = "1.6.0")] + pub fn extend_from_slice(&mut self, other: &[T]) { + self.spec_extend(other.iter()) + } +} + +impl Vec { + /// Resizes the `Vec` in-place so that `len` is equal to `new_len`. + /// + /// If `new_len` is greater than `len`, the `Vec` is extended by the + /// difference, with each additional slot filled with `Default::default()`. + /// If `new_len` is less than `len`, the `Vec` is simply truncated. + /// + /// This method uses `Default` to create new values on every push. If + /// you'd rather `Clone` a given value, use [`resize`]. + /// + /// + /// # Examples + /// + /// ``` + /// #![feature(vec_resize_default)] + /// + /// let mut vec = vec![1, 2, 3]; + /// vec.resize_default(5); + /// assert_eq!(vec, [1, 2, 3, 0, 0]); + /// + /// let mut vec = vec![1, 2, 3, 4]; + /// vec.resize_default(2); + /// assert_eq!(vec, [1, 2]); + /// ``` + /// + /// [`resize`]: #method.resize + #[unstable(feature = "vec_resize_default", issue = "41758")] + pub fn resize_default(&mut self, new_len: usize) { + let len = self.len(); + + if new_len > len { + self.extend_with(new_len - len, ExtendDefault); } else { self.truncate(new_len); } } +} - /// Extend the vector by `n` additional clones of `value`. - fn extend_with_element(&mut self, n: usize, value: T) { +// This code generalises `extend_with_{element,default}`. +trait ExtendWith { + fn next(&self) -> T; + fn last(self) -> T; +} + +struct ExtendElement(T); +impl ExtendWith for ExtendElement { + fn next(&self) -> T { self.0.clone() } + fn last(self) -> T { self.0 } +} + +struct ExtendDefault; +impl ExtendWith for ExtendDefault { + fn next(&self) -> T { Default::default() } + fn last(self) -> T { Default::default() } +} +impl Vec { + /// Extend the vector by `n` values, using the given generator. + fn extend_with>(&mut self, n: usize, value: E) { self.reserve(n); unsafe { @@ -1261,43 +1345,21 @@ impl Vec { // Write all elements except the last one for _ in 1..n { - ptr::write(ptr, value.clone()); + ptr::write(ptr, value.next()); ptr = ptr.offset(1); - // Increment the length in every step in case clone() panics + // Increment the length in every step in case next() panics local_len.increment_len(1); } if n > 0 { // We can write the last element directly without cloning needlessly - ptr::write(ptr, value); + ptr::write(ptr, value.last()); local_len.increment_len(1); } // len set by scope guard } } - - /// Clones and appends all elements in a slice to the `Vec`. - /// - /// Iterates over the slice `other`, clones each element, and then appends - /// it to this `Vec`. The `other` vector is traversed in-order. - /// - /// Note that this function is same as `extend` except that it is - /// specialized to work with slices instead. If and when Rust gets - /// specialization this function will likely be deprecated (but still - /// available). - /// - /// # Examples - /// - /// ``` - /// let mut vec = vec![1]; - /// vec.extend_from_slice(&[2, 3, 4]); - /// assert_eq!(vec, [1, 2, 3, 4]); - /// ``` - #[stable(feature = "vec_extend_from_slice", since = "1.6.0")] - pub fn extend_from_slice(&mut self, other: &[T]) { - self.spec_extend(other.iter()) - } } // Set the length of the vec when the `SetLenOnDrop` value goes out of scope. @@ -1389,7 +1451,7 @@ trait SpecFromElem: Sized { impl SpecFromElem for T { default fn from_elem(elem: Self, n: usize) -> Vec { let mut v = Vec::with_capacity(n); - v.extend_with_element(n, elem); + v.extend_with(n, ExtendElement(elem)); v } } @@ -1424,7 +1486,7 @@ macro_rules! impl_spec_from_elem { } } let mut v = Vec::with_capacity(n); - v.extend_with_element(n, elem); + v.extend_with(n, ExtendElement(elem)); v } }