@@ -845,11 +845,12 @@ impl<T> Vec<T> {
845
845
#[ inline]
846
846
pub fn into_iter ( self ) -> MoveItems < T > {
847
847
unsafe {
848
- let iter = mem:: transmute ( self . as_slice ( ) . iter ( ) ) ;
849
848
let ptr = self . ptr ;
850
849
let cap = self . cap ;
850
+ let begin = self . ptr as * const T ;
851
+ let end = ( self . ptr as uint + self . len ( ) ) as * const T ;
851
852
mem:: forget ( self ) ;
852
- MoveItems { allocation : ptr, cap : cap, iter : iter }
853
+ MoveItems { allocation : ptr, cap : cap, ptr : begin , end : end }
853
854
}
854
855
}
855
856
@@ -1773,7 +1774,8 @@ impl<T> MutableSeq<T> for Vec<T> {
1773
1774
pub struct MoveItems < T > {
1774
1775
allocation : * mut T , // the block of memory allocated for the vector
1775
1776
cap : uint , // the capacity of the vector
1776
- iter : Items < ' static , T >
1777
+ ptr : * const T ,
1778
+ end : * const T
1777
1779
}
1778
1780
1779
1781
impl < T > MoveItems < T > {
@@ -1793,29 +1795,55 @@ impl<T> Iterator<T> for MoveItems<T> {
1793
1795
#[ inline]
1794
1796
fn next < ' a > ( & ' a mut self ) -> Option < T > {
1795
1797
unsafe {
1796
- // Unsafely transmute from Items<'static, T> to Items<'a,
1797
- // T> because otherwise the type checker requires that T
1798
- // be bounded by 'static.
1799
- let iter: & mut Items < ' a , T > = mem:: transmute ( & mut self . iter ) ;
1800
- iter. next ( ) . map ( |x| ptr:: read ( x) )
1798
+ if self . ptr == self . end {
1799
+ None
1800
+ } else {
1801
+ if mem:: size_of :: < T > ( ) == 0 {
1802
+ // purposefully don't use 'ptr.offset' because for
1803
+ // vectors with 0-size elements this would return the
1804
+ // same pointer.
1805
+ self . ptr = mem:: transmute ( self . ptr as uint + 1 ) ;
1806
+
1807
+ // Use a non-null pointer value
1808
+ Some ( ptr:: read ( mem:: transmute ( 1 u) ) )
1809
+ } else {
1810
+ let old = self . ptr ;
1811
+ self . ptr = self . ptr . offset ( 1 ) ;
1812
+
1813
+ Some ( ptr:: read ( old) )
1814
+ }
1815
+ }
1801
1816
}
1802
1817
}
1803
1818
1804
1819
#[ inline]
1805
1820
fn size_hint ( & self ) -> ( uint , Option < uint > ) {
1806
- self . iter . size_hint ( )
1821
+ let diff = ( self . end as uint ) - ( self . ptr as uint ) ;
1822
+ let size = mem:: size_of :: < T > ( ) ;
1823
+ let exact = diff / ( if size == 0 { 1 } else { size} ) ;
1824
+ ( exact, Some ( exact) )
1807
1825
}
1808
1826
}
1809
1827
1810
1828
impl < T > DoubleEndedIterator < T > for MoveItems < T > {
1811
1829
#[ inline]
1812
1830
fn next_back < ' a > ( & ' a mut self ) -> Option < T > {
1813
1831
unsafe {
1814
- // Unsafely transmute from Items<'static, T> to Items<'a,
1815
- // T> because otherwise the type checker requires that T
1816
- // be bounded by 'static.
1817
- let iter: & mut Items < ' a , T > = mem:: transmute ( & mut self . iter ) ;
1818
- iter. next_back ( ) . map ( |x| ptr:: read ( x) )
1832
+ if self . end == self . ptr {
1833
+ None
1834
+ } else {
1835
+ if mem:: size_of :: < T > ( ) == 0 {
1836
+ // See above for why 'ptr.offset' isn't used
1837
+ self . end = mem:: transmute ( self . end as uint - 1 ) ;
1838
+
1839
+ // Use a non-null pointer value
1840
+ Some ( ptr:: read ( mem:: transmute ( 1 u) ) )
1841
+ } else {
1842
+ self . end = self . end . offset ( -1 ) ;
1843
+
1844
+ Some ( ptr:: read ( mem:: transmute ( self . end ) ) )
1845
+ }
1846
+ }
1819
1847
}
1820
1848
}
1821
1849
}
0 commit comments