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}