Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 22 additions & 47 deletions library/core/src/slice/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2203,16 +2203,13 @@ unsafe impl<T> Sync for ChunksExactMut<'_, T> where T: Sync {}
#[unstable(feature = "array_windows", issue = "75027")]
#[must_use = "iterators are lazy and do nothing unless consumed"]
pub struct ArrayWindows<'a, T: 'a, const N: usize> {
slice_head: *const T,
num: usize,
marker: PhantomData<&'a [T; N]>,
v: &'a [T],
}

impl<'a, T: 'a, const N: usize> ArrayWindows<'a, T, N> {
#[inline]
pub(super) const fn new(slice: &'a [T]) -> Self {
let num_windows = slice.len().saturating_sub(N - 1);
Self { slice_head: slice.as_ptr(), num: num_windows, marker: PhantomData }
Self { v: slice }
}
}

Expand All @@ -2222,82 +2219,60 @@ impl<'a, T, const N: usize> Iterator for ArrayWindows<'a, T, N> {

#[inline]
fn next(&mut self) -> Option<Self::Item> {
if self.num == 0 {
return None;
let ret = self.v.first_chunk();
if ret.is_some() {
self.v = &self.v[1..];
}
// SAFETY:
// This is safe because it's indexing into a slice guaranteed to be length > N.
let ret = unsafe { &*self.slice_head.cast::<[T; N]>() };
// SAFETY: Guaranteed that there are at least 1 item remaining otherwise
// earlier branch would've been hit
self.slice_head = unsafe { self.slice_head.add(1) };

self.num -= 1;
Some(ret)
ret
}

#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
(self.num, Some(self.num))
let size = self.v.len().saturating_sub(N - 1);
(size, Some(size))
}

#[inline]
fn count(self) -> usize {
self.num
self.len()
}

#[inline]
fn nth(&mut self, n: usize) -> Option<Self::Item> {
if self.num <= n {
self.num = 0;
return None;
}
// SAFETY:
// This is safe because it's indexing into a slice guaranteed to be length > N.
let ret = unsafe { &*self.slice_head.add(n).cast::<[T; N]>() };
// SAFETY: Guaranteed that there are at least n items remaining
self.slice_head = unsafe { self.slice_head.add(n + 1) };

self.num -= n + 1;
Some(ret)
let idx = n.min(self.v.len());
self.v = &self.v[idx..];
self.next()
}

#[inline]
fn last(mut self) -> Option<Self::Item> {
self.nth(self.num.checked_sub(1)?)
fn last(self) -> Option<Self::Item> {
self.v.last_chunk()
}
}

#[unstable(feature = "array_windows", issue = "75027")]
impl<'a, T, const N: usize> DoubleEndedIterator for ArrayWindows<'a, T, N> {
#[inline]
fn next_back(&mut self) -> Option<&'a [T; N]> {
if self.num == 0 {
return None;
let ret = self.v.last_chunk();
if ret.is_some() {
self.v = &self.v[..self.v.len() - 1];
}
// SAFETY: Guaranteed that there are n items remaining, n-1 for 0-indexing.
let ret = unsafe { &*self.slice_head.add(self.num - 1).cast::<[T; N]>() };
self.num -= 1;
Some(ret)
ret
}

#[inline]
fn nth_back(&mut self, n: usize) -> Option<&'a [T; N]> {
if self.num <= n {
self.num = 0;
return None;
}
// SAFETY: Guaranteed that there are n items remaining, n-1 for 0-indexing.
let ret = unsafe { &*self.slice_head.add(self.num - (n + 1)).cast::<[T; N]>() };
self.num -= n + 1;
Some(ret)
let idx = self.v.len().saturating_sub(n);
self.v = &self.v[..idx];
self.next_back()
}
}

#[unstable(feature = "array_windows", issue = "75027")]
impl<T, const N: usize> ExactSizeIterator for ArrayWindows<'_, T, N> {
fn is_empty(&self) -> bool {
self.num == 0
self.v.len() < N
}
}

Expand Down
Loading