@@ -403,6 +403,8 @@ where
403403 vec : & ' a mut SmallVec < T , N > ,
404404 /// The index of the item that will be inspected by the next call to `next`.
405405 idx : usize ,
406+ /// Elements at and beyond this point will be retained. Must be equal or smaller than `old_len`.
407+ end : usize ,
406408 /// The number of items that have been drained (removed) thus far.
407409 del : usize ,
408410 /// The original length of `vec` prior to draining.
@@ -433,7 +435,7 @@ where
433435
434436 fn next ( & mut self ) -> Option < T > {
435437 unsafe {
436- while self . idx < self . old_len {
438+ while self . idx < self . end {
437439 let i = self . idx ;
438440 let v = core:: slice:: from_raw_parts_mut ( self . vec . as_mut_ptr ( ) , self . old_len ) ;
439441 let drained = ( self . pred ) ( & mut v[ i] ) ;
@@ -456,7 +458,7 @@ where
456458 }
457459
458460 fn size_hint ( & self ) -> ( usize , Option < usize > ) {
459- ( 0 , Some ( self . old_len - self . idx ) )
461+ ( 0 , Some ( self . end - self . idx ) )
460462 }
461463}
462464
@@ -903,12 +905,15 @@ impl<T, const N: usize> SmallVec<T, N> {
903905 }
904906
905907 #[ 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.
907909 ///
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.
909911 /// If the closure returns false, the element will remain in the vector and will not be yielded
910912 /// by the iterator.
911913 ///
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+ ///
912917 /// If the returned `ExtractIf` is not exhausted, e.g. because it is dropped without iterating
913918 /// or the iteration short-circuits, then the remaining elements will be retained.
914919 /// 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> {
918923 /// Using this method is equivalent to the following code:
919924 /// ```
920925 /// # use smallvec::SmallVec;
926+ /// # use std::cmp::min;
921927 /// # let some_predicate = |x: &mut i32| { *x == 2 || *x == 3 || *x == 6 };
922928 /// # let mut vec: SmallVec<i32, 8> = SmallVec::from_slice(&[1i32, 2, 3, 4, 5, 6]);
929+ /// # let range = 1..4;
923930 /// let mut i = 0;
924- /// while i < vec.len() {
931+ /// while i < min( vec.len(), range.end ) {
925932 /// if some_predicate(&mut vec[i]) {
926933 /// let val = vec.remove(i);
927934 /// // your code here
@@ -936,8 +943,12 @@ impl<T, const N: usize> SmallVec<T, N> {
936943 /// But `extract_if` is easier to use. `extract_if` is also more efficient,
937944 /// because it can backshift the elements of the array in bulk.
938945 ///
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.
941952 ///
942953 /// # Examples
943954 ///
@@ -947,17 +958,58 @@ impl<T, const N: usize> SmallVec<T, N> {
947958 /// # use smallvec::SmallVec;
948959 /// let mut numbers: SmallVec<i32, 16> = SmallVec::from_slice(&[1i32, 2, 3, 4, 5, 6, 8, 9, 11, 13, 14, 15]);
949960 ///
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>>();
951962 /// let odds = numbers;
952963 ///
953964 /// assert_eq!(evens, SmallVec::<i32, 16>::from_slice(&[2i32, 4, 6, 8, 14]));
954965 /// assert_eq!(odds, SmallVec::<i32, 16>::from_slice(&[1i32, 3, 5, 9, 11, 13, 15]));
955966 /// ```
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 >
957978 where
958979 F : FnMut ( & mut T ) -> bool ,
980+ R : core:: ops:: RangeBounds < usize > ,
959981 {
960982 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+ } ;
9611013
9621014 // Guard against us getting leaked (leak amplification)
9631015 unsafe {
@@ -966,7 +1018,8 @@ impl<T, const N: usize> SmallVec<T, N> {
9661018
9671019 ExtractIf {
9681020 vec : self ,
969- idx : 0 ,
1021+ idx : start,
1022+ end,
9701023 del : 0 ,
9711024 old_len,
9721025 pred : filter,
0 commit comments