@@ -24,7 +24,10 @@ use cmp::Ordering;
2424use convert:: TryFrom ;
2525use fmt;
2626use hash:: { Hash , self } ;
27- use marker:: Unsize ;
27+ use iter:: { FusedIterator , TrustedLen } ;
28+ use marker:: { PhantomData , Unsize } ;
29+ use mem:: { ManuallyDrop , self } ;
30+ use ptr;
2831use slice:: { Iter , IterMut } ;
2932
3033/// Utility trait implemented only on arrays of fixed size
@@ -52,6 +55,7 @@ unsafe impl<T, A: Unsize<[T]>> FixedSizeArray<T> for A {
5255 fn as_slice ( & self ) -> & [ T ] {
5356 self
5457 }
58+
5559 #[ inline]
5660 fn as_mut_slice ( & mut self ) -> & mut [ T ] {
5761 self
@@ -210,6 +214,21 @@ macro_rules! array_impls {
210214 }
211215 }
212216
217+ #[ unstable( feature = "array_into_iter" , issue = "0" ) ]
218+ impl <T > IntoIterator for [ T ; $N] {
219+ type Item = T ;
220+ type IntoIter = IntoIter <T , Self >;
221+
222+ fn into_iter( self ) -> Self :: IntoIter {
223+ Self :: IntoIter {
224+ array: ManuallyDrop :: new( self ) ,
225+ index: 0 ,
226+ index_back: $N,
227+ _marker: PhantomData ,
228+ }
229+ }
230+ }
231+
213232 // NOTE: some less important impls are omitted to reduce code bloat
214233 __impl_slice_eq1! { [ A ; $N] , [ B ; $N] }
215234 __impl_slice_eq2! { [ A ; $N] , [ B ] }
@@ -285,3 +304,171 @@ macro_rules! array_impl_default {
285304}
286305
287306array_impl_default ! { 32 , T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T }
307+
308+
309+ /// An iterator that moves out of an array.
310+ ///
311+ /// This `struct` is created by the `into_iter` method on [arrays]
312+ /// (provided by the [`IntoIterator`] trait).
313+ ///
314+ /// [arrays]: ../../std/primitive.array.html
315+ /// [`IntoIterator`]: ../../std/iter/trait.IntoIterator.html
316+ #[ unstable( feature = "array_into_iter" , issue = "0" ) ]
317+ pub struct IntoIter < T , A : FixedSizeArray < T > > {
318+ // Invariants: index <= index_back <= array.len()
319+ // Only values in array[index..index_back] are alive at any given time.
320+ // Values from array[..index] and array[index_back..] are already moved/dropped.
321+ array : ManuallyDrop < A > ,
322+ index : usize ,
323+ index_back : usize ,
324+ _marker : PhantomData < T > ,
325+ }
326+
327+ impl < T , A : FixedSizeArray < T > > IntoIter < T , A > {
328+ /// Returns the remaining items of this iterator as a slice.
329+ ///
330+ /// # Examples
331+ ///
332+ /// ```
333+ /// #![feature(array_into_iter)]
334+ ///
335+ /// # fn main() {
336+ /// let array = ['a', 'b', 'c'];
337+ /// let mut into_iter = array.into_iter();
338+ /// assert_eq!(into_iter.as_slice(), &['a', 'b', 'c']);
339+ /// let _ = into_iter.next().unwrap();
340+ /// assert_eq!(into_iter.as_slice(), &['b', 'c']);
341+ /// # }
342+ /// ```
343+ #[ inline]
344+ #[ unstable( feature = "array_into_iter" , issue = "0" ) ]
345+ pub fn as_slice ( & self ) -> & [ T ] {
346+ & self . array . as_slice ( ) [ self . index ..self . index_back ]
347+ }
348+
349+ /// Returns the remaining items of this iterator as a mutable slice.
350+ ///
351+ /// # Examples
352+ ///
353+ /// ```
354+ /// #![feature(array_into_iter)]
355+ ///
356+ /// # fn main() {
357+ /// let array = ['a', 'b', 'c'];
358+ /// let mut into_iter = array.into_iter();
359+ /// assert_eq!(into_iter.as_slice(), &['a', 'b', 'c']);
360+ /// into_iter.as_mut_slice()[2] = 'z';
361+ /// assert_eq!(into_iter.next().unwrap(), 'a');
362+ /// assert_eq!(into_iter.next().unwrap(), 'b');
363+ /// assert_eq!(into_iter.next().unwrap(), 'z');
364+ /// # }
365+ /// ```
366+ #[ inline]
367+ #[ unstable( feature = "array_into_iter" , issue = "0" ) ]
368+ pub fn as_mut_slice ( & mut self ) -> & mut [ T ] {
369+ & mut self . array . as_mut_slice ( ) [ self . index ..self . index_back ]
370+ }
371+ }
372+
373+ #[ unstable( feature = "array_into_iter" , issue = "0" ) ]
374+ impl < T , A : FixedSizeArray < T > > Drop for IntoIter < T , A > {
375+ #[ inline]
376+ fn drop ( & mut self ) {
377+ // Drop values that are still alive.
378+ for p in self . as_mut_slice ( ) {
379+ unsafe { ptr:: drop_in_place ( p) ; }
380+ }
381+ }
382+ }
383+
384+ #[ unstable( feature = "array_into_iter" , issue = "0" ) ]
385+ impl < T : Clone , A : FixedSizeArray < T > > Clone for IntoIter < T , A > {
386+ fn clone ( & self ) -> Self {
387+ unsafe {
388+ let mut iter = Self {
389+ array : ManuallyDrop :: new ( mem:: uninitialized ( ) ) ,
390+ index : 0 ,
391+ index_back : 0 ,
392+ _marker : PhantomData ,
393+ } ;
394+
395+ // Clone values that are still alive.
396+ for ( dst, src) in iter. array . as_mut_slice ( ) . iter_mut ( ) . zip ( self . as_slice ( ) ) {
397+ ptr:: write ( dst, src. clone ( ) ) ;
398+ iter. index_back += 1 ;
399+ }
400+
401+ iter
402+ }
403+ }
404+ }
405+
406+ #[ unstable( feature = "array_into_iter" , issue = "0" ) ]
407+ impl < T : fmt:: Debug , A : FixedSizeArray < T > > fmt:: Debug for IntoIter < T , A > {
408+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
409+ f. debug_tuple ( "IntoIter" )
410+ . field ( & self . as_slice ( ) )
411+ . finish ( )
412+ }
413+ }
414+
415+ #[ unstable( feature = "array_into_iter" , issue = "0" ) ]
416+ impl < T , A : FixedSizeArray < T > > Iterator for IntoIter < T , A > {
417+ type Item = T ;
418+
419+ #[ inline]
420+ fn next ( & mut self ) -> Option < T > {
421+ if self . index < self . index_back {
422+ let p = & self . array . as_slice ( ) [ self . index ] ;
423+ self . index += 1 ;
424+ unsafe { Some ( ptr:: read ( p) ) }
425+ } else {
426+ None
427+ }
428+ }
429+
430+ #[ inline]
431+ fn size_hint ( & self ) -> ( usize , Option < usize > ) {
432+ let len = self . len ( ) ;
433+ ( len, Some ( len) )
434+ }
435+
436+ #[ inline]
437+ fn count ( self ) -> usize {
438+ self . len ( )
439+ }
440+ }
441+
442+ #[ unstable( feature = "array_into_iter" , issue = "0" ) ]
443+ impl < T , A : FixedSizeArray < T > > DoubleEndedIterator for IntoIter < T , A > {
444+ #[ inline]
445+ fn next_back ( & mut self ) -> Option < T > {
446+ if self . index < self . index_back {
447+ self . index_back -= 1 ;
448+ let p = & self . array . as_slice ( ) [ self . index_back ] ;
449+ unsafe { Some ( ptr:: read ( p) ) }
450+ } else {
451+ None
452+ }
453+ }
454+ }
455+
456+ #[ unstable( feature = "array_into_iter" , issue = "0" ) ]
457+ impl < T , A : FixedSizeArray < T > > ExactSizeIterator for IntoIter < T , A > {
458+ #[ inline]
459+ fn len ( & self ) -> usize {
460+ self . index_back - self . index
461+ }
462+
463+ #[ inline]
464+ fn is_empty ( & self ) -> bool {
465+ self . index_back == self . index
466+ }
467+ }
468+
469+ #[ unstable( feature = "array_into_iter" , issue = "0" ) ]
470+ impl < T , A : FixedSizeArray < T > > FusedIterator for IntoIter < T , A > { }
471+
472+ // #[unstable(feature = "trusted_len", issue = "37572")]
473+ #[ unstable( feature = "array_into_iter" , issue = "0" ) ]
474+ unsafe impl < T , A : FixedSizeArray < T > > TrustedLen for IntoIter < T , A > { }
0 commit comments