1use std::{
2 collections::{hash_map, HashMap},
3 hash::{BuildHasher, Hash},
4};
5
6use crate::join;
7
8pub fn merge_in_parallel<T: Merge>(mut items: Vec<T>) -> T {
9 assert!(!items.is_empty());
10
11 if items.len() == 1 {
12 return items.into_iter().next().unwrap();
13 }
14
15 let b = items.split_off(items.len() / 2);
16
17 let (mut a, b) = join(
18 move || merge_in_parallel(items),
19 move || merge_in_parallel(b),
20 );
21
22 a.merge(b);
23
24 a
25}
26
27pub trait Merge: Send {
29 fn merge(&mut self, other: Self);
30}
31
32impl<K, V, S> Merge for HashMap<K, V, S>
33where
34 Self: Send,
35 K: Hash + Eq,
36 V: Merge,
37 S: BuildHasher,
38{
39 fn merge(&mut self, other: Self) {
40 self.reserve(other.len());
41
42 for (k, val) in other {
43 match self.entry(k) {
44 hash_map::Entry::Occupied(mut o) => o.get_mut().merge(val),
45 hash_map::Entry::Vacant(v) => {
46 v.insert(val);
47 }
48 }
49 }
50 }
51}
52
53#[cfg(feature = "indexmap")]
54impl<K, V, S> Merge for indexmap::IndexMap<K, V, S>
55where
56 Self: Send,
57 K: Eq + Hash,
58 V: Merge,
59 S: BuildHasher,
60{
61 fn merge(&mut self, other: Self) {
62 self.reserve(other.len());
63
64 for (k, v) in other {
65 match self.entry(k) {
66 indexmap::map::Entry::Occupied(mut e) => {
67 e.get_mut().merge(v);
68 }
69 indexmap::map::Entry::Vacant(e) => {
70 e.insert(v);
71 }
72 }
73 }
74 }
75}