Skip to content

Commit d5c2211

Browse files
committedJan 31, 2021
add Vec::extend_from_within method
Implement <rust-lang/rfcs#2714>, changes from the RFC: - Rename the method `append_from_within` => `extend_from_within` - Loose :Copy bound => :Clone - Specialize in case of :Copy This commit also adds `Vec::split_at_spare` private method and use it to implement `Vec::spare_capacity_mut` and `Vec::extend_from_within`. This method returns 2 slices - initialized elements (same as `&mut vec[..]`) and uninitialized but allocated space (same as `vec.spare_capacity_mut()`).
1 parent 95cbcad commit d5c2211

File tree

4 files changed

+181
-4
lines changed

4 files changed

+181
-4
lines changed
 

‎library/alloc/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@
7676
#![cfg_attr(test, feature(test))]
7777
#![cfg_attr(test, feature(new_uninit))]
7878
#![feature(allocator_api)]
79+
#![feature(vec_extend_from_within)]
7980
#![feature(array_chunks)]
8081
#![feature(array_methods)]
8182
#![feature(array_value_iter)]

‎library/alloc/src/vec/mod.rs

+109-4
Original file line numberDiff line numberDiff line change
@@ -1796,11 +1796,27 @@ impl<T, A: Allocator> Vec<T, A> {
17961796
#[unstable(feature = "vec_spare_capacity", issue = "75017")]
17971797
#[inline]
17981798
pub fn spare_capacity_mut(&mut self) -> &mut [MaybeUninit<T>] {
1799+
self.split_at_spare_mut().1
1800+
}
1801+
1802+
#[inline]
1803+
fn split_at_spare_mut(&mut self) -> (&mut [T], &mut [MaybeUninit<T>]) {
1804+
let ptr = self.as_mut_ptr();
1805+
1806+
// Safety:
1807+
// - `ptr` is guaranteed to be in bounds for `capacity` elements
1808+
// - `len` is guaranteed to less or equal to `capacity`
1809+
// - `MaybeUninit<T>` has the same layout as `T`
1810+
let spare_ptr = unsafe { ptr.cast::<MaybeUninit<T>>().add(self.len) };
1811+
1812+
// Safety:
1813+
// - `ptr` is guaranteed to be valid for `len` elements
1814+
// - `spare_ptr` is offseted from `ptr` by `len`, so it doesn't overlap `initialized` slice
17991815
unsafe {
1800-
slice::from_raw_parts_mut(
1801-
self.as_mut_ptr().add(self.len) as *mut MaybeUninit<T>,
1802-
self.buf.capacity() - self.len,
1803-
)
1816+
let initialized = slice::from_raw_parts_mut(ptr, self.len);
1817+
let spare = slice::from_raw_parts_mut(spare_ptr, self.buf.capacity() - self.len);
1818+
1819+
(initialized, spare)
18041820
}
18051821
}
18061822
}
@@ -1862,6 +1878,39 @@ impl<T: Clone, A: Allocator> Vec<T, A> {
18621878
pub fn extend_from_slice(&mut self, other: &[T]) {
18631879
self.spec_extend(other.iter())
18641880
}
1881+
1882+
/// Copies elements from `src` range to the end of the vector.
1883+
///
1884+
/// ## Examples
1885+
///
1886+
/// ```
1887+
/// #![feature(vec_extend_from_within)]
1888+
///
1889+
/// let mut vec = vec![0, 1, 2, 3, 4];
1890+
///
1891+
/// vec.extend_from_within(2..);
1892+
/// assert_eq!(vec, [0, 1, 2, 3, 4, 2, 3, 4]);
1893+
///
1894+
/// vec.extend_from_within(..2);
1895+
/// assert_eq!(vec, [0, 1, 2, 3, 4, 2, 3, 4, 0, 1]);
1896+
///
1897+
/// vec.extend_from_within(4..8);
1898+
/// assert_eq!(vec, [0, 1, 2, 3, 4, 2, 3, 4, 0, 1, 4, 2, 3, 4]);
1899+
/// ```
1900+
#[unstable(feature = "vec_extend_from_within", issue = "none")]
1901+
pub fn extend_from_within<R>(&mut self, src: R)
1902+
where
1903+
R: RangeBounds<usize>,
1904+
{
1905+
let range = src.assert_len(self.len());
1906+
self.reserve(range.len());
1907+
1908+
// SAFETY:
1909+
// - `assert_len` guarantees that the given range is valid for indexing self
1910+
unsafe {
1911+
self.spec_extend_from_within(range);
1912+
}
1913+
}
18651914
}
18661915

18671916
// This code generalizes `extend_with_{element,default}`.
@@ -1969,6 +2018,62 @@ pub fn from_elem_in<T: Clone, A: Allocator>(elem: T, n: usize, alloc: A) -> Vec<
19692018
<T as SpecFromElem>::from_elem(elem, n, alloc)
19702019
}
19712020

