@@ -160,7 +160,7 @@ use core::ops::Bound;
160160use core:: ops:: { Deref , DerefMut , RangeBounds } ;
161161use core:: ptr:: NonNull ;
162162use core:: slice:: Iter ;
163- use core:: { fmt, mem, ptr, slice} ;
163+ use core:: { fmt, mem, ops , ptr, slice} ;
164164
165165use impl_details:: * ;
166166
@@ -1591,20 +1591,85 @@ impl<T> ThinVec<T> {
15911591 /// assert_eq!(evens, thin_vec![2, 4, 6, 8, 14]);
15921592 /// assert_eq!(odds, thin_vec![1, 3, 5, 9, 11, 13, 15]);
15931593 /// ```
1594- pub fn extract_if < F > ( & mut self , filter : F ) -> ExtractIf < ' _ , T , F >
1594+ pub fn extract_if < F , R : RangeBounds < usize > > (
1595+ & mut self ,
1596+ filter : F ,
1597+ range : R ,
1598+ ) -> ExtractIf < ' _ , T , F >
15951599 where
15961600 F : FnMut ( & mut T ) -> bool ,
15971601 {
1602+ // Copy of https://github.com/rust-lang/rust/blob/ee361e8fca1c30e13e7a31cc82b64c045339d3a8/library/core/src/slice/index.rs#L37
1603+ fn slice_index_fail ( start : usize , end : usize , len : usize ) -> ! {
1604+ if start > len {
1605+ panic ! (
1606+ "range start index {} out of range for slice of length {}" ,
1607+ start, len
1608+ )
1609+ }
1610+
1611+ if end > len {
1612+ panic ! (
1613+ "range end index {} out of range for slice of length {}" ,
1614+ end, len
1615+ )
1616+ }
1617+
1618+ if start > end {
1619+ panic ! ( "slice index starts at {} but ends at {}" , start, end)
1620+ }
1621+
1622+ // Only reachable if the range was a `RangeInclusive` or a
1623+ // `RangeToInclusive`, with `end == len`.
1624+ panic ! (
1625+ "range end index {} out of range for slice of length {}" ,
1626+ end, len
1627+ )
1628+ }
1629+
1630+ // Backport of https://github.com/rust-lang/rust/blob/ee361e8fca1c30e13e7a31cc82b64c045339d3a8/library/core/src/slice/index.rs#L855
1631+ pub fn slice_range < R > ( range : R , bounds : ops:: RangeTo < usize > ) -> ops:: Range < usize >
1632+ where
1633+ R : ops:: RangeBounds < usize > ,
1634+ {
1635+ let len = bounds. end ;
1636+
1637+ let end = match range. end_bound ( ) {
1638+ ops:: Bound :: Included ( & end) if end >= len => slice_index_fail ( 0 , end, len) ,
1639+ // Cannot overflow because `end < len` implies `end < usize::MAX`.
1640+ ops:: Bound :: Included ( & end) => end + 1 ,
1641+
1642+ ops:: Bound :: Excluded ( & end) if end > len => slice_index_fail ( 0 , end, len) ,
1643+ ops:: Bound :: Excluded ( & end) => end,
1644+ ops:: Bound :: Unbounded => len,
1645+ } ;
1646+
1647+ let start = match range. start_bound ( ) {
1648+ ops:: Bound :: Excluded ( & start) if start >= end => slice_index_fail ( start, end, len) ,
1649+ // Cannot overflow because `start < end` implies `start < usize::MAX`.
1650+ ops:: Bound :: Excluded ( & start) => start + 1 ,
1651+
1652+ ops:: Bound :: Included ( & start) if start > end => slice_index_fail ( start, end, len) ,
1653+ ops:: Bound :: Included ( & start) => start,
1654+
1655+ ops:: Bound :: Unbounded => 0 ,
1656+ } ;
1657+
1658+ ops:: Range { start, end }
1659+ }
1660+
15981661 let old_len = self . len ( ) ;
1599- // Guard against us getting leaked (leak amplification)
1662+ let ops:: Range { start, end } = slice_range ( range, ..old_len) ;
1663+
1664+ // Guard against the vec getting leaked (leak amplification)
16001665 unsafe {
16011666 self . set_len ( 0 ) ;
16021667 }
1603-
16041668 ExtractIf {
16051669 vec : self ,
1606- idx : 0 ,
1670+ idx : start ,
16071671 del : 0 ,
1672+ end,
16081673 old_len,
16091674 pred : filter,
16101675 }
@@ -2851,6 +2916,8 @@ pub struct ExtractIf<'a, T, F> {
28512916 vec : & ' a mut ThinVec < T > ,
28522917 /// The index of the item that will be inspected by the next call to `next`.
28532918 idx : usize ,
2919+ /// Elements at and beyond this point will be retained. Must be equal or smaller than `old_len`.
2920+ end : usize ,
28542921 /// The number of items that have been drained (removed) thus far.
28552922 del : usize ,
28562923 /// The original length of `vec` prior to draining.
@@ -2865,9 +2932,9 @@ where
28652932{
28662933 type Item = T ;
28672934
2868- fn next ( & mut self ) -> Option < Self :: Item > {
2935+ fn next ( & mut self ) -> Option < T > {
28692936 unsafe {
2870- while self . idx < self . old_len {
2937+ while self . idx < self . end {
28712938 let i = self . idx ;
28722939 let v = slice:: from_raw_parts_mut ( self . vec . as_mut_ptr ( ) , self . old_len ) ;
28732940 let drained = ( self . pred ) ( & mut v[ i] ) ;
@@ -2890,7 +2957,7 @@ where
28902957 }
28912958
28922959 fn size_hint ( & self ) -> ( usize , Option < usize > ) {
2893- ( 0 , Some ( self . old_len - self . idx ) )
2960+ ( 0 , Some ( self . end - self . idx ) )
28942961 }
28952962}
28962963
0 commit comments