swc_parallel/
merge.rs

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
27/// Used to merge in parallel.
28pub 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}