@@ -625,6 +625,36 @@ impl<'a, T> IntoIterator for &'a mut [T] {
625625 }
626626}
627627
628+ #[ inline( always) ]
629+ fn size_from_ptr < T > ( _: * const T ) -> usize {
630+ mem:: size_of :: < T > ( )
631+ }
632+
633+
634+ // Use macro to be generic over const/mut
635+ macro_rules! slice_offset {
636+ ( $ptr: expr, $by: expr) => { {
637+ let ptr = $ptr;
638+ if size_from_ptr( ptr) == 0 {
639+ transmute( ptr as usize + $by)
640+ } else {
641+ ptr. offset( $by)
642+ }
643+ } } ;
644+ }
645+
646+ macro_rules! slice_ref {
647+ ( $ptr: expr) => { {
648+ let ptr = $ptr;
649+ if size_from_ptr( ptr) == 0 {
650+ // Use a non-null pointer value
651+ & mut * ( 1 as * mut _)
652+ } else {
653+ transmute( ptr)
654+ }
655+ } } ;
656+ }
657+
628658// The shared definition of the `Iter` and `IterMut` iterators
629659macro_rules! iterator {
630660 ( struct $name: ident -> $ptr: ty, $elem: ty) => {
@@ -641,20 +671,9 @@ macro_rules! iterator {
641671 if self . ptr == self . end {
642672 None
643673 } else {
644- if mem:: size_of:: <T >( ) == 0 {
645- // purposefully don't use 'ptr.offset' because for
646- // vectors with 0-size elements this would return the
647- // same pointer.
648- self . ptr = transmute( self . ptr as usize + 1 ) ;
649-
650- // Use a non-null pointer value
651- Some ( & mut * ( 1 as * mut _) )
652- } else {
653- let old = self . ptr;
654- self . ptr = self . ptr. offset( 1 ) ;
655-
656- Some ( transmute( old) )
657- }
674+ let old = self . ptr;
675+ self . ptr = slice_offset!( self . ptr, 1 ) ;
676+ Some ( slice_ref!( old) )
658677 }
659678 }
660679 }
@@ -666,6 +685,22 @@ macro_rules! iterator {
666685 let exact = diff / ( if size == 0 { 1 } else { size} ) ;
667686 ( exact, Some ( exact) )
668687 }
688+
689+ #[ inline]
690+ fn count( self ) -> usize {
691+ self . size_hint( ) . 0
692+ }
693+
694+ #[ inline]
695+ fn nth( & mut self , n: usize ) -> Option <$elem> {
696+ // Call helper method. Can't put the definition here because mut versus const.
697+ self . iter_nth( n)
698+ }
699+
700+ #[ inline]
701+ fn last( mut self ) -> Option <$elem> {
702+ self . next_back( )
703+ }
669704 }
670705
671706 #[ stable( feature = "rust1" , since = "1.0.0" ) ]
@@ -679,17 +714,8 @@ macro_rules! iterator {
679714 if self . end == self . ptr {
680715 None
681716 } else {
682- if mem:: size_of:: <T >( ) == 0 {
683- // See above for why 'ptr.offset' isn't used
684- self . end = transmute( self . end as usize - 1 ) ;
685-
686- // Use a non-null pointer value
687- Some ( & mut * ( 1 as * mut _) )
688- } else {
689- self . end = self . end. offset( -1 ) ;
690-
691- Some ( transmute( self . end) )
692- }
717+ self . end = slice_offset!( self . end, -1 ) ;
718+ Some ( slice_ref!( self . end) )
693719 }
694720 }
695721 }
@@ -785,6 +811,20 @@ impl<'a, T> Iter<'a, T> {
785811 pub fn as_slice ( & self ) -> & ' a [ T ] {
786812 make_slice ! ( T => & ' a [ T ] : self . ptr, self . end)
787813 }
814+
815+ // Helper function for Iter::nth
816+ fn iter_nth ( & mut self , n : usize ) -> Option < & ' a T > {
817+ match self . as_slice ( ) . get ( n) {
818+ Some ( elem_ref) => unsafe {
819+ self . ptr = slice_offset ! ( elem_ref as * const _, 1 ) ;
820+ Some ( slice_ref ! ( elem_ref) )
821+ } ,
822+ None => {
823+ self . ptr = self . end ;
824+ None
825+ }
826+ }
827+ }
788828}
789829
790830iterator ! { struct Iter -> * const T , & ' a T }
@@ -914,6 +954,20 @@ impl<'a, T> IterMut<'a, T> {
914954 pub fn into_slice ( self ) -> & ' a mut [ T ] {
915955 make_mut_slice ! ( T => & ' a mut [ T ] : self . ptr, self . end)
916956 }
957+
958+ // Helper function for IterMut::nth
959+ fn iter_nth ( & mut self , n : usize ) -> Option < & ' a mut T > {
960+ match make_mut_slice ! ( T => & ' a mut [ T ] : self . ptr, self . end) . get_mut ( n) {
961+ Some ( elem_ref) => unsafe {
962+ self . ptr = slice_offset ! ( elem_ref as * mut _, 1 ) ;
963+ Some ( slice_ref ! ( elem_ref) )
964+ } ,
965+ None => {
966+ self . ptr = self . end ;
967+ None
968+ }
969+ }
970+ }
917971}
918972
919973iterator ! { struct IterMut -> * mut T , & ' a mut T }
0 commit comments