fingerprint_struct/
impls.rs1#[allow(unused_imports)]
2use core::hash::Hash;
3
4use crate::Fingerprint;
5use digest::Update;
6
7macro_rules! impl_method {
8 ($type: ty, $member: ident ($($arg: expr),*)) => {
9 impl Fingerprint for $type {
10 #[inline(always)]
11 fn fingerprint<U: Update>(&self, hasher: &mut U) {
12 self.$member($($arg),*).fingerprint(hasher);
13 }
14 }
15 };
16}
17
18macro_rules! impl_inner {
19 ($type: ty) => {
20 impl<T: Fingerprint> Fingerprint for $type {
21 #[inline(always)]
22 fn fingerprint<U: Update>(&self, hasher: &mut U) {
23 self.0.fingerprint(hasher);
24 }
25 }
26 };
27}
28
29macro_rules! impl_deref {
30 ($type: ty) => {
31 impl<T: Fingerprint + ?Sized> Fingerprint for $type {
32 #[inline(always)]
33 fn fingerprint<U: Update>(&self, hasher: &mut U) {
34 (**self).fingerprint(hasher);
35 }
36 }
37 };
38}
39
40impl_deref!(&T);
41impl_deref!(&mut T);
42#[cfg(feature = "alloc")]
43impl_deref!(alloc::boxed::Box<T>);
44#[cfg(feature = "alloc")]
45impl_deref!(alloc::rc::Rc<T>);
46#[cfg(feature = "alloc")]
47impl_deref!(alloc::sync::Arc<T>);
48
49#[cfg(feature = "alloc")]
50impl<'a, T: Fingerprint + Clone> Fingerprint for alloc::borrow::Cow<'a, T> {
51 #[inline(always)]
52 fn fingerprint<U: Update>(&self, hasher: &mut U) {
53 (**self).fingerprint(hasher);
54 }
55}
56
57impl<T: Fingerprint + Copy> Fingerprint for core::cell::Cell<T> {
58 #[inline(always)]
59 fn fingerprint<U: Update>(&self, hasher: &mut U) {
60 self.get().fingerprint(hasher);
61 }
62}
63
64macro_rules! impl_primitive {
65 ($type: ty) => {
66 impl Fingerprint for $type {
67 #[inline(always)]
68 fn fingerprint<U: Update>(&self, hasher: &mut U) {
69 hasher.update(&self.to_le_bytes());
70 }
71 }
72 };
73}
74
75impl_primitive!(i8);
76impl_primitive!(i16);
77impl_primitive!(i32);
78impl_primitive!(i64);
79impl_primitive!(i128);
80impl_primitive!(u8);
81impl_primitive!(u16);
82impl_primitive!(u32);
83impl_primitive!(u64);
84impl_primitive!(u128);
85impl_primitive!(f32);
86impl_primitive!(f64);
87
88macro_rules! impl_through_cast {
89 ($type: ty, $cast: ty) => {
90 impl Fingerprint for $type {
91 #[inline(always)]
92 fn fingerprint<U: Update>(&self, hasher: &mut U) {
93 (*self as $cast).fingerprint(hasher);
94 }
95 }
96 };
97}
98
99impl_through_cast!(char, u32);
100impl_through_cast!(bool, u8);
101
102macro_rules! impl_through_from {
103 ($type: ty, $into: ty) => {
104 impl Fingerprint for $type {
105 #[inline(always)]
106 fn fingerprint<U: Update>(&self, hasher: &mut U) {
107 <$into>::from(*self).fingerprint(hasher);
108 }
109 }
110 };
111}
112
113impl_through_from!(core::num::NonZeroI8, i8);
114impl_through_from!(core::num::NonZeroI16, i16);
115impl_through_from!(core::num::NonZeroI32, i32);
116impl_through_from!(core::num::NonZeroI64, i64);
117impl_through_from!(core::num::NonZeroI128, i128);
118impl_through_from!(core::num::NonZeroIsize, isize);
119impl_through_from!(core::num::NonZeroU8, u8);
120impl_through_from!(core::num::NonZeroU16, u16);
121impl_through_from!(core::num::NonZeroU32, u32);
122impl_through_from!(core::num::NonZeroU64, u64);
123impl_through_from!(core::num::NonZeroU128, u128);
124impl_through_from!(core::num::NonZeroUsize, usize);
125
126impl_method!(
127 core::sync::atomic::AtomicBool,
128 load(core::sync::atomic::Ordering::Relaxed)
129);
130impl_method!(
131 core::sync::atomic::AtomicI8,
132 load(core::sync::atomic::Ordering::Relaxed)
133);
134impl_method!(
135 core::sync::atomic::AtomicI16,
136 load(core::sync::atomic::Ordering::Relaxed)
137);
138impl_method!(
139 core::sync::atomic::AtomicI32,
140 load(core::sync::atomic::Ordering::Relaxed)
141);
142impl_method!(
143 core::sync::atomic::AtomicI64,
144 load(core::sync::atomic::Ordering::Relaxed)
145);
146impl_method!(
147 core::sync::atomic::AtomicIsize,
148 load(core::sync::atomic::Ordering::Relaxed)
149);
150impl_method!(
151 core::sync::atomic::AtomicU8,
152 load(core::sync::atomic::Ordering::Relaxed)
153);
154impl_method!(
155 core::sync::atomic::AtomicU16,
156 load(core::sync::atomic::Ordering::Relaxed)
157);
158impl_method!(
159 core::sync::atomic::AtomicU32,
160 load(core::sync::atomic::Ordering::Relaxed)
161);
162impl_method!(
163 core::sync::atomic::AtomicU64,
164 load(core::sync::atomic::Ordering::Relaxed)
165);
166impl_method!(
167 core::sync::atomic::AtomicUsize,
168 load(core::sync::atomic::Ordering::Relaxed)
169);
170
171impl Fingerprint for usize {
172 #[inline]
179 fn fingerprint<U: Update>(&self, hasher: &mut U) {
180 let mut rest = *self;
181
182 loop {
183 let digit = rest & ((1 << 7) - 1);
184 rest >>= 7;
185
186 let digit = digit as u8;
187 let digit = digit | if rest > 0 { 1 << 7 } else { 0 };
188
189 digit.fingerprint(hasher);
190
191 if rest == 0 {
192 break;
193 }
194 }
195 }
196}
197
198impl Fingerprint for isize {
199 #[inline]
204 fn fingerprint<U: Update>(&self, hasher: &mut U) {
205 let value = *self;
206 let value = (value << 1) ^ (value >> (isize::BITS - 1));
207 let value = value as usize;
208 value.fingerprint(hasher);
209 }
210}
211
212impl<T: Fingerprint, const N: usize> Fingerprint for [T; N] {
213 #[inline(always)]
214 fn fingerprint<U: Update>(&self, hasher: &mut U) {
215 for i in self {
216 i.fingerprint(hasher);
217 }
218 }
219}
220
221macro_rules! impl_tuple {
222 ($($num: tt: $name: ident)*) => {
223 impl<$($name: Fingerprint),*> Fingerprint for ($($name,)*) {
224 #[inline(always)]
225 #[allow(unused_variables)] fn fingerprint<U: Update>(&self, hasher: &mut U) {
227 $(
228 self.$num.fingerprint(hasher);
229 )*
230 }
231 }
232 };
233}
234
235impl_tuple!();
236impl_tuple!(0: T0);
237impl_tuple!(0: T0 1: T1);
238impl_tuple!(0: T0 1: T1 2: T2);
239impl_tuple!(0: T0 1: T1 2: T2 3: T3);
240impl_tuple!(0: T0 1: T1 2: T2 3: T3 4: T4);
241impl_tuple!(0: T0 1: T1 2: T2 3: T3 4: T4 5: T5);
242impl_tuple!(0: T0 1: T1 2: T2 3: T3 4: T4 5: T5 6: T6);
243impl_tuple!(0: T0 1: T1 2: T2 3: T3 4: T4 5: T5 6: T6 7: T7);
244impl_tuple!(0: T0 1: T1 2: T2 3: T3 4: T4 5: T5 6: T6 7: T7 8: T8);
245impl_tuple!(0: T0 1: T1 2: T2 3: T3 4: T4 5: T5 6: T6 7: T7 8: T8 9: T9);
246impl_tuple!(0: T0 1: T1 2: T2 3: T3 4: T4 5: T5 6: T6 7: T7 8: T8 9: T9 10: T10);
247impl_tuple!(0: T0 1: T1 2: T2 3: T3 4: T4 5: T5 6: T6 7: T7 8: T8 9: T9 10: T10 11: T11);
248impl_tuple!(0: T0 1: T1 2: T2 3: T3 4: T4 5: T5 6: T6 7: T7 8: T8 9: T9 10: T10 11: T11 12: T12);
249impl_tuple!(0: T0 1: T1 2: T2 3: T3 4: T4 5: T5 6: T6 7: T7 8: T8 9: T9 10: T10 11: T11 12: T12 13: T13);
250impl_tuple!(0: T0 1: T1 2: T2 3: T3 4: T4 5: T5 6: T6 7: T7 8: T8 9: T9 10: T10 11: T11 12: T12 13: T13 14: T14);
251impl_tuple!(0: T0 1: T1 2: T2 3: T3 4: T4 5: T5 6: T6 7: T7 8: T8 9: T9 10: T10 11: T11 12: T12 13: T13 14: T14 15: T15);
252
253macro_rules! impl_string_like {
254 ($type: ty) => {
255 impl Fingerprint for $type {
256 #[inline]
257 fn fingerprint<U: Update>(&self, hasher: &mut U) {
258 self.len().fingerprint(hasher);
259 hasher.update(self.as_bytes());
260 }
261 }
262 };
263}
264
265impl_string_like!(str);
266#[cfg(feature = "alloc")]
267impl_string_like!(alloc::string::String);
268
269#[cfg(feature = "std")]
270macro_rules! impl_cstring_like {
271 ($type: ty) => {
272 impl Fingerprint for $type {
273 #[inline]
274 fn fingerprint<U: Update>(&self, hasher: &mut U) {
275 hasher.update(self.to_bytes_with_nul());
276 }
277 }
278 };
279}
280
281#[cfg(feature = "std")]
282impl_cstring_like!(std::ffi::CStr);
283#[cfg(feature = "std")]
284impl_cstring_like!(std::ffi::CString);
285
286impl<T: Fingerprint> Fingerprint for Option<T> {
287 #[inline]
288 fn fingerprint<U: Update>(&self, hasher: &mut U) {
289 match self {
290 Some(value) => {
291 0u8.fingerprint(hasher);
292 value.fingerprint(hasher);
293 }
294 None => 1u8.fingerprint(hasher),
295 }
296 }
297}
298
299impl<T: Fingerprint, E: Fingerprint> Fingerprint for Result<T, E> {
300 #[inline]
301 fn fingerprint<U: Update>(&self, hasher: &mut U) {
302 match self {
303 Ok(value) => {
304 0u8.fingerprint(hasher);
305 value.fingerprint(hasher);
306 }
307 Err(value) => {
308 1u8.fingerprint(hasher);
309 value.fingerprint(hasher);
310 }
311 }
312 }
313}
314
315impl<T: ?Sized> Fingerprint for core::marker::PhantomData<T> {
316 #[inline]
317 fn fingerprint<U: Update>(&self, _hasher: &mut U) {}
318}
319
320macro_rules! impl_ordered_seq {
321 ($type: ty $(,$bound: tt)?) => {
322 impl<T: Fingerprint $(+ $bound)?> Fingerprint for $type {
323 #[inline]
324 fn fingerprint<U: Update>(&self, hasher: &mut U) {
325 self.len().fingerprint(hasher);
326
327 for element in self.iter() {
328 element.fingerprint(hasher);
329 }
330 }
331 }
332 };
333}
334
335impl_ordered_seq!([T]);
336#[cfg(feature = "alloc")]
337impl_ordered_seq!(alloc::vec::Vec<T>);
338#[cfg(feature = "alloc")]
339impl_ordered_seq!(alloc::collections::BTreeSet<T>, Ord);
340#[cfg(feature = "alloc")]
341impl_ordered_seq!(alloc::collections::LinkedList<T>);
342#[cfg(feature = "alloc")]
343impl_ordered_seq!(alloc::collections::VecDeque<T>);
344
345#[cfg(feature = "alloc")]
346macro_rules! impl_unordered_seq {
347 ($type: ty $(,$bound: tt)*) => {
348 impl<T: Fingerprint + Ord $(+ $bound)*> Fingerprint for $type {
349 #[inline]
350 fn fingerprint<U: Update>(&self, hasher: &mut U) {
351 let mut vec: alloc::vec::Vec<&T> = self.iter().collect();
352 vec.sort();
353
354 vec.fingerprint(hasher);
355 }
356 }
357 };
358}
359
360#[cfg(feature = "alloc")]
361impl_unordered_seq!(alloc::collections::BinaryHeap<T>);
362#[cfg(feature = "std")]
363impl_unordered_seq!(std::collections::HashSet<T>, Eq, Hash);
364
365#[cfg(feature = "alloc")]
366impl<K: Fingerprint + Ord, V: Fingerprint> Fingerprint for alloc::collections::BTreeMap<K, V> {
367 #[inline]
368 fn fingerprint<U: Update>(&self, hasher: &mut U) {
369 self.len().fingerprint(hasher);
370
371 for element in self.iter() {
372 element.fingerprint(hasher);
373 }
374 }
375}
376
377#[cfg(feature = "std")]
378impl<K: Fingerprint + Ord + Eq + Hash, V: Fingerprint> Fingerprint
379 for std::collections::HashMap<K, V>
380{
381 #[inline]
382 fn fingerprint<U: Update>(&self, hasher: &mut U) {
383 let mut vec: alloc::vec::Vec<(&K, &V)> = self.iter().collect();
384 vec.sort_by_key(|t| t.0);
385
386 vec.fingerprint(hasher);
387 }
388}
389
390impl<T: Fingerprint> Fingerprint for core::ops::Range<T> {
391 #[inline]
392 fn fingerprint<U: Update>(&self, hasher: &mut U) {
393 self.start.fingerprint(hasher);
394 self.end.fingerprint(hasher);
395 }
396}
397
398impl<T: Fingerprint> Fingerprint for core::ops::RangeInclusive<T> {
399 #[inline]
400 fn fingerprint<U: Update>(&self, hasher: &mut U) {
401 self.start().fingerprint(hasher);
402 self.end().fingerprint(hasher);
403 }
404}
405
406impl<T: Fingerprint> Fingerprint for core::ops::Bound<T> {
407 #[inline]
408 fn fingerprint<U: Update>(&self, hasher: &mut U) {
409 match self {
410 core::ops::Bound::Included(bound) => {
411 0u8.fingerprint(hasher);
412 bound.fingerprint(hasher);
413 }
414 core::ops::Bound::Excluded(bound) => {
415 1u8.fingerprint(hasher);
416 bound.fingerprint(hasher);
417 }
418 core::ops::Bound::Unbounded => {
419 2u8.fingerprint(hasher);
420 }
421 }
422 }
423}
424
425impl_method!(core::time::Duration, as_nanos());
426
427#[cfg(all(feature = "std", feature = "os"))]
428impl Fingerprint for std::time::SystemTime {
429 #[inline]
430 fn fingerprint<U: Update>(&self, hasher: &mut U) {
431 match self.duration_since(std::time::SystemTime::UNIX_EPOCH) {
432 Ok(duration) => {
433 0u8.fingerprint(hasher);
434 duration.fingerprint(hasher);
435 }
436 Err(error) => {
437 1u8.fingerprint(hasher);
438 error.duration().fingerprint(hasher);
439 }
440 }
441 }
442}
443
444#[cfg(feature = "std")]
445impl_method!(std::net::Ipv4Addr, octets());
446#[cfg(feature = "std")]
447impl_method!(std::net::Ipv6Addr, octets());
448
449#[cfg(feature = "std")]
450impl Fingerprint for std::net::IpAddr {
451 #[inline]
452 fn fingerprint<U: Update>(&self, hasher: &mut U) {
453 match self {
454 std::net::IpAddr::V4(address) => {
455 4u8.fingerprint(hasher);
456 address.fingerprint(hasher);
457 }
458 std::net::IpAddr::V6(address) => {
459 6u8.fingerprint(hasher);
460 address.fingerprint(hasher);
461 }
462 }
463 }
464}
465
466#[cfg(feature = "std")]
467impl Fingerprint for std::net::SocketAddrV4 {
468 #[inline]
469 fn fingerprint<U: Update>(&self, hasher: &mut U) {
470 self.ip().fingerprint(hasher);
471 self.port().fingerprint(hasher);
472 }
473}
474
475#[cfg(feature = "std")]
476impl Fingerprint for std::net::SocketAddrV6 {
477 #[inline]
478 fn fingerprint<U: Update>(&self, hasher: &mut U) {
479 self.ip().fingerprint(hasher);
480 self.port().fingerprint(hasher);
481 self.flowinfo().fingerprint(hasher);
482 self.scope_id().fingerprint(hasher);
483 }
484}
485
486#[cfg(feature = "std")]
487impl Fingerprint for std::net::SocketAddr {
488 #[inline]
489 fn fingerprint<U: Update>(&self, hasher: &mut U) {
490 match self {
491 std::net::SocketAddr::V4(address) => {
492 4u8.fingerprint(hasher);
493 address.fingerprint(hasher);
494 }
495 std::net::SocketAddr::V6(address) => {
496 6u8.fingerprint(hasher);
497 address.fingerprint(hasher);
498 }
499 }
500 }
501}
502
503impl_inner!(core::num::Wrapping<T>);
504impl_inner!(core::cmp::Reverse<T>);