Skip to content

Commit e23c155

Browse files
committed
implement VecDeque extend_front and prepend, add tests
1 parent d85276b commit e23c155

File tree

4 files changed

+222
-1
lines changed

4 files changed

+222
-1
lines changed

library/alloc/src/collections/vec_deque/mod.rs

Lines changed: 83 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ pub use self::iter::Iter;
5252

5353
mod iter;
5454

55-
use self::spec_extend::SpecExtend;
55+
use self::spec_extend::{SpecExtend, SpecExtendFront};
5656

5757
mod spec_extend;
5858

@@ -179,6 +179,21 @@ impl<T, A: Allocator> VecDeque<T, A> {
179179
self.len += 1;
180180
}
181181

182+
/// Prepends an element to the buffer.
183+
///
184+
/// # Safety
185+
///
186+
/// May only be called if `deque.len() < deque.capacity()`
187+
#[inline]
188+
unsafe fn push_front_unchecked(&mut self, element: T) {
189+
self.head = self.wrap_sub(self.head, 1);
190+
// SAFETY: Because of the precondition, it's guaranteed that there is space
191+
// in the logical array before the first element (where self.head is now).
192+
unsafe { self.buffer_write(self.head, element) };
193+
// This can't overflow because `deque.len() < deque.capacity() <= usize::MAX`.
194+
self.len += 1;
195+
}
196+
182197
/// Moves an element out of the buffer
183198
#[inline]
184199
unsafe fn buffer_read(&mut self, off: usize) -> T {
@@ -2122,6 +2137,73 @@ impl<T, A: Allocator> VecDeque<T, A> {
21222137
unsafe { self.buffer_write(self.to_physical_idx(len), value) }
21232138
}
21242139

2140+
/// Prepends all contents of the iterator to the front of the deque.
2141+
/// The order of the contents is preserved.
2142+
///
2143+
/// To get behavior like [`append`][VecDeque::append] where elements are moved
2144+
/// from the other collection to this one, use `self.prepend(other.drain(..))`.
2145+
///
2146+
/// # Examples
2147+
///
2148+
/// ```
2149+
/// #![feature(deque_extend_front)]
2150+
/// use std::collections::VecDeque;
2151+
///
2152+
/// let mut deque = VecDeque::from([4, 5, 6]);
2153+
/// deque.prepend([1, 2, 3]);
2154+
/// assert_eq!(deque, [1, 2, 3, 4, 5, 6]);
2155+
/// ```
2156+
///
2157+
/// Move values between collections like [`append`][VecDeque::append] does but prepend to the front:
2158+
///
2159+
/// ```
2160+
/// #![feature(deque_extend_front)]
2161+
/// use std::collections::VecDeque;
2162+
///
2163+
/// let mut deque1 = VecDeque::from([4, 5, 6]);
2164+
/// let mut deque2 = VecDeque::from([1, 2, 3]);
2165+
/// deque1.prepend(deque2.drain(..));
2166+
/// assert_eq!(deque1, [1, 2, 3, 4, 5, 6]);
2167+
/// assert!(deque2.is_empty());
2168+
/// ```
2169+
#[unstable(feature = "deque_extend_front", issue = "146975")]
2170+
#[track_caller]
2171+
pub fn prepend<I: IntoIterator<Item = T, IntoIter: DoubleEndedIterator>>(&mut self, other: I) {
2172+
self.extend_front(other.into_iter().rev())
2173+
}
2174+
2175+
/// Prepends all contents of the iterator to the front of the deque,
2176+
/// as if [`push_front`][VecDeque::push_front] was called repeatedly with
2177+
/// the values yielded by the iterator.
2178+
///
2179+
/// # Examples
2180+
///
2181+
/// ```
2182+
/// #![feature(deque_extend_front)]
2183+
/// use std::collections::VecDeque;
2184+
///
2185+
/// let mut deque = VecDeque::from([4, 5, 6]);
2186+
/// deque.extend_front([3, 2, 1]);
2187+
/// assert_eq!(deque, [1, 2, 3, 4, 5, 6]);
2188+
/// ```
2189+
///
2190+
/// This behaves like [`push_front`][VecDeque::push_front] was called repeatedly:
2191+
///
2192+
/// ```
2193+
/// use std::collections::VecDeque;
2194+
///
2195+
/// let mut deque = VecDeque::from([4, 5, 6]);
2196+
/// for v in [3, 2, 1] {
2197+
/// deque.push_front(v);
2198+
/// }
2199+
/// assert_eq!(deque, [1, 2, 3, 4, 5, 6]);
2200+
/// ```
2201+
#[unstable(feature = "deque_extend_front", issue = "146975")]
2202+
#[track_caller]
2203+
pub fn extend_front<I: IntoIterator<Item = T>>(&mut self, iter: I) {
2204+
<Self as SpecExtendFront<T, I::IntoIter>>::spec_extend_front(self, iter.into_iter());
2205+
}
2206+
21252207
#[inline]
21262208
fn is_contiguous(&self) -> bool {
21272209
// Do the calculation like this to avoid overflowing if len + head > usize::MAX

library/alloc/src/collections/vec_deque/spec_extend.rs

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
#[cfg(not(test))]
2+
use core::iter::Rev;
13
use core::iter::TrustedLen;
24
use core::slice;
35

@@ -114,3 +116,96 @@ where
114116
}
115117
}
116118
}
119+
120+
// Specialization trait used for VecDeque::extend_front
121+
pub(super) trait SpecExtendFront<T, I> {
122+
#[track_caller]
123+
fn spec_extend_front(&mut self, iter: I);
124+
}
125+
126+
impl<T, I, A: Allocator> SpecExtendFront<T, I> for VecDeque<T, A>
127+
where
128+
I: Iterator<Item = T>,
129+
{
130+
#[track_caller]
131+
default fn spec_extend_front(&mut self, mut iter: I) {
132+
// This function should be the moral equivalent of:
133+
//
134+
// for item in iter {
135+
// self.push_front(item);
136+
// }
137+
138+
while let Some(element) = iter.next() {
139+
let (lower, _) = iter.size_hint();
140+
self.reserve(lower.saturating_add(1));
141+
142+
// SAFETY: We just reserved space for at least one element.
143+
unsafe { self.push_front_unchecked(element) };
144+
145+
// Inner loop to avoid repeatedly calling `reserve`.
146+
while self.len < self.capacity() {
147+
let Some(element) = iter.next() else {
148+
return;
149+
};
150+
// SAFETY: The loop condition guarantees that `self.len() < self.capacity()`.
151+
unsafe { self.push_front_unchecked(element) };
152+
}
153+
}
154+
}
155+
}
156+
157+
#[cfg(not(test))]
158+
impl<T, A: Allocator> SpecExtendFront<T, vec::IntoIter<T>> for VecDeque<T, A> {
159+
#[track_caller]
160+
fn spec_extend_front(&mut self, mut iterator: vec::IntoIter<T>) {
161+
let slice = iterator.as_mut_slice();
162+
slice.reverse();
163+
unsafe { prepend(self, slice) };
164+
iterator.forget_remaining_elements();
165+
}
166+
}
167+
168+
#[cfg(not(test))]
169+
impl<T, A: Allocator> SpecExtendFront<T, Rev<vec::IntoIter<T>>> for VecDeque<T, A> {
170+
#[track_caller]
171+
fn spec_extend_front(&mut self, iterator: Rev<vec::IntoIter<T>>) {
172+
let mut iterator = iterator.into_inner();
173+
unsafe { prepend(self, iterator.as_slice()) };
174+
iterator.forget_remaining_elements();
175+
}
176+
}
177+
178+
// impl<T, A: Allocator> SpecExtendFront<T, Copied<slice::Iter<'_, T>>> for VecDeque<T, A>
179+
// where
180+
// T: Copy,
181+
// {
182+
// #[track_caller]
183+
// fn spec_extend_front(&mut self, _iter: Copied<slice::Iter<'_, T>>) {
184+
// // unsafe { prepend(self, slice) };
185+
// // reverse in place?
186+
// }
187+
// }
188+
189+
// impl<T, A: Allocator> SpecExtendFront<T, Rev<Copied<slice::Iter<'_, T>>>> for VecDeque<T, A>
190+
// where
191+
// T: Copy,
192+
// {
193+
// #[track_caller]
194+
// fn spec_extend_front(&mut self, iter: Rev<Copied<slice::Iter<'_, T>>>) {
195+
// unsafe { prepend(self, iter.into_inner().it.as_slice()) };
196+
// }
197+
// }
198+
199+
/// # Safety
200+
///
201+
/// `slice` will be copied into the deque, make sure to forget the items if `T` is not `Copy`.
202+
#[cfg(not(test))]
203+
unsafe fn prepend<T, A: Allocator>(deque: &mut VecDeque<T, A>, slice: &[T]) {
204+
deque.reserve(slice.len());
205+
206+
unsafe {
207+
deque.head = deque.wrap_sub(deque.head, slice.len());
208+
deque.copy_slice(deque.head, slice);
209+
deque.len += slice.len();
210+
}
211+
}

