Skip to content

Commit f6cb45a

Browse files
committed
Auto merge of #79015 - WaffleLapkin:vec_append_from_within, r=KodrAus
add `Vec::extend_from_within` method under `vec_extend_from_within` feature gate Implement <rust-lang/rfcs#2714> ### tl;dr This PR adds a `extend_from_within` method to `Vec` which allows copying elements from a range to the end: ```rust #![feature(vec_extend_from_within)] let mut vec = vec![0, 1, 2, 3, 4]; vec.extend_from_within(2..); assert_eq!(vec, [0, 1, 2, 3, 4, 2, 3, 4]); vec.extend_from_within(..2); assert_eq!(vec, [0, 1, 2, 3, 4, 2, 3, 4, 0, 1]); vec.extend_from_within(4..8); assert_eq!(vec, [0, 1, 2, 3, 4, 2, 3, 4, 0, 1, 4, 2, 3, 4]); ``` ### Implementation notes Originally I've copied `@Shnatsel's` [implementation](https://github.com/WanzenBug/rle-decode-helper/blob/690742a0de158d391b7bde1a0c71cccfdad33ab3/src/lib.rs#L74) with some minor changes to support other ranges: ```rust pub fn append_from_within<R>(&mut self, src: R) where T: Copy, R: RangeBounds<usize>, { let len = self.len(); let Range { start, end } = src.assert_len(len);; let count = end - start; self.reserve(count); unsafe { // This is safe because `reserve()` above succeeded, // so `self.len() + count` did not overflow usize ptr::copy_nonoverlapping( self.get_unchecked(src.start), self.as_mut_ptr().add(len), count, ); self.set_len(len + count); } } ``` But then I've realized that this duplicates most of the code from (private) `Vec::append_elements`, so I've used it instead. Then I've applied `@KodrAus` suggestions from #79015 (comment).
2 parents d60b29d + 125ec78 commit f6cb45a

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_windows)]

library/alloc/src/vec/mod.rs

+109-4
Original file line numberDiff line numberDiff line change
@@ -1825,11 +1825,27 @@ impl<T, A: Allocator> Vec<T, A> {
18251825
#[unstable(feature = "vec_spare_capacity", issue = "75017")]
18261826
#[inline]
18271827
pub fn spare_capacity_mut(&mut self) -> &mut [MaybeUninit<T>] {
1828+
self.split_at_spare_mut().1
1829+
}
1830+
1831+
#[inline]
1832+
fn split_at_spare_mut(&mut self) -> (&mut [T], &mut [MaybeUninit<T>]) {
1833+
let ptr = self.as_mut_ptr();
1834+
1835+
// Safety:
1836+
// - `ptr` is guaranteed to be in bounds for `capacity` elements
1837+
// - `len` is guaranteed to less or equal to `capacity`
1838+
// - `MaybeUninit<T>` has the same layout as `T`
1839+
let spare_ptr = unsafe { ptr.cast::<MaybeUninit<T>>().add(self.len) };
1840+
1841+
// Safety:
1842+
// - `ptr` is guaranteed to be valid for `len` elements
1843+
// - `spare_ptr` is offseted from `ptr` by `len`, so it doesn't overlap `initialized` slice
18281844
unsafe {
1829-
slice::from_raw_parts_mut(
1830-
self.as_mut_ptr().add(self.len) as *mut MaybeUninit<T>,
1831-
self.buf.capacity() - self.len,
1832-
)
1845+
let initialized = slice::from_raw_parts_mut(ptr, self.len);
1846+
let spare = slice::from_raw_parts_mut(spare_ptr, self.buf.capacity() - self.len);
1847+
1848+
(initialized, spare)
18331849
}
18341850
}
18351851
}
@@ -1891,6 +1907,39 @@ impl<T: Clone, A: Allocator> Vec<T, A> {
18911907
pub fn extend_from_slice(&mut self, other: &[T]) {
18921908
self.spec_extend(other.iter())
18931909
}
1910+
1911+
/// Copies elements from `src` range to the end of the vector.
1912+
///
1913+
/// ## Examples
1914+
///
1915+
/// ```
1916+
/// #![feature(vec_extend_from_within)]
1917+
///
1918+
/// let mut vec = vec![0, 1, 2, 3, 4];
1919+
///
1920+
/// vec.extend_from_within(2..);
1921+
/// assert_eq!(vec, [0, 1, 2, 3, 4, 2, 3, 4]);
1922+
///
1923+
/// vec.extend_from_within(..2);
1924+
/// assert_eq!(vec, [0, 1, 2, 3, 4, 2, 3, 4, 0, 1]);
1925+
///
1926+
/// vec.extend_from_within(4..8);
1927+
/// assert_eq!(vec, [0, 1, 2, 3, 4, 2, 3, 4, 0, 1, 4, 2, 3, 4]);
1928+
/// ```
1929+
#[unstable(feature = "vec_extend_from_within", issue = "81656")]
1930+
pub fn extend_from_within<R>(&mut self, src: R)
1931+
where
1932+
R: RangeBounds<usize>,
1933+
{
1934+
let range = src.assert_len(self.len());
1935+
self.reserve(range.len());
1936+
1937+
// SAFETY:
1938+
// - `assert_len` guarantees that the given range is valid for indexing self
1939+
unsafe {
1940+
self.spec_extend_from_within(range);
1941+
}
1942+
}
18941943
}
18951944

