@@ -380,6 +380,191 @@ impl<'a, T: 'a, const N: usize> Drop for Drain<'a, T, N> {
380
380
}
381
381
}
382
382
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
+
383
568
/// An iterator that consumes a `SmallVec` and yields its items by value.
384
569
///
385
570
/// Returned from [`SmallVec::into_iter`][1].
@@ -732,6 +917,71 @@ impl<T, const N: usize> SmallVec<T, N> {
732
917
}
733
918
}
734
919
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
+
735
985
#[ inline]
736
986
pub fn push ( & mut self , value : T ) {
737
987
let len = self . len ( ) ;
0 commit comments