@@ -1601,15 +1601,15 @@ impl<'a, T> DoubleEndedIterator for Chunks<'a, T> {
16011601 #[ inline]
16021602 fn nth_back ( & mut self , n : usize ) -> Option < Self :: Item > {
16031603 let len = self . len ( ) ;
1604- if n >= len {
1605- self . v = & self . v [ ..0 ] ; // cheaper than &[]
1606- None
1607- } else {
1604+ if n < len {
16081605 let start = ( len - 1 - n) * self . chunk_size ;
16091606 let end = start + ( self . v . len ( ) - start) . min ( self . chunk_size ) ;
16101607 let nth_back = & self . v [ start..end] ;
16111608 self . v = & self . v [ ..start] ;
16121609 Some ( nth_back)
1610+ } else {
1611+ self . v = & self . v [ ..0 ] ; // cheaper than &[]
1612+ None
16131613 }
16141614 }
16151615}
@@ -1770,10 +1770,7 @@ impl<'a, T> DoubleEndedIterator for ChunksMut<'a, T> {
17701770 #[ inline]
17711771 fn nth_back ( & mut self , n : usize ) -> Option < Self :: Item > {
17721772 let len = self . len ( ) ;
1773- if n >= len {
1774- self . v = & mut [ ] ;
1775- None
1776- } else {
1773+ if n < len {
17771774 let start = ( len - 1 - n) * self . chunk_size ;
17781775 let end = match start. checked_add ( self . chunk_size ) {
17791776 Some ( res) => cmp:: min ( self . v . len ( ) , res) ,
@@ -1786,6 +1783,9 @@ impl<'a, T> DoubleEndedIterator for ChunksMut<'a, T> {
17861783 self . v = head;
17871784 // SAFETY: Nothing else points to or will point to the contents of this slice.
17881785 Some ( unsafe { & mut * nth_back } )
1786+ } else {
1787+ self . v = & mut [ ] ;
1788+ None
17891789 }
17901790 }
17911791}
@@ -1952,15 +1952,15 @@ impl<'a, T> DoubleEndedIterator for ChunksExact<'a, T> {
19521952 #[ inline]
19531953 fn nth_back ( & mut self , n : usize ) -> Option < Self :: Item > {
19541954 let len = self . len ( ) ;
1955- if n >= len {
1956- self . v = & self . v [ ..0 ] ; // cheaper than &[]
1957- None
1958- } else {
1955+ if n < len {
19591956 let start = ( len - 1 - n) * self . chunk_size ;
19601957 let end = start + self . chunk_size ;
19611958 let nth_back = & self . v [ start..end] ;
19621959 self . v = & self . v [ ..start] ;
19631960 Some ( nth_back)
1961+ } else {
1962+ self . v = & self . v [ ..0 ] ; // cheaper than &[]
1963+ None
19641964 }
19651965 }
19661966}
@@ -2111,10 +2111,7 @@ impl<'a, T> DoubleEndedIterator for ChunksExactMut<'a, T> {
21112111 #[ inline]
21122112 fn nth_back ( & mut self , n : usize ) -> Option < Self :: Item > {
21132113 let len = self . len ( ) ;
2114- if n >= len {
2115- self . v = & mut [ ] ;
2116- None
2117- } else {
2114+ if n < len {
21182115 let start = ( len - 1 - n) * self . chunk_size ;
21192116 let end = start + self . chunk_size ;
21202117 // SAFETY: The self.v contract ensures that any split_at_mut is valid.
@@ -2124,6 +2121,9 @@ impl<'a, T> DoubleEndedIterator for ChunksExactMut<'a, T> {
21242121 self . v = head;
21252122 // SAFETY: Nothing else points to or will point to the contents of this slice.
21262123 Some ( unsafe { & mut * nth_back } )
2124+ } else {
2125+ self . v = & mut [ ] ;
2126+ None
21272127 }
21282128 }
21292129}
@@ -2307,16 +2307,12 @@ impl<'a, T> Iterator for RChunks<'a, T> {
23072307 if self . v . is_empty ( ) {
23082308 None
23092309 } else {
2310- let len = self . v . len ( ) ;
2311- let chunksz = cmp:: min ( len, self . chunk_size ) ;
2312- // SAFETY: split_at_unchecked just requires the argument be less
2313- // than the length. This could only happen if the expression `len -
2314- // chunksz` overflows. This could only happen if `chunksz > len`,
2315- // which is impossible as we initialize it as the `min` of `len` and
2316- // `self.chunk_size`.
2317- let ( fst, snd) = unsafe { self . v . split_at_unchecked ( len - chunksz) } ;
2318- self . v = fst;
2319- Some ( snd)
2310+ let idx = self . v . len ( ) . saturating_sub ( self . chunk_size ) ;
2311+ // SAFETY: self.chunk_size() > 0, so 0 <= idx < self.v.len().
2312+ // Thus `idx` is in-bounds for `self.v` and can be used as a valid argument for `split_at_mut_unchecked`.
2313+ let ( rest, chunk) = unsafe { self . v . split_at_unchecked ( idx) } ;
2314+ self . v = rest;
2315+ Some ( chunk)
23202316 }
23212317 }
23222318
@@ -2389,17 +2385,16 @@ impl<'a, T> DoubleEndedIterator for RChunks<'a, T> {
23892385 #[ inline]
23902386 fn nth_back ( & mut self , n : usize ) -> Option < Self :: Item > {
23912387 let len = self . len ( ) ;
2392- if n >= len {
2393- self . v = & self . v [ ..0 ] ; // cheaper than &[]
2394- None
2395- } else {
2396- // can't underflow because `n < len`
2388+ if n < len {
23972389 let offset_from_end = ( len - 1 - n) * self . chunk_size ;
23982390 let end = self . v . len ( ) - offset_from_end;
23992391 let start = end. saturating_sub ( self . chunk_size ) ;
24002392 let nth_back = & self . v [ start..end] ;
24012393 self . v = & self . v [ end..] ;
24022394 Some ( nth_back)
2395+ } else {
2396+ self . v = & self . v [ ..0 ] ; // cheaper than &[]
2397+ None
24032398 }
24042399 }
24052400}
@@ -2471,17 +2466,13 @@ impl<'a, T> Iterator for RChunksMut<'a, T> {
24712466 if self . v . is_empty ( ) {
24722467 None
24732468 } else {
2474- let sz = cmp:: min ( self . v . len ( ) , self . chunk_size ) ;
2475- let len = self . v . len ( ) ;
2476- // SAFETY: split_at_mut_unchecked just requires the argument be less
2477- // than the length. This could only happen if the expression
2478- // `len - sz` overflows. This could only happen if `sz >
2479- // len`, which is impossible as we initialize it as the `min` of
2480- // `self.v.len()` (e.g. `len`) and `self.chunk_size`.
2481- let ( head, tail) = unsafe { self . v . split_at_mut_unchecked ( len - sz) } ;
2482- self . v = head;
2469+ let idx = self . v . len ( ) . saturating_sub ( self . chunk_size ) ;
2470+ // SAFETY: self.chunk_size() > 0, so 0 <= idx < self.v.len().
2471+ // Thus `idx` is in-bounds for `self.v` and can be used as a valid argument for `split_at_mut_unchecked`.
2472+ let ( rest, chunk) = unsafe { self . v . split_at_mut_unchecked ( idx) } ;
2473+ self . v = rest;
24832474 // SAFETY: Nothing else points to or will point to the contents of this slice.
2484- Some ( unsafe { & mut * tail } )
2475+ Some ( unsafe { & mut * chunk } )
24852476 }
24862477 }
24872478
@@ -2502,12 +2493,9 @@ impl<'a, T> Iterator for RChunksMut<'a, T> {
25022493
25032494 #[ inline]
25042495 fn nth ( & mut self , n : usize ) -> Option < & ' a mut [ T ] > {
2505- let ( end, overflow) = n. overflowing_mul ( self . chunk_size ) ;
2506- if end >= self . v . len ( ) || overflow {
2507- self . v = & mut [ ] ;
2508- None
2509- } else {
2510- // Can't underflow because of the check above
2496+ if let Some ( end) = n. checked_mul ( self . chunk_size )
2497+ && end < self . v . len ( )
2498+ {
25112499 let end = self . v . len ( ) - end;
25122500 let start = match end. checked_sub ( self . chunk_size ) {
25132501 Some ( sum) => sum,
@@ -2522,6 +2510,9 @@ impl<'a, T> Iterator for RChunksMut<'a, T> {
25222510 self . v = head;
25232511 // SAFETY: Nothing else points to or will point to the contents of this slice.
25242512 Some ( unsafe { & mut * nth } )
2513+ } else {
2514+ self . v = & mut [ ] ;
2515+ None
25252516 }
25262517 }
25272518
@@ -2566,10 +2557,7 @@ impl<'a, T> DoubleEndedIterator for RChunksMut<'a, T> {
25662557 #[ inline]
25672558 fn nth_back ( & mut self , n : usize ) -> Option < Self :: Item > {
25682559 let len = self . len ( ) ;
2569- if n >= len {
2570- self . v = & mut [ ] ;
2571- None
2572- } else {
2560+ if n < len {
25732561 // can't underflow because `n < len`
25742562 let offset_from_end = ( len - 1 - n) * self . chunk_size ;
25752563 let end = self . v . len ( ) - offset_from_end;
@@ -2581,6 +2569,9 @@ impl<'a, T> DoubleEndedIterator for RChunksMut<'a, T> {
25812569 self . v = tail;
25822570 // SAFETY: Nothing else points to or will point to the contents of this slice.
25832571 Some ( unsafe { & mut * nth_back } )
2572+ } else {
2573+ self . v = & mut [ ] ;
2574+ None
25842575 }
25852576 }
25862577}
@@ -2711,14 +2702,14 @@ impl<'a, T> Iterator for RChunksExact<'a, T> {
27112702
27122703 #[ inline]
27132704 fn nth ( & mut self , n : usize ) -> Option < Self :: Item > {
2714- let ( end, overflow) = n. overflowing_mul ( self . chunk_size ) ;
2715- if end >= self . v . len ( ) || overflow {
2705+ if let Some ( end) = n. checked_mul ( self . chunk_size )
2706+ && end < self . v . len ( )
2707+ {
2708+ self . v = & self . v [ ..self . v . len ( ) - end] ;
2709+ self . next ( )
2710+ } else {
27162711 self . v = & self . v [ ..0 ] ; // cheaper than &[]
27172712 None
2718- } else {
2719- let ( fst, _) = self . v . split_at ( self . v . len ( ) - end) ;
2720- self . v = fst;
2721- self . next ( )
27222713 }
27232714 }
27242715
@@ -2751,10 +2742,7 @@ impl<'a, T> DoubleEndedIterator for RChunksExact<'a, T> {
27512742 #[ inline]
27522743 fn nth_back ( & mut self , n : usize ) -> Option < Self :: Item > {
27532744 let len = self . len ( ) ;
2754- if n >= len {
2755- self . v = & self . v [ ..0 ] ; // cheaper than &[]
2756- None
2757- } else {
2745+ if n < len {
27582746 // now that we know that `n` corresponds to a chunk,
27592747 // none of these operations can underflow/overflow
27602748 let offset = ( len - n) * self . chunk_size ;
@@ -2763,6 +2751,9 @@ impl<'a, T> DoubleEndedIterator for RChunksExact<'a, T> {
27632751 let nth_back = & self . v [ start..end] ;
27642752 self . v = & self . v [ end..] ;
27652753 Some ( nth_back)
2754+ } else {
2755+ self . v = & self . v [ ..0 ] ; // cheaper than &[]
2756+ None
27662757 }
27672758 }
27682759}
@@ -2875,16 +2866,17 @@ impl<'a, T> Iterator for RChunksExactMut<'a, T> {
28752866
28762867 #[ inline]
28772868 fn nth ( & mut self , n : usize ) -> Option < & ' a mut [ T ] > {
2878- let ( end, overflow) = n. overflowing_mul ( self . chunk_size ) ;
2879- if end >= self . v . len ( ) || overflow {
2880- self . v = & mut [ ] ;
2881- None
2882- } else {
2883- let len = self . v . len ( ) ;
2869+ if let Some ( end) = n. checked_mul ( self . chunk_size )
2870+ && end < self . v . len ( )
2871+ {
2872+ let idx = self . v . len ( ) - end;
28842873 // SAFETY: The self.v contract ensures that any split_at_mut is valid.
2885- let ( fst, _) = unsafe { self . v . split_at_mut ( len - end ) } ;
2874+ let ( fst, _) = unsafe { self . v . split_at_mut ( idx ) } ;
28862875 self . v = fst;
28872876 self . next ( )
2877+ } else {
2878+ self . v = & mut [ ] ;
2879+ None
28882880 }
28892881 }
28902882
@@ -2919,10 +2911,7 @@ impl<'a, T> DoubleEndedIterator for RChunksExactMut<'a, T> {
29192911 #[ inline]
29202912 fn nth_back ( & mut self , n : usize ) -> Option < Self :: Item > {
29212913 let len = self . len ( ) ;
2922- if n >= len {
2923- self . v = & mut [ ] ;
2924- None
2925- } else {
2914+ if n < len {
29262915 // now that we know that `n` corresponds to a chunk,
29272916 // none of these operations can underflow/overflow
29282917 let offset = ( len - n) * self . chunk_size ;
@@ -2935,6 +2924,9 @@ impl<'a, T> DoubleEndedIterator for RChunksExactMut<'a, T> {
29352924 self . v = tail;
29362925 // SAFETY: Nothing else points to or will point to the contents of this slice.
29372926 Some ( unsafe { & mut * nth_back } )
2927+ } else {
2928+ self . v = & mut [ ] ;
2929+ None
29382930 }
29392931 }
29402932}
0 commit comments