@@ -841,6 +841,41 @@ impl<T> [T] {
841
841
ChunksExactMut { v : fst, rem : snd, chunk_size }
842
842
}
843
843
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
+
844
879
/// Returns an iterator over `chunk_size` elements of the slice at a time, starting at the end
845
880
/// of the slice.
846
881
///
@@ -5432,6 +5467,151 @@ unsafe impl<'a, T> TrustedRandomAccess for ChunksExactMut<'a, T> {
5432
5467
}
5433
5468
}
5434
5469
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
+
5435
5615
/// An iterator over a slice in (non-overlapping) chunks (`chunk_size` elements at a
5436
5616
/// time), starting at the end of the slice.
5437
5617
///
0 commit comments