@@ -680,7 +680,7 @@ impl<T> [T] {
680680 #[ stable( feature = "rust1" , since = "1.0.0" ) ]
681681 #[ inline]
682682 pub fn windows ( & self , size : usize ) -> Windows < ' _ , T > {
683- assert ! ( size != 0 ) ;
683+ assert_ne ! ( size, 0 ) ;
684684 Windows { v : self , size }
685685 }
686686
@@ -714,7 +714,7 @@ impl<T> [T] {
714714 #[ stable( feature = "rust1" , since = "1.0.0" ) ]
715715 #[ inline]
716716 pub fn chunks ( & self , chunk_size : usize ) -> Chunks < ' _ , T > {
717- assert ! ( chunk_size != 0 ) ;
717+ assert_ne ! ( chunk_size, 0 ) ;
718718 Chunks { v : self , chunk_size }
719719 }
720720
@@ -752,7 +752,7 @@ impl<T> [T] {
752752 #[ stable( feature = "rust1" , since = "1.0.0" ) ]
753753 #[ inline]
754754 pub fn chunks_mut ( & mut self , chunk_size : usize ) -> ChunksMut < ' _ , T > {
755- assert ! ( chunk_size != 0 ) ;
755+ assert_ne ! ( chunk_size, 0 ) ;
756756 ChunksMut { v : self , chunk_size }
757757 }
758758
@@ -789,7 +789,7 @@ impl<T> [T] {
789789 #[ stable( feature = "chunks_exact" , since = "1.31.0" ) ]
790790 #[ inline]
791791 pub fn chunks_exact ( & self , chunk_size : usize ) -> ChunksExact < ' _ , T > {
792- assert ! ( chunk_size != 0 ) ;
792+ assert_ne ! ( chunk_size, 0 ) ;
793793 let rem = self . len ( ) % chunk_size;
794794 let len = self . len ( ) - rem;
795795 let ( fst, snd) = self . split_at ( len) ;
@@ -834,13 +834,52 @@ impl<T> [T] {
834834 #[ stable( feature = "chunks_exact" , since = "1.31.0" ) ]
835835 #[ inline]
836836 pub fn chunks_exact_mut ( & mut self , chunk_size : usize ) -> ChunksExactMut < ' _ , T > {
837- assert ! ( chunk_size != 0 ) ;
837+ assert_ne ! ( chunk_size, 0 ) ;
838838 let rem = self . len ( ) % chunk_size;
839839 let len = self . len ( ) - rem;
840840 let ( fst, snd) = self . split_at_mut ( len) ;
841841 ChunksExactMut { v : fst, rem : snd, chunk_size }
842842 }
843843
844+ /// Returns an iterator over `N` elements of the slice at a time, starting at the
845+ /// beginning of the slice.
846+ ///
847+ /// The chunks are slices and do not overlap. If `N` does not divide the length of the
848+ /// slice, then the last up to `N-1` elements will be omitted and can be retrieved
849+ /// from the `remainder` function of the iterator.
850+ ///
851+ /// This method is the const generic equivalent of [`chunks_exact`].
852+ ///
853+ /// # Panics
854+ ///
855+ /// Panics if `N` is 0. This check will most probably get changed to a compile time
856+ /// error before this method gets stabilized.
857+ ///
858+ /// # Examples
859+ ///
860+ /// ```
861+ /// #![feature(array_chunks)]
862+ /// let slice = ['l', 'o', 'r', 'e', 'm'];
863+ /// let mut iter = slice.array_chunks();
864+ /// assert_eq!(iter.next().unwrap(), &['l', 'o']);
865+ /// assert_eq!(iter.next().unwrap(), &['r', 'e']);
866+ /// assert!(iter.next().is_none());
867+ /// assert_eq!(iter.remainder(), &['m']);
868+ /// ```
869+ ///
870+ /// [`chunks_exact`]: #method.chunks_exact
871+ #[ unstable( feature = "array_chunks" , issue = "74985" ) ]
872+ #[ inline]
873+ pub fn array_chunks < const N : usize > ( & self ) -> ArrayChunks < ' _ , T , N > {
874+ assert_ne ! ( N , 0 ) ;
875+ let len = self . len ( ) / N ;
876+ let ( fst, snd) = self . split_at ( len * N ) ;
877+ // SAFETY: We cast a slice of `len * N` elements into
878+ // a slice of `len` many `N` elements chunks.
879+ let array_slice: & [ [ T ; N ] ] = unsafe { from_raw_parts ( fst. as_ptr ( ) . cast ( ) , len) } ;
880+ ArrayChunks { iter : array_slice. iter ( ) , rem : snd }
881+ }
882+
844883 /// Returns an iterator over `chunk_size` elements of the slice at a time, starting at the end
845884 /// of the slice.
846885 ///
@@ -5432,6 +5471,110 @@ unsafe impl<'a, T> TrustedRandomAccess for ChunksExactMut<'a, T> {
54325471 }
54335472}
54345473
5474+ /// An iterator over a slice in (non-overlapping) chunks (`N` elements at a
5475+ /// time), starting at the beginning of the slice.
5476+ ///
5477+ /// When the slice len is not evenly divided by the chunk size, the last
5478+ /// up to `chunk_size-1` elements will be omitted but can be retrieved from
5479+ /// the [`remainder`] function from the iterator.
5480+ ///
5481+ /// This struct is created by the [`array_chunks`] method on [slices].
5482+ ///
5483+ /// [`array_chunks`]: ../../std/primitive.slice.html#method.array_chunks
5484+ /// [`remainder`]: ../../std/slice/struct.ArrayChunks.html#method.remainder
5485+ /// [slices]: ../../std/primitive.slice.html
5486+ #[ derive( Debug ) ]
5487+ #[ unstable( feature = "array_chunks" , issue = "74985" ) ]
5488+ pub struct ArrayChunks < ' a , T : ' a , const N : usize > {
5489+ iter : Iter < ' a , [ T ; N ] > ,
5490+ rem : & ' a [ T ] ,
5491+ }
5492+
5493+ impl < ' a , T , const N : usize > ArrayChunks < ' a , T , N > {
5494+ /// Returns the remainder of the original slice that is not going to be
5495+ /// returned by the iterator. The returned slice has at most `chunk_size-1`
5496+ /// elements.
5497+ #[ unstable( feature = "array_chunks" , issue = "74985" ) ]
5498+ pub fn remainder ( & self ) -> & ' a [ T ] {
5499+ self . rem
5500+ }
5501+ }
5502+
5503+ // FIXME(#26925) Remove in favor of `#[derive(Clone)]`
5504+ #[ unstable( feature = "array_chunks" , issue = "74985" ) ]
5505+ impl < T , const N : usize > Clone for ArrayChunks < ' _ , T , N > {
5506+ fn clone ( & self ) -> Self {
5507+ ArrayChunks { iter : self . iter . clone ( ) , rem : self . rem }
5508+ }
5509+ }
5510+
5511+ #[ unstable( feature = "array_chunks" , issue = "74985" ) ]
5512+ impl < ' a , T , const N : usize > Iterator for ArrayChunks < ' a , T , N > {
5513+ type Item = & ' a [ T ; N ] ;
5514+
5515+ #[ inline]
5516+ fn next ( & mut self ) -> Option < & ' a [ T ; N ] > {
5517+ self . iter . next ( )
5518+ }
5519+
5520+ #[ inline]
5521+ fn size_hint ( & self ) -> ( usize , Option < usize > ) {
5522+ self . iter . size_hint ( )
5523+ }
5524+
5525+ #[ inline]
5526+ fn count ( self ) -> usize {
5527+ self . iter . count ( )
5528+ }
5529+
5530+ #[ inline]
5531+ fn nth ( & mut self , n : usize ) -> Option < Self :: Item > {
5532+ self . iter . nth ( n)
5533+ }
5534+
5535+ #[ inline]
5536+ fn last ( self ) -> Option < Self :: Item > {
5537+ self . iter . last ( )
5538+ }
5539+ }
5540+
5541+ #[ unstable( feature = "array_chunks" , issue = "74985" ) ]
5542+ impl < ' a , T , const N : usize > DoubleEndedIterator for ArrayChunks < ' a , T , N > {
5543+ #[ inline]
5544+ fn next_back ( & mut self ) -> Option < & ' a [ T ; N ] > {
5545+ self . iter . next_back ( )
5546+ }
5547+
5548+ #[ inline]
5549+ fn nth_back ( & mut self , n : usize ) -> Option < Self :: Item > {
5550+ self . iter . nth_back ( n)
5551+ }
5552+ }
5553+
5554+ #[ unstable( feature = "array_chunks" , issue = "74985" ) ]
5555+ impl < T , const N : usize > ExactSizeIterator for ArrayChunks < ' _ , T , N > {
5556+ fn is_empty ( & self ) -> bool {
5557+ self . iter . is_empty ( )
5558+ }
5559+ }
5560+
5561+ #[ unstable( feature = "trusted_len" , issue = "37572" ) ]
5562+ unsafe impl < T , const N : usize > TrustedLen for ArrayChunks < ' _ , T , N > { }
5563+
5564+ #[ unstable( feature = "array_chunks" , issue = "74985" ) ]
5565+ impl < T , const N : usize > FusedIterator for ArrayChunks < ' _ , T , N > { }
5566+
5567+ #[ doc( hidden) ]
5568+ #[ unstable( feature = "array_chunks" , issue = "74985" ) ]
5569+ unsafe impl < ' a , T , const N : usize > TrustedRandomAccess for ArrayChunks < ' a , T , N > {
5570+ unsafe fn get_unchecked ( & mut self , i : usize ) -> & ' a [ T ; N ] {
5571+ unsafe { self . iter . get_unchecked ( i) }
5572+ }
5573+ fn may_have_side_effect ( ) -> bool {
5574+ false
5575+ }
5576+ }
5577+
54355578/// An iterator over a slice in (non-overlapping) chunks (`chunk_size` elements at a
54365579/// time), starting at the end of the slice.
54375580///
0 commit comments