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