18961945
// This code generalizes `extend_with_{element,default}`.
@@ -1998,6 +2047,62 @@ pub fn from_elem_in<T: Clone, A: Allocator>(elem: T, n: usize, alloc: A) -> Vec<
19982047
<T as SpecFromElem>::from_elem(elem, n, alloc)
19992048
}
20002049

2050+
trait ExtendFromWithinSpec {
2051+
/// Safety:
2052+
/// - `src` needs to be valid index
2053+
/// - `self.capacity() - self.len()` must be `>= src.len()`
2054+
unsafe fn spec_extend_from_within(&mut self, src: Range<usize>);
2055+
}
2056+
2057+
impl<T: Clone, A: Allocator> ExtendFromWithinSpec for Vec<T, A> {
2058+
default unsafe fn spec_extend_from_within(&mut self, src: Range<usize>) {
2059+
let initialized = {
2060+
let (this, spare) = self.split_at_spare_mut();
2061+
2062+
// Safety:
2063+
// - caller guaratees that src is a valid index
2064+
let to_clone = unsafe { this.get_unchecked(src) };
2065+
2066+
to_clone.iter().cloned().zip(spare.iter_mut()).map(|(e, s)| s.write(e)).count()
2067+
};
2068+
2069+
// Safety:
2070+
// - elements were just initialized
2071+
unsafe {
2072+
let new_len = self.len() + initialized;
2073+
self.set_len(new_len);
2074+
}
2075+
}
2076+
}
2077+
2078+
impl<T: Copy, A: Allocator> ExtendFromWithinSpec for Vec<T, A> {
2079+
unsafe fn spec_extend_from_within(&mut self, src: Range<usize>) {
2080+
let count = src.len();
2081+
{
2082+
let (init, spare) = self.split_at_spare_mut();
2083+
2084+
// Safety:
2085+
// - caller guaratees that `src` is a valid index
2086+
let source = unsafe { init.get_unchecked(src) };
2087+
2088+
// Safety:
2089+
// - Both pointers are created from unique slice references (`&mut [_]`)
2090+
// so they are valid and do not overlap.
2091+
// - Elements are :Copy so it's OK to to copy them, without doing
2092+
// anything with the original values
2093+
// - `count` is equal to the len of `source`, so source is valid for
2094+
// `count` reads
2095+
// - `.reserve(count)` guarantees that `spare.len() >= count` so spare
2096+
// is valid for `count` writes
2097+
unsafe { ptr::copy_nonoverlapping(source.as_ptr(), spare.as_mut_ptr() as _, count) };
2098+
}
2099+
2100+
// Safety:
2101+
// - The elements were just initialized by `copy_nonoverlapping`
2102+
self.len += count;
2103+
}
2104+
}
2105+
20012106
////////////////////////////////////////////////////////////////////////////////
20022107
// Common trait implementations for Vec
20032108
////////////////////////////////////////////////////////////////////////////////

library/alloc/tests/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#![feature(iter_map_while)]
2020
#![feature(vecdeque_binary_search)]
2121
#![feature(slice_group_by)]
22+
#![feature(vec_extend_from_within)]
2223

2324
use std::collections::hash_map::DefaultHasher;
2425
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)