Skip to main content

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 uv_redacted::SafeUrl;
12use uv_redacted::policy::SerializationPolicy;
13
14/// A trait for types that can be hashed in a stable way across versions and platforms. Equivalent
15/// to Ruff's [`CacheKey`] trait.
16pub 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}