@@ -60,13 +60,13 @@ use std::hash::{Hash, Hasher};
6060use std:: hint:: unreachable_unchecked;
6161#[ cfg( feature = "std" ) ]
6262use std:: io;
63- use std:: iter:: { repeat, FromIterator , IntoIterator } ;
63+ use std:: iter:: { repeat, FromIterator , FusedIterator , IntoIterator } ;
6464#[ cfg( feature = "serde" ) ]
6565use std:: marker:: PhantomData ;
6666use std:: mem;
6767use std:: mem:: MaybeUninit ;
68- use std:: ops;
69- use std:: ptr;
68+ use std:: ops:: { self , Bound , RangeBounds } ;
69+ use std:: ptr:: { self , NonNull } ;
7070use std:: slice:: { self , SliceIndex } ;
7171
7272/// Creates a [`SmallVec`] containing the arguments.
@@ -182,15 +182,30 @@ unsafe fn deallocate<T>(ptr: *mut T, capacity: usize) {
182182/// Returned from [`SmallVec::drain`][1].
183183///
184184/// [1]: struct.SmallVec.html#method.drain
185- pub struct Drain < ' a , T : ' a > {
186- iter : slice:: IterMut < ' a , T > ,
185+ pub struct Drain < ' a , T : ' a + Array > {
186+ tail_start : usize ,
187+ tail_len : usize ,
188+ iter : slice:: Iter < ' a , T :: Item > ,
189+ vec : NonNull < SmallVec < T > > ,
187190}
188191
189- impl < ' a , T : ' a > Iterator for Drain < ' a , T > {
190- type Item = T ;
192+ impl < ' a , T : ' a + Array > fmt:: Debug for Drain < ' a , T >
193+ where
194+ T :: Item : fmt:: Debug ,
195+ {
196+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
197+ f. debug_tuple ( "Drain" ) . field ( & self . iter . as_slice ( ) ) . finish ( )
198+ }
199+ }
200+
201+ unsafe impl < ' a , T : Sync + Array > Sync for Drain < ' a , T > { }
202+ unsafe impl < ' a , T : Send + Array > Send for Drain < ' a , T > { }
203+
204+ impl < ' a , T : ' a + Array > Iterator for Drain < ' a , T > {
205+ type Item = T :: Item ;
191206
192207 #[ inline]
193- fn next ( & mut self ) -> Option < T > {
208+ fn next ( & mut self ) -> Option < T :: Item > {
194209 self . iter
195210 . next ( )
196211 . map ( |reference| unsafe { ptr:: read ( reference) } )
@@ -202,21 +217,43 @@ impl<'a, T: 'a> Iterator for Drain<'a, T> {
202217 }
203218}
204219
205- impl < ' a , T : ' a > DoubleEndedIterator for Drain < ' a , T > {
220+ impl < ' a , T : ' a + Array > DoubleEndedIterator for Drain < ' a , T > {
206221 #[ inline]
207- fn next_back ( & mut self ) -> Option < T > {
222+ fn next_back ( & mut self ) -> Option < T :: Item > {
208223 self . iter
209224 . next_back ( )
210225 . map ( |reference| unsafe { ptr:: read ( reference) } )
211226 }
212227}
213228
214- impl < ' a , T > ExactSizeIterator for Drain < ' a , T > { }
229+ impl < ' a , T : Array > ExactSizeIterator for Drain < ' a , T > {
230+ #[ inline]
231+ fn len ( & self ) -> usize {
232+ self . iter . len ( )
233+ }
234+ }
215235
216- impl < ' a , T : ' a > Drop for Drain < ' a , T > {
236+ impl < ' a , T : Array > FusedIterator for Drain < ' a , T > { }
237+
238+ impl < ' a , T : ' a + Array > Drop for Drain < ' a , T > {
217239 fn drop ( & mut self ) {
218- // Destroy the remaining elements.
219- for _ in self . by_ref ( ) { }
240+ self . for_each ( drop) ;
241+
242+ if self . tail_len > 0 {
243+ unsafe {
244+ let source_vec = self . vec . as_mut ( ) ;
245+
246+ // memmove back untouched tail, update to new length
247+ let start = source_vec. len ( ) ;
248+ let tail = self . tail_start ;
249+ if tail != start {
250+ let src = source_vec. as_ptr ( ) . add ( tail) ;
251+ let dst = source_vec. as_mut_ptr ( ) . add ( start) ;
252+ ptr:: copy ( src, dst, self . tail_len ) ;
253+ }
254+ source_vec. set_len ( start + self . tail_len ) ;
255+ }
256+ }
220257 }
221258}
222259
@@ -548,18 +585,50 @@ impl<A: Array> SmallVec<A> {
548585 self . capacity > A :: size ( )
549586 }
550587
551- /// Empty the vector and return an iterator over its former contents.
552- pub fn drain ( & mut self ) -> Drain < A :: Item > {
553- unsafe {
554- let ptr = self . as_mut_ptr ( ) ;
588+ /// Creates a draining iterator that removes the specified range in the vector
589+ /// and yields the removed items.
590+ ///
591+ /// Note 1: The element range is removed even if the iterator is only
592+ /// partially consumed or not consumed at all.
593+ ///
594+ /// Note 2: It is unspecified how many elements are removed from the vector
595+ /// if the `Drain` value is leaked.
596+ ///
597+ /// # Panics
598+ ///
599+ /// Panics if the starting point is greater than the end point or if
600+ /// the end point is greater than the length of the vector.
601+ pub fn drain < R > ( & mut self , range : R ) -> Drain < A >
602+ where
603+ R : RangeBounds < usize > ,
604+ {
605+ use Bound :: * ;
555606
556- let current_len = self . len ( ) ;
557- self . set_len ( 0 ) ;
607+ let len = self . len ( ) ;
608+ let start = match range. start_bound ( ) {
609+ Included ( & n) => n,
610+ Excluded ( & n) => n + 1 ,
611+ Unbounded => 0 ,
612+ } ;
613+ let end = match range. end_bound ( ) {
614+ Included ( & n) => n + 1 ,
615+ Excluded ( & n) => n,
616+ Unbounded => len,
617+ } ;
618+
619+ assert ! ( start <= end) ;
620+ assert ! ( end <= len) ;
621+
622+ unsafe {
623+ self . set_len ( start) ;
558624
559- let slice = slice:: from_raw_parts_mut ( ptr , current_len ) ;
625+ let range_slice = slice:: from_raw_parts_mut ( self . as_mut_ptr ( ) . add ( start ) , end - start ) ;
560626
561627 Drain {
562- iter : slice. iter_mut ( ) ,
628+ tail_start : end,
629+ tail_len : len - end,
630+ iter : range_slice. iter ( ) ,
631+ vec : NonNull :: from ( self ) ,
563632 }
564633 }
565634 }
@@ -1697,26 +1766,36 @@ mod tests {
16971766 fn drain ( ) {
16981767 let mut v: SmallVec < [ u8 ; 2 ] > = SmallVec :: new ( ) ;
16991768 v. push ( 3 ) ;
1700- assert_eq ! ( v. drain( ) . collect:: <Vec <_>>( ) , & [ 3 ] ) ;
1769+ assert_eq ! ( v. drain( .. ) . collect:: <Vec <_>>( ) , & [ 3 ] ) ;
17011770
17021771 // spilling the vec
17031772 v. push ( 3 ) ;
17041773 v. push ( 4 ) ;
17051774 v. push ( 5 ) ;
1706- assert_eq ! ( v. drain( ) . collect:: <Vec <_>>( ) , & [ 3 , 4 , 5 ] ) ;
1775+ let old_capacity = v. capacity ( ) ;
1776+ assert_eq ! ( v. drain( 1 ..) . collect:: <Vec <_>>( ) , & [ 4 , 5 ] ) ;
1777+ // drain should not change the capacity
1778+ assert_eq ! ( v. capacity( ) , old_capacity) ;
17071779 }
17081780
17091781 #[ test]
17101782 fn drain_rev ( ) {
17111783 let mut v: SmallVec < [ u8 ; 2 ] > = SmallVec :: new ( ) ;
17121784 v. push ( 3 ) ;
1713- assert_eq ! ( v. drain( ) . rev( ) . collect:: <Vec <_>>( ) , & [ 3 ] ) ;
1785+ assert_eq ! ( v. drain( .. ) . rev( ) . collect:: <Vec <_>>( ) , & [ 3 ] ) ;
17141786
17151787 // spilling the vec
17161788 v. push ( 3 ) ;
17171789 v. push ( 4 ) ;
17181790 v. push ( 5 ) ;
1719- assert_eq ! ( v. drain( ) . rev( ) . collect:: <Vec <_>>( ) , & [ 5 , 4 , 3 ] ) ;
1791+ assert_eq ! ( v. drain( ..) . rev( ) . collect:: <Vec <_>>( ) , & [ 5 , 4 , 3 ] ) ;
1792+ }
1793+
1794+ #[ test]
1795+ fn drain_forget ( ) {
1796+ let mut v: SmallVec < [ u8 ; 1 ] > = smallvec ! [ 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 ] ;
1797+ std:: mem:: forget ( v. drain ( 2 ..5 ) ) ;
1798+ assert_eq ! ( v. len( ) , 2 ) ;
17201799 }
17211800
17221801 #[ test]
@@ -2157,7 +2236,8 @@ mod tests {
21572236 fn test_exact_size_iterator ( ) {
21582237 let mut vec = SmallVec :: < [ u32 ; 2 ] > :: from ( & [ 1 , 2 , 3 ] [ ..] ) ;
21592238 assert_eq ! ( vec. clone( ) . into_iter( ) . len( ) , 3 ) ;
2160- assert_eq ! ( vec. drain( ) . len( ) , 3 ) ;
2239+ assert_eq ! ( vec. drain( ..2 ) . len( ) , 2 ) ;
2240+ assert_eq ! ( vec. into_iter( ) . len( ) , 1 ) ;
21612241 }
21622242
21632243 #[ test]
0 commit comments