uv_cache_key/
cache_key.rs1use std::borrow::Cow;
2use std::collections::{BTreeMap, BTreeSet};
3use std::hash::{Hash, Hasher};
4use std::num::{
5 NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI128, NonZeroU8, NonZeroU16, NonZeroU32,
6 NonZeroU64, NonZeroU128,
7};
8use std::path::{Path, PathBuf};
9
10use seahash::SeaHasher;
11use uv_redacted::SafeUrl;
12use uv_redacted::policy::SerializationPolicy;
13
14pub trait CacheKey {
17 fn cache_key(&self, state: &mut CacheKeyHasher);
18
19 fn cache_key_slice(data: &[Self], state: &mut CacheKeyHasher)
20 where
21 Self: Sized,
22 {
23 for piece in data {
24 piece.cache_key(state);
25 }
26 }
27}
28
29impl CacheKey for bool {
30 #[inline]
31 fn cache_key(&self, state: &mut CacheKeyHasher) {
32 state.write_u8(u8::from(*self));
33 }
34}
35
36impl CacheKey for char {
37 #[inline]
38 fn cache_key(&self, state: &mut CacheKeyHasher) {
39 state.write_u32(*self as u32);
40 }
41}
42
43impl CacheKey for usize {
44 #[inline]
45 fn cache_key(&self, state: &mut CacheKeyHasher) {
46 state.write_usize(*self);
47 }
48}
49
50impl CacheKey for u128 {
51 #[inline]
52 fn cache_key(&self, state: &mut CacheKeyHasher) {
53 state.write_u128(*self);
54 }
55}
56
57impl CacheKey for u64 {
58 #[inline]
59 fn cache_key(&self, state: &mut CacheKeyHasher) {
60 state.write_u64(*self);
61 }
62}
63
64impl CacheKey for u32 {
65 #[inline]
66 fn cache_key(&self, state: &mut CacheKeyHasher) {
67 state.write_u32(*self);
68 }
69}
70
71impl CacheKey for u16 {
72 #[inline]
73 fn cache_key(&self, state: &mut CacheKeyHasher) {
74 state.write_u16(*self);
75 }
76}
77
78impl CacheKey for u8 {
79 #[inline]
80 fn cache_key(&self, state: &mut CacheKeyHasher) {
81 state.write_u8(*self);
82 }
83}
84
85impl CacheKey for isize {
86 #[inline]
87 fn cache_key(&self, state: &mut CacheKeyHasher) {
88 state.write_isize(*self);
89 }
90}
91
92impl CacheKey for i128 {
93 #[inline]
94 fn cache_key(&self, state: &mut CacheKeyHasher) {
95 state.write_i128(*self);
96 }
97}
98
99impl CacheKey for i64 {
100 #[inline]
101 fn cache_key(&self, state: &mut CacheKeyHasher) {
102 state.write_i64(*self);
103 }
104}
105
106impl CacheKey for i32 {
107 #[inline]
108 fn cache_key(&self, state: &mut CacheKeyHasher) {
109 state.write_i32(*self);
110 }
111}
112
113impl CacheKey for i16 {
114 #[inline]
115 fn cache_key(&self, state: &mut CacheKeyHasher) {
116 state.write_i16(*self);
117 }
118}
119
120impl CacheKey for i8 {
121 #[inline]
122 fn cache_key(&self, state: &mut CacheKeyHasher) {
123 state.write_i8(*self);
124 }
125}
126macro_rules! impl_cache_key_non_zero {
127 ($name:ident) => {
128 impl CacheKey for $name {
129 #[inline]
130 fn cache_key(&self, state: &mut CacheKeyHasher) {
131 self.get().cache_key(state)
132 }
133 }
134 };
135}
136
137impl_cache_key_non_zero!(NonZeroU8);
138impl_cache_key_non_zero!(NonZeroU16);
139impl_cache_key_non_zero!(NonZeroU32);
140impl_cache_key_non_zero!(NonZeroU64);
141impl_cache_key_non_zero!(NonZeroU128);
142
143impl_cache_key_non_zero!(NonZeroI8);
144impl_cache_key_non_zero!(NonZeroI16);
145impl_cache_key_non_zero!(NonZeroI32);
146impl_cache_key_non_zero!(NonZeroI64);
147impl_cache_key_non_zero!(NonZeroI128);
148
149macro_rules! impl_cache_key_tuple {
150 () => (
151 impl CacheKey for () {
152 #[inline]
153 fn cache_key(&self, _state: &mut CacheKeyHasher) {}
154 }
155 );
156
157 ( $($name:ident)+) => (
158 impl<$($name: CacheKey),+> CacheKey for ($($name,)+) where last_type!($($name,)+): ?Sized {
159 #[allow(non_snake_case)]
160 #[inline]
161 fn cache_key(&self, state: &mut CacheKeyHasher) {
162 let ($(ref $name,)+) = *self;
163 $($name.cache_key(state);)+
164 }
165 }
166 );
167}
168
169macro_rules! last_type {
170 ($a:ident,) => { $a };
171 ($a:ident, $($rest_a:ident,)+) => { last_type!($($rest_a,)+) };
172}
173
174impl_cache_key_tuple! {}
175impl_cache_key_tuple! { T }
176impl_cache_key_tuple! { T B }
177impl_cache_key_tuple! { T B C }
178impl_cache_key_tuple! { T B C D }
179impl_cache_key_tuple! { T B C D E }
180impl_cache_key_tuple! { T B C D E F }
181impl_cache_key_tuple! { T B C D E F G }
182impl_cache_key_tuple! { T B C D E F G H }
183impl_cache_key_tuple! { T B C D E F G H I }
184impl_cache_key_tuple! { T B C D E F G H I J }
185impl_cache_key_tuple! { T B C D E F G H I J K }
186impl_cache_key_tuple! { T B C D E F G H I J K L }
187
188impl CacheKey for str {
189 #[inline]
190 fn cache_key(&self, state: &mut CacheKeyHasher) {
191 self.hash(&mut *state);
192 }
193}
194
195impl CacheKey for String {
196 #[inline]
197 fn cache_key(&self, state: &mut CacheKeyHasher) {
198 self.hash(&mut *state);
199 }
200}
201
202impl CacheKey for Path {
203 #[inline]
204 fn cache_key(&self, state: &mut CacheKeyHasher) {
205 self.hash(&mut *state);
206 }
207}
208
209impl CacheKey for PathBuf {
210 #[inline]
211 fn cache_key(&self, state: &mut CacheKeyHasher) {
212 self.as_path().cache_key(state);
213 }
214}
215
216impl<P: SerializationPolicy> CacheKey for SafeUrl<P> {
217 #[inline]
218 fn cache_key(&self, state: &mut CacheKeyHasher) {
219 self.as_str().cache_key(state);
220 }
221}
222
223impl<T: CacheKey> CacheKey for Option<T> {
224 #[inline]
225 fn cache_key(&self, state: &mut CacheKeyHasher) {
226 match self {
227 None => state.write_usize(0),
228 Some(value) => {
229 state.write_usize(1);
230 value.cache_key(state);
231 }
232 }
233 }
234}
235
236impl<T: CacheKey> CacheKey for [T] {
237 #[inline]
238 fn cache_key(&self, state: &mut CacheKeyHasher) {
239 state.write_usize(self.len());
240 CacheKey::cache_key_slice(self, state);
241 }
242}
243
244impl<T: ?Sized + CacheKey> CacheKey for &T {
245 #[inline]
246 fn cache_key(&self, state: &mut CacheKeyHasher) {
247 (**self).cache_key(state);
248 }
249}
250
251impl<T: ?Sized + CacheKey> CacheKey for &mut T {
252 #[inline]
253 fn cache_key(&self, state: &mut CacheKeyHasher) {
254 (**self).cache_key(state);
255 }
256}
257
258impl<T> CacheKey for Vec<T>
259where
260 T: CacheKey,
261{
262 fn cache_key(&self, state: &mut CacheKeyHasher) {
263 state.write_usize(self.len());
264 CacheKey::cache_key_slice(self, state);
265 }
266}
267
268impl<V: CacheKey> CacheKey for BTreeSet<V> {
269 fn cache_key(&self, state: &mut CacheKeyHasher) {
270 state.write_usize(self.len());
271 for item in self {
272 item.cache_key(state);
273 }
274 }
275}
276
277impl<K: CacheKey + Ord, V: CacheKey> CacheKey for BTreeMap<K, V> {
278 fn cache_key(&self, state: &mut CacheKeyHasher) {
279 state.write_usize(self.len());
280
281 for (key, value) in self {
282 key.cache_key(state);
283 value.cache_key(state);
284 }
285 }
286}
287
288impl<V: ?Sized> CacheKey for Cow<'_, V>
289where
290 V: CacheKey + ToOwned,
291{
292 fn cache_key(&self, state: &mut CacheKeyHasher) {
293 (**self).cache_key(state);
294 }
295}
296
297#[derive(Clone)]
298pub struct CacheKeyHasher {
299 inner: SeaHasher,
300}
301
302impl CacheKeyHasher {
303 pub(crate) fn new() -> Self {
304 Self {
305 inner: SeaHasher::new(),
306 }
307 }
308}
309
310impl Hasher for CacheKeyHasher {
311 #[inline]
312 fn finish(&self) -> u64 {
313 self.inner.finish()
314 }
315
316 #[inline]
317 fn write(&mut self, bytes: &[u8]) {
318 self.inner.write(bytes);
319 }
320
321 #[inline]
322 fn write_u8(&mut self, i: u8) {
323 self.inner.write_u8(i);
324 }
325
326 #[inline]
327 fn write_u16(&mut self, i: u16) {
328 self.inner.write_u16(i);
329 }
330
331 #[inline]
332 fn write_u32(&mut self, i: u32) {
333 self.inner.write_u32(i);
334 }
335
336 #[inline]
337 fn write_u64(&mut self, i: u64) {
338 self.inner.write_u64(i);
339 }
340
341 #[inline]
342 fn write_u128(&mut self, i: u128) {
343 self.inner.write_u128(i);
344 }
345
346 #[inline]
347 fn write_usize(&mut self, i: usize) {
348 self.inner.write_usize(i);
349 }
350
351 #[inline]
352 fn write_i8(&mut self, i: i8) {
353 self.inner.write_i8(i);
354 }
355
356 #[inline]
357 fn write_i16(&mut self, i: i16) {
358 self.inner.write_i16(i);
359 }
360
361 #[inline]
362 fn write_i32(&mut self, i: i32) {
363 self.inner.write_i32(i);
364 }
365
366 #[inline]
367 fn write_i64(&mut self, i: i64) {
368 self.inner.write_i64(i);
369 }
370
371 #[inline]
372 fn write_i128(&mut self, i: i128) {
373 self.inner.write_i128(i);
374 }
375
376 #[inline]
377 fn write_isize(&mut self, i: isize) {
378 self.inner.write_isize(i);
379 }
380}