@@ -841,6 +841,41 @@ impl<T> [T] {
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+ /// # Panics
852+ ///
853+ /// Panics if `N` is 0.
854+ ///
855+ /// # Examples
856+ ///
857+ /// ```
858+ /// #![feature(array_chunks)]
859+ /// let slice = ['l', 'o', 'r', 'e', 'm'];
860+ /// let mut iter = slice.array_chunks();
861+ /// assert_eq!(iter.next().unwrap(), &['l', 'o']);
862+ /// assert_eq!(iter.next().unwrap(), &['r', 'e']);
863+ /// assert!(iter.next().is_none());
864+ /// assert_eq!(iter.remainder(), &['m']);
865+ /// ```
866+ ///
867+ /// [`chunks`]: #method.chunks
868+ /// [`rchunks_exact`]: #method.rchunks_exact
869+ #[ unstable( feature = "array_chunks" , issue = "none" ) ]
870+ #[ inline]
871+ pub fn array_chunks < const N : usize > ( & self ) -> ArrayChunks < ' _ , T , N > {
872+ assert_ne ! ( N , 0 ) ;
873+ let rem = self . len ( ) % N ;
874+ let len = self . len ( ) - rem;
875+ let ( fst, snd) = self . split_at ( len) ;
876+ ArrayChunks { v : fst, rem : snd }
877+ }
878+
844879 /// Returns an iterator over `chunk_size` elements of the slice at a time, starting at the end
845880 /// of the slice.
846881 ///
@@ -5432,6 +5467,151 @@ unsafe impl<'a, T> TrustedRandomAccess for ChunksExactMut<'a, T> {
54325467 }
54335468}
54345469
5470+ /// An iterator over a slice in (non-overlapping) chunks (`N` elements at a
5471+ /// time), starting at the beginning of the slice.
5472+ ///
5473+ /// When the slice len is not evenly divided by the chunk size, the last
5474+ /// up to `chunk_size-1` elements will be omitted but can be retrieved from
5475+ /// the [`remainder`] function from the iterator.
5476+ ///
5477+ /// This struct is created by the [`array_chunks`] method on [slices].
5478+ ///
5479+ /// [`array_chunks`]: ../../std/primitive.slice.html#method.array_chunks
5480+ /// [`remainder`]: ../../std/slice/struct.ArrayChunks.html#method.remainder
5481+ /// [slices]: ../../std/primitive.slice.html
5482+ #[ derive( Debug ) ]
5483+ #[ unstable( feature = "array_chunks" , issue = "none" ) ]
5484+ pub struct ArrayChunks < ' a , T : ' a , const N : usize > {
5485+ v : & ' a [ T ] ,
5486+ rem : & ' a [ T ] ,
5487+ }
5488+
5489+ impl < ' a , T , const N : usize > ArrayChunks < ' a , T , N > {
5490+ /// Returns the remainder of the original slice that is not going to be
5491+ /// returned by the iterator. The returned slice has at most `chunk_size-1`
5492+ /// elements.
5493+ #[ unstable( feature = "array_chunks" , issue = "none" ) ]
5494+ pub fn remainder ( & self ) -> & ' a [ T ] {
5495+ self . rem
5496+ }
5497+ }
5498+
5499+ // FIXME(#26925) Remove in favor of `#[derive(Clone)]`
5500+ #[ unstable( feature = "array_chunks" , issue = "none" ) ]
5501+ impl < T , const N : usize > Clone for ArrayChunks < ' _ , T , N > {
5502+ fn clone ( & self ) -> Self {
5503+ ArrayChunks { v : self . v , rem : self . rem }
5504+ }
5505+ }
5506+
5507+ #[ unstable( feature = "array_chunks" , issue = "none" ) ]
5508+ impl < ' a , T , const N : usize > Iterator for ArrayChunks < ' a , T , N > {
5509+ type Item = & ' a [ T ; N ] ;
5510+
5511+ #[ inline]
5512+ fn next ( & mut self ) -> Option < & ' a [ T ; N ] > {
5513+ if self . v . len ( ) < N {
5514+ None
5515+ } else {
5516+ let ( fst, snd) = self . v . split_at ( N ) ;
5517+ self . v = snd;
5518+ // SAFETY: This is safe as fst is exactly N elements long.
5519+ let ptr = fst. as_ptr ( ) as * const [ T ; N ] ;
5520+ unsafe { Some ( & * ptr) }
5521+ }
5522+ }
5523+
5524+ #[ inline]
5525+ fn size_hint ( & self ) -> ( usize , Option < usize > ) {
5526+ let n = self . v . len ( ) / N ;
5527+ ( n, Some ( n) )
5528+ }
5529+
5530+ #[ inline]
5531+ fn count ( self ) -> usize {
5532+ self . len ( )
5533+ }
5534+
5535+ #[ inline]
5536+ fn nth ( & mut self , n : usize ) -> Option < Self :: Item > {
5537+ let ( start, overflow) = n. overflowing_mul ( N ) ;
5538+ if start >= self . v . len ( ) || overflow {
5539+ self . v = & [ ] ;
5540+ None
5541+ } else {
5542+ let ( _, snd) = self . v . split_at ( start) ;
5543+ self . v = snd;
5544+ self . next ( )
5545+ }
5546+ }
5547+
5548+ #[ inline]
5549+ fn last ( mut self ) -> Option < Self :: Item > {
5550+ self . next_back ( )
5551+ }
5552+ }
5553+
5554+ #[ unstable( feature = "array_chunks" , issue = "none" ) ]
5555+ impl < ' a , T , const N : usize > DoubleEndedIterator for ArrayChunks < ' a , T , N > {
5556+ #[ inline]
5557+ fn next_back ( & mut self ) -> Option < & ' a [ T ; N ] > {
5558+ if self . v . len ( ) < N {
5559+ None
5560+ } else {
5561+ let ( fst, snd) = self . v . split_at ( self . v . len ( ) - N ) ;
5562+ self . v = fst;
5563+ // SAFETY: This is safe as snd is exactly N elements long.
5564+ let ptr = snd. as_ptr ( ) as * const [ T ; N ] ;
5565+ unsafe { Some ( & * ptr) }
5566+ }
5567+ }
5568+
5569+ #[ inline]
5570+ fn nth_back ( & mut self , n : usize ) -> Option < Self :: Item > {
5571+ let len = self . len ( ) ;
5572+ if n >= len {
5573+ self . v = & [ ] ;
5574+ None
5575+ } else {
5576+ let start = ( len - 1 - n) * N ;
5577+ let end = start + N ;
5578+ let nth_back = & self . v [ start..end] ;
5579+ self . v = & self . v [ ..start] ;
5580+ // SAFETY: This is safe as snd is exactly N elements long.
5581+ let ptr = nth_back. as_ptr ( ) as * const [ T ; N ] ;
5582+ unsafe { Some ( & * ptr) }
5583+ }
5584+ }
5585+ }
5586+
5587+ #[ unstable( feature = "array_chunks" , issue = "none" ) ]
5588+ impl < T , const N : usize > ExactSizeIterator for ArrayChunks < ' _ , T , N > {
5589+ fn is_empty ( & self ) -> bool {
5590+ self . v . is_empty ( )
5591+ }
5592+ }
5593+
5594+ #[ unstable( feature = "trusted_len" , issue = "37572" ) ]
5595+ unsafe impl < T , const N : usize > TrustedLen for ArrayChunks < ' _ , T , N > { }
5596+
5597+ #[ unstable( feature = "array_chunks" , issue = "none" ) ]
5598+ impl < T , const N : usize > FusedIterator for ArrayChunks < ' _ , T , N > { }
5599+
5600+ #[ doc( hidden) ]
5601+ #[ unstable( feature = "array_chunks" , issue = "none" ) ]
5602+ unsafe impl < ' a , T , const N : usize > TrustedRandomAccess for ArrayChunks < ' a , T , N > {
5603+ unsafe fn get_unchecked ( & mut self , i : usize ) -> & ' a [ T ; N ] {
5604+ let start = i * N ;
5605+ // SAFETY: This is safe as `i` must be less than `self.size_hint`.
5606+ let segment = unsafe { from_raw_parts ( self . v . as_ptr ( ) . add ( start) , N ) } ;
5607+ // SAFETY: This is safe as segment is exactly `N` elements long.
5608+ unsafe { & * ( segment. as_ptr ( ) as * const [ T ; N ] ) }
5609+ }
5610+ fn may_have_side_effect ( ) -> bool {
5611+ false
5612+ }
5613+ }
5614+
54355615/// An iterator over a slice in (non-overlapping) chunks (`chunk_size` elements at a
54365616/// time), starting at the end of the slice.
54375617///
0 commit comments