async_std/collections/hash_map/
extend.rs

1use std::collections::HashMap;
2use std::hash::{BuildHasher, Hash};
3use std::pin::Pin;
4
5use crate::prelude::*;
6use crate::stream::{self, IntoStream};
7
8impl<K, V, H> stream::Extend<(K, V)> for HashMap<K, V, H>
9where
10    K: Eq + Hash + Send,
11    V: Send,
12    H: BuildHasher + Default + Send,
13{
14    fn extend<'a, S: IntoStream<Item = (K, V)> + 'a>(
15        &'a mut self,
16        stream: S,
17    ) -> Pin<Box<dyn Future<Output = ()> + 'a + Send>>
18    where
19        <S as IntoStream>::IntoStream: Send,
20    {
21        let stream = stream.into_stream();
22
23        // The following is adapted from the hashbrown source code:
24        // https://github.com/rust-lang/hashbrown/blob/d1ad4fc3aae2ade446738eea512e50b9e863dd0c/src/map.rs#L2470-L2491
25        //
26        // Keys may be already present or show multiple times in the stream. Reserve the entire
27        // hint lower bound if the map is empty. Otherwise reserve half the hint (rounded up), so
28        // the map will only resize twice in the worst case.
29
30        let additional = if self.is_empty() {
31            stream.size_hint().0
32        } else {
33            (stream.size_hint().0 + 1) / 2
34        };
35        self.reserve(additional);
36
37        Box::pin(stream.for_each(move |(k, v)| {
38            self.insert(k, v);
39        }))
40    }
41}