@@ -69,6 +69,8 @@ use core::usize;
6969
7070use borrow:: { Cow , IntoCow } ;
7171
72+ use super :: range:: RangeArgument ;
73+
7274// FIXME- fix places which assume the max vector allowed has memory usize::MAX.
7375static MAX_MEMORY_SIZE : usize = isize:: MAX as usize ;
7476
@@ -714,36 +716,61 @@ impl<T> Vec<T> {
714716 unsafe { other. set_len ( 0 ) ; }
715717 }
716718
717- /// Creates a draining iterator that clears the `Vec` and iterates over
718- /// the removed items from start to end.
719+ /// Create a draining iterator that removes the specified range in the vector
720+ /// and yields the removed items from start to end. The element range is
721+ /// removed even if the iterator is not consumed until the end.
722+ ///
723+ /// Note: It is unspecified how many elements are removed from the vector,
724+ /// if the `Drain` value is leaked.
725+ ///
726+ /// # Panics
727+ ///
728+ /// Panics if the starting point is greater than the end point or if
729+ /// the end point is greater than the length of the vector.
719730 ///
720731 /// # Examples
721732 ///
722733 /// ```
723- /// # #![feature(collections )]
724- /// let mut v = vec!["a".to_string(), "b".to_string()];
725- /// for s in v.drain() {
726- /// // s has type String, not &String
727- /// println!("{}", s );
728- /// }
729- /// assert!(v.is_empty() );
734+ /// # #![feature(collections_drain, collections_range )]
735+ ///
736+ /// // Draining using `..` clears the whole vector.
737+ /// let mut v = vec![1, 2, 3];
738+ /// let u: Vec<_> = v.drain(..).collect( );
739+ /// assert_eq!(v, &[]);
740+ /// assert_eq!(u, &[1, 2, 3] );
730741 /// ```
731- #[ inline]
732- #[ unstable( feature = "collections" ,
733- reason = "matches collection reform specification, waiting for dust to settle" ) ]
734- pub fn drain ( & mut self ) -> Drain < T > {
742+ #[ unstable( feature = "collections_drain" ,
743+ reason = "recently added, matches RFC" ) ]
744+ pub fn drain < R > ( & mut self , range : R ) -> Drain < T > where R : RangeArgument < usize > {
745+ // Memory safety
746+ //
747+ // When the Drain is first created, it shortens the length of
748+ // the source vector to make sure no uninitalized or moved-from elements
749+ // are accessible at all if the Drain's destructor never gets to run.
750+ //
751+ // Drain will ptr::read out the values to remove.
752+ // When finished, remaining tail of the vec is copied back to cover
753+ // the hole, and the vector length is restored to the new length.
754+ //
755+ let len = self . len ( ) ;
756+ let start = * range. start ( ) . unwrap_or ( & 0 ) ;
757+ let end = * range. end ( ) . unwrap_or ( & len) ;
758+ assert ! ( start <= end) ;
759+ assert ! ( end <= len) ;
760+
735761 unsafe {
736- let begin = * self . ptr as * const T ;
737- let end = if mem :: size_of :: < T > ( ) == 0 {
738- ( * self . ptr as usize + self . len ( ) ) as * const T
739- } else {
740- ( * self . ptr ) . offset ( self . len ( ) as isize ) as * const T
741- } ;
742- self . set_len ( 0 ) ;
762+ // set self.vec length's to start, to be safe in case Drain is leaked
763+ self . set_len ( start ) ;
764+ // Use the borrow in the IterMut to indicate borrowing behavior of the
765+ // whole Drain iterator (like &mut T).
766+ let range_slice = slice :: from_raw_parts_mut (
767+ self . as_mut_ptr ( ) . offset ( start as isize ) ,
768+ end - start ) ;
743769 Drain {
744- ptr : begin,
745- end : end,
746- marker : PhantomData ,
770+ tail_start : end,
771+ tail_len : len - end,
772+ iter : range_slice. iter_mut ( ) ,
773+ vec : self as * mut _ ,
747774 }
748775 }
749776 }
@@ -1795,14 +1822,16 @@ impl<T> Drop for IntoIter<T> {
17951822 }
17961823}
17971824
1798- /// An iterator that drains a vector.
1799- #[ unsafe_no_drop_flag]
1800- #[ unstable( feature = "collections" ,
1801- reason = "recently added as part of collections reform 2" ) ]
1802- pub struct Drain < ' a , T : ' a > {
1803- ptr : * const T ,
1804- end : * const T ,
1805- marker : PhantomData < & ' a T > ,
1825+ /// A draining iterator for `Vec<T>`.
1826+ #[ unstable( feature = "collections_drain" , reason = "recently added" ) ]
1827+ pub struct Drain < ' a , T : ' a > {
1828+ /// Index of tail to preserve
1829+ tail_start : usize ,
1830+ /// Length of tail
1831+ tail_len : usize ,
1832+ /// Current remaining range to remove
1833+ iter : slice:: IterMut < ' a , T > ,
1834+ vec : * mut Vec < T > ,
18061835}
18071836
18081837unsafe impl < ' a , T : Sync > Sync for Drain < ' a , T > { }
@@ -1814,76 +1843,56 @@ impl<'a, T> Iterator for Drain<'a, T> {
18141843
18151844 #[ inline]
18161845 fn next ( & mut self ) -> Option < T > {
1817- unsafe {
1818- if self . ptr == self . end {
1819- None
1820- } else {
1821- if mem:: size_of :: < T > ( ) == 0 {
1822- // purposefully don't use 'ptr.offset' because for
1823- // vectors with 0-size elements this would return the
1824- // same pointer.
1825- self . ptr = mem:: transmute ( self . ptr as usize + 1 ) ;
1826-
1827- // Use a non-null pointer value
1828- Some ( ptr:: read ( EMPTY as * mut T ) )
1829- } else {
1830- let old = self . ptr ;
1831- self . ptr = self . ptr . offset ( 1 ) ;
1832-
1833- Some ( ptr:: read ( old) )
1834- }
1846+ self . iter . next ( ) . map ( |elt|
1847+ unsafe {
1848+ ptr:: read ( elt as * const _ )
18351849 }
1836- }
1850+ )
18371851 }
18381852
1839- #[ inline]
18401853 fn size_hint ( & self ) -> ( usize , Option < usize > ) {
1841- let diff = ( self . end as usize ) - ( self . ptr as usize ) ;
1842- let size = mem:: size_of :: < T > ( ) ;
1843- let exact = diff / ( if size == 0 { 1 } else { size} ) ;
1844- ( exact, Some ( exact) )
1854+ self . iter . size_hint ( )
18451855 }
18461856}
18471857
18481858#[ stable( feature = "rust1" , since = "1.0.0" ) ]
18491859impl < ' a , T > DoubleEndedIterator for Drain < ' a , T > {
18501860 #[ inline]
18511861 fn next_back ( & mut self ) -> Option < T > {
1852- unsafe {
1853- if self . end == self . ptr {
1854- None
1855- } else {
1856- if mem:: size_of :: < T > ( ) == 0 {
1857- // See above for why 'ptr.offset' isn't used
1858- self . end = mem:: transmute ( self . end as usize - 1 ) ;
1859-
1860- // Use a non-null pointer value
1861- Some ( ptr:: read ( EMPTY as * mut T ) )
1862- } else {
1863- self . end = self . end . offset ( -1 ) ;
1864-
1865- Some ( ptr:: read ( self . end ) )
1866- }
1862+ self . iter . next_back ( ) . map ( |elt|
1863+ unsafe {
1864+ ptr:: read ( elt as * const _ )
18671865 }
1868- }
1866+ )
18691867 }
18701868}
18711869
1872- #[ stable( feature = "rust1" , since = "1.0.0" ) ]
1873- impl < ' a , T > ExactSizeIterator for Drain < ' a , T > { }
1874-
18751870#[ unsafe_destructor]
18761871#[ stable( feature = "rust1" , since = "1.0.0" ) ]
18771872impl < ' a , T > Drop for Drain < ' a , T > {
18781873 fn drop ( & mut self ) {
1879- // self.ptr == self.end == mem::POST_DROP_USIZE if drop has already been called,
1880- // so we can use #[unsafe_no_drop_flag].
1874+ // exhaust self first
1875+ while let Some ( _ ) = self . next ( ) { }
18811876
1882- // destroy the remaining elements
1883- for _x in self . by_ref ( ) { }
1877+ if self . tail_len > 0 {
1878+ unsafe {
1879+ let source_vec = & mut * self . vec ;
1880+ // memmove back untouched tail, update to new length
1881+ let start = source_vec. len ( ) ;
1882+ let tail = self . tail_start ;
1883+ let src = source_vec. as_ptr ( ) . offset ( tail as isize ) ;
1884+ let dst = source_vec. as_mut_ptr ( ) . offset ( start as isize ) ;
1885+ ptr:: copy ( src, dst, self . tail_len ) ;
1886+ source_vec. set_len ( start + self . tail_len ) ;
1887+ }
1888+ }
18841889 }
18851890}
18861891
1892+
1893+ #[ stable( feature = "rust1" , since = "1.0.0" ) ]
1894+ impl < ' a , T > ExactSizeIterator for Drain < ' a , T > { }
1895+
18871896////////////////////////////////////////////////////////////////////////////////
18881897// Conversion from &[T] to &Vec<T>
18891898////////////////////////////////////////////////////////////////////////////////
0 commit comments