uv_cache_key/
cache_key.rs

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