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