Skip to content

Commit a7ee7c8

Browse files
committed
slice iter: more cleanup
1 parent c62abb6 commit a7ee7c8

File tree

2 files changed

+52
-65
lines changed

2 files changed

+52
-65
lines changed

library/core/src/slice/iter.rs

Lines changed: 45 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1415,26 +1415,21 @@ impl<'a, T> Iterator for Windows<'a, T> {
14151415
#[stable(feature = "rust1", since = "1.0.0")]
14161416
impl<'a, T> DoubleEndedIterator for Windows<'a, T> {
14171417
#[inline]
1418-
fn next_back(&mut self) -> Option<&'a [T]> {
1419-
if self.size.get() > self.v.len() {
1420-
None
1421-
} else {
1422-
let ret = Some(&self.v[self.v.len() - self.size.get()..]);
1423-
self.v = &self.v[..self.v.len() - 1];
1424-
ret
1425-
}
1418+
fn next_back(&mut self) -> Option<Self::Item> {
1419+
self.nth_back(0)
14261420
}
14271421

14281422
#[inline]
14291423
fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
1430-
let (end, overflow) = self.v.len().overflowing_sub(n);
1431-
if end < self.size.get() || overflow {
1424+
if let Some(end) = self.v.len().checked_sub(n)
1425+
&& let Some(start) = end.checked_sub(self.size.get())
1426+
{
1427+
let res = &self.v[start..end];
1428+
self.v = &self.v[..end - 1];
1429+
Some(res)
1430+
} else {
14321431
self.v = &self.v[..0]; // cheaper than &[]
14331432
None
1434-
} else {
1435-
let ret = &self.v[end - self.size.get()..end];
1436-
self.v = &self.v[..end - 1];
1437-
Some(ret)
14381433
}
14391434
}
14401435
}
@@ -1523,9 +1518,7 @@ impl<'a, T> Iterator for Chunks<'a, T> {
15231518
if self.v.is_empty() {
15241519
(0, Some(0))
15251520
} else {
1526-
let n = self.v.len() / self.chunk_size;
1527-
let rem = self.v.len() % self.chunk_size;
1528-
let n = if rem > 0 { n + 1 } else { n };
1521+
let n = self.v.len().div_ceil(self.chunk_size);
15291522
(n, Some(n))
15301523
}
15311524
}
@@ -1613,7 +1606,7 @@ impl<'a, T> DoubleEndedIterator for Chunks<'a, T> {
16131606
None
16141607
} else {
16151608
let start = (len - 1 - n) * self.chunk_size;
1616-
let end = (start + self.chunk_size).min(self.v.len());
1609+
let end = start + (self.v.len() - start).min(self.chunk_size);
16171610
let nth_back = &self.v[start..end];
16181611
self.v = &self.v[..start];
16191612
Some(nth_back)
@@ -1702,9 +1695,7 @@ impl<'a, T> Iterator for ChunksMut<'a, T> {
17021695
if self.v.is_empty() {
17031696
(0, Some(0))
17041697
} else {
1705-
let n = self.v.len() / self.chunk_size;
1706-
let rem = self.v.len() % self.chunk_size;
1707-
let n = if rem > 0 { n + 1 } else { n };
1698+
let n = self.v.len().div_ceil(self.chunk_size);
17081699
(n, Some(n))
17091700
}
17101701
}
@@ -1903,13 +1894,10 @@ impl<'a, T> Iterator for ChunksExact<'a, T> {
19031894

19041895
#[inline]
19051896
fn next(&mut self) -> Option<&'a [T]> {
1906-
if self.v.len() < self.chunk_size {
1907-
None
1908-
} else {
1909-
let (fst, snd) = self.v.split_at(self.chunk_size);
1910-
self.v = snd;
1911-
Some(fst)
1912-
}
1897+
self.v.split_at_checked(self.chunk_size).and_then(|(chunk, rest)| {
1898+
self.v = rest;
1899+
Some(chunk)
1900+
})
19131901
}
19141902

19151903
#[inline]
@@ -1925,14 +1913,14 @@ impl<'a, T> Iterator for ChunksExact<'a, T> {
19251913

19261914
#[inline]
19271915
fn nth(&mut self, n: usize) -> Option<Self::Item> {
1928-
let (start, overflow) = n.overflowing_mul(self.chunk_size);
1929-
if start >= self.v.len() || overflow {
1916+
if let Some(start) = n.checked_mul(self.chunk_size)
1917+
&& start < self.v.len()
1918+
{
1919+
self.v = &self.v[start..];
1920+
self.next()
1921+
} else {
19301922
self.v = &self.v[..0]; // cheaper than &[]
19311923
None
1932-
} else {
1933-
let (_, snd) = self.v.split_at(start);
1934-
self.v = snd;
1935-
self.next()
19361924
}
19371925
}
19381926

@@ -2061,15 +2049,11 @@ impl<'a, T> Iterator for ChunksExactMut<'a, T> {
20612049

20622050
#[inline]
20632051
fn next(&mut self) -> Option<&'a mut [T]> {
2064-
if self.v.len() < self.chunk_size {
2065-
None
2066-
} else {
2067-
// SAFETY: self.chunk_size is inbounds because we compared above against self.v.len()
2068-
let (head, tail) = unsafe { self.v.split_at_mut(self.chunk_size) };
2069-
self.v = tail;
2070-
// SAFETY: Nothing else points to or will point to the contents of this slice.
2071-
Some(unsafe { &mut *head })
2072-
}
2052+
// SAFETY: we have `&mut self`, so are allowed to temporarily materialize a mut slice
2053+
unsafe { &mut *self.v }.split_at_mut_checked(self.chunk_size).and_then(|(chunk, rest)| {
2054+
self.v = rest;
2055+
Some(chunk)
2056+
})
20732057
}
20742058

20752059
#[inline]
@@ -2085,15 +2069,15 @@ impl<'a, T> Iterator for ChunksExactMut<'a, T> {
20852069

20862070
#[inline]
20872071
fn nth(&mut self, n: usize) -> Option<&'a mut [T]> {
2088-
let (start, overflow) = n.overflowing_mul(self.chunk_size);
2089-
if start >= self.v.len() || overflow {
2072+
if let Some(start) = n.checked_mul(self.chunk_size)
2073+
&& start < self.v.len()
2074+
{
2075+
// SAFETY: `start < self.v.len()`
2076+
self.v = unsafe { self.v.split_at_mut(start).1 };
2077+
self.next()
2078+
} else {
20902079
self.v = &mut [];
20912080
None
2092-
} else {
2093-
// SAFETY: The self.v contract ensures that any split_at_mut is valid.
2094-
let (_, snd) = unsafe { self.v.split_at_mut(start) };
2095-
self.v = snd;
2096-
self.next()
20972081
}
20982082
}
20992083

@@ -2341,9 +2325,7 @@ impl<'a, T> Iterator for RChunks<'a, T> {
23412325
if self.v.is_empty() {
23422326
(0, Some(0))
23432327
} else {
2344-
let n = self.v.len() / self.chunk_size;
2345-
let rem = self.v.len() % self.chunk_size;
2346-
let n = if rem > 0 { n + 1 } else { n };
2328+
let n = self.v.len().div_ceil(self.chunk_size);
23472329
(n, Some(n))
23482330
}
23492331
}
@@ -2355,17 +2337,17 @@ impl<'a, T> Iterator for RChunks<'a, T> {
23552337

23562338
#[inline]
23572339
fn nth(&mut self, n: usize) -> Option<Self::Item> {
2358-
let (end, overflow) = n.overflowing_mul(self.chunk_size);
2359-
if end >= self.v.len() || overflow {
2340+
if let Some(end) = n.checked_mul(self.chunk_size)
2341+
&& end < self.v.len()
2342+
{
2343+
let end = self.v.len() - end;
2344+
let rest = &self.v[..end];
2345+
let (rest, chunk) = rest.split_at(end.saturating_sub(self.chunk_size));
2346+
self.v = rest;
2347+
Some(chunk)
2348+
} else {
23602349
self.v = &self.v[..0]; // cheaper than &[]
23612350
None
2362-
} else {
2363-
// Can't underflow because of the check above
2364-
let end = self.v.len() - end;
2365-
let start = end.saturating_sub(self.chunk_size);
2366-
let nth = &self.v[start..end];
2367-
self.v = &self.v[0..start];
2368-
Some(nth)
23692351
}
23702352
}
23712353

@@ -2508,9 +2490,7 @@ impl<'a, T> Iterator for RChunksMut<'a, T> {
25082490
if self.v.is_empty() {
25092491
(0, Some(0))
25102492
} else {
2511-
let n = self.v.len() / self.chunk_size;
2512-
let rem = self.v.len() % self.chunk_size;
2513-
let n = if rem > 0 { n + 1 } else { n };
2493+
let n = self.v.len().div_ceil(self.chunk_size);
25142494
(n, Some(n))
25152495
}
25162496
}

library/coretests/tests/slice.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,13 @@ fn test_chunks_exact_mut_zip_aliasing() {
432432
assert_eq!(first, (&mut [0, 1][..], &[6, 7][..]));
433433
}
434434

435+
#[test]
436+
fn test_chunks_zst() {
437+
const SIZE: usize = 16;
438+
let mut it = [(); usize::MAX].chunks(SIZE);
439+
assert_eq!(it.nth_back(0), Some(&[(); SIZE - 1][..]));
440+
}
441+
435442
#[test]
436443
fn test_rchunks_mut_zip_aliasing() {
437444
let v1: &mut [i32] = &mut [0, 1, 2, 3, 4];

0 commit comments

Comments
 (0)