2021+
trait ExtendFromWithinSpec {
2022+
/// Safety:
2023+
/// - `src` needs to be valid index
2024+
/// - `self.capacity() - self.len()` must be `>= src.len()`
2025+
unsafe fn spec_extend_from_within(&mut self, src: Range<usize>);
2026+
}
2027+
2028+
impl<T: Clone, A: Allocator> ExtendFromWithinSpec for Vec<T, A> {
2029+
default unsafe fn spec_extend_from_within(&mut self, src: Range<usize>) {
2030+
let initialized = {
2031+
let (this, spare) = self.split_at_spare_mut();
2032+
2033+
// Safety:
2034+
// - caller guaratees that src is a valid index
2035+
let to_clone = unsafe { this.get_unchecked(src) };
2036+
2037+
to_clone.iter().cloned().zip(spare.iter_mut()).map(|(e, s)| s.write(e)).count()
2038+
};
2039+
2040+
// Safety:
2041+
// - elements were just initialized
2042+
unsafe {
2043+
let new_len = self.len() + initialized;
2044+
self.set_len(new_len);
2045+
}
2046+
}
2047+
}
2048+
2049+
impl<T: Copy, A: Allocator> ExtendFromWithinSpec for Vec<T, A> {
2050+
unsafe fn spec_extend_from_within(&mut self, src: Range<usize>) {
2051+
let count = src.len();
2052+
{
2053+
let (init, spare) = self.split_at_spare_mut();
2054+
2055+
// Safety:
2056+
// - caller guaratees that `src` is a valid index
2057+
let source = unsafe { init.get_unchecked(src) };
2058+
2059+
// Safety:
2060+
// - Both pointers are created from unique slice references (`&mut [_]`)
2061+
// so they are valid and do not overlap.
2062+
// - Elements are :Copy so it's OK to to copy them, without doing
2063+
// anything with the original values
2064+
// - `count` is equal to the len of `source`, so source is valid for
2065+
// `count` reads
2066+
// - `.reserve(count)` guarantees that `spare.len() >= count` so spare
2067+
// is valid for `count` writes
2068+
unsafe { ptr::copy_nonoverlapping(source.as_ptr(), spare.as_mut_ptr() as _, count) };
2069+
}
2070+
2071+
// Safety:
2072+
// - The elements were just initialized by `copy_nonoverlapping`
2073+
self.len += count;
2074+
}
2075+
}
2076+
19722077
////////////////////////////////////////////////////////////////////////////////
19732078
// Common trait implementations for Vec
19742079
////////////////////////////////////////////////////////////////////////////////

‎library/alloc/tests/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#![feature(int_bits_const)]
2121
#![feature(vecdeque_binary_search)]
2222
#![feature(slice_group_by)]
23+
#![feature(vec_extend_from_within)]
2324

2425
use std::collections::hash_map::DefaultHasher;
2526
use std::hash::{Hash, Hasher};

‎library/alloc/tests/vec.rs

+70
Original file line numberDiff line numberDiff line change
@@ -1954,3 +1954,73 @@ fn test_vec_swap() {
19541954
assert_eq!(a[0], 42);
19551955
assert_eq!(n, 0);
19561956
}
1957+
1958+
#[test]
1959+
fn test_extend_from_within_spec() {
1960+
#[derive(Copy)]
1961+
struct CopyOnly;
1962+
1963+
impl Clone for CopyOnly {
1964+
fn clone(&self) -> Self {
1965+
panic!("extend_from_within must use specialization on copy");
1966+
}
1967+
}
1968+
1969+
vec![CopyOnly, CopyOnly].extend_from_within(..);
1970+
}
1971+
1972+
#[test]
1973+
fn test_extend_from_within_clone() {
1974+
let mut v = vec![String::from("sssss"), String::from("12334567890"), String::from("c")];
1975+
v.extend_from_within(1..);
1976+
1977+
assert_eq!(v, ["sssss", "12334567890", "c", "12334567890", "c"]);
1978+
}
1979+
1980+
#[test]
1981+
fn test_extend_from_within_complete_rande() {
1982+
let mut v = vec![0, 1, 2, 3];
1983+
v.extend_from_within(..);
1984+
1985+
assert_eq!(v, [0, 1, 2, 3, 0, 1, 2, 3]);
1986+
}
1987+
1988+
#[test]
1989+
fn test_extend_from_within_empty_rande() {
1990+
let mut v = vec![0, 1, 2, 3];
1991+
v.extend_from_within(1..1);
1992+
1993+
assert_eq!(v, [0, 1, 2, 3]);
1994+
}
1995+
1996+
#[test]
1997+
#[should_panic]
1998+
fn test_extend_from_within_out_of_rande() {
1999+
let mut v = vec![0, 1];
2000+
v.extend_from_within(..3);
2001+
}
2002+
2003+
#[test]
2004+
fn test_extend_from_within_zst() {
2005+
let mut v = vec![(); 8];
2006+
v.extend_from_within(3..7);
2007+
2008+
assert_eq!(v, [(); 12]);
2009+
}
2010+
2011+
#[test]
2012+
fn test_extend_from_within_empty_vec() {
2013+
let mut v = Vec::<i32>::new();
2014+
v.extend_from_within(..);
2015+
2016+
assert_eq!(v, []);
2017+
}
2018+
2019+
#[test]
2020+
fn test_extend_from_within() {
2021+
let mut v = vec![String::from("a"), String::from("b"), String::from("c")];
2022+
v.extend_from_within(1..=2);
2023+
v.extend_from_within(..=1);
2024+
2025+
assert_eq!(v, ["a", "b", "c", "b", "c", "a", "b"]);
2026+
}

0 commit comments

Comments
 (0)
Please sign in to comment.