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