@@ -791,11 +791,16 @@ impl<T> Vec<T> {
791
791
#[ inline]
792
792
pub fn into_iter ( self ) -> MoveItems < T > {
793
793
unsafe {
794
- let iter = mem:: transmute ( self . as_slice ( ) . iter ( ) ) ;
795
794
let ptr = self . ptr ;
796
795
let cap = self . cap ;
796
+ let begin = self . ptr as * const T ;
797
+ let end = if mem:: size_of :: < T > ( ) == 0 {
798
+ ( ptr as uint + self . len ( ) ) as * const T
799
+ } else {
800
+ ptr. offset ( self . len ( ) as int ) as * const T
801
+ } ;
797
802
mem:: forget ( self ) ;
798
- MoveItems { allocation : ptr, cap : cap, iter : iter }
803
+ MoveItems { allocation : ptr, cap : cap, ptr : begin , end : end }
799
804
}
800
805
}
801
806
@@ -1719,7 +1724,8 @@ impl<T> MutableSeq<T> for Vec<T> {
1719
1724
pub struct MoveItems < T > {
1720
1725
allocation : * mut T , // the block of memory allocated for the vector
1721
1726
cap : uint , // the capacity of the vector
1722
- iter : Items < ' static , T >
1727
+ ptr : * const T ,
1728
+ end : * const T
1723
1729
}
1724
1730
1725
1731
impl < T > MoveItems < T > {
@@ -1728,7 +1734,7 @@ impl<T> MoveItems<T> {
1728
1734
pub fn unwrap ( mut self ) -> Vec < T > {
1729
1735
unsafe {
1730
1736
for _x in self { }
1731
- let MoveItems { allocation, cap, iter : _iter } = self ;
1737
+ let MoveItems { allocation, cap, ptr : _ptr , end : _end } = self ;
1732
1738
mem:: forget ( self ) ;
1733
1739
Vec { ptr : allocation, cap : cap, len : 0 }
1734
1740
}
@@ -1739,29 +1745,55 @@ impl<T> Iterator<T> for MoveItems<T> {
1739
1745
#[ inline]
1740
1746
fn next < ' a > ( & ' a mut self ) -> Option < T > {
1741
1747
unsafe {
1742
- // Unsafely transmute from Items<'static, T> to Items<'a,
1743
- // T> because otherwise the type checker requires that T
1744
- // be bounded by 'static.
1745
- let iter: & mut Items < ' a , T > = mem:: transmute ( & mut self . iter ) ;
1746
- iter. next ( ) . map ( |x| ptr:: read ( x) )
1748
+ if self . ptr == self . end {
1749
+ None
1750
+ } else {
1751
+ if mem:: size_of :: < T > ( ) == 0 {
1752
+ // purposefully don't use 'ptr.offset' because for
1753
+ // vectors with 0-size elements this would return the
1754
+ // same pointer.
1755
+ self . ptr = mem:: transmute ( self . ptr as uint + 1 ) ;
1756
+
1757
+ // Use a non-null pointer value
1758
+ Some ( ptr:: read ( mem:: transmute ( 1 u) ) )
1759
+ } else {
1760
+ let old = self . ptr ;
1761
+ self . ptr = self . ptr . offset ( 1 ) ;
1762
+
1763
+ Some ( ptr:: read ( old) )
1764
+ }
1765
+ }
1747
1766
}
1748
1767
}
1749
1768
1750
1769
#[ inline]
1751
1770
fn size_hint ( & self ) -> ( uint , Option < uint > ) {
1752
- self . iter . size_hint ( )
1771
+ let diff = ( self . end as uint ) - ( self . ptr as uint ) ;
1772
+ let size = mem:: size_of :: < T > ( ) ;
1773
+ let exact = diff / ( if size == 0 { 1 } else { size} ) ;
1774
+ ( exact, Some ( exact) )
1753
1775
}
1754
1776
}
1755
1777
1756
1778
impl < T > DoubleEndedIterator < T > for MoveItems < T > {
1757
1779
#[ inline]
1758
1780
fn next_back < ' a > ( & ' a mut self ) -> Option < T > {
1759
1781
unsafe {
1760
- // Unsafely transmute from Items<'static, T> to Items<'a,
1761
- // T> because otherwise the type checker requires that T
1762
- // be bounded by 'static.
1763
- let iter: & mut Items < ' a , T > = mem:: transmute ( & mut self . iter ) ;
1764
- iter. next_back ( ) . map ( |x| ptr:: read ( x) )
1782
+ if self . end == self . ptr {
1783
+ None
1784
+ } else {
1785
+ if mem:: size_of :: < T > ( ) == 0 {
1786
+ // See above for why 'ptr.offset' isn't used
1787
+ self . end = mem:: transmute ( self . end as uint - 1 ) ;
1788
+
1789
+ // Use a non-null pointer value
1790
+ Some ( ptr:: read ( mem:: transmute ( 1 u) ) )
1791
+ } else {
1792
+ self . end = self . end . offset ( -1 ) ;
1793
+
1794
+ Some ( ptr:: read ( mem:: transmute ( self . end ) ) )
1795
+ }
1796
+ }
1765
1797
}
1766
1798
}
1767
1799
}
@@ -2473,6 +2505,36 @@ mod tests {
2473
2505
assert_eq ! ( v. map_in_place( |_| ZeroSized ) . as_slice( ) , [ ZeroSized , ZeroSized ] . as_slice( ) ) ;
2474
2506
}
2475
2507
2508
+ #[ test]
2509
+ fn test_move_items ( ) {
2510
+ let mut vec = vec ! ( 1 i, 2 , 3 ) ;
2511
+ let mut vec2 : Vec < int > = vec ! ( ) ;
2512
+ for i in vec. into_iter ( ) {
2513
+ vec2. push ( i) ;
2514
+ }
2515
+ assert ! ( vec2 == vec!( 1 i, 2 , 3 ) ) ;
2516
+ }
2517
+
2518
+ #[ test]
2519
+ fn test_move_items_reverse ( ) {
2520
+ let mut vec = vec ! ( 1 i, 2 , 3 ) ;
2521
+ let mut vec2 : Vec < int > = vec ! ( ) ;
2522
+ for i in vec. into_iter ( ) . rev ( ) {
2523
+ vec2. push ( i) ;
2524
+ }
2525
+ assert ! ( vec2 == vec!( 3 i, 2 , 1 ) ) ;
2526
+ }
2527
+
2528
+ #[ test]
2529
+ fn test_move_items_zero_sized ( ) {
2530
+ let mut vec = vec ! ( ( ) , ( ) , ( ) ) ;
2531
+ let mut vec2 : Vec < ( ) > = vec ! ( ) ;
2532
+ for i in vec. into_iter ( ) {
2533
+ vec2. push ( i) ;
2534
+ }
2535
+ assert ! ( vec2 == vec!( ( ) , ( ) , ( ) ) ) ;
2536
+ }
2537
+
2476
2538
#[ bench]
2477
2539
fn bench_new ( b : & mut Bencher ) {
2478
2540
b. iter ( || {
0 commit comments