Skip to content

Commit 02127f2

Browse files
committed
Added FromStream and Extend impls for HashMap
1 parent 526d318 commit 02127f2

File tree

4 files changed

+72
-0
lines changed

4 files changed

+72
-0
lines changed

src/collections/hash_map/extend.rs

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
use std::pin::Pin;
2+
use std::hash::{Hash, BuildHasher};
3+
use std::collections::HashMap;
4+
5+
use crate::prelude::*;
6+
use crate::stream::{Extend, IntoStream};
7+
8+
impl<K, V, H> Extend<(K, V)> for HashMap<K, V, H>
9+
where K: Eq + Hash,
10+
H: BuildHasher + Default {
11+
fn stream_extend<'a, S: IntoStream<Item = (K, V)> + 'a>(
12+
&'a mut self,
13+
stream: S,
14+
) -> Pin<Box<dyn Future<Output = ()> + 'a>> {
15+
let stream = stream.into_stream();
16+
17+
// The following is adapted from the hashbrown source code:
18+
// https://github.com/rust-lang/hashbrown/blob/d1ad4fc3aae2ade446738eea512e50b9e863dd0c/src/map.rs#L2470-L2491
19+
//
20+
// Keys may be already present or show multiple times in the stream. Reserve the entire
21+
// hint lower bound if the map is empty. Otherwise reserve half the hint (rounded up), so
22+
// the map will only resize twice in the worst case.
23+
24+
//TODO: Add this back in when size_hint is added to Stream/StreamExt
25+
//let reserve = if self.is_empty() {
26+
// stream.size_hint().0
27+
//} else {
28+
// (stream.size_hint().0 + 1) / 2
29+
//};
30+
//self.reserve(reserve);
31+
32+
Box::pin(stream.for_each(move |(k, v)| {
33+
self.insert(k, v);
34+
}))
35+
}
36+
}
+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
use std::pin::Pin;
2+
use std::hash::{Hash, BuildHasher};
3+
use std::collections::HashMap;
4+
5+
use crate::stream::{Extend, FromStream, IntoStream};
6+
7+
impl<K, V, H> FromStream<(K, V)> for HashMap<K, V, H>
8+
where K: Eq + Hash,
9+
H: BuildHasher + Default {
10+
#[inline]
11+
fn from_stream<'a, S: IntoStream<Item = (K, V)>>(
12+
stream: S,
13+
) -> Pin<Box<dyn core::future::Future<Output = Self> + 'a>>
14+
where
15+
<S as IntoStream>::IntoStream: 'a,
16+
{
17+
let stream = stream.into_stream();
18+
19+
Box::pin(async move {
20+
pin_utils::pin_mut!(stream);
21+
22+
let mut out = HashMap::with_hasher(Default::default());
23+
out.stream_extend(stream).await;
24+
out
25+
})
26+
}
27+
}

src/collections/hash_map/mod.rs

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
//! The Rust hash map, implemented with quadratic probing and SIMD lookup.
2+
3+
mod extend;
4+
mod from_stream;
5+
6+
#[doc(inline)]
7+
pub use std::collections::HashMap;

src/collections/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44
//! data structures.
55
66
pub mod vec_deque;
7+
pub mod hash_map;
78
pub mod btree_map;
89

910
pub use vec_deque::VecDeque;
11+
pub use hash_map::HashMap;
1012
pub use btree_map::BTreeMap;

0 commit comments

Comments
 (0)