Skip to main content

apollo_compiler/
collections.rs

1//! Type aliases for hashing-based collections configured with a specific hasher,
2//! as used in various places thorough the API
3
4use std::hash::DefaultHasher;
5use std::hash::Hash;
6use std::hash::Hasher;
7
8/// [`indexmap::IndexMap`] configured with a specific hasher
9pub type IndexMap<K, V> = indexmap::IndexMap<K, V, ahash::RandomState>;
10
11/// [`indexmap::IndexSet`] configured with a specific hasher
12pub type IndexSet<T> = indexmap::IndexSet<T, ahash::RandomState>;
13
14/// [`std::collections::HashMap`] configured with a specific hasher
15pub type HashMap<K, V> = std::collections::HashMap<K, V, ahash::RandomState>;
16
17/// [`std::collections::HashSet`] configured with a specific hasher
18pub type HashSet<T> = std::collections::HashSet<T, ahash::RandomState>;
19
20/// Order-independent equality for collections of uniquely-named items
21/// (e.g. arguments, input value definitions). Assumes names are unique per the
22/// GraphQL spec; behavior is unspecified for duplicate names.
23pub(crate) fn eq_unique_by_name<T: PartialEq>(
24    a: &[crate::Node<T>],
25    b: &[crate::Node<T>],
26    get_name: impl Fn(&T) -> &crate::Name,
27) -> bool {
28    if a.len() != b.len() {
29        return false;
30    }
31    a.iter().all(|item_a| {
32        let name = get_name(item_a);
33        b.iter()
34            .filter(|item_b| get_name(item_b) == name)
35            .any(|item_b| item_a == item_b)
36    })
37}
38
39/// Order-independent hash for collections whose `PartialEq` is order-independent
40/// (e.g. `IndexMap`, `IndexSet`). Uses commutative XOR of per-element hashes.
41pub(crate) fn hash_unordered<H: Hasher, T: Hash>(
42    items: impl Iterator<Item = T>,
43    state: &mut H,
44    len: usize,
45) {
46    len.hash(state);
47    let mut combined = 0u64;
48    for item in items {
49        let mut h = DefaultHasher::new();
50        item.hash(&mut h);
51        combined ^= h.finish();
52    }
53    combined.hash(state);
54}