1use alloc::borrow::ToOwned;
2use core::hash::Hasher;
3
4pub trait TypeHash {
6 #[allow(unused)]
12 fn type_hash() -> u64 {
13 let mut hasher = fnv::FnvHasher::default();
14 Self::write_hash(&mut hasher);
15 hasher.finish()
16 }
17
18 fn write_hash(hasher: &mut impl Hasher);
20}
21
22macro_rules! impl_type_hash {
23 ($( $($ty: ident)::* $(<$($l: lifetime,)* $($T: ident $(: $(? $Sized: ident)? $($(+)? $B: ident)*)?),+>)?,)*) => {
24 $(
25 impl $(<$($l,)* $($T: $crate::TypeHash $($(+ ?$Sized)? $(+ $B)*)? ),*>)? TypeHash for $($ty)::* $(<$($l,)* $($T),+>)? {
26 fn write_hash(hasher: &mut impl core::hash::Hasher) {
27 hasher.write(stringify!($($ty)::*).as_bytes());
28 $($(
29 $T::write_hash(hasher);
30 )+)?
31 }
32 }
33 )*
34 };
35}
36
37impl_type_hash!(
38 bool,
39 u8,
40 i8,
41 u16,
42 i16,
43 u32,
44 i32,
45 u64,
46 i64,
47 u128,
48 i128,
49 usize,
50 isize,
51 f32,
52 f64,
53 str,
54 core::any::TypeId,
55 alloc::borrow::Cow<'a, T: ?Sized + ToOwned>,
56 alloc::boxed::Box<T: ?Sized>,
57 core::cell::Cell<T: ?Sized>,
58 core::cell::Ref<'a, T: ?Sized>,
59 core::cell::RefCell<T: ?Sized>,
60 core::cell::RefMut<'a, T>,
61 core::cell::UnsafeCell<T>,
62 core::cmp::Ordering,
63 core::cmp::Reverse<T>,
64 alloc::collections::BinaryHeap<T>,
65 alloc::collections::BTreeMap<K, V>,
66 alloc::collections::BTreeSet<T>,
67 alloc::collections::LinkedList<T>,
68 alloc::collections::VecDeque<T>,
69 core::hash::BuildHasherDefault<T>,
70 core::marker::PhantomData<T: ?Sized>,
71 core::mem::ManuallyDrop<T: ?Sized>,
72 core::mem::MaybeUninit<T>,
73 core::net::IpAddr,
74 core::net::Ipv4Addr,
75 core::net::Ipv6Addr,
76 core::net::SocketAddr,
77 core::net::SocketAddrV4,
78 core::net::SocketAddrV6,
79 core::num::FpCategory,
80 core::num::NonZeroI128,
81 core::num::NonZeroI16,
82 core::num::NonZeroI32,
83 core::num::NonZeroI64,
84 core::num::NonZeroI8,
85 core::num::NonZeroIsize,
86 core::num::NonZeroU128,
87 core::num::NonZeroU16,
88 core::num::NonZeroU32,
89 core::num::NonZeroU64,
90 core::num::NonZeroU8,
91 core::num::NonZeroUsize,
92 core::num::Wrapping<T>,
93 core::ops::Bound<T>,
94 core::ops::Range<T>,
95 core::ops::RangeFrom<T>,
96 core::ops::RangeInclusive<T>,
97 core::ops::RangeFull,
98 core::ops::RangeTo<T>,
99 core::ops::RangeToInclusive<T>,
100 core::option::Option<T>,
101 core::pin::Pin<T>,
102 core::primitive::char,
103 core::ptr::NonNull<T: ?Sized>,
104 alloc::rc::Rc<T: ?Sized>,
105 alloc::rc::Weak<T: ?Sized>,
106 core::result::Result<T, E>,
107 alloc::string::String,
108 core::time::Duration,
109 alloc::vec::Vec<T>,
110 hashbrown::HashMap<K, V>,
111 hashbrown::HashSet<T>,
112 portable_atomic::AtomicBool,
113 portable_atomic::AtomicI16,
114 portable_atomic::AtomicI32,
115 portable_atomic::AtomicI64,
116 portable_atomic::AtomicI8,
117 portable_atomic::AtomicIsize,
118 portable_atomic::AtomicPtr<T>,
119 portable_atomic::AtomicU16,
120 portable_atomic::AtomicU32,
121 portable_atomic::AtomicU64,
122 portable_atomic::AtomicU8,
123 portable_atomic::AtomicUsize,
124);
125
126macro_rules! impl_type_hash_tuple {
127 ($($T: ident),*) => {
128 impl <$($T: $crate::TypeHash),*> TypeHash for ($($T,)*) {
129 fn write_hash(hasher: &mut impl core::hash::Hasher) {
130 hasher.write(b"()");
131 $(
132 $T::write_hash(hasher);
133 )*
134 }
135 }
136 };
137}
138
139variadics_please::all_tuples!(impl_type_hash_tuple, 0, 16, T);
140
141impl<T: TypeHash, const N: usize> TypeHash for [T; N] {
142 fn write_hash(hasher: &mut impl core::hash::Hasher) {
143 hasher.write(b"[;]");
144 hasher.write_usize(N);
145 T::write_hash(hasher);
146 }
147}
148
149impl<T: TypeHash + ?Sized> TypeHash for *const T {
150 fn write_hash(hasher: &mut impl Hasher) {
151 hasher.write(b"*const");
152 T::write_hash(hasher);
153 }
154}
155
156impl<T: TypeHash + ?Sized> TypeHash for *mut T {
157 fn write_hash(hasher: &mut impl Hasher) {
158 hasher.write(b"*mut");
159 T::write_hash(hasher);
160 }
161}
162
163impl<T: TypeHash> TypeHash for [T] {
164 fn write_hash(hasher: &mut impl Hasher) {
165 hasher.write(b"[]");
166 T::write_hash(hasher);
167 }
168}
169
170impl<T: TypeHash + ?Sized> TypeHash for &T {
171 fn write_hash(hasher: &mut impl Hasher) {
172 hasher.write(b"&");
173 T::write_hash(hasher);
174 }
175}
176
177impl<T: TypeHash + ?Sized> TypeHash for &mut T {
178 fn write_hash(hasher: &mut impl Hasher) {
179 hasher.write(b"&mut");
180 T::write_hash(hasher);
181 }
182}