@@ -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,57 @@ 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
+ /// let mut items: SmallVec<i32, 16> = SmallVec::from_slice(&[0, 0, 0, 0, 0, 0, 0, 1, 2, 1, 2, 1, 2]);
972
+ /// let ones = items.extract_if(7.., |x| *x == 1).collect::<SmallVec<i32, 16>>();
973
+ /// assert_eq!(items, SmallVec<i32, 16>::from_slice(&[0, 0, 0, 0, 0, 0, 0, 2, 2, 2]));
974
+ /// assert_eq!(ones.len(), 3);
975
+ /// ```
976
+ pub fn extract_if < F , R > ( & mut self , range : R , filter : F ) -> ExtractIf < ' _ , T , N , F >
957
977
where
958
978
F : FnMut ( & mut T ) -> bool ,
979
+ R : core:: ops:: RangeBounds < usize > ,
959
980
{
960
981
let old_len = self . len ( ) ;
982
+ // This line can be used instead once `core::slice::range` is stable.
983
+ //let core::ops::Range { start, end } = core::slice::range(range, ..old_len);
984
+ let ( start, end) = {
985
+ let len = old_len;
986
+
987
+ let start = match range. start_bound ( ) {
988
+ core:: ops:: Bound :: Included ( & start) => start,
989
+ core:: ops:: Bound :: Excluded ( start) => {
990
+ start. checked_add ( 1 ) . unwrap_or_else ( || panic ! ( "attempted to index slice from after maximum usize" ) )
991
+ }
992
+ core:: ops:: Bound :: Unbounded => 0 ,
993
+ } ;
994
+
995
+ let end = match range. end_bound ( ) {
996
+ core:: ops:: Bound :: Included ( end) => {
997
+ end. checked_add ( 1 ) . unwrap_or_else ( || panic ! ( "attempted to index slice up to maximum usize" ) )
998
+ }
999
+ core:: ops:: Bound :: Excluded ( & end) => end,
1000
+ core:: ops:: Bound :: Unbounded => len,
1001
+ } ;
1002
+
1003
+ if start > end {
1004
+ panic ! ( "slice index starts at {start} but ends at {end}" ) ;
1005
+ }
1006
+ if end > len {
1007
+ panic ! ( "range end index {end} out of range for slice of length {len}" ) ;
1008
+ }
1009
+
1010
+ ( start, end)
1011
+ } ;
961
1012
962
1013
// Guard against us getting leaked (leak amplification)
963
1014
unsafe {
@@ -966,7 +1017,8 @@ impl<T, const N: usize> SmallVec<T, N> {
966
1017
967
1018
ExtractIf {
968
1019
vec : self ,
969
- idx : 0 ,
1020
+ idx : start,
1021
+ end,
970
1022
del : 0 ,
971
1023
old_len,
972
1024
pred : filter,
0 commit comments