turbo_tasks_hash/
deterministic_hash.rs1use std::mem::Discriminant;
2
3use smallvec::SmallVec;
4pub use turbo_tasks_macros::DeterministicHash;
5
6macro_rules! deterministic_hash_number {
7 ($(($ty:ident, $meth:ident),)*) => {$(
8 impl DeterministicHash for $ty {
9 fn deterministic_hash<H: DeterministicHasher>(&self, state: &mut H) {
10 state.$meth(*self);
11 }
12 }
13 )*}
14}
15
16macro_rules! impl_write_number {
17 ($(($ty:ident, $meth:ident),)*) => {$(
18 #[inline]
20 fn $meth(&mut self, i: $ty) {
21 let little_endian = i.to_le_bytes();
23 self.write_bytes(&little_endian);
24 }
25 )*}
26}
27
28pub trait DeterministicHash {
37 fn deterministic_hash<H: DeterministicHasher>(&self, state: &mut H);
40}
41
42pub trait DeterministicHasher {
47 fn finish(&self) -> u64;
48 fn write_bytes(&mut self, bytes: &[u8]);
49
50 #[inline]
52 fn write_u8(&mut self, i: u8) {
53 self.write_bytes(&[i]);
54 }
55
56 #[inline]
58 fn write_usize(&mut self, i: usize) {
59 self.write_u64(i as u64);
63 }
64
65 #[inline]
67 fn write_isize(&mut self, i: isize) {
68 self.write_i64(i as i64);
72 }
73
74 impl_write_number! {
75 (u16, write_u16),
76 (u32, write_u32),
77 (u64, write_u64),
78 (i8, write_i8),
79 (i16, write_i16),
80 (i32, write_i32),
81 (i64, write_i64),
82 (u128, write_u128),
83 (i128, write_i128),
84 }
85}
86
87deterministic_hash_number! {
88 (u8, write_u8),
89 (u16, write_u16),
90 (u32, write_u32),
91 (u64, write_u64),
92 (usize, write_usize),
93 (i8, write_i8),
94 (i16, write_i16),
95 (i32, write_i32),
96 (i64, write_i64),
97 (isize, write_isize),
98 (u128, write_u128),
99 (i128, write_i128),
100}
101
102impl<T: ?Sized + DeterministicHash> DeterministicHash for &T {
103 fn deterministic_hash<H: DeterministicHasher>(&self, state: &mut H) {
104 (**self).deterministic_hash(state);
105 }
106}
107
108impl DeterministicHash for [u8] {
109 fn deterministic_hash<H: DeterministicHasher>(&self, state: &mut H) {
110 state.write_usize(self.len());
111 state.write_bytes(self);
112 }
113}
114
115impl DeterministicHash for String {
116 fn deterministic_hash<H: DeterministicHasher>(&self, state: &mut H) {
117 state.write_usize(self.len());
118 state.write_bytes(self.as_bytes());
119 }
120}
121
122impl DeterministicHash for &str {
123 fn deterministic_hash<H: DeterministicHasher>(&self, state: &mut H) {
124 state.write_usize(self.len());
125 state.write_bytes(self.as_bytes());
126 }
127}
128
129impl DeterministicHash for bool {
130 fn deterministic_hash<H: DeterministicHasher>(&self, state: &mut H) {
131 state.write_u8(*self as u8);
132 }
133}
134
135impl<T: DeterministicHash> DeterministicHash for Option<T> {
136 fn deterministic_hash<H: DeterministicHasher>(&self, state: &mut H) {
137 match self {
138 None => state.write_u8(0),
139 Some(v) => {
140 state.write_u8(1);
141 v.deterministic_hash(state);
142 }
143 }
144 }
145}
146
147impl<T: DeterministicHash> DeterministicHash for Vec<T> {
148 fn deterministic_hash<H: DeterministicHasher>(&self, state: &mut H) {
149 state.write_usize(self.len());
150 for v in self {
151 v.deterministic_hash(state);
152 }
153 }
154}
155
156impl<T: DeterministicHash, const N: usize> DeterministicHash for SmallVec<[T; N]> {
157 fn deterministic_hash<H: DeterministicHasher>(&self, state: &mut H) {
158 state.write_usize(self.len());
159 for v in self {
160 v.deterministic_hash(state);
161 }
162 }
163}
164
165impl DeterministicHash for () {
166 fn deterministic_hash<H: DeterministicHasher>(&self, _state: &mut H) {}
167}
168
169macro_rules! tuple_impls {
170 ( $( $name:ident )+ ) => {
171 impl<$($name: DeterministicHash),+> DeterministicHash for ($($name,)+)
172 {
173 #[allow(non_snake_case)]
174 fn deterministic_hash<Hasher: DeterministicHasher>(&self, state: &mut Hasher) {
175 let ($(ref $name,)+) = *self;
176 $($name.deterministic_hash(state);)+
177 }
178 }
179 };
180}
181
182tuple_impls! { A }
184tuple_impls! { A B }
185tuple_impls! { A B C }
186tuple_impls! { A B C D }
187tuple_impls! { A B C D E }
188tuple_impls! { A B C D E F }
189tuple_impls! { A B C D E F G }
190tuple_impls! { A B C D E F G H }
191tuple_impls! { A B C D E F G H I }
192tuple_impls! { A B C D E F G H I J }
193tuple_impls! { A B C D E F G H I J K }
194tuple_impls! { A B C D E F G H I J K L }
195
196struct HasherWrapper<'a, D: DeterministicHasher>(&'a mut D);
199impl<D: DeterministicHasher> std::hash::Hasher for HasherWrapper<'_, D> {
200 fn write(&mut self, bytes: &[u8]) {
201 self.0.write_bytes(bytes);
202 }
203
204 fn finish(&self) -> u64 {
205 unimplemented!();
206 }
207}
208
209impl<T> DeterministicHash for Discriminant<T> {
210 fn deterministic_hash<H: DeterministicHasher>(&self, state: &mut H) {
211 let mut wrapper = HasherWrapper(state);
214 std::hash::Hash::hash(self, &mut wrapper);
215 }
216}