Skip to content

Commit 2da709e

Browse files
authored
Rollup merge of #74099 - jonhoo:deque-range, r=dtolnay
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.
2 parents 427ef98 + a1a19cb commit 2da709e

File tree

3 files changed

+163
-13
lines changed

3 files changed

+163
-13
lines changed

src/liballoc/collections/vec_deque.rs

+103-13
Original file line numberDiff line numberDiff line change
@@ -1084,6 +1084,108 @@ 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+
/// #![feature(deque_range)]
1118+
///
1119+
/// use std::collections::VecDeque;
1120+
///
1121+
/// let v: VecDeque<_> = vec![1, 2, 3].into_iter().collect();
1122+
/// let range = v.range(2..).copied().collect::<VecDeque<_>>();
1123+
/// assert_eq!(range, [3]);
1124+
///
1125+
/// // A full range covers all contents
1126+
/// let all = v.range(..);
1127+
/// assert_eq!(all.len(), 3);
1128+
/// ```
1129+
#[inline]
1130+
#[unstable(feature = "deque_range", issue = "74217")]
1131+
pub fn range<R>(&self, range: R) -> Iter<'_, T>
1132+
where
1133+
R: RangeBounds<usize>,
1134+
{
1135+
let (start, end) = self.range_start_end(range);
1136+
let tail = self.wrap_add(self.tail, start);
1137+
let head = self.wrap_add(self.tail, end);
1138+
Iter {
1139+
tail,
1140+
head,
1141+
// The shared reference we have in &self is maintained in the '_ of Iter.
1142+
ring: unsafe { self.buffer_as_slice() },
1143+
}
1144+
}
1145+
1146+
/// Creates an iterator that covers the specified mutable range in the `VecDeque`.
1147+
///
1148+
/// # Panics
1149+
///
1150+
/// Panics if the starting point is greater than the end point or if
1151+
/// the end point is greater than the length of the vector.
1152+
///
1153+
/// # Examples
1154+
///
1155+
/// ```
1156+
/// #![feature(deque_range)]
1157+
///
1158+
/// use std::collections::VecDeque;
1159+
///
1160+
/// let mut v: VecDeque<_> = vec![1, 2, 3].into_iter().collect();
1161+
/// for v in v.range_mut(2..) {
1162+
/// *v *= 2;
1163+
/// }
1164+
/// assert_eq!(v, vec![1, 2, 6]);
1165+
///
1166+
/// // A full range covers all contents
1167+
/// for v in v.range_mut(..) {
1168+
/// *v *= 2;
1169+
/// }
1170+
/// assert_eq!(v, vec![2, 4, 12]);
1171+
/// ```
1172+
#[inline]
1173+
#[unstable(feature = "deque_range", issue = "74217")]
1174+
pub fn range_mut<R>(&mut self, range: R) -> IterMut<'_, T>
1175+
where
1176+
R: RangeBounds<usize>,
1177+
{
1178+
let (start, end) = self.range_start_end(range);
1179+
let tail = self.wrap_add(self.tail, start);
1180+
let head = self.wrap_add(self.tail, end);
1181+
IterMut {
1182+
tail,
1183+
head,
1184+
// The shared reference we have in &mut self is maintained in the '_ of IterMut.
1185+
ring: unsafe { self.buffer_as_mut_slice() },
1186+
}
1187+
}
1188+
10871189
/// Creates a draining iterator that removes the specified range in the
10881190
/// `VecDeque` and yields the removed items.
10891191
///
@@ -1129,19 +1231,7 @@ impl<T> VecDeque<T> {
11291231
// When finished, the remaining data will be copied back to cover the hole,
11301232
// and the head/tail values will be restored correctly.
11311233
//
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");
1234+
let (start, end) = self.range_start_end(range);
11451235

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

src/liballoc/collections/vec_deque/tests.rs

+59
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 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 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).map(|v| *v).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);

src/liballoc/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@
8989
#![feature(const_in_array_repeat_expressions)]
9090
#![cfg_attr(bootstrap, feature(const_if_match))]
9191
#![feature(cow_is_borrowed)]
92+
#![feature(deque_range)]
9293
#![feature(dispatch_from_dyn)]
9394
#![feature(core_intrinsics)]
9495
#![feature(container_error_extra)]

0 commit comments

Comments
 (0)