Skip to content

Commit 05b52b7

Browse files
committed
Add Range parameter to BTreeMap::extract_if and BTreeSet::extract_if
This change was requested in the extract_if tracking issue: rust-lang#70530 (comment) Related: rust-lang#70530
1 parent fe348cd commit 05b52b7

File tree

2 files changed

+50
-19
lines changed

2 files changed

+50
-19
lines changed

library/alloc/src/collections/btree/map.rs

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1151,7 +1151,7 @@ impl<K, V, A: Allocator + Clone> BTreeMap<K, V, A> {
11511151
K: Ord,
11521152
F: FnMut(&K, &mut V) -> bool,
11531153
{
1154-
self.extract_if(|k, v| !f(k, v)).for_each(drop);
1154+
self.extract_if(.., |k, v| !f(k, v)).for_each(drop);
11551155
}
11561156

11571157
/// Moves all elements from `other` into `self`, leaving `other` empty.
@@ -1427,27 +1427,30 @@ impl<K, V, A: Allocator + Clone> BTreeMap<K, V, A> {
14271427
/// assert_eq!(odds.keys().copied().collect::<Vec<_>>(), [1, 3, 5, 7]);
14281428
/// ```
14291429
#[unstable(feature = "btree_extract_if", issue = "70530")]
1430-
pub fn extract_if<F>(&mut self, pred: F) -> ExtractIf<'_, K, V, F, A>
1430+
pub fn extract_if<F, R>(&mut self, range: R, pred: F) -> ExtractIf<'_, K, V, R, F, A>
14311431
where
14321432
K: Ord,
1433+
R: RangeBounds<K>,
14331434
F: FnMut(&K, &mut V) -> bool,
14341435
{
1435-
let (inner, alloc) = self.extract_if_inner();
1436+
let (inner, alloc) = self.extract_if_inner(range);
14361437
ExtractIf { pred, inner, alloc }
14371438
}
14381439

1439-
pub(super) fn extract_if_inner(&mut self) -> (ExtractIfInner<'_, K, V>, A)
1440+
pub(super) fn extract_if_inner<R>(&mut self, range: R) -> (ExtractIfInner<'_, K, V, R>, A)
14401441
where
14411442
K: Ord,
1443+
R: RangeBounds<K>,
14421444
{
14431445
if let Some(root) = self.root.as_mut() {
14441446
let (root, dormant_root) = DormantMutRef::new(root);
1445-
let front = root.borrow_mut().first_leaf_edge();
1447+
let first = root.borrow_mut().lower_bound(SearchBound::from_range(range.start_bound()));
14461448
(
14471449
ExtractIfInner {
14481450
length: &mut self.length,
14491451
dormant_root: Some(dormant_root),
1450-
cur_leaf_edge: Some(front),
1452+
cur_leaf_edge: Some(first),
1453+
range,
14511454
},
14521455
(*self.alloc).clone(),
14531456
)
@@ -1457,6 +1460,7 @@ impl<K, V, A: Allocator + Clone> BTreeMap<K, V, A> {
14571460
length: &mut self.length,
14581461
dormant_root: None,
14591462
cur_leaf_edge: None,
1463+
range,
14601464
},
14611465
(*self.alloc).clone(),
14621466
)
@@ -1915,18 +1919,19 @@ pub struct ExtractIf<
19151919
'a,
19161920
K,
19171921
V,
1922+
R,
19181923
F,
19191924
#[unstable(feature = "allocator_api", issue = "32838")] A: Allocator + Clone = Global,
19201925
> {
19211926
pred: F,
1922-
inner: ExtractIfInner<'a, K, V>,
1927+
inner: ExtractIfInner<'a, K, V, R>,
19231928
/// The BTreeMap will outlive this IntoIter so we don't care about drop order for `alloc`.
19241929
alloc: A,
19251930
}
19261931

19271932
/// Most of the implementation of ExtractIf are generic over the type
19281933
/// of the predicate, thus also serving for BTreeSet::ExtractIf.
1929-
pub(super) struct ExtractIfInner<'a, K, V> {
1934+
pub(super) struct ExtractIfInner<'a, K, V, R> {
19301935
/// Reference to the length field in the borrowed map, updated live.
19311936
length: &'a mut usize,
19321937
/// Buried reference to the root field in the borrowed map.
@@ -1936,10 +1941,13 @@ pub(super) struct ExtractIfInner<'a, K, V> {
19361941
/// Empty if the map has no root, if iteration went beyond the last leaf edge,
19371942
/// or if a panic occurred in the predicate.
19381943
cur_leaf_edge: Option<Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::Edge>>,
1944+
/// Range over which iteration was requested. We don't need the left side, but we
1945+
/// can't extract the right side without requiring K: Clone.
1946+
range: R,
19391947
}
19401948

19411949
#[unstable(feature = "btree_extract_if", issue = "70530")]
1942-
impl<K, V, F, A> fmt::Debug for ExtractIf<'_, K, V, F, A>
1950+
impl<K, V, R, F, A> fmt::Debug for ExtractIf<'_, K, V, R, F, A>
19431951
where
19441952
K: fmt::Debug,
19451953
V: fmt::Debug,
@@ -1951,8 +1959,10 @@ where
19511959
}
19521960

19531961
#[unstable(feature = "btree_extract_if", issue = "70530")]
1954-
impl<K, V, F, A: Allocator + Clone> Iterator for ExtractIf<'_, K, V, F, A>
1962+
impl<K, V, R, F, A: Allocator + Clone> Iterator for ExtractIf<'_, K, V, R, F, A>
19551963
where
1964+
K: PartialOrd,
1965+
R: RangeBounds<K>,
19561966
F: FnMut(&K, &mut V) -> bool,
19571967
{
19581968
type Item = (K, V);
@@ -1966,7 +1976,7 @@ where
19661976
}
19671977
}
19681978

1969-
impl<'a, K, V> ExtractIfInner<'a, K, V> {
1979+
impl<'a, K, V, R> ExtractIfInner<'a, K, V, R> {
19701980
/// Allow Debug implementations to predict the next element.
19711981
pub(super) fn peek(&self) -> Option<(&K, &V)> {
19721982
let edge = self.cur_leaf_edge.as_ref()?;
@@ -1976,10 +1986,15 @@ impl<'a, K, V> ExtractIfInner<'a, K, V> {
19761986
/// Implementation of a typical `ExtractIf::next` method, given the predicate.
19771987
pub(super) fn next<F, A: Allocator + Clone>(&mut self, pred: &mut F, alloc: A) -> Option<(K, V)>
19781988
where
1989+
K: PartialOrd,
1990+
R: RangeBounds<K>,
19791991
F: FnMut(&K, &mut V) -> bool,
19801992
{
19811993
while let Ok(mut kv) = self.cur_leaf_edge.take()?.next_kv() {
19821994
let (k, v) = kv.kv_mut();
1995+
if !self.range.contains(k) {
1996+
return None;
1997+
}
19831998
if pred(k, v) {
19841999
*self.length -= 1;
19852000
let (kv, pos) = kv.remove_kv_tracking(
@@ -2011,7 +2026,13 @@ impl<'a, K, V> ExtractIfInner<'a, K, V> {
20112026
}
20122027

20132028
#[unstable(feature = "btree_extract_if", issue = "70530")]
2014-
impl<K, V, F> FusedIterator for ExtractIf<'_, K, V, F> where F: FnMut(&K, &mut V) -> bool {}
2029+
impl<K, V, R, F> FusedIterator for ExtractIf<'_, K, V, R, F>
2030+
where
2031+
K: PartialOrd,
2032+
R: RangeBounds<K>,
2033+
F: FnMut(&K, &mut V) -> bool,
2034+
{
2035+
}
20152036

20162037
#[stable(feature = "btree_range", since = "1.17.0")]
20172038
impl<'a, K, V> Iterator for Range<'a, K, V> {

library/alloc/src/collections/btree/set.rs

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1109,7 +1109,7 @@ impl<T, A: Allocator + Clone> BTreeSet<T, A> {
11091109
T: Ord,
11101110
F: FnMut(&T) -> bool,
11111111
{
1112-
self.extract_if(|v| !f(v)).for_each(drop);
1112+
self.extract_if(.., |v| !f(v)).for_each(drop);
11131113
}
11141114

11151115
/// Moves all elements from `other` into `self`, leaving `other` empty.
@@ -1214,12 +1214,13 @@ impl<T, A: Allocator + Clone> BTreeSet<T, A> {
12141214
/// assert_eq!(odds.into_iter().collect::<Vec<_>>(), vec![1, 3, 5, 7]);
12151215
/// ```
12161216
#[unstable(feature = "btree_extract_if", issue = "70530")]
1217-
pub fn extract_if<'a, F>(&'a mut self, pred: F) -> ExtractIf<'a, T, F, A>
1217+
pub fn extract_if<'a, F, R>(&'a mut self, range: R, pred: F) -> ExtractIf<'a, T, R, F, A>
12181218
where
12191219
T: Ord,
1220+
R: RangeBounds<T>,
12201221
F: 'a + FnMut(&T) -> bool,
12211222
{
1222-
let (inner, alloc) = self.map.extract_if_inner();
1223+
let (inner, alloc) = self.map.extract_if_inner(range);
12231224
ExtractIf { pred, inner, alloc }
12241225
}
12251226

@@ -1554,17 +1555,18 @@ impl<'a, T, A: Allocator + Clone> IntoIterator for &'a BTreeSet<T, A> {
15541555
pub struct ExtractIf<
15551556
'a,
15561557
T,
1558+
R,
15571559
F,
15581560
#[unstable(feature = "allocator_api", issue = "32838")] A: Allocator + Clone = Global,
15591561
> {
15601562
pred: F,
1561-
inner: super::map::ExtractIfInner<'a, T, SetValZST>,
1563+
inner: super::map::ExtractIfInner<'a, T, SetValZST, R>,
15621564
/// The BTreeMap will outlive this IntoIter so we don't care about drop order for `alloc`.
15631565
alloc: A,
15641566
}
15651567

15661568
#[unstable(feature = "btree_extract_if", issue = "70530")]
1567-
impl<T, F, A> fmt::Debug for ExtractIf<'_, T, F, A>
1569+
impl<T, R, F, A> fmt::Debug for ExtractIf<'_, T, R, F, A>
15681570
where
15691571
T: fmt::Debug,
15701572
A: Allocator + Clone,
@@ -1577,8 +1579,10 @@ where
15771579
}
15781580

15791581
#[unstable(feature = "btree_extract_if", issue = "70530")]
1580-
impl<'a, T, F, A: Allocator + Clone> Iterator for ExtractIf<'_, T, F, A>
1582+
impl<'a, T, R, F, A: Allocator + Clone> Iterator for ExtractIf<'_, T, R, F, A>
15811583
where
1584+
T: PartialOrd,
1585+
R: RangeBounds<T>,
15821586
F: 'a + FnMut(&T) -> bool,
15831587
{
15841588
type Item = T;
@@ -1595,7 +1599,13 @@ where
15951599
}
15961600

15971601
#[unstable(feature = "btree_extract_if", issue = "70530")]
1598-
impl<T, F, A: Allocator + Clone> FusedIterator for ExtractIf<'_, T, F, A> where F: FnMut(&T) -> bool {}
1602+
impl<T, R, F, A: Allocator + Clone> FusedIterator for ExtractIf<'_, T, R, F, A>
1603+
where
1604+
T: PartialOrd,
1605+
R: RangeBounds<T>,
1606+
F: FnMut(&T) -> bool,
1607+
{
1608+
}
15991609

16001610
#[stable(feature = "rust1", since = "1.0.0")]
16011611
impl<T: Ord, A: Allocator + Clone> Extend<T> for BTreeSet<T, A> {

0 commit comments

Comments
 (0)