Skip to content

Commit 7fb2693

Browse files
committed
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.
1 parent 0c03aee commit 7fb2693

File tree

2 files changed

+158
-13
lines changed

2 files changed

+158
-13
lines changed

src/liballoc/collections/vec_deque.rs

Lines changed: 99 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1084,6 +1084,104 @@ impl<T> VecDeque<T> {
10841084
self.tail == self.head
10851085
}
10861086

1087+
fn range_start_end<R>(&self, range: R) -> (usize, usize)
1088+
where
1089+
R: RangeBounds<usize>,
1090+
{
1091+
let len = self.len();
1092+
let start = match range.start_bound() {
1093+
Included(&n) => n,
1094+
Excluded(&n) => n + 1,
1095+
Unbounded => 0,
1096+
};
1097+
let end = match range.end_bound() {
1098+
Included(&n) => n + 1,
1099+
Excluded(&n) => n,
1100+
Unbounded => len,
1101+
};
1102+
assert!(start <= end, "lower bound was too large");
1103+
assert!(end <= len, "upper bound was too large");
1104+
(start, end)
1105+
}
1106+
1107+
/// Creates an iterator that covers the specified range in the `VecDeque`.
1108+
///
1109+
/// # Panics
1110+
///
1111+
/// Panics if the starting point is greater than the end point or if
1112+
/// the end point is greater than the length of the vector.
1113+
///
1114+
/// # Examples
1115+
///
1116+
/// ```
1117+
/// use std::collections::VecDeque;
1118+
///
1119+
/// let v: VecDeque<_> = vec![1, 2, 3].into_iter().collect();
1120+
/// let range = v.iter_rage(2..).copied().collect::<VecDeque<_>>();
1121+
/// assert_eq!(range, [3]);
1122+
///
1123+
/// // A full range covers all contents
1124+
/// let all = v.range(..);
1125+
/// assert_eq!(all.len(), 3);
1126+
/// ```
1127+
#[inline]
1128+
#[unstable(feature = "deque_range", issue = "none")]
1129+
pub fn range<R>(&self, range: R) -> Iter<'_, T>
1130+
where
1131+
R: RangeBounds<usize>,
1132+
{
1133+
let (start, end) = self.range_start_end(range);
1134+
let tail = self.wrap_add(self.tail, start);
1135+
let head = self.wrap_add(self.tail, end);
1136+
Iter {
1137+
tail,
1138+
head,
1139+
// The shared reference we have in &self is maintained in the '_ of Iter.
1140+
ring: unsafe { self.buffer_as_slice() },
1141+
}
1142+
}
1143+
1144+
/// Creates an iterator that covers the specified mutable range in the `VecDeque`.
1145+
///
1146+
/// # Panics
1147+
///
1148+
/// Panics if the starting point is greater than the end point or if
1149+
/// the end point is greater than the length of the vector.
1150+
///
1151+
/// # Examples
1152+
///
1153+
/// ```
1154+
/// use std::collections::VecDeque;
1155+
///
1156+
/// let mut v: VecDeque<_> = vec![1, 2, 3].into_iter().collect();
1157+
/// for v in v.range_mut(2..) {
1158+
/// *v *= 2;
1159+
/// }
1160+
/// assert_eq!(v, vec![1, 2, 6]);
1161+
///
1162+
/// // A full range covers all contents
1163+
/// for v in v.range_mut(..) {
1164+
/// *v *= 2;
1165+
/// }
1166+
/// assert_eq!(v, vec![2, 4, 12]);
1167+
/// ```
1168+
#[inline]
1169+
#[unstable(feature = "deque_range", issue = "none")]
1170+
pub fn range_mut<R>(&mut self, range: R) -> IterMut<'_, T>
1171+
where
1172+
R: RangeBounds<usize>,
1173+
{
1174+
let (start, end) = self.range_start_end(range);
1175+
let tail = self.wrap_add(self.tail, start);
1176+
let head = self.wrap_add(self.tail, end);
1177+
IterMut {
1178+
tail,
1179+
head,
1180+
// The shared reference we have in &mut self is maintained in the '_ of IterMut.
1181+
ring: unsafe { self.buffer_as_mut_slice() },
1182+
}
1183+
}
1184+
10871185
/// Creates a draining iterator that removes the specified range in the
10881186
/// `VecDeque` and yields the removed items.
10891187
///
@@ -1129,19 +1227,7 @@ impl<T> VecDeque<T> {
11291227
// When finished, the remaining data will be copied back to cover the hole,
11301228
// and the head/tail values will be restored correctly.
11311229
//
1132-
let len = self.len();
1133-
let start = match range.start_bound() {
1134-
Included(&n) => n,
1135-
Excluded(&n) => n + 1,
1136-
Unbounded => 0,
1137-
};
1138-
let end = match range.end_bound() {
1139-
Included(&n) => n + 1,
1140-
Excluded(&n) => n,
1141-
Unbounded => len,
1142-
};
1143-
assert!(start <= end, "drain lower bound was too large");
1144-
assert!(end <= len, "drain upper bound was too large");
1230+
let (start, end) = self.range_start_end(range);
11451231

11461232
// The deque's elements are parted into three segments:
11471233
// * self.tail -> drain_tail

src/liballoc/collections/vec_deque/tests.rs

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,65 @@ fn test_remove() {
246246
}
247247
}
248248

249+
#[test]
250+
fn test_range() {
251+
let mut tester: VecDeque<usize> = VecDeque::with_capacity(7);
252+
253+
let cap = tester.capacity();
254+
for len in 0..=cap {
255+
for tail in 0..=cap {
256+
for start in 0..=len {
257+
for end in drain_start..=len {
258+
tester.tail = tail;
259+
tester.head = tail;
260+
for i in 0..len {
261+
tester.push_back(i);
262+
}
263+
264+
// Check that we iterate over the correct values
265+
let range: VecDeque<_> = tester.range(start..end).copied().collect();
266+
let expected: VecDeque<_> = (start..end).collect();
267+
assert_eq!(range, expected);
268+
}
269+
}
270+
}
271+
}
272+
}
273+
274+
#[test]
275+
fn test_range_mut() {
276+
let mut tester: VecDeque<usize> = VecDeque::with_capacity(7);
277+
278+
let cap = tester.capacity();
279+
for len in 0..=cap {
280+
for tail in 0..=cap {
281+
for start in 0..=len {
282+
for end in drain_start..=len {
283+
tester.tail = tail;
284+
tester.head = tail;
285+
for i in 0..len {
286+
tester.push_back(i);
287+
}
288+
289+
let head_was = tester.head;
290+
let tail_was = tester.tail;
291+
292+
// Check that we iterate over the correct values
293+
let range: VecDeque<_> = tester.range_mut(start..end).copied().collect();
294+
let expected: VecDeque<_> = (start..end).collect();
295+
assert_eq!(range, expected);
296+
297+
// We shouldn't have changed the capacity or made the
298+
// head or tail out of bounds
299+
assert_eq!(tester.capacity(), cap);
300+
assert_eq!(tester.tail, tail_was);
301+
assert_eq!(tester.head, head_was);
302+
}
303+
}
304+
}
305+
}
306+
}
307+
249308
#[test]
250309
fn test_drain() {
251310
let mut tester: VecDeque<usize> = VecDeque::with_capacity(7);

0 commit comments

Comments
 (0)