Skip to content

Commit

Permalink
allow empty windows
Browse files Browse the repository at this point in the history
  • Loading branch information
lcnr committed Aug 4, 2021
1 parent 7f3dc04 commit 664584a
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 29 deletions.
31 changes: 15 additions & 16 deletions library/core/src/slice/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ use crate::intrinsics::{assume, exact_div, unchecked_sub};
use crate::iter::{FusedIterator, TrustedLen, TrustedRandomAccess, TrustedRandomAccessNoCoerce};
use crate::marker::{PhantomData, Send, Sized, Sync};
use crate::mem;
use crate::num::NonZeroUsize;
use crate::ptr::NonNull;

use super::{from_raw_parts, from_raw_parts_mut};
Expand Down Expand Up @@ -1193,12 +1192,12 @@ forward_iterator! { RSplitNMut: T, &'a mut [T] }
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Windows<'a, T: 'a> {
v: &'a [T],
size: NonZeroUsize,
size: usize,
}

impl<'a, T: 'a> Windows<'a, T> {
#[inline]
pub(super) fn new(slice: &'a [T], size: NonZeroUsize) -> Self {
pub(super) fn new(slice: &'a [T], size: usize) -> Self {
Self { v: slice, size }
}
}
Expand All @@ -1217,21 +1216,21 @@ impl<'a, T> Iterator for Windows<'a, T> {

#[inline]
fn next(&mut self) -> Option<&'a [T]> {
if self.size.get() > self.v.len() {
if self.size > self.v.len() {
None
} else {
let ret = Some(&self.v[..self.size.get()]);
let ret = Some(&self.v[..self.size]);
self.v = &self.v[1..];
ret
}
}

#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
if self.size.get() > self.v.len() {
if self.size > self.v.len() {
(0, Some(0))
} else {
let size = self.v.len() - self.size.get() + 1;
let size = self.v.len() - self.size + 1;
(size, Some(size))
}
}
Expand All @@ -1243,7 +1242,7 @@ impl<'a, T> Iterator for Windows<'a, T> {

#[inline]
fn nth(&mut self, n: usize) -> Option<Self::Item> {
let (end, overflow) = self.size.get().overflowing_add(n);
let (end, overflow) = self.size.overflowing_add(n);
if end > self.v.len() || overflow {
self.v = &[];
None
Expand All @@ -1256,10 +1255,10 @@ impl<'a, T> Iterator for Windows<'a, T> {

#[inline]
fn last(self) -> Option<Self::Item> {
if self.size.get() > self.v.len() {
if self.size > self.v.len() {
None
} else {
let start = self.v.len() - self.size.get();
let start = self.v.len() - self.size;
Some(&self.v[start..])
}
}
Expand All @@ -1270,18 +1269,18 @@ impl<'a, T> Iterator for Windows<'a, T> {
// which means that `i` cannot overflow an `isize`, and the
// slice created by `from_raw_parts` is a subslice of `self.v`
// thus is guaranteed to be valid for the lifetime `'a` of `self.v`.
unsafe { from_raw_parts(self.v.as_ptr().add(idx), self.size.get()) }
unsafe { from_raw_parts(self.v.as_ptr().add(idx), self.size) }
}
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T> DoubleEndedIterator for Windows<'a, T> {
#[inline]
fn next_back(&mut self) -> Option<&'a [T]> {
if self.size.get() > self.v.len() {
if self.size > self.v.len() {
None
} else {
let ret = Some(&self.v[self.v.len() - self.size.get()..]);
let ret = Some(&self.v[self.v.len() - self.size..]);
self.v = &self.v[..self.v.len() - 1];
ret
}
Expand All @@ -1290,11 +1289,11 @@ impl<'a, T> DoubleEndedIterator for Windows<'a, T> {
#[inline]
fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
let (end, overflow) = self.v.len().overflowing_sub(n);
if end < self.size.get() || overflow {
if end < self.size || overflow {
self.v = &[];
None
} else {
let ret = &self.v[end - self.size.get()..end];
let ret = &self.v[end - self.size..end];
self.v = &self.v[..end - 1];
Some(ret)
}
Expand Down Expand Up @@ -1995,7 +1994,7 @@ pub struct ArrayWindows<'a, T: 'a, const N: usize> {
impl<'a, T: 'a, const N: usize> ArrayWindows<'a, T, N> {
#[inline]
pub(super) fn new(slice: &'a [T]) -> Self {
let num_windows = slice.len().saturating_sub(N - 1);
let num_windows = (slice.len() + 1).saturating_sub(N);
Self { slice_head: slice.as_ptr(), num: num_windows, marker: PhantomData }
}
}
Expand Down
14 changes: 1 addition & 13 deletions library/core/src/slice/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
use crate::cmp::Ordering::{self, Greater, Less};
use crate::marker::Copy;
use crate::mem;
use crate::num::NonZeroUsize;
use crate::ops::{FnMut, Range, RangeBounds};
use crate::option::Option;
use crate::option::Option::{None, Some};
Expand Down Expand Up @@ -725,13 +724,9 @@ impl<T> [T] {
}

/// Returns an iterator over all contiguous windows of length
/// `size`. The windows overlap. If the slice is shorter than
/// `size`. The windows may overlap. If the slice is shorter than
/// `size`, the iterator returns no values.
///
/// # Panics
///
/// Panics if `size` is 0.
///
/// # Examples
///
/// ```
Expand All @@ -753,7 +748,6 @@ impl<T> [T] {
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn windows(&self, size: usize) -> Windows<'_, T> {
let size = NonZeroUsize::new(size).expect("size is zero");
Windows::new(self, size)
}

Expand Down Expand Up @@ -1199,11 +1193,6 @@ impl<T> [T] {
///
/// If `N` is greater than the size of the slice, it will return no windows.
///
/// # Panics
///
/// Panics if `N` is 0. This check will most probably get changed to a compile time
/// error before this method gets stabilized.
///
/// # Examples
///
/// ```
Expand All @@ -1220,7 +1209,6 @@ impl<T> [T] {
#[unstable(feature = "array_windows", issue = "75027")]
#[inline]
pub fn array_windows<const N: usize>(&self) -> ArrayWindows<'_, T, N> {
assert_ne!(N, 0);
ArrayWindows::new(self)
}

Expand Down
20 changes: 20 additions & 0 deletions library/core/tests/slice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -726,6 +726,18 @@ fn test_array_windows_infer() {
assert_eq!(total, 3 + 6 + 9 + 12 + 15);
}

#[test]
fn test_array_windows_zero() {
let v: &[i32] = &[0, 1, 2];
let mut iter = v.array_windows::<0>();

assert_eq!(iter.next(), Some(&[]));
assert_eq!(iter.next(), Some(&[]));
assert_eq!(iter.next(), Some(&[]));
assert_eq!(iter.next(), Some(&[]));
assert_eq!(iter.next(), None);
}

#[test]
fn test_array_windows_count() {
let v: &[i32] = &[0, 1, 2, 3, 4, 5];
Expand All @@ -739,6 +751,10 @@ fn test_array_windows_count() {
let v3: &[i32] = &[];
let c3 = v3.array_windows::<2>();
assert_eq!(c3.count(), 0);

let v4: &[i32] = &[0, 1, 2];
let c4 = c4.array_windows::<0>();
assert_eq!(c4.count(), 4);
}

#[test]
Expand Down Expand Up @@ -1050,6 +1066,10 @@ fn test_windows_count() {
let v3: &[i32] = &[];
let c3 = v3.windows(2);
assert_eq!(c3.count(), 0);

let v4: &[i32] = &[0, 1, 2, 3, 4];
let c4 = v4.windows(0);
assert_eq!(c4.count(), 6);
}

#[test]
Expand Down

0 comments on commit 664584a

Please sign in to comment.