@@ -835,6 +835,41 @@ impl<T> [T] {
835
835
ChunksExactMut { v : fst, rem : snd, chunk_size }
836
836
}
837
837
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
+
838
873
/// Returns an iterator over `chunk_size` elements of the slice at a time, starting at the end
839
874
/// of the slice.
840
875
///
@@ -5152,6 +5187,151 @@ unsafe impl<'a, T> TrustedRandomAccess for ChunksExactMut<'a, T> {
5152
5187
}
5153
5188
}
5154
5189
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
+
5155
5335
/// An iterator over a slice in (non-overlapping) chunks (`chunk_size` elements at a
5156
5336
/// time), starting at the end of the slice.
5157
5337
///
0 commit comments