diff options
| author | Manish Goregaokar <manishsmail@gmail.com> | 2020-07-10 23:26:36 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-07-10 23:26:36 -0700 |
| commit | 2da709ea212871674800c3808e548d756cdca249 (patch) | |
| tree | ebd7d84dffbc08f5fa15c702927aa2702141d26c /src/liballoc | |
| parent | 427ef98bc3ed87190f389bebc64cc76604c0213a (diff) | |
| parent | a1a19cbbe1c17dc03ca689db002181c9bd95f529 (diff) | |
| download | rust-2da709ea212871674800c3808e548d756cdca249.tar.gz rust-2da709ea212871674800c3808e548d756cdca249.zip | |
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.
Diffstat (limited to 'src/liballoc')
| -rw-r--r-- | src/liballoc/collections/vec_deque.rs | 116 | ||||
| -rw-r--r-- | src/liballoc/collections/vec_deque/tests.rs | 59 | ||||
| -rw-r--r-- | src/liballoc/lib.rs | 1 |
3 files changed, 163 insertions, 13 deletions
diff --git a/src/liballoc/collections/vec_deque.rs b/src/liballoc/collections/vec_deque.rs index 15f3a94ca2d..2efb94e8afe 100644 --- a/src/liballoc/collections/vec_deque.rs +++ b/src/liballoc/collections/vec_deque.rs @@ -1084,6 +1084,108 @@ 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 + /// + /// ``` + /// #![feature(deque_range)] + /// + /// use std::collections::VecDeque; + /// + /// let v: VecDeque<_> = vec![1, 2, 3].into_iter().collect(); + /// let range = v.range(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 = "74217")] + 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 + /// + /// ``` + /// #![feature(deque_range)] + /// + /// 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 = "74217")] + 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 +1231,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 diff --git a/src/liballoc/collections/vec_deque/tests.rs b/src/liballoc/collections/vec_deque/tests.rs index 960af4bfda0..e5edfe02a52 100644 --- a/src/liballoc/collections/vec_deque/tests.rs +++ b/src/liballoc/collections/vec_deque/tests.rs @@ -247,6 +247,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 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 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).map(|v| *v).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); diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index 79bfd57a00f..2ec777ac85c 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -89,6 +89,7 @@ #![feature(const_in_array_repeat_expressions)] #![cfg_attr(bootstrap, feature(const_if_match))] #![feature(cow_is_borrowed)] +#![feature(deque_range)] #![feature(dispatch_from_dyn)] #![feature(core_intrinsics)] #![feature(container_error_extra)] |
