Skip to content

Commit de72f44

Browse files
committed
BTree: add drain methods
1 parent ea30b90 commit de72f44

File tree

8 files changed

+630
-12
lines changed

8 files changed

+630
-12
lines changed

library/alloc/benches/btree/map.rs

+57-9
Original file line numberDiff line numberDiff line change
@@ -384,17 +384,33 @@ pub fn clone_slim_100_and_clear(b: &mut Bencher) {
384384
}
385385

386386
#[bench]
387-
pub fn clone_slim_100_and_drain_all(b: &mut Bencher) {
387+
pub fn clone_slim_100_and_drain_range_all(b: &mut Bencher) {
388+
let src = slim_map(100);
389+
b.iter(|| src.clone().drain(..).count())
390+
}
391+
392+
#[bench]
393+
pub fn clone_slim_100_and_drain_filter_all(b: &mut Bencher) {
388394
let src = slim_map(100);
389395
b.iter(|| src.clone().drain_filter(|_, _| true).count())
390396
}
391397

392398
#[bench]
393-
pub fn clone_slim_100_and_drain_half(b: &mut Bencher) {
399+
pub fn clone_slim_100_and_drain_range_half(b: &mut Bencher) {
400+
let src = slim_map(100);
401+
b.iter(|| {
402+
let mut map = src.clone();
403+
assert_eq!(map.drain(25..75).count(), 100 / 2);
404+
assert_eq!(map.len(), 100 / 2);
405+
})
406+
}
407+
408+
#[bench]
409+
pub fn clone_slim_100_and_drain_filter_half(b: &mut Bencher) {
394410
let src = slim_map(100);
395411
b.iter(|| {
396412
let mut map = src.clone();
397-
assert_eq!(map.drain_filter(|i, _| i % 2 == 0).count(), 100 / 2);
413+
assert_eq!(map.drain_filter(|i, _| (25..75).contains(i)).count(), 100 / 2);
398414
assert_eq!(map.len(), 100 / 2);
399415
})
400416
}
@@ -455,17 +471,33 @@ pub fn clone_slim_10k_and_clear(b: &mut Bencher) {
455471
}
456472

457473
#[bench]
458-
pub fn clone_slim_10k_and_drain_all(b: &mut Bencher) {
474+
pub fn clone_slim_10k_and_drain_range_all(b: &mut Bencher) {
475+
let src = slim_map(10_000);
476+
b.iter(|| src.clone().drain(..).count())
477+
}
478+
479+
#[bench]
480+
pub fn clone_slim_10k_and_drain_filter_all(b: &mut Bencher) {
459481
let src = slim_map(10_000);
460482
b.iter(|| src.clone().drain_filter(|_, _| true).count())
461483
}
462484

463485
#[bench]
464-
pub fn clone_slim_10k_and_drain_half(b: &mut Bencher) {
486+
pub fn clone_slim_10k_and_drain_range_half(b: &mut Bencher) {
487+
let src = slim_map(10_000);
488+
b.iter(|| {
489+
let mut map = src.clone();
490+
assert_eq!(map.drain(2500..7500).count(), 10_000 / 2);
491+
assert_eq!(map.len(), 10_000 / 2);
492+
})
493+
}
494+
495+
#[bench]
496+
pub fn clone_slim_10k_and_drain_filter_half(b: &mut Bencher) {
465497
let src = slim_map(10_000);
466498
b.iter(|| {
467499
let mut map = src.clone();
468-
assert_eq!(map.drain_filter(|i, _| i % 2 == 0).count(), 10_000 / 2);
500+
assert_eq!(map.drain_filter(|i, _| (2500..7500).contains(i)).count(), 10_000 / 2);
469501
assert_eq!(map.len(), 10_000 / 2);
470502
})
471503
}
@@ -526,17 +558,33 @@ pub fn clone_fat_val_100_and_clear(b: &mut Bencher) {
526558
}
527559

528560
#[bench]
529-
pub fn clone_fat_val_100_and_drain_all(b: &mut Bencher) {
561+
pub fn clone_fat_val_100_and_drain_range_all(b: &mut Bencher) {
562+
let src = fat_val_map(100);
563+
b.iter(|| src.clone().drain(..).count())
564+
}
565+
566+
#[bench]
567+
pub fn clone_fat_val_100_and_drain_filter_all(b: &mut Bencher) {
530568
let src = fat_val_map(100);
531569
b.iter(|| src.clone().drain_filter(|_, _| true).count())
532570
}
533571

534572
#[bench]
535-
pub fn clone_fat_val_100_and_drain_half(b: &mut Bencher) {
573+
pub fn clone_fat_val_100_and_drain_range_half(b: &mut Bencher) {
574+
let src = fat_val_map(100);
575+
b.iter(|| {
576+
let mut map = src.clone();
577+
assert_eq!(map.drain(25..75).count(), 100 / 2);
578+
assert_eq!(map.len(), 100 / 2);
579+
})
580+
}
581+
582+
#[bench]
583+
pub fn clone_fat_val_100_and_drain_filter_half(b: &mut Bencher) {
536584
let src = fat_val_map(100);
537585
b.iter(|| {
538586
let mut map = src.clone();
539-
assert_eq!(map.drain_filter(|i, _| i % 2 == 0).count(), 100 / 2);
587+
assert_eq!(map.drain_filter(|i, _| (25..75).contains(i)).count(), 100 / 2);
540588
assert_eq!(map.len(), 100 / 2);
541589
})
542590
}

library/alloc/benches/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Disabling on android for the time being
22
// See https://github.com/rust-lang/rust/issues/73535#event-3477699747
33
#![cfg(not(target_os = "android"))]
4+
#![feature(btree_drain)]
45
#![feature(btree_drain_filter)]
56
#![feature(map_first_last)]
67
#![feature(repr_simd)]

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

+91
Original file line numberDiff line numberDiff line change
@@ -1264,6 +1264,66 @@ impl<K, V> BTreeMap<K, V> {
12641264
BTreeMap { root: Some(right_root), length: right_len }
12651265
}
12661266

1267+
/// Removes at once all keys within the range from the map, returning the
1268+
/// removed key-value pairs as an iterator in ascending key order. If the
1269+
/// iterator is dropped before being fully consumed, it drops the remaining
1270+
/// removed key-value pairs.
1271+
///
1272+
/// The returned iterator keeps a mutable borrow on the map to allow
1273+
/// optimizing its implementation.
1274+
///
1275+
/// # Panics
1276+
///
1277+
/// Panics if range `start > end`.
1278+
/// Panics if range `start == end` and both bounds are `Excluded`.
1279+
/// May panic if the [`Ord`] implementation of type `T` is ill-defined,
1280+
/// either because it does not form a total order or because it does not
1281+
/// correspond to the [`Ord`] implementation of type `K`.
1282+
///
1283+
/// # Leaking
1284+
///
1285+
/// If the returned iterator goes out of scope without being dropped (due to
1286+
/// [`mem::forget`], for example), the map may have lost and leaked
1287+
/// key-value pairs arbitrarily, including key-value pairs outside the range.
1288+
///
1289+
/// # Examples
1290+
///
1291+
/// ```
1292+
/// #![feature(btree_drain)]
1293+
/// use std::collections::BTreeMap;
1294+
///
1295+
/// let mut a = BTreeMap::new();
1296+
/// a.insert(1, "a");
1297+
/// a.insert(2, "b");
1298+
/// a.insert(3, "c");
1299+
/// a.insert(17, "d");
1300+
/// a.insert(41, "e");
1301+
///
1302+
/// let b: Vec<_> = a.drain(3..33).collect();
1303+
/// assert_eq!(b, vec![(3, "c"), (17, "d")]);
1304+
/// assert_eq!(a.len(), 3);
1305+
/// ```
1306+
#[unstable(feature = "btree_drain", issue = "81074")]
1307+
pub fn drain<T: ?Sized, R>(&mut self, range: R) -> Drain<'_, K, V>
1308+
where
1309+
T: Ord,
1310+
K: Borrow<T> + Ord,
1311+
R: RangeBounds<T>,
1312+
{
1313+
let inner = if let Some(left_root) = self.root.as_mut() {
1314+
let total_num = self.length;
1315+
let right_root = left_root.split_off_range(range);
1316+
let (new_left_len, right_len) =
1317+
Root::calc_split_length(total_num, &left_root, &right_root);
1318+
self.length = new_left_len;
1319+
let right_range = right_root.into_dying().full_range();
1320+
IntoIter { range: right_range, length: right_len }
1321+
} else {
1322+
IntoIter { range: LazyLeafRange::none(), length: 0 }
1323+
};
1324+
Drain { inner, _marker: PhantomData }
1325+
}
1326+
12671327
/// Creates an iterator that visits all elements (key-value pairs) in
12681328
/// ascending key order and uses a closure to determine if an element should
12691329
/// be removed. If the closure returns `true`, the element is removed from
@@ -1712,6 +1772,37 @@ impl<K, V> Clone for Values<'_, K, V> {
17121772
}
17131773
}
17141774

1775+
/// An iterator produced by calling `drain` on BTreeMap.
1776+
#[unstable(feature = "btree_drain", issue = "81074")]
1777+
#[derive(Debug)]
1778+
pub struct Drain<'a, K, V> {
1779+
inner: IntoIter<K, V>,
1780+
_marker: PhantomData<&'a mut BTreeMap<K, V>>,
1781+
}
1782+
1783+
#[unstable(feature = "btree_drain", issue = "81074")]
1784+
impl<K, V> Iterator for Drain<'_, K, V> {
1785+
type Item = (K, V);
1786+
1787+
fn next(&mut self) -> Option<(K, V)> {
1788+
self.inner.next()
1789+
}
1790+
1791+
fn size_hint(&self) -> (usize, Option<usize>) {
1792+
self.inner.size_hint()
1793+
}
1794+
}
1795+
1796+
#[stable(feature = "rust1", since = "1.0.0")]
1797+
impl<K, V> ExactSizeIterator for Drain<'_, K, V> {
1798+
fn len(&self) -> usize {
1799+
self.inner.len()
1800+
}
1801+
}
1802+
1803+
#[stable(feature = "fused", since = "1.26.0")]
1804+
impl<K, V> FusedIterator for Drain<'_, K, V> {}
1805+
17151806
/// An iterator produced by calling `drain_filter` on BTreeMap.
17161807
#[unstable(feature = "btree_drain_filter", issue = "70530")]
17171808
pub struct DrainFilter<'a, K, V, F>

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

+1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use std::ops::RangeBounds;
1717
use std::panic::{catch_unwind, AssertUnwindSafe};
1818
use std::sync::atomic::{AtomicUsize, Ordering::SeqCst};
1919

20+
mod drain;
2021
mod split_off_range;
2122

2223
// Minimum number of elements to insert, to guarantee a tree with 2 levels,

0 commit comments

Comments
 (0)