@@ -69,6 +69,8 @@ use core::usize;
69
69
70
70
use borrow:: { Cow , IntoCow } ;
71
71
72
+ use super :: range:: RangeArgument ;
73
+
72
74
// FIXME- fix places which assume the max vector allowed has memory usize::MAX.
73
75
static MAX_MEMORY_SIZE : usize = isize:: MAX as usize ;
74
76
@@ -718,36 +720,61 @@ impl<T> Vec<T> {
718
720
unsafe { other. set_len ( 0 ) ; }
719
721
}
720
722
721
- /// Creates a draining iterator that clears the `Vec` and iterates over
722
- /// the removed items from start to end.
723
+ /// Create a draining iterator that removes the specified range in the vector
724
+ /// and yields the removed items from start to end. The element range is
725
+ /// removed even if the iterator is not consumed until the end.
726
+ ///
727
+ /// Note: It is unspecified how many elements are removed from the vector,
728
+ /// if the `Drain` value is leaked.
729
+ ///
730
+ /// # Panics
731
+ ///
732
+ /// Panics if the starting point is greater than the end point or if
733
+ /// the end point is greater than the length of the vector.
723
734
///
724
735
/// # Examples
725
736
///
726
737
/// ```
727
738
/// # #![feature(collections)]
728
- /// let mut v = vec!["a".to_string(), "b".to_string()];
729
- /// for s in v.drain() {
730
- /// // s has type String, not &String
731
- /// println!("{}", s );
732
- /// }
733
- /// assert!(v.is_empty() );
739
+ ///
740
+ /// // Draining using `..` clears the whole vector.
741
+ /// let mut v = vec![1, 2, 3];
742
+ /// let u: Vec<_> = v.drain(..).collect( );
743
+ /// assert_eq!(v, &[]);
744
+ /// assert_eq!(u, &[1, 2, 3] );
734
745
/// ```
735
- #[ inline]
736
746
#[ unstable( feature = "collections" ,
737
- reason = "matches collection reform specification, waiting for dust to settle" ) ]
738
- pub fn drain ( & mut self ) -> Drain < T > {
747
+ reason = "recently added, matches RFC" ) ]
748
+ pub fn drain < R > ( & mut self , range : R ) -> Drain < T > where
749
+ R : RangeArgument < usize > ,
750
+ {
751
+ // Memory safety
752
+ //
753
+ // When the Drain is first created, it shortens the length of
754
+ // the source vector to make sure no uninitalized or moved-from elements
755
+ // are accessible at all if the Drain's destructor never gets to run.
756
+ //
757
+ // Drain will ptr::read out the values to remove.
758
+ // When finished, remaining tail of the vec is copied back to cover
759
+ // the hole, and the vector length is restored to the new length.
760
+ //
761
+ let len = self . len ( ) ;
762
+ let start = * range. start ( ) . unwrap_or ( & 0 ) ;
763
+ let end = * range. end ( ) . unwrap_or ( & len) ;
764
+ assert ! ( start <= end) ;
765
+ assert ! ( end <= len) ;
766
+
739
767
unsafe {
740
- let begin = * self . ptr as * const T ;
741
- let end = if mem:: size_of :: < T > ( ) == 0 {
742
- ( * self . ptr as usize + self . len ( ) ) as * const T
743
- } else {
744
- ( * self . ptr ) . offset ( self . len ( ) as isize ) as * const T
745
- } ;
746
- self . set_len ( 0 ) ;
768
+ // set self.vec length's to start, to be safe in case Drain is leaked
769
+ self . set_len ( start) ;
770
+ let range_slice = slice:: from_raw_parts ( self . as_ptr ( ) . offset ( start as isize ) ,
771
+ end - start) ;
747
772
Drain {
748
- ptr : begin,
749
- end : end,
750
- marker : PhantomData ,
773
+ tail_start : end,
774
+ tail_len : len - end,
775
+ iter : range_slice. iter ( ) ,
776
+ vec : self as * mut _ ,
777
+ _marker : PhantomData ,
751
778
}
752
779
}
753
780
}
@@ -1799,95 +1826,92 @@ impl<T> Drop for IntoIter<T> {
1799
1826
}
1800
1827
}
1801
1828
1802
- /// An iterator that drains a vector.
1803
- #[ unsafe_no_drop_flag]
1804
- #[ unstable( feature = "collections" ,
1805
- reason = "recently added as part of collections reform 2" ) ]
1806
- pub struct Drain < ' a , T : ' a > {
1807
- ptr : * const T ,
1808
- end : * const T ,
1809
- marker : PhantomData < & ' a T > ,
1829
+ /// A draining iterator for `Vec<T>`.
1830
+ #[ unstable( feature = "collections" , reason = "recently added" ) ]
1831
+ pub struct Drain < ' a , T : ' a >
1832
+ {
1833
+ /// Index of tail to preserve
1834
+ tail_start : usize ,
1835
+ /// Length of tail
1836
+ tail_len : usize ,
1837
+ /// Current remaining range to remove
1838
+ iter : slice:: Iter < ' a , T > ,
1839
+ vec : * mut Vec < T > ,
1840
+ _marker : PhantomData < & ' a mut Vec < T > > ,
1810
1841
}
1811
1842
1812
1843
unsafe impl < ' a , T : Sync > Sync for Drain < ' a , T > { }
1813
1844
unsafe impl < ' a , T : Send > Send for Drain < ' a , T > { }
1814
1845
1815
1846
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
1816
- impl < ' a , T > Iterator for Drain < ' a , T > {
1847
+ impl < ' a , T > Iterator for Drain < ' a , T >
1848
+ {
1817
1849
type Item = T ;
1818
1850
1819
1851
#[ inline]
1820
- fn next ( & mut self ) -> Option < T > {
1821
- unsafe {
1822
- if self . ptr == self . end {
1823
- None
1824
- } else {
1825
- if mem:: size_of :: < T > ( ) == 0 {
1826
- // purposefully don't use 'ptr.offset' because for
1827
- // vectors with 0-size elements this would return the
1828
- // same pointer.
1829
- self . ptr = mem:: transmute ( self . ptr as usize + 1 ) ;
1830
-
1831
- // Use a non-null pointer value
1832
- Some ( ptr:: read ( EMPTY as * mut T ) )
1833
- } else {
1834
- let old = self . ptr ;
1835
- self . ptr = self . ptr . offset ( 1 ) ;
1836
-
1837
- Some ( ptr:: read ( old) )
1852
+ fn next ( & mut self ) -> Option < T >
1853
+ {
1854
+ match self . iter . next ( ) {
1855
+ None => None ,
1856
+ Some ( elt) => {
1857
+ unsafe {
1858
+ Some ( ptr:: read ( elt as * const _ ) )
1838
1859
}
1839
1860
}
1840
1861
}
1841
1862
}
1842
1863
1843
- #[ inline]
1844
- fn size_hint ( & self ) -> ( usize , Option < usize > ) {
1845
- let diff = ( self . end as usize ) - ( self . ptr as usize ) ;
1846
- let size = mem:: size_of :: < T > ( ) ;
1847
- let exact = diff / ( if size == 0 { 1 } else { size} ) ;
1848
- ( exact, Some ( exact) )
1864
+ fn size_hint ( & self ) -> ( usize , Option < usize > )
1865
+ {
1866
+ self . iter . size_hint ( )
1849
1867
}
1850
1868
}
1851
1869
1852
1870
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
1853
- impl < ' a , T > DoubleEndedIterator for Drain < ' a , T > {
1871
+ impl < ' a , T > DoubleEndedIterator for Drain < ' a , T >
1872
+ {
1854
1873
#[ inline]
1855
- fn next_back ( & mut self ) -> Option < T > {
1856
- unsafe {
1857
- if self . end == self . ptr {
1858
- None
1859
- } else {
1860
- if mem:: size_of :: < T > ( ) == 0 {
1861
- // See above for why 'ptr.offset' isn't used
1862
- self . end = mem:: transmute ( self . end as usize - 1 ) ;
1863
-
1864
- // Use a non-null pointer value
1865
- Some ( ptr:: read ( EMPTY as * mut T ) )
1866
- } else {
1867
- self . end = self . end . offset ( -1 ) ;
1868
-
1869
- Some ( ptr:: read ( self . end ) )
1874
+ fn next_back ( & mut self ) -> Option < T >
1875
+ {
1876
+ match self . iter . next_back ( ) {
1877
+ None => None ,
1878
+ Some ( elt) => {
1879
+ unsafe {
1880
+ Some ( ptr:: read ( elt as * const _ ) )
1870
1881
}
1871
1882
}
1872
1883
}
1873
1884
}
1874
1885
}
1875
1886
1876
- #[ stable( feature = "rust1" , since = "1.0.0" ) ]
1877
- impl < ' a , T > ExactSizeIterator for Drain < ' a , T > { }
1878
-
1879
1887
#[ unsafe_destructor]
1880
1888
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
1881
- impl < ' a , T > Drop for Drain < ' a , T > {
1882
- fn drop ( & mut self ) {
1883
- // self.ptr == self.end == mem::POST_DROP_USIZE if drop has already been called,
1884
- // so we can use #[unsafe_no_drop_flag].
1885
-
1886
- // destroy the remaining elements
1887
- for _x in self . by_ref ( ) { }
1889
+ impl < ' a , T > Drop for Drain < ' a , T >
1890
+ {
1891
+ fn drop ( & mut self )
1892
+ {
1893
+ // exhaust self first
1894
+ while let Some ( _) = self . next ( ) { }
1895
+
1896
+ if self . tail_len > 0 {
1897
+ unsafe {
1898
+ let source_vec = & mut * self . vec ;
1899
+ // memmove back untouched tail, update to new length
1900
+ let start = source_vec. len ( ) ;
1901
+ let tail = self . tail_start ;
1902
+ let src = source_vec. as_ptr ( ) . offset ( tail as isize ) ;
1903
+ let dst = source_vec. as_mut_ptr ( ) . offset ( start as isize ) ;
1904
+ ptr:: copy ( src, dst, self . tail_len ) ;
1905
+ source_vec. set_len ( start + self . tail_len ) ;
1906
+ }
1907
+ }
1888
1908
}
1889
1909
}
1890
1910
1911
+
1912
+ #[ stable( feature = "rust1" , since = "1.0.0" ) ]
1913
+ impl < ' a , T > ExactSizeIterator for Drain < ' a , T > { }
1914
+
1891
1915
////////////////////////////////////////////////////////////////////////////////
1892
1916
// Conversion from &[T] to &Vec<T>
1893
1917
////////////////////////////////////////////////////////////////////////////////
0 commit comments