26
26
//! When this feature is enabled, `SmallVec<u8, _>` implements the `std::io::Write` trait.
27
27
//! This feature is not compatible with `#![no_std]` programs.
28
28
//!
29
- //! ### `drain_filter `
29
+ //! ### `extract_if `
30
30
//!
31
- //! **This feature is unstable.** It may change to match the unstable `drain_filter ` method in libstd.
31
+ //! **This feature is unstable.** It may change to match the unstable `extract_if ` method in libstd.
32
32
//!
33
- //! Enables the `drain_filter ` method, which produces an iterator that calls a user-provided
33
+ //! Enables the `extract_if ` method, which produces an iterator that calls a user-provided
34
34
//! closure to determine which elements of the vector to remove and yield from the iterator.
35
35
//!
36
36
//! ### `specialization`
@@ -380,13 +380,13 @@ impl<'a, T: 'a, const N: usize> Drop for Drain<'a, T, N> {
380
380
}
381
381
}
382
382
383
- #[ cfg( feature = "drain_filter " ) ]
383
+ #[ cfg( feature = "extract_if " ) ]
384
384
/// An iterator which uses a closure to determine if an element should be removed.
385
385
///
386
- /// Returned from [`SmallVec::drain_filter `][1].
386
+ /// Returned from [`SmallVec::extract_if `][1].
387
387
///
388
- /// [1]: struct.SmallVec.html#method.drain_filter
389
- pub struct DrainFilter < ' a , T , const N : usize , F >
388
+ /// [1]: struct.SmallVec.html#method.extract_if
389
+ pub struct ExtractIf < ' a , T , const N : usize , F >
390
390
where
391
391
F : FnMut ( & mut T ) -> bool ,
392
392
{
@@ -399,29 +399,23 @@ where
399
399
old_len : usize ,
400
400
/// The filter test predicate.
401
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
402
}
409
403
410
- #[ cfg( feature = "drain_filter " ) ]
411
- impl < T , const N : usize , F > core:: fmt:: Debug for DrainFilter < ' _ , T , N , F >
404
+ #[ cfg( feature = "extract_if " ) ]
405
+ impl < T , const N : usize , F > core:: fmt:: Debug for ExtractIf < ' _ , T , N , F >
412
406
where
413
407
F : FnMut ( & mut T ) -> bool ,
414
408
T : core:: fmt:: Debug ,
415
409
{
416
410
fn fmt ( & self , f : & mut core:: fmt:: Formatter < ' _ > ) -> core:: fmt:: Result {
417
- f. debug_tuple ( "DrainFilter " )
411
+ f. debug_tuple ( "ExtractIf " )
418
412
. field ( & self . vec . as_slice ( ) )
419
413
. finish ( )
420
414
}
421
415
}
422
416
423
- #[ cfg( feature = "drain_filter " ) ]
424
- impl < T , F , const N : usize > Iterator for DrainFilter < ' _ , T , N , F >
417
+ #[ cfg( feature = "extract_if " ) ]
418
+ impl < T , F , const N : usize > Iterator for ExtractIf < ' _ , T , N , F >
425
419
where
426
420
F : FnMut ( & mut T ) -> bool ,
427
421
{
@@ -432,9 +426,7 @@ where
432
426
while self . idx < self . old_len {
433
427
let i = self . idx ;
434
428
let v = core:: slice:: from_raw_parts_mut ( self . vec . as_mut_ptr ( ) , self . old_len ) ;
435
- self . panic_flag = true ;
436
429
let drained = ( self . pred ) ( & mut v[ i] ) ;
437
- self . panic_flag = false ;
438
430
// Update the index *after* the predicate is called. If the index
439
431
// is updated prior and the predicate panics, the element at this
440
432
// index would be leaked.
@@ -444,8 +436,8 @@ where
444
436
return Some ( core:: ptr:: read ( & v[ i] ) ) ;
445
437
} else if self . del > 0 {
446
438
let del = self . del ;
447
- let src: * const Self :: Item = & v[ i] ;
448
- let dst: * mut Self :: Item = & mut v[ i - del] ;
439
+ let src: * const T = & v[ i] ;
440
+ let dst: * mut T = & mut v[ i - del] ;
449
441
core:: ptr:: copy_nonoverlapping ( src, dst, 1 ) ;
450
442
}
451
443
}
@@ -458,109 +450,27 @@ where
458
450
}
459
451
}
460
452
461
- #[ cfg( feature = "drain_filter " ) ]
462
- impl < T , F , const N : usize > Drop for DrainFilter < ' _ , T , N , F >
453
+ #[ cfg( feature = "extract_if " ) ]
454
+ impl < T , F , const N : usize > Drop for ExtractIf < ' _ , T , N , F >
463
455
where
464
456
F : FnMut ( & mut T ) -> bool ,
465
457
{
466
458
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
459
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 ;
460
+ if self . idx < self . old_len && self . del > 0 {
461
+ // This is a pretty messed up state, and there isn't really an
462
+ // obviously right thing to do. We don't want to keep trying
463
+ // to execute `pred`, so we just backshift all the unprocessed
464
+ // elements and tell the vec that they still exist. The backshift
465
+ // is required to prevent a double-drop of the last successfully
466
+ // drained item prior to a panic in the predicate.
467
+ let ptr = self . vec . as_mut_ptr ( ) ;
468
+ let src = ptr. add ( self . idx ) ;
469
+ let dst = src. sub ( self . del ) ;
470
+ let tail_len = self . old_len - self . idx ;
559
471
src. copy_to ( dst, tail_len) ;
560
472
}
561
-
562
- let new_len = this. old_len - this. del ;
563
- this. vec . set_len ( new_len) ;
473
+ self . vec . set_len ( self . old_len - self . del ) ;
564
474
}
565
475
}
566
476
}
@@ -961,11 +871,18 @@ impl<T, const N: usize> SmallVec<T, N> {
961
871
}
962
872
}
963
873
964
- #[ cfg( feature = "drain_filter " ) ]
874
+ #[ cfg( feature = "extract_if " ) ]
965
875
/// Creates an iterator which uses a closure to determine if an element should be removed.
966
876
///
967
- /// If the closure returns true, the element is removed and yielded. If the closure returns
968
- /// false, the element will remain in the vector and will not be yielded by the iterator.
877
+ /// If the closure returns true, the element is removed and yielded.
878
+ /// If the closure returns false, the element will remain in the vector and will not be yielded
879
+ /// by the iterator.
880
+ ///
881
+ /// If the returned `ExtractIf` is not exhausted, e.g. because it is dropped without iterating
882
+ /// or the iteration short-circuits, then the remaining elements will be retained.
883
+ /// Use [`retain`] with a negated predicate if you do not need the returned iterator.
884
+ ///
885
+ /// [`retain`]: SmallVec::retain
969
886
///
970
887
/// Using this method is equivalent to the following code:
971
888
/// ```
@@ -984,11 +901,11 @@ impl<T, const N: usize> SmallVec<T, N> {
984
901
///
985
902
/// # assert_eq!(vec, SmallVec::<i32, 8>::from_slice(&[1i32, 4, 5]));
986
903
/// ```
987
- /// ///
988
- /// But `drain_filter ` is easier to use. `drain_filter ` is also more efficient,
904
+ ///
905
+ /// But `extract_if ` is easier to use. `extract_if ` is also more efficient,
989
906
/// because it can backshift the elements of the array in bulk.
990
907
///
991
- /// Note that `drain_filter ` also lets you mutate every element in the filter closure,
908
+ /// Note that `extract_if ` also lets you mutate every element in the filter closure,
992
909
/// regardless of whether you choose to keep or remove it.
993
910
///
994
911
/// # Examples
@@ -999,13 +916,13 @@ impl<T, const N: usize> SmallVec<T, N> {
999
916
/// # use smallvec::SmallVec;
1000
917
/// let mut numbers: SmallVec<i32, 16> = SmallVec::from_slice(&[1i32, 2, 3, 4, 5, 6, 8, 9, 11, 13, 14, 15]);
1001
918
///
1002
- /// let evens = numbers.drain_filter (|x| *x % 2 == 0).collect::<SmallVec<i32, 16>>();
919
+ /// let evens = numbers.extract_if (|x| *x % 2 == 0).collect::<SmallVec<i32, 16>>();
1003
920
/// let odds = numbers;
1004
921
///
1005
922
/// assert_eq!(evens, SmallVec::<i32, 16>::from_slice(&[2i32, 4, 6, 8, 14]));
1006
923
/// assert_eq!(odds, SmallVec::<i32, 16>::from_slice(&[1i32, 3, 5, 9, 11, 13, 15]));
1007
924
/// ```
1008
- pub fn drain_filter < F > ( & mut self , filter : F ) -> DrainFilter < ' _ , T , N , F >
925
+ pub fn extract_if < F > ( & mut self , filter : F ) -> ExtractIf < ' _ , T , N , F >
1009
926
where
1010
927
F : FnMut ( & mut T ) -> bool ,
1011
928
{
@@ -1016,13 +933,12 @@ impl<T, const N: usize> SmallVec<T, N> {
1016
933
self . set_len ( 0 ) ;
1017
934
}
1018
935
1019
- DrainFilter {
936
+ ExtractIf {
1020
937
vec : self ,
1021
938
idx : 0 ,
1022
939
del : 0 ,
1023
940
old_len,
1024
941
pred : filter,
1025
- panic_flag : false ,
1026
942
}
1027
943
}
1028
944
0 commit comments