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