1use crate::config::Config;
15#[cfg(feature = "alloc")]
16use alloc::borrow::ToOwned;
17
18pub trait Fingerprint<C: Config> {
26 const SCHEMA_HASH: u64;
28}
29
30macro_rules! impl_fingerprint {
31 ($($t:ty => $name:expr),*) => {
32 $(
33 impl<C: Config> Fingerprint<C> for $t {
34 const SCHEMA_HASH: u64 = rapidhash::v3::rapidhash_v3_seeded($name, &rapidhash::v3::RapidSecrets::seed_cpp(C::CONFIG_HASH));
35 }
36 )*
37 };
38}
39
40impl_fingerprint! {
41 u8 => b"u8",
42 u16 => b"u16",
43 u32 => b"u32",
44 u64 => b"u64",
45 u128 => b"u128",
46 usize => b"usize",
47 i8 => b"i8",
48 i16 => b"i16",
49 i32 => b"i32",
50 i64 => b"i64",
51 i128 => b"i128",
52 isize => b"isize",
53 bool => b"bool",
54 f32 => b"f32",
55 f64 => b"f64",
56 char => b"char",
57 str => b"str"
58}
59
60impl<C: Config, T: Fingerprint<C>, const N: usize> Fingerprint<C> for [T; N] {
61 const SCHEMA_HASH: u64 = rapidhash::v3::rapidhash_v3_seeded(
62 &N.to_le_bytes(),
63 &rapidhash::v3::RapidSecrets::seed_cpp(T::SCHEMA_HASH),
64 );
65}
66
67#[cfg(feature = "alloc")]
68impl<C: Config, T: Fingerprint<C>> Fingerprint<C> for alloc::vec::Vec<T> {
69 const SCHEMA_HASH: u64 = rapidhash::v3::rapidhash_v3_seeded(
70 b"Vec",
71 &rapidhash::v3::RapidSecrets::seed_cpp(T::SCHEMA_HASH),
72 );
73}
74
75#[cfg(feature = "alloc")]
76impl<C: Config> Fingerprint<C> for alloc::string::String {
77 const SCHEMA_HASH: u64 = rapidhash::v3::rapidhash_v3_seeded(
78 b"str",
79 &rapidhash::v3::RapidSecrets::seed_cpp(C::CONFIG_HASH),
80 );
81}
82
83impl<C: Config> Fingerprint<C> for () {
84 const SCHEMA_HASH: u64 = rapidhash::v3::rapidhash_v3_seeded(
85 b"()",
86 &rapidhash::v3::RapidSecrets::seed_cpp(C::CONFIG_HASH),
87 );
88}
89
90impl<C: Config, T1: Fingerprint<C>> Fingerprint<C> for (T1,) {
91 const SCHEMA_HASH: u64 = T1::SCHEMA_HASH;
92}
93
94impl<C: Config, T1: Fingerprint<C>, T2: Fingerprint<C>> Fingerprint<C> for (T1, T2) {
95 const SCHEMA_HASH: u64 = rapidhash::v3::rapidhash_v3_seeded(
96 &T2::SCHEMA_HASH.to_le_bytes(),
97 &rapidhash::v3::RapidSecrets::seed_cpp(T1::SCHEMA_HASH),
98 );
99}
100
101impl<C: Config, T: Fingerprint<C>> Fingerprint<C> for Option<T> {
102 const SCHEMA_HASH: u64 = rapidhash::v3::rapidhash_v3_seeded(
103 b"Option",
104 &rapidhash::v3::RapidSecrets::seed_cpp(T::SCHEMA_HASH),
105 );
106}
107
108impl<C: Config, T: Fingerprint<C>, E: Fingerprint<C>> Fingerprint<C> for Result<T, E> {
109 const SCHEMA_HASH: u64 = rapidhash::v3::rapidhash_v3_seeded(
110 &E::SCHEMA_HASH.to_le_bytes(),
111 &rapidhash::v3::RapidSecrets::seed_cpp(rapidhash::v3::rapidhash_v3_seeded(
112 b"Result",
113 &rapidhash::v3::RapidSecrets::seed_cpp(T::SCHEMA_HASH),
114 )),
115 );
116}
117
118impl<C: Config, T: ?Sized> Fingerprint<C> for core::marker::PhantomData<T> {
119 const SCHEMA_HASH: u64 = rapidhash::v3::rapidhash_v3_seeded(
120 b"PhantomData",
121 &rapidhash::v3::RapidSecrets::seed_cpp(C::CONFIG_HASH),
122 );
123}
124
125impl<C: Config, T: ?Sized + Fingerprint<C>> Fingerprint<C> for &T {
126 const SCHEMA_HASH: u64 = T::SCHEMA_HASH;
127}
128
129impl<C: Config, T: ?Sized + Fingerprint<C>> Fingerprint<C> for &mut T {
130 const SCHEMA_HASH: u64 = T::SCHEMA_HASH;
131}
132
133#[cfg(feature = "alloc")]
134impl<C: Config, T: ?Sized + Fingerprint<C>> Fingerprint<C> for alloc::boxed::Box<T> {
135 const SCHEMA_HASH: u64 = T::SCHEMA_HASH;
136}
137
138#[cfg(feature = "alloc")]
139impl<C: Config, T: Fingerprint<C> + ToOwned + ?Sized> Fingerprint<C> for alloc::borrow::Cow<'_, T> {
140 const SCHEMA_HASH: u64 = T::SCHEMA_HASH;
141}
142
143#[cfg(feature = "alloc")]
144impl<C: Config, T: ?Sized + Fingerprint<C>> Fingerprint<C> for alloc::rc::Rc<T> {
145 const SCHEMA_HASH: u64 = T::SCHEMA_HASH;
146}
147
148#[cfg(feature = "alloc")]
149impl<C: Config, T: ?Sized + Fingerprint<C>> Fingerprint<C> for alloc::sync::Arc<T> {
150 const SCHEMA_HASH: u64 = T::SCHEMA_HASH;
151}
152
153#[cfg(feature = "alloc")]
154impl<C: Config, T: Fingerprint<C>> Fingerprint<C> for alloc::collections::VecDeque<T> {
155 const SCHEMA_HASH: u64 = rapidhash::v3::rapidhash_v3_seeded(
156 b"VecDeque",
157 &rapidhash::v3::RapidSecrets::seed_cpp(T::SCHEMA_HASH),
158 );
159}
160
161#[cfg(feature = "alloc")]
162impl<C: Config, T: Fingerprint<C>> Fingerprint<C> for alloc::collections::BinaryHeap<T> {
163 const SCHEMA_HASH: u64 = rapidhash::v3::rapidhash_v3_seeded(
164 b"BinaryHeap",
165 &rapidhash::v3::RapidSecrets::seed_cpp(T::SCHEMA_HASH),
166 );
167}
168
169#[cfg(feature = "alloc")]
170impl<C: Config, K: Fingerprint<C>, V: Fingerprint<C>> Fingerprint<C>
171 for alloc::collections::BTreeMap<K, V>
172{
173 const SCHEMA_HASH: u64 = rapidhash::v3::rapidhash_v3_seeded(
174 b"BTreeMap",
175 &rapidhash::v3::RapidSecrets::seed_cpp(rapidhash::v3::rapidhash_v3_seeded(
176 &V::SCHEMA_HASH.to_le_bytes(),
177 &rapidhash::v3::RapidSecrets::seed_cpp(K::SCHEMA_HASH),
178 )),
179 );
180}
181
182#[cfg(feature = "alloc")]
183impl<C: Config, T: Fingerprint<C>> Fingerprint<C> for alloc::collections::BTreeSet<T> {
184 const SCHEMA_HASH: u64 = rapidhash::v3::rapidhash_v3_seeded(
185 b"BTreeSet",
186 &rapidhash::v3::RapidSecrets::seed_cpp(T::SCHEMA_HASH),
187 );
188}
189
190#[cfg(feature = "std")]
191impl<C: Config, K: Fingerprint<C>, V: Fingerprint<C>, S> Fingerprint<C>
192 for std::collections::HashMap<K, V, S>
193{
194 const SCHEMA_HASH: u64 = rapidhash::v3::rapidhash_v3_seeded(
195 b"HashMap",
196 &rapidhash::v3::RapidSecrets::seed_cpp(rapidhash::v3::rapidhash_v3_seeded(
197 &V::SCHEMA_HASH.to_le_bytes(),
198 &rapidhash::v3::RapidSecrets::seed_cpp(K::SCHEMA_HASH),
199 )),
200 );
201}
202
203#[cfg(feature = "std")]
204impl<C: Config, T: Fingerprint<C>, S> Fingerprint<C> for std::collections::HashSet<T, S> {
205 const SCHEMA_HASH: u64 = rapidhash::v3::rapidhash_v3_seeded(
206 b"HashSet",
207 &rapidhash::v3::RapidSecrets::seed_cpp(T::SCHEMA_HASH),
208 );
209}
210
211impl<C: Config> Fingerprint<C> for core::time::Duration {
212 const SCHEMA_HASH: u64 = rapidhash::v3::rapidhash_v3_seeded(
213 b"Duration",
214 &rapidhash::v3::RapidSecrets::seed_cpp(C::CONFIG_HASH),
215 );
216}
217
218#[cfg(feature = "std")]
219impl<C: Config> Fingerprint<C> for std::time::SystemTime {
220 const SCHEMA_HASH: u64 = rapidhash::v3::rapidhash_v3_seeded(
221 b"SystemTime",
222 &rapidhash::v3::RapidSecrets::seed_cpp(C::CONFIG_HASH),
223 );
224}
225
226#[cfg(feature = "std")]
227impl<C: Config> Fingerprint<C> for std::net::IpAddr {
228 const SCHEMA_HASH: u64 = rapidhash::v3::rapidhash_v3_seeded(
229 b"IpAddr",
230 &rapidhash::v3::RapidSecrets::seed_cpp(C::CONFIG_HASH),
231 );
232}
233
234#[cfg(feature = "std")]
235impl<C: Config> Fingerprint<C> for std::net::Ipv4Addr {
236 const SCHEMA_HASH: u64 = rapidhash::v3::rapidhash_v3_seeded(
237 b"Ipv4Addr",
238 &rapidhash::v3::RapidSecrets::seed_cpp(C::CONFIG_HASH),
239 );
240}
241
242#[cfg(feature = "std")]
243impl<C: Config> Fingerprint<C> for std::net::Ipv6Addr {
244 const SCHEMA_HASH: u64 = rapidhash::v3::rapidhash_v3_seeded(
245 b"Ipv6Addr",
246 &rapidhash::v3::RapidSecrets::seed_cpp(C::CONFIG_HASH),
247 );
248}
249
250#[cfg(feature = "std")]
251impl<C: Config> Fingerprint<C> for std::net::SocketAddr {
252 const SCHEMA_HASH: u64 = rapidhash::v3::rapidhash_v3_seeded(
253 b"SocketAddr",
254 &rapidhash::v3::RapidSecrets::seed_cpp(C::CONFIG_HASH),
255 );
256}
257
258#[cfg(feature = "std")]
259impl<C: Config> Fingerprint<C> for std::net::SocketAddrV4 {
260 const SCHEMA_HASH: u64 = rapidhash::v3::rapidhash_v3_seeded(
261 b"SocketAddrV4",
262 &rapidhash::v3::RapidSecrets::seed_cpp(C::CONFIG_HASH),
263 );
264}
265
266#[cfg(feature = "std")]
267impl<C: Config> Fingerprint<C> for std::net::SocketAddrV6 {
268 const SCHEMA_HASH: u64 = rapidhash::v3::rapidhash_v3_seeded(
269 b"SocketAddrV6",
270 &rapidhash::v3::RapidSecrets::seed_cpp(C::CONFIG_HASH),
271 );
272}
273
274#[cfg(feature = "std")]
275impl<C: Config> Fingerprint<C> for std::path::Path {
276 const SCHEMA_HASH: u64 = rapidhash::v3::rapidhash_v3_seeded(
277 b"Path",
278 &rapidhash::v3::RapidSecrets::seed_cpp(C::CONFIG_HASH),
279 );
280}
281
282#[cfg(feature = "std")]
283impl<C: Config> Fingerprint<C> for std::path::PathBuf {
284 const SCHEMA_HASH: u64 = rapidhash::v3::rapidhash_v3_seeded(
285 b"PathBuf",
286 &rapidhash::v3::RapidSecrets::seed_cpp(C::CONFIG_HASH),
287 );
288}
289
290#[cfg(feature = "std")]
291impl<C: Config> Fingerprint<C> for std::ffi::CStr {
292 const SCHEMA_HASH: u64 = rapidhash::v3::rapidhash_v3_seeded(
293 b"CStr",
294 &rapidhash::v3::RapidSecrets::seed_cpp(C::CONFIG_HASH),
295 );
296}
297
298#[cfg(feature = "std")]
299impl<C: Config> Fingerprint<C> for std::ffi::CString {
300 const SCHEMA_HASH: u64 = rapidhash::v3::rapidhash_v3_seeded(
301 b"CString",
302 &rapidhash::v3::RapidSecrets::seed_cpp(C::CONFIG_HASH),
303 );
304}
305
306#[cfg(feature = "std")]
307impl<C: Config, T: Fingerprint<C>> Fingerprint<C> for std::sync::Mutex<T> {
308 const SCHEMA_HASH: u64 = T::SCHEMA_HASH;
309}
310
311#[cfg(feature = "std")]
312impl<C: Config, T: Fingerprint<C>> Fingerprint<C> for std::sync::RwLock<T> {
313 const SCHEMA_HASH: u64 = T::SCHEMA_HASH;
314}
315
316macro_rules! impl_tuple {
317 ($($t:ident),*) => {
318 impl<C: Config, $($t: Fingerprint<C>),*> Fingerprint<C> for ($($t,)*) {
319 const SCHEMA_HASH: u64 = {
320 let mut hash = C::CONFIG_HASH;
321 $(
322 hash = rapidhash::v3::rapidhash_v3_seeded(&$t::SCHEMA_HASH.to_le_bytes(), &rapidhash::v3::RapidSecrets::seed_cpp(hash));
323 )*
324 hash
325 };
326 }
327 };
328}
329
330impl_tuple!(T1, T2, T3);
331impl_tuple!(T1, T2, T3, T4);
332impl_tuple!(T1, T2, T3, T4, T5);
333impl_tuple!(T1, T2, T3, T4, T5, T6);
334impl_tuple!(T1, T2, T3, T4, T5, T6, T7);
335impl_tuple!(T1, T2, T3, T4, T5, T6, T7, T8);