library/alloc/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@
134134
#![feature(ptr_alignment_type)]
135135
#![feature(ptr_internals)]
136136
#![feature(ptr_metadata)]
137+
#![feature(rev_into_inner)]
137138
#![feature(set_ptr_value)]
138139
#![feature(sized_type_properties)]
139140
#![feature(slice_from_ptr_range)]

library/alloctests/tests/vec_deque.rs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2081,3 +2081,46 @@ fn test_extend_and_prepend_from_within() {
20812081
v.extend_from_within(..);
20822082
assert_eq!(v.iter().map(|s| &**s).collect::<String>(), "123123123123");
20832083
}
2084+
2085+
#[test]
2086+
fn test_extend_front() {
2087+
let mut v = VecDeque::new();
2088+
v.extend_front(0..3);
2089+
assert_eq!(v, [2, 1, 0]);
2090+
v.extend_front(3..6);
2091+
assert_eq!(v, [5, 4, 3, 2, 1, 0]);
2092+
v.prepend([1; 4]);
2093+
assert_eq!(v, [1, 1, 1, 1, 5, 4, 3, 2, 1, 0]);
2094+
2095+
let mut v = VecDeque::with_capacity(8);
2096+
let cap = v.capacity();
2097+
v.extend(0..4);
2098+
v.truncate_front(2);
2099+
v.extend_front(4..8);
2100+
assert_eq!(v.as_slices(), ([7, 6].as_slice(), [5, 4, 2, 3].as_slice()));
2101+
assert_eq!(v.capacity(), cap);
2102+
2103+
let mut v = VecDeque::new();
2104+
v.extend_front([]);
2105+
v.extend_front(None);
2106+
v.extend_front(vec![]);
2107+
v.prepend([]);
2108+
v.prepend(None);
2109+
v.prepend(vec![]);
2110+
assert_eq!(v.capacity(), 0);
2111+
v.extend_front(Some(123));
2112+
assert_eq!(v, [123]);
2113+
}
2114+
2115+
#[test]
2116+
fn test_extend_front_specialization() {
2117+
let mut v = VecDeque::with_capacity(4);
2118+
v.prepend(vec![1, 2, 3]);
2119+
assert_eq!(v, [1, 2, 3]);
2120+
v.pop_front();
2121+
v.prepend((-4..2).collect::<Vec<_>>());
2122+
assert_eq!(v, (-4..=3).collect::<Vec<_>>());
2123+
v.clear();
2124+
v.extend_front(vec![1, 2, 3]);
2125+
assert_eq!(v, [3, 2, 1]);
2126+
}

0 commit comments

Comments
 (0)