@@ -380,6 +380,191 @@ impl<'a, T: 'a, const N: usize> Drop for Drain<'a, T, N> {
380380 }
381381}
382382
383+ #[ cfg( feature = "drain_filter" ) ]
384+ /// An iterator which uses a closure to determine if an element should be removed.
385+ ///
386+ /// Returned from [`SmallVec::drain_filter`][1].
387+ ///
388+ /// [1]: struct.SmallVec.html#method.drain_filter
389+ pub struct DrainFilter < ' a , T , const N : usize , F >
390+ where
391+ F : FnMut ( & mut T ) -> bool ,
392+ {
393+ vec : & ' a mut SmallVec < T , N > ,
394+ /// The index of the item that will be inspected by the next call to `next`.
395+ idx : usize ,
396+ /// The number of items that have been drained (removed) thus far.
397+ del : usize ,
398+ /// The original length of `vec` prior to draining.
399+ old_len : usize ,
400+ /// The filter test predicate.
401+ pred : F ,
402+ /// A flag that indicates a panic has occurred in the filter test predicate.
403+ /// This is used as a hint in the drop implementation to prevent consumption
404+ /// of the remainder of the `DrainFilter`. Any unprocessed items will be
405+ /// backshifted in the `vec`, but no further items will be dropped or
406+ /// tested by the filter predicate.
407+ panic_flag : bool ,
408+ }
409+
410+ #[ cfg( feature = "drain_filter" ) ]
411+ impl < T , const N : usize , F > core:: fmt:: Debug for DrainFilter < ' _ , T , N , F >
412+ where
413+ F : FnMut ( & mut T ) -> bool ,
414+ T : core:: fmt:: Debug ,
415+ {
416+ fn fmt ( & self , f : & mut core:: fmt:: Formatter < ' _ > ) -> core:: fmt:: Result {
417+ f. debug_tuple ( "DrainFilter" )
418+ . field ( & self . vec . as_slice ( ) )
419+ . finish ( )
420+ }
421+ }
422+
423+ #[ cfg( feature = "drain_filter" ) ]
424+ impl < T , F , const N : usize > Iterator for DrainFilter < ' _ , T , N , F >
425+ where
426+ F : FnMut ( & mut T ) -> bool ,
427+ {
428+ type Item = T ;
429+
430+ fn next ( & mut self ) -> Option < T > {
431+ unsafe {
432+ while self . idx < self . old_len {
433+ let i = self . idx ;
434+ let v = core:: slice:: from_raw_parts_mut ( self . vec . as_mut_ptr ( ) , self . old_len ) ;
435+ self . panic_flag = true ;
436+ let drained = ( self . pred ) ( & mut v[ i] ) ;
437+ self . panic_flag = false ;
438+ // Update the index *after* the predicate is called. If the index
439+ // is updated prior and the predicate panics, the element at this
440+ // index would be leaked.
441+ self . idx += 1 ;
442+ if drained {
443+ self . del += 1 ;
444+ return Some ( core:: ptr:: read ( & v[ i] ) ) ;
445+ } else if self . del > 0 {
446+ let del = self . del ;
447+ let src: * const Self :: Item = & v[ i] ;
448+ let dst: * mut Self :: Item = & mut v[ i - del] ;
449+ core:: ptr:: copy_nonoverlapping ( src, dst, 1 ) ;
450+ }
451+ }
452+ None
453+ }
454+ }
455+
456+ fn size_hint ( & self ) -> ( usize , Option < usize > ) {
457+ ( 0 , Some ( self . old_len - self . idx ) )
458+ }
459+ }
460+
461+ #[ cfg( feature = "drain_filter" ) ]
462+ impl < T , F , const N : usize > Drop for DrainFilter < ' _ , T , N , F >
463+ where
464+ F : FnMut ( & mut T ) -> bool ,
465+ {
466+ fn drop ( & mut self ) {
467+ struct BackshiftOnDrop < ' a , ' b , T , const N : usize , F >
468+ where
469+ F : FnMut ( & mut T ) -> bool ,
470+ {
471+ drain : & ' b mut DrainFilter < ' a , T , N , F > ,
472+ }
473+
474+ impl < ' a , ' b , T , const N : usize , F > Drop for BackshiftOnDrop < ' a , ' b , T , N , F >
475+ where
476+ F : FnMut ( & mut T ) -> bool ,
477+ {
478+ fn drop ( & mut self ) {
479+ unsafe {
480+ if self . drain . idx < self . drain . old_len && self . drain . del > 0 {
481+ // This is a pretty messed up state, and there isn't really an
482+ // obviously right thing to do. We don't want to keep trying
483+ // to execute `pred`, so we just backshift all the unprocessed
484+ // elements and tell the vec that they still exist. The backshift
485+ // is required to prevent a double-drop of the last successfully
486+ // drained item prior to a panic in the predicate.
487+ let ptr = self . drain . vec . as_mut_ptr ( ) ;
488+ let src = ptr. add ( self . drain . idx ) ;
489+ let dst = src. sub ( self . drain . del ) ;
490+ let tail_len = self . drain . old_len - self . drain . idx ;
491+ src. copy_to ( dst, tail_len) ;
492+ }
493+ self . drain . vec . set_len ( self . drain . old_len - self . drain . del ) ;
494+ }
495+ }
496+ }
497+
498+ let backshift = BackshiftOnDrop { drain : self } ;
499+
500+ // Attempt to consume any remaining elements if the filter predicate
501+ // has not yet panicked. We'll backshift any remaining elements
502+ // whether we've already panicked or if the consumption here panics.
503+ if !backshift. drain . panic_flag {
504+ backshift. drain . for_each ( drop) ;
505+ }
506+ }
507+ }
508+
509+ #[ cfg( feature = "drain_keep_rest" ) ]
510+ impl < T , F , const N : usize > DrainFilter < ' _ , T , N , F >
511+ where
512+ F : FnMut ( & mut T ) -> bool ,
513+ {
514+ /// Keep unyielded elements in the source `Vec`.
515+ ///
516+ /// # Examples
517+ ///
518+ /// ```
519+ /// # use smallvec::{smallvec, SmallVec};
520+ ///
521+ /// let mut vec: SmallVec<char, 2> = smallvec!['a', 'b', 'c'];
522+ /// let mut drain = vec.drain_filter(|_| true);
523+ ///
524+ /// assert_eq!(drain.next().unwrap(), 'a');
525+ ///
526+ /// // This call keeps 'b' and 'c' in the vec.
527+ /// drain.keep_rest();
528+ ///
529+ /// // If we wouldn't call `keep_rest()`,
530+ /// // `vec` would be empty.
531+ /// assert_eq!(vec, SmallVec::<char, 2>::from_slice(&['b', 'c']));
532+ /// ```
533+ pub fn keep_rest ( self ) {
534+ // At this moment layout looks like this:
535+ //
536+ // _____________________/-- old_len
537+ // / \
538+ // [kept] [yielded] [tail]
539+ // \_______/ ^-- idx
540+ // \-- del
541+ //
542+ // Normally `Drop` impl would drop [tail] (via .for_each(drop), ie still calling `pred`)
543+ //
544+ // 1. Move [tail] after [kept]
545+ // 2. Update length of the original vec to `old_len - del`
546+ // a. In case of ZST, this is the only thing we want to do
547+ // 3. Do *not* drop self, as everything is put in a consistent state already, there is nothing to do
548+ let mut this = ManuallyDrop :: new ( self ) ;
549+
550+ unsafe {
551+ // ZSTs have no identity, so we don't need to move them around.
552+ let needs_move = core:: mem:: size_of :: < T > ( ) != 0 ;
553+
554+ if needs_move && this. idx < this. old_len && this. del > 0 {
555+ let ptr = this. vec . as_mut_ptr ( ) ;
556+ let src = ptr. add ( this. idx ) ;
557+ let dst = src. sub ( this. del ) ;
558+ let tail_len = this. old_len - this. idx ;
559+ src. copy_to ( dst, tail_len) ;
560+ }
561+
562+ let new_len = this. old_len - this. del ;
563+ this. vec . set_len ( new_len) ;
564+ }
565+ }
566+ }
567+
383568/// An iterator that consumes a `SmallVec` and yields its items by value.
384569///
385570/// Returned from [`SmallVec::into_iter`][1].
@@ -732,6 +917,71 @@ impl<T, const N: usize> SmallVec<T, N> {
732917 }
733918 }
734919
920+ #[ cfg( feature = "drain_filter" ) ]
921+ /// Creates an iterator which uses a closure to determine if an element should be removed.
922+ ///
923+ /// If the closure returns true, the element is removed and yielded. If the closure returns
924+ /// false, the element will remain in the vector and will not be yielded by the iterator.
925+ ///
926+ /// Using this method is equivalent to the following code:
927+ /// ```
928+ /// # use smallvec::SmallVec;
929+ /// # let some_predicate = |x: &mut i32| { *x == 2 || *x == 3 || *x == 6 };
930+ /// # let mut vec: SmallVec<i32, 8> = SmallVec::from_slice(&[1i32, 2, 3, 4, 5, 6]);
931+ /// let mut i = 0;
932+ /// while i < vec.len() {
933+ /// if some_predicate(&mut vec[i]) {
934+ /// let val = vec.remove(i);
935+ /// // your code here
936+ /// } else {
937+ /// i += 1;
938+ /// }
939+ /// }
940+ ///
941+ /// # assert_eq!(vec, SmallVec::<i32, 8>::from_slice(&[1i32, 4, 5]));
942+ /// ```
943+ /// ///
944+ /// But `drain_filter` is easier to use. `drain_filter` is also more efficient,
945+ /// because it can backshift the elements of the array in bulk.
946+ ///
947+ /// Note that `drain_filter` also lets you mutate every element in the filter closure,
948+ /// regardless of whether you choose to keep or remove it.
949+ ///
950+ /// # Examples
951+ ///
952+ /// Splitting an array into evens and odds, reusing the original allocation:
953+ ///
954+ /// ```
955+ /// # use smallvec::SmallVec;
956+ /// let mut numbers: SmallVec<i32, 16> = SmallVec::from_slice(&[1i32, 2, 3, 4, 5, 6, 8, 9, 11, 13, 14, 15]);
957+ ///
958+ /// let evens = numbers.drain_filter(|x| *x % 2 == 0).collect::<SmallVec<i32, 16>>();
959+ /// let odds = numbers;
960+ ///
961+ /// assert_eq!(evens, SmallVec::<i32, 16>::from_slice(&[2i32, 4, 6, 8, 14]));
962+ /// assert_eq!(odds, SmallVec::<i32, 16>::from_slice(&[1i32, 3, 5, 9, 11, 13, 15]));
963+ /// ```
964+ pub fn drain_filter < F > ( & mut self , filter : F ) -> DrainFilter < ' _ , T , N , F >
965+ where
966+ F : FnMut ( & mut T ) -> bool ,
967+ {
968+ let old_len = self . len ( ) ;
969+
970+ // Guard against us getting leaked (leak amplification)
971+ unsafe {
972+ self . set_len ( 0 ) ;
973+ }
974+
975+ DrainFilter {
976+ vec : self ,
977+ idx : 0 ,
978+ del : 0 ,
979+ old_len,
980+ pred : filter,
981+ panic_flag : false ,
982+ }
983+ }
984+
735985 #[ inline]
736986 pub fn push ( & mut self , value : T ) {
737987 let len = self . len ( ) ;
0 commit comments