@@ -403,6 +403,8 @@ where
403
403
vec : & ' a mut SmallVec < T , N > ,
404
404
/// The index of the item that will be inspected by the next call to `next`.
405
405
idx : usize ,
406
+ /// Elements at and beyond this point will be retained. Must be equal or smaller than `old_len`.
407
+ end : usize ,
406
408
/// The number of items that have been drained (removed) thus far.
407
409
del : usize ,
408
410
/// The original length of `vec` prior to draining.
@@ -433,7 +435,7 @@ where
433
435
434
436
fn next ( & mut self ) -> Option < T > {
435
437
unsafe {
436
- while self . idx < self . old_len {
438
+ while self . idx < self . end {
437
439
let i = self . idx ;
438
440
let v = core:: slice:: from_raw_parts_mut ( self . vec . as_mut_ptr ( ) , self . old_len ) ;
439
441
let drained = ( self . pred ) ( & mut v[ i] ) ;
@@ -456,7 +458,7 @@ where
456
458
}
457
459
458
460
fn size_hint ( & self ) -> ( usize , Option < usize > ) {
459
- ( 0 , Some ( self . old_len - self . idx ) )
461
+ ( 0 , Some ( self . end - self . idx ) )
460
462
}
461
463
}
462
464
@@ -903,12 +905,15 @@ impl<T, const N: usize> SmallVec<T, N> {
903
905
}
904
906
905
907
#[ cfg( feature = "extract_if" ) ]
906
- /// Creates an iterator which uses a closure to determine if an element should be removed.
908
+ /// Creates an iterator which uses a closure to determine if element in the range should be removed.
907
909
///
908
- /// If the closure returns true, the element is removed and yielded.
910
+ /// If the closure returns true, then the element is removed and yielded.
909
911
/// If the closure returns false, the element will remain in the vector and will not be yielded
910
912
/// by the iterator.
911
913
///
914
+ /// Only elements that fall in the provided range are considered for extraction, but any elements
915
+ /// after the range will still have to be moved if any element has been extracted.
916
+ ///
912
917
/// If the returned `ExtractIf` is not exhausted, e.g. because it is dropped without iterating
913
918
/// or the iteration short-circuits, then the remaining elements will be retained.
914
919
/// Use [`retain`] with a negated predicate if you do not need the returned iterator.
@@ -918,10 +923,12 @@ impl<T, const N: usize> SmallVec<T, N> {
918
923
/// Using this method is equivalent to the following code:
919
924
/// ```
920
925
/// # use smallvec::SmallVec;
926
+ /// # use std::cmp::min;
921
927
/// # let some_predicate = |x: &mut i32| { *x == 2 || *x == 3 || *x == 6 };
922
928
/// # let mut vec: SmallVec<i32, 8> = SmallVec::from_slice(&[1i32, 2, 3, 4, 5, 6]);
929
+ /// # let range = 1..4;
923
930
/// let mut i = 0;
924
- /// while i < vec.len() {
931
+ /// while i < min( vec.len(), range.end ) {
925
932
/// if some_predicate(&mut vec[i]) {
926
933
/// let val = vec.remove(i);
927
934
/// // your code here
@@ -936,8 +943,12 @@ impl<T, const N: usize> SmallVec<T, N> {
936
943
/// But `extract_if` is easier to use. `extract_if` is also more efficient,
937
944
/// because it can backshift the elements of the array in bulk.
938
945
///
939
- /// Note that `extract_if` also lets you mutate every element in the filter closure,
940
- /// regardless of whether you choose to keep or remove it.
946
+ /// Note that `extract_if` also lets you mutate the elements passed to the filter closure,
947
+ /// regardless of whether you choose to keep or remove them.
948
+ ///
949
+ /// # Panics
950
+ ///
951
+ /// If `range` is out of bounds.
941
952
///
942
953
/// # Examples
943
954
///
@@ -947,17 +958,58 @@ impl<T, const N: usize> SmallVec<T, N> {
947
958
/// # use smallvec::SmallVec;
948
959
/// let mut numbers: SmallVec<i32, 16> = SmallVec::from_slice(&[1i32, 2, 3, 4, 5, 6, 8, 9, 11, 13, 14, 15]);
949
960
///
950
- /// let evens = numbers.extract_if(|x| *x % 2 == 0).collect::<SmallVec<i32, 16>>();
961
+ /// let evens = numbers.extract_if(.., |x| *x % 2 == 0).collect::<SmallVec<i32, 16>>();
951
962
/// let odds = numbers;
952
963
///
953
964
/// assert_eq!(evens, SmallVec::<i32, 16>::from_slice(&[2i32, 4, 6, 8, 14]));
954
965
/// assert_eq!(odds, SmallVec::<i32, 16>::from_slice(&[1i32, 3, 5, 9, 11, 13, 15]));
955
966
/// ```
956
- pub fn extract_if < F > ( & mut self , filter : F ) -> ExtractIf < ' _ , T , N , F >
967
+ ///
968
+ /// Using the range argument to only process a part of the vector:
969
+ ///
970
+ /// ```
971
+ /// # use smallvec::SmallVec;
972
+ /// let mut items: SmallVec<i32, 16> = SmallVec::from_slice(&[0, 0, 0, 0, 0, 0, 0, 1, 2, 1, 2, 1, 2]);
973
+ /// let ones = items.extract_if(7.., |x| *x == 1).collect::<SmallVec<i32, 16>>();
974
+ /// assert_eq!(items, SmallVec::<i32, 16>::from_slice(&[0, 0, 0, 0, 0, 0, 0, 2, 2, 2]));
975
+ /// assert_eq!(ones.len(), 3);
976
+ /// ```
977
+ pub fn extract_if < F , R > ( & mut self , range : R , filter : F ) -> ExtractIf < ' _ , T , N , F >
957
978
where
958
979
F : FnMut ( & mut T ) -> bool ,
980
+ R : core:: ops:: RangeBounds < usize > ,
959
981
{
960
982
let old_len = self . len ( ) ;
983
+ // This line can be used instead once `core::slice::range` is stable.
984
+ //let core::ops::Range { start, end } = core::slice::range(range, ..old_len);
985
+ let ( start, end) = {
986
+ let len = old_len;
987
+
988
+ let start = match range. start_bound ( ) {
989
+ core:: ops:: Bound :: Included ( & start) => start,
990
+ core:: ops:: Bound :: Excluded ( start) => {
991
+ start. checked_add ( 1 ) . unwrap_or_else ( || panic ! ( "attempted to index slice from after maximum usize" ) )
992
+ }
993
+ core:: ops:: Bound :: Unbounded => 0 ,
994
+ } ;
995
+
996
+ let end = match range. end_bound ( ) {
997
+ core:: ops:: Bound :: Included ( end) => {
998
+ end. checked_add ( 1 ) . unwrap_or_else ( || panic ! ( "attempted to index slice up to maximum usize" ) )
999
+ }
1000
+ core:: ops:: Bound :: Excluded ( & end) => end,
1001
+ core:: ops:: Bound :: Unbounded => len,
1002
+ } ;
1003
+
1004
+ if start > end {
1005
+ panic ! ( "slice index starts at {start} but ends at {end}" ) ;
1006
+ }
1007
+ if end > len {
1008
+ panic ! ( "range end index {end} out of range for slice of length {len}" ) ;
1009
+ }
1010
+
1011
+ ( start, end)
1012
+ } ;
961
1013
962
1014
// Guard against us getting leaked (leak amplification)
963
1015
unsafe {
@@ -966,7 +1018,8 @@ impl<T, const N: usize> SmallVec<T, N> {
966
1018
967
1019
ExtractIf {
968
1020
vec : self ,
969
- idx : 0 ,
1021
+ idx : start,
1022
+ end,
970
1023
del : 0 ,
971
1024
old_len,
972
1025
pred : filter,
0 commit comments