1use core::hash::{Hash, Hasher};
10
11use serde::{Deserialize, Serialize};
12use xxhash_rust::xxh3;
13
14#[repr(transparent)]
15#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
16#[serde(transparent)]
17pub struct Hash64(pub u64);
18
19impl From<u64> for Hash64 {
20 fn from(value: u64) -> Self {
21 Hash64(value)
22 }
23}
24
25impl From<Hash64> for u64 {
26 fn from(hash: Hash64) -> Self {
27 hash.0
28 }
29}
30
31impl Hash for Hash64 {
32 fn hash<H: Hasher>(&self, state: &mut H) {
33 state.write_u64(self.0)
34 }
35}
36
37#[repr(transparent)]
38#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
39#[serde(transparent)]
40pub struct Hash128(pub u128);
41
42impl From<u128> for Hash128 {
43 fn from(value: u128) -> Self {
44 Hash128(value)
45 }
46}
47
48impl From<Hash128> for u128 {
49 fn from(hash: Hash128) -> Self {
50 hash.0
51 }
52}
53
54impl Hash for Hash128 {
55 fn hash<H: Hasher>(&self, state: &mut H) {
56 state.write_u128(self.0)
57 }
58}
59
60impl Hash128 {
61 #[inline]
63 pub fn to_hex_string(self) -> String {
64 const HEX_DIGITS: &[u8; 16] = b"0123456789abcdef";
65 let mut buf = String::with_capacity(32);
66 let val = self.0;
67 for i in (0..32).rev() {
68 let nibble = ((val >> (i * 4)) & 0xf) as usize;
69 buf.push(HEX_DIGITS[nibble] as char);
70 }
71 buf
72 }
73
74 #[inline]
76 pub fn to_hex_string_prefixed(self) -> String {
77 const HEX_DIGITS: &[u8; 16] = b"0123456789abcdef";
78 let mut buf = String::with_capacity(34);
79 buf.push_str("0x");
80 let val = self.0;
81 for i in (0..32).rev() {
82 let nibble = ((val >> (i * 4)) & 0xf) as usize;
83 buf.push(HEX_DIGITS[nibble] as char);
84 }
85 buf
86 }
87}
88
89#[inline]
91pub fn xxh3_64(data: &[u8]) -> Hash64 {
92 Hash64(xxh3::xxh3_64(data))
93}
94
95#[inline]
97pub fn xxh3_128(data: &[u8]) -> Hash128 {
98 Hash128(xxh3::xxh3_128(data))
99}
100
101#[cfg(test)]
102mod tests {
103 use super::*;
104
105 #[test]
106 fn test_xxh3_64() {
107 let data = b"hello world";
108 let hash = xxh3_64(data);
109 assert_eq!(hash, xxh3_64(data));
111 assert_ne!(hash, xxh3_64(b"different data"));
112 }
113
114 #[test]
115 fn test_xxh3_128() {
116 let data = b"hello world";
117 let hash = xxh3_128(data);
118 assert_eq!(hash, xxh3_128(data));
120 assert_ne!(hash, xxh3_128(b"different data"));
121 }
122
123 #[test]
124 fn test_hash64_conversions() {
125 let value: u64 = 12345;
126 let hash = Hash64::from(value);
127 assert_eq!(u64::from(hash), value);
128 }
129
130 #[test]
131 fn test_hash128_conversions() {
132 let value: u128 = 123456789;
133 let hash = Hash128::from(value);
134 assert_eq!(u128::from(hash), value);
135 }
136}