Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
135 changes: 55 additions & 80 deletions library/core/src/slice/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1415,26 +1415,21 @@ impl<'a, T> Iterator for Windows<'a, T> {
#[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() {
None
} else {
let ret = Some(&self.v[self.v.len() - self.size.get()..]);
self.v = &self.v[..self.v.len() - 1];
ret
}
fn next_back(&mut self) -> Option<Self::Item> {
self.nth_back(0)
}

#[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 let Some(end) = self.v.len().checked_sub(n)
&& let Some(start) = end.checked_sub(self.size.get())
{
let res = &self.v[start..end];
self.v = &self.v[..end - 1];
Some(res)
} else {
self.v = &self.v[..0]; // cheaper than &[]
None
} else {
let ret = &self.v[end - self.size.get()..end];
self.v = &self.v[..end - 1];
Some(ret)
}
}
}
Expand Down Expand Up @@ -1537,13 +1532,13 @@ impl<'a, T> Iterator for Chunks<'a, T> {

#[inline]
fn nth(&mut self, n: usize) -> Option<Self::Item> {
let (start, overflow) = n.overflowing_mul(self.chunk_size);
// min(len) makes a wrong start harmless, but enables optimizing this to brachless code
let chunk_start = &self.v[start.min(self.v.len())..];
let (nth, remainder) = chunk_start.split_at(self.chunk_size.min(chunk_start.len()));
if !overflow && start < self.v.len() {
self.v = remainder;
Some(nth)
if let Some(start) = n.checked_mul(self.chunk_size)
&& start < self.v.len()
{
let rest = &self.v[start..];
let (chunk, rest) = rest.split_at(self.chunk_size.min(rest.len()));
self.v = rest;
Some(chunk)
} else {
self.v = &self.v[..0]; // cheaper than &[]
None
Expand Down Expand Up @@ -1613,10 +1608,7 @@ impl<'a, T> DoubleEndedIterator for Chunks<'a, T> {
None
} else {
let start = (len - 1 - n) * self.chunk_size;
let end = match start.checked_add(self.chunk_size) {
Some(res) => cmp::min(self.v.len(), res),
None => self.v.len(),
};
let end = (start + self.chunk_size).min(self.v.len());
let nth_back = &self.v[start..end];
self.v = &self.v[..start];
Some(nth_back)
Expand Down Expand Up @@ -1719,22 +1711,19 @@ impl<'a, T> Iterator for ChunksMut<'a, T> {

#[inline]
fn nth(&mut self, n: usize) -> Option<&'a mut [T]> {
let (start, overflow) = n.overflowing_mul(self.chunk_size);
if start >= self.v.len() || overflow {
if let Some(start) = n.checked_mul(self.chunk_size)
&& start < self.v.len()
{
// SAFETY: `start < self.v.len()` ensures this is in bounds
let (_, rest) = unsafe { self.v.split_at_mut(start) };
// SAFETY: `.min(rest.len()` ensures this is in bounds
let (chunk, rest) = unsafe { rest.split_at_mut(self.chunk_size.min(rest.len())) };
self.v = rest;
// SAFETY: Nothing else points to or will point to the contents of this slice.
Some(unsafe { &mut *chunk })
} else {
self.v = &mut [];
None
} else {
let end = match start.checked_add(self.chunk_size) {
Some(sum) => cmp::min(self.v.len(), sum),
None => self.v.len(),
};
// SAFETY: The self.v contract ensures that any split_at_mut is valid.
let (head, tail) = unsafe { self.v.split_at_mut(end) };
// SAFETY: The self.v contract ensures that any split_at_mut is valid.
let (_, nth) = unsafe { head.split_at_mut(start) };
self.v = tail;
// SAFETY: Nothing else points to or will point to the contents of this slice.
Some(unsafe { &mut *nth })
}
}

Expand Down Expand Up @@ -1909,13 +1898,10 @@ impl<'a, T> Iterator for ChunksExact<'a, T> {

#[inline]
fn next(&mut self) -> Option<&'a [T]> {
if self.v.len() < self.chunk_size {
None
} else {
let (fst, snd) = self.v.split_at(self.chunk_size);
self.v = snd;
Some(fst)
}
self.v.split_at_checked(self.chunk_size).and_then(|(chunk, rest)| {
self.v = rest;
Some(chunk)
})
}

#[inline]
Expand All @@ -1931,14 +1917,14 @@ impl<'a, T> Iterator for ChunksExact<'a, T> {

#[inline]
fn nth(&mut self, n: usize) -> Option<Self::Item> {
let (start, overflow) = n.overflowing_mul(self.chunk_size);
if start >= self.v.len() || overflow {
if let Some(start) = n.checked_mul(self.chunk_size)
&& start < self.v.len()
{
self.v = &self.v[start..];
self.next()
} else {
self.v = &self.v[..0]; // cheaper than &[]
None
} else {
let (_, snd) = self.v.split_at(start);
self.v = snd;
self.next()
}
}

Expand Down Expand Up @@ -2067,15 +2053,13 @@ impl<'a, T> Iterator for ChunksExactMut<'a, T> {

#[inline]
fn next(&mut self) -> Option<&'a mut [T]> {
if self.v.len() < self.chunk_size {
None
} else {
// SAFETY: self.chunk_size is inbounds because we compared above against self.v.len()
let (head, tail) = unsafe { self.v.split_at_mut(self.chunk_size) };
self.v = tail;
// SAFETY: Nothing else points to or will point to the contents of this slice.
Some(unsafe { &mut *head })
}
// SAFETY: we have `&mut self`, so are allowed to temporarily materialize a mut slice
unsafe { crate::slice::from_raw_parts_mut(self.v as *mut T, self.v.len()) }
.split_at_mut_checked(self.chunk_size)
.and_then(|(chunk, rest)| {
self.v = rest;
Some(chunk)
})
}

#[inline]
Expand All @@ -2091,15 +2075,15 @@ impl<'a, T> Iterator for ChunksExactMut<'a, T> {

#[inline]
fn nth(&mut self, n: usize) -> Option<&'a mut [T]> {
let (start, overflow) = n.overflowing_mul(self.chunk_size);
if start >= self.v.len() || overflow {
if let Some(start) = n.checked_mul(self.chunk_size)
&& start < self.v.len()
{
// SAFETY: `start < self.v.len()`
self.v = unsafe { self.v.split_at_mut(start).1 };
self.next()
} else {
self.v = &mut [];
None
} else {
// SAFETY: The self.v contract ensures that any split_at_mut is valid.
let (_, snd) = unsafe { self.v.split_at_mut(start) };
self.v = snd;
self.next()
}
}

Expand Down Expand Up @@ -2393,10 +2377,7 @@ impl<'a, T> Iterator for RChunks<'a, T> {
} else {
// Can't underflow because of the check above
let end = self.v.len() - end;
let start = match end.checked_sub(self.chunk_size) {
Some(sum) => sum,
None => 0,
};
let start = end.saturating_sub(self.chunk_size);
let nth = &self.v[start..end];
self.v = &self.v[0..start];
Some(nth)
Expand All @@ -2416,10 +2397,7 @@ impl<'a, T> Iterator for RChunks<'a, T> {

unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item {
let end = self.v.len() - idx * self.chunk_size;
let start = match end.checked_sub(self.chunk_size) {
None => 0,
Some(start) => start,
};
let start = end.saturating_sub(self.chunk_size);
// SAFETY: mostly identical to `Chunks::__iterator_get_unchecked`.
unsafe { from_raw_parts(self.v.as_ptr().add(start), end - start) }
}
Expand Down Expand Up @@ -2596,10 +2574,7 @@ impl<'a, T> Iterator for RChunksMut<'a, T> {

unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item {
let end = self.v.len() - idx * self.chunk_size;
let start = match end.checked_sub(self.chunk_size) {
None => 0,
Some(start) => start,
};
let start = end.saturating_sub(self.chunk_size);
// SAFETY: see comments for `RChunks::__iterator_get_unchecked` and
// `ChunksMut::__iterator_get_unchecked`, `self.v`.
unsafe { from_raw_parts_mut(self.v.as_mut_ptr().add(start), end - start) }
Expand Down
Loading