@@ -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
@@ -718,36 +720,61 @@ impl<T> Vec<T> {
718720 unsafe { other. set_len ( 0 ) ; }
719721 }
720722
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.
723734 ///
724735 /// # Examples
725736 ///
726737 /// ```
727- /// # #![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() );
738+ /// # #![feature(collections_drain, collections_range )]
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] );
734745 /// ```
735- #[ inline]
736- #[ unstable( feature = "collections" ,
737- reason = "matches collection reform specification, waiting for dust to settle" ) ]
738- pub fn drain ( & mut self ) -> Drain < T > {
746+ #[ unstable( feature = "collections_drain" ,
747+ reason = "recently added, matches RFC" ) ]
748+ pub fn drain < R > ( & mut self , range : R ) -> Drain < T > where R : RangeArgument < usize > {
749+ // Memory safety
750+ //
751+ // When the Drain is first created, it shortens the length of
752+ // the source vector to make sure no uninitalized or moved-from elements
753+ // are accessible at all if the Drain's destructor never gets to run.
754+ //
755+ // Drain will ptr::read out the values to remove.
756+ // When finished, remaining tail of the vec is copied back to cover
757+ // the hole, and the vector length is restored to the new length.
758+ //
759+ let len = self . len ( ) ;
760+ let start = * range. start ( ) . unwrap_or ( & 0 ) ;
761+ let end = * range. end ( ) . unwrap_or ( & len) ;
762+ assert ! ( start <= end) ;
763+ assert ! ( end <= len) ;
764+
739765 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 ) ;
766+ // set self.vec length's to start, to be safe in case Drain is leaked
767+ self . set_len ( start ) ;
768+ // Use the borrow in the IterMut to indicate borrowing behavior of the
769+ // whole Drain iterator (like &mut T).
770+ let range_slice = slice :: from_raw_parts_mut (
771+ self . as_mut_ptr ( ) . offset ( start as isize ) ,
772+ end - start ) ;
747773 Drain {
748- ptr : begin,
749- end : end,
750- marker : PhantomData ,
774+ tail_start : end,
775+ tail_len : len - end,
776+ iter : range_slice. iter_mut ( ) ,
777+ vec : self as * mut _ ,
751778 }
752779 }
753780 }
@@ -1799,14 +1826,16 @@ impl<T> Drop for IntoIter<T> {
17991826 }
18001827}
18011828
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_drain" , reason = "recently added" ) ]
1831+ pub struct Drain < ' a , T : ' a > {
1832+ /// Index of tail to preserve
1833+ tail_start : usize ,
1834+ /// Length of tail
1835+ tail_len : usize ,
1836+ /// Current remaining range to remove
1837+ iter : slice:: IterMut < ' a , T > ,
1838+ vec : * mut Vec < T > ,
18101839}
18111840
18121841unsafe impl < ' a , T : Sync > Sync for Drain < ' a , T > { }
@@ -1818,76 +1847,56 @@ impl<'a, T> Iterator for Drain<'a, T> {
18181847
18191848 #[ inline]
18201849 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) )
1838- }
1850+ self . iter . next ( ) . map ( |elt|
1851+ unsafe {
1852+ ptr:: read ( elt as * const _ )
18391853 }
1840- }
1854+ )
18411855 }
18421856
1843- #[ inline]
18441857 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) )
1858+ self . iter . size_hint ( )
18491859 }
18501860}
18511861
18521862#[ stable( feature = "rust1" , since = "1.0.0" ) ]
18531863impl < ' a , T > DoubleEndedIterator for Drain < ' a , T > {
18541864 #[ inline]
18551865 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 ) )
1870- }
1866+ self . iter . next_back ( ) . map ( |elt|
1867+ unsafe {
1868+ ptr:: read ( elt as * const _ )
18711869 }
1872- }
1870+ )
18731871 }
18741872}
18751873
1876- #[ stable( feature = "rust1" , since = "1.0.0" ) ]
1877- impl < ' a , T > ExactSizeIterator for Drain < ' a , T > { }
1878-
18791874#[ unsafe_destructor]
18801875#[ stable( feature = "rust1" , since = "1.0.0" ) ]
18811876impl < ' a , T > Drop for Drain < ' a , T > {
18821877 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].
1878+ // exhaust self first
1879+ while let Some ( _ ) = self . next ( ) { }
18851880
1886- // destroy the remaining elements
1887- for _x in self . by_ref ( ) { }
1881+ if self . tail_len > 0 {
1882+ unsafe {
1883+ let source_vec = & mut * self . vec ;
1884+ // memmove back untouched tail, update to new length
1885+ let start = source_vec. len ( ) ;
1886+ let tail = self . tail_start ;
1887+ let src = source_vec. as_ptr ( ) . offset ( tail as isize ) ;
1888+ let dst = source_vec. as_mut_ptr ( ) . offset ( start as isize ) ;
1889+ ptr:: copy ( src, dst, self . tail_len ) ;
1890+ source_vec. set_len ( start + self . tail_len ) ;
1891+ }
1892+ }
18881893 }
18891894}
18901895
1896+
1897+ #[ stable( feature = "rust1" , since = "1.0.0" ) ]
1898+ impl < ' a , T > ExactSizeIterator for Drain < ' a , T > { }
1899+
18911900////////////////////////////////////////////////////////////////////////////////
18921901// Conversion from &[T] to &Vec<T>
18931902////////////////////////////////////////////////////////////////////////////////
0 commit comments