@@ -835,6 +835,41 @@ impl<T> [T] {
835835 ChunksExactMut { v : fst, rem : snd, chunk_size }
836836 }
837837
838+ /// Returns an iterator over `N` elements of the slice at a time, starting at the
839+ /// beginning of the slice.
840+ ///
841+ /// The chunks are slices and do not overlap. If `N` does not divide the length of the
842+ /// slice, then the last up to `N-1` elements will be omitted and can be retrieved
843+ /// from the `remainder` function of the iterator.
844+ ///
845+ /// # Panics
846+ ///
847+ /// Panics if `N` is 0.
848+ ///
849+ /// # Examples
850+ ///
851+ /// ```
852+ /// #![feature(array_chunks)]
853+ /// let slice = ['l', 'o', 'r', 'e', 'm'];
854+ /// let mut iter = slice.array_chunks();
855+ /// assert_eq!(iter.next().unwrap(), &['l', 'o']);
856+ /// assert_eq!(iter.next().unwrap(), &['r', 'e']);
857+ /// assert!(iter.next().is_none());
858+ /// assert_eq!(iter.remainder(), &['m']);
859+ /// ```
860+ ///
861+ /// [`chunks`]: #method.chunks
862+ /// [`rchunks_exact`]: #method.rchunks_exact
863+ #[ unstable( feature = "array_chunks" , issue = "none" ) ]
864+ #[ inline]
865+ pub fn array_chunks < const N : usize > ( & self ) -> ArrayChunks < ' _ , T , N > {
866+ assert_ne ! ( N , 0 ) ;
867+ let rem = self . len ( ) % N ;
868+ let len = self . len ( ) - rem;
869+ let ( fst, snd) = self . split_at ( len) ;
870+ ArrayChunks { v : fst, rem : snd }
871+ }
872+
838873 /// Returns an iterator over `chunk_size` elements of the slice at a time, starting at the end
839874 /// of the slice.
840875 ///
@@ -5152,6 +5187,151 @@ unsafe impl<'a, T> TrustedRandomAccess for ChunksExactMut<'a, T> {
51525187 }
51535188}
51545189
5190+ /// An iterator over a slice in (non-overlapping) chunks (`N` elements at a
5191+ /// time), starting at the beginning of the slice.
5192+ ///
5193+ /// When the slice len is not evenly divided by the chunk size, the last
5194+ /// up to `chunk_size-1` elements will be omitted but can be retrieved from
5195+ /// the [`remainder`] function from the iterator.
5196+ ///
5197+ /// This struct is created by the [`array_chunks`] method on [slices].
5198+ ///
5199+ /// [`array_chunks`]: ../../std/primitive.slice.html#method.array_chunks
5200+ /// [`remainder`]: ../../std/slice/struct.ArrayChunks.html#method.remainder
5201+ /// [slices]: ../../std/primitive.slice.html
5202+ #[ derive( Debug ) ]
5203+ #[ unstable( feature = "array_chunks" , issue = "none" ) ]
5204+ pub struct ArrayChunks < ' a , T : ' a , const N : usize > {
5205+ v : & ' a [ T ] ,
5206+ rem : & ' a [ T ] ,
5207+ }
5208+
5209+ impl < ' a , T , const N : usize > ArrayChunks < ' a , T , N > {
5210+ /// Returns the remainder of the original slice that is not going to be
5211+ /// returned by the iterator. The returned slice has at most `chunk_size-1`
5212+ /// elements.
5213+ #[ unstable( feature = "array_chunks" , issue = "none" ) ]
5214+ pub fn remainder ( & self ) -> & ' a [ T ] {
5215+ self . rem
5216+ }
5217+ }
5218+
5219+ // FIXME(#26925) Remove in favor of `#[derive(Clone)]`
5220+ #[ unstable( feature = "array_chunks" , issue = "none" ) ]
5221+ impl < T , const N : usize > Clone for ArrayChunks < ' _ , T , N > {
5222+ fn clone ( & self ) -> Self {
5223+ ArrayChunks { v : self . v , rem : self . rem }
5224+ }
5225+ }
5226+
5227+ #[ unstable( feature = "array_chunks" , issue = "none" ) ]
5228+ impl < ' a , T , const N : usize > Iterator for ArrayChunks < ' a , T , N > {
5229+ type Item = & ' a [ T ; N ] ;
5230+
5231+ #[ inline]
5232+ fn next ( & mut self ) -> Option < & ' a [ T ; N ] > {
5233+ if self . v . len ( ) < N {
5234+ None
5235+ } else {
5236+ let ( fst, snd) = self . v . split_at ( N ) ;
5237+ self . v = snd;
5238+ // SAFETY: This is safe as fst is exactly N elements long.
5239+ let ptr = fst. as_ptr ( ) as * const [ T ; N ] ;
5240+ unsafe { Some ( & * ptr) }
5241+ }
5242+ }
5243+
5244+ #[ inline]
5245+ fn size_hint ( & self ) -> ( usize , Option < usize > ) {
5246+ let n = self . v . len ( ) / N ;
5247+ ( n, Some ( n) )
5248+ }
5249+
5250+ #[ inline]
5251+ fn count ( self ) -> usize {
5252+ self . len ( )
5253+ }
5254+
5255+ #[ inline]
5256+ fn nth ( & mut self , n : usize ) -> Option < Self :: Item > {
5257+ let ( start, overflow) = n. overflowing_mul ( N ) ;
5258+ if start >= self . v . len ( ) || overflow {
5259+ self . v = & [ ] ;
5260+ None
5261+ } else {
5262+ let ( _, snd) = self . v . split_at ( start) ;
5263+ self . v = snd;
5264+ self . next ( )
5265+ }
5266+ }
5267+
5268+ #[ inline]
5269+ fn last ( mut self ) -> Option < Self :: Item > {
5270+ self . next_back ( )
5271+ }
5272+ }
5273+
5274+ #[ unstable( feature = "array_chunks" , issue = "none" ) ]
5275+ impl < ' a , T , const N : usize > DoubleEndedIterator for ArrayChunks < ' a , T , N > {
5276+ #[ inline]
5277+ fn next_back ( & mut self ) -> Option < & ' a [ T ; N ] > {
5278+ if self . v . len ( ) < N {
5279+ None
5280+ } else {
5281+ let ( fst, snd) = self . v . split_at ( self . v . len ( ) - N ) ;
5282+ self . v = fst;
5283+ // SAFETY: This is safe as snd is exactly N elements long.
5284+ let ptr = snd. as_ptr ( ) as * const [ T ; N ] ;
5285+ unsafe { Some ( & * ptr) }
5286+ }
5287+ }
5288+
5289+ #[ inline]
5290+ fn nth_back ( & mut self , n : usize ) -> Option < Self :: Item > {
5291+ let len = self . len ( ) ;
5292+ if n >= len {
5293+ self . v = & [ ] ;
5294+ None
5295+ } else {
5296+ let start = ( len - 1 - n) * N ;
5297+ let end = start + N ;
5298+ let nth_back = & self . v [ start..end] ;
5299+ self . v = & self . v [ ..start] ;
5300+ // SAFETY: This is safe as snd is exactly N elements long.
5301+ let ptr = nth_back. as_ptr ( ) as * const [ T ; N ] ;
5302+ unsafe { Some ( & * ptr) }
5303+ }
5304+ }
5305+ }
5306+
5307+ #[ unstable( feature = "array_chunks" , issue = "none" ) ]
5308+ impl < T , const N : usize > ExactSizeIterator for ArrayChunks < ' _ , T , N > {
5309+ fn is_empty ( & self ) -> bool {
5310+ self . v . is_empty ( )
5311+ }
5312+ }
5313+
5314+ #[ unstable( feature = "trusted_len" , issue = "37572" ) ]
5315+ unsafe impl < T , const N : usize > TrustedLen for ArrayChunks < ' _ , T , N > { }
5316+
5317+ #[ unstable( feature = "array_chunks" , issue = "none" ) ]
5318+ impl < T , const N : usize > FusedIterator for ArrayChunks < ' _ , T , N > { }
5319+
5320+ #[ doc( hidden) ]
5321+ #[ unstable( feature = "array_chunks" , issue = "none" ) ]
5322+ unsafe impl < ' a , T , const N : usize > TrustedRandomAccess for ArrayChunks < ' a , T , N > {
5323+ unsafe fn get_unchecked ( & mut self , i : usize ) -> & ' a [ T ; N ] {
5324+ let start = i * N ;
5325+ let segment = from_raw_parts ( self . v . as_ptr ( ) . add ( start) , N ) ;
5326+ // SAFETY: This is safe as segment is exactly N elements long.
5327+ let ptr = segment. as_ptr ( ) as * const [ T ; N ] ;
5328+ & * ptr
5329+ }
5330+ fn may_have_side_effect ( ) -> bool {
5331+ false
5332+ }
5333+ }
5334+
51555335/// An iterator over a slice in (non-overlapping) chunks (`chunk_size` elements at a
51565336/// time), starting at the end of the slice.
51575337///
0 commit comments