Add VecDeque::range* methods

This patch adds `VecDeque::range` and `VecDeque::range_mut` to provide
iterators over a sub-range of a `VecDeque`. This behavior can be
emulated with `skip` and `take`, but directly providing a `Range` is
more ergonomic. This also partially makes up for `VecDeque`'s lack of
`SliceIndex` support.
This commit is contained in:
Jon Gjengset 2020-07-06 10:33:24 -04:00
parent 0c03aee8b8
commit 7fb26938b1
No known key found for this signature in database
GPG Key ID: 3CB1EC545A706318
2 changed files with 158 additions and 13 deletions

View File

@ -1084,6 +1084,104 @@ impl<T> VecDeque<T> {
self.tail == self.head
}
fn range_start_end<R>(&self, range: R) -> (usize, usize)
where
R: RangeBounds<usize>,
{
let len = self.len();
let start = match range.start_bound() {
Included(&n) => n,
Excluded(&n) => n + 1,
Unbounded => 0,
};
let end = match range.end_bound() {
Included(&n) => n + 1,
Excluded(&n) => n,
Unbounded => len,
};
assert!(start <= end, "lower bound was too large");
assert!(end <= len, "upper bound was too large");
(start, end)
}
/// Creates an iterator that covers the specified range in the `VecDeque`.
///
/// # Panics
///
/// Panics if the starting point is greater than the end point or if
/// the end point is greater than the length of the vector.
///
/// # Examples
///
/// ```
/// use std::collections::VecDeque;
///
/// let v: VecDeque<_> = vec![1, 2, 3].into_iter().collect();
/// let range = v.iter_rage(2..).copied().collect::<VecDeque<_>>();
/// assert_eq!(range, [3]);
///
/// // A full range covers all contents
/// let all = v.range(..);
/// assert_eq!(all.len(), 3);
/// ```
#[inline]
#[unstable(feature = "deque_range", issue = "none")]
pub fn range<R>(&self, range: R) -> Iter<'_, T>
where
R: RangeBounds<usize>,
{
let (start, end) = self.range_start_end(range);
let tail = self.wrap_add(self.tail, start);
let head = self.wrap_add(self.tail, end);
Iter {
tail,
head,
// The shared reference we have in &self is maintained in the '_ of Iter.
ring: unsafe { self.buffer_as_slice() },
}
}
/// Creates an iterator that covers the specified mutable range in the `VecDeque`.
///
/// # Panics
///
/// Panics if the starting point is greater than the end point or if
/// the end point is greater than the length of the vector.
///
/// # Examples
///
/// ```
/// use std::collections::VecDeque;
///
/// let mut v: VecDeque<_> = vec![1, 2, 3].into_iter().collect();
/// for v in v.range_mut(2..) {
/// *v *= 2;
/// }
/// assert_eq!(v, vec![1, 2, 6]);
///
/// // A full range covers all contents
/// for v in v.range_mut(..) {
/// *v *= 2;
/// }
/// assert_eq!(v, vec![2, 4, 12]);
/// ```
#[inline]
#[unstable(feature = "deque_range", issue = "none")]
pub fn range_mut<R>(&mut self, range: R) -> IterMut<'_, T>
where
R: RangeBounds<usize>,
{
let (start, end) = self.range_start_end(range);
let tail = self.wrap_add(self.tail, start);
let head = self.wrap_add(self.tail, end);
IterMut {
tail,
head,
// The shared reference we have in &mut self is maintained in the '_ of IterMut.
ring: unsafe { self.buffer_as_mut_slice() },
}
}
/// Creates a draining iterator that removes the specified range in the
/// `VecDeque` and yields the removed items.
///
@ -1129,19 +1227,7 @@ impl<T> VecDeque<T> {
// When finished, the remaining data will be copied back to cover the hole,
// and the head/tail values will be restored correctly.
//
let len = self.len();
let start = match range.start_bound() {
Included(&n) => n,
Excluded(&n) => n + 1,
Unbounded => 0,
};
let end = match range.end_bound() {
Included(&n) => n + 1,
Excluded(&n) => n,
Unbounded => len,
};
assert!(start <= end, "drain lower bound was too large");
assert!(end <= len, "drain upper bound was too large");
let (start, end) = self.range_start_end(range);
// The deque's elements are parted into three segments:
// * self.tail -> drain_tail

View File

@ -246,6 +246,65 @@ fn test_remove() {
}
}
#[test]
fn test_range() {
let mut tester: VecDeque<usize> = VecDeque::with_capacity(7);
let cap = tester.capacity();
for len in 0..=cap {
for tail in 0..=cap {
for start in 0..=len {
for end in drain_start..=len {
tester.tail = tail;
tester.head = tail;
for i in 0..len {
tester.push_back(i);
}
// Check that we iterate over the correct values
let range: VecDeque<_> = tester.range(start..end).copied().collect();
let expected: VecDeque<_> = (start..end).collect();
assert_eq!(range, expected);
}
}
}
}
}
#[test]
fn test_range_mut() {
let mut tester: VecDeque<usize> = VecDeque::with_capacity(7);
let cap = tester.capacity();
for len in 0..=cap {
for tail in 0..=cap {
for start in 0..=len {
for end in drain_start..=len {
tester.tail = tail;
tester.head = tail;
for i in 0..len {
tester.push_back(i);
}
let head_was = tester.head;
let tail_was = tester.tail;
// Check that we iterate over the correct values
let range: VecDeque<_> = tester.range_mut(start..end).copied().collect();
let expected: VecDeque<_> = (start..end).collect();
assert_eq!(range, expected);
// We shouldn't have changed the capacity or made the
// head or tail out of bounds
assert_eq!(tester.capacity(), cap);
assert_eq!(tester.tail, tail_was);
assert_eq!(tester.head, head_was);
}
}
}
}
}
#[test]
fn test_drain() {
let mut tester: VecDeque<usize> = VecDeque::with_capacity(7);