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:
parent
0c03aee8b8
commit
7fb26938b1
@ -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
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user