graphql_tools/parser/
hash.rs1use std::hash::{Hash, Hasher};
2use xxhash_rust::xxh3::Xxh3;
3
4use crate::parser::query::{Directive, Number, Type, Value};
5
6pub fn hash_list_unordered<TIterator: Iterator>(items: TIterator) -> u64
7where
8 TIterator::Item: Hash,
9{
10 let mut xor = 0u64;
11 let mut sum = 0u64;
12 let mut count = 0u64;
13 for item in items {
14 let mut hasher = Xxh3::new();
15 item.hash(&mut hasher);
16 let value = hasher.finish();
17 xor ^= value;
18 sum = sum.wrapping_add(value);
19 count = count.wrapping_add(1);
20 }
21 let mut hasher = Xxh3::new();
22 xor.hash(&mut hasher);
23 sum.hash(&mut hasher);
24 count.hash(&mut hasher);
25 hasher.finish()
26}
27
28impl Hash for Directive<'_, String> {
29 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
30 "Directive".hash(state);
31 self.name.hash(state);
32 hash_list_unordered(self.arguments.iter()).hash(state);
33 }
34}
35
36impl Hash for Value<'_, String> {
37 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
38 match self {
39 Value::Variable(v) => {
40 "Value::Variable".hash(state);
41 v.hash(state);
42 }
43 Value::Int(i) => {
44 "Value::Int".hash(state);
45 i.hash(state);
46 }
47 Value::Float(f) => {
48 "Value::Float".hash(state);
49 let canonical = if f.is_nan() {
53 f64::NAN
54 } else if f.is_infinite() {
55 if f.is_sign_positive() {
56 f64::INFINITY
57 } else {
58 f64::NEG_INFINITY
59 }
60 } else {
61 *f
62 };
63 canonical.to_bits().hash(state);
64 }
65 Value::String(s) => {
66 "Value::String".hash(state);
67 s.hash(state);
68 }
69 Value::Boolean(b) => {
70 "Value::Boolean".hash(state);
71 b.hash(state);
72 }
73 Value::Null => {
74 "Value::Null".hash(state);
75 }
76 Value::Enum(v) => {
77 "Value::Enum".hash(state);
78 v.hash(state);
79 }
80 Value::List(l) => {
81 "Value::List".hash(state);
82 l.len().hash(state);
83 for item in l {
84 item.hash(state);
85 }
86 }
87 Value::Object(o) => {
88 "Value::Object".hash(state);
89
90 hash_list_unordered(o.iter()).hash(state);
91 }
92 }
93 }
94}
95
96impl Hash for Type<'_, String> {
97 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
98 match self {
99 Type::NamedType(n) => {
100 "Type::NamedType".hash(state);
101 n.hash(state);
102 }
103 Type::ListType(t) => {
104 "Type::ListType".hash(state);
105 t.hash(state);
106 }
107 Type::NonNullType(t) => {
108 "Type::NonNullType".hash(state);
109 t.hash(state);
110 }
111 }
112 }
113}
114
115impl Hash for Number {
116 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
117 self.0.hash(state);
118 }
119}