fasthash_fork/
xxh3.rs

1//! XXH3 is a new hash algorithm, featuring vastly improved speed performance for both small and large inputs.
2use std::hash::Hasher;
3use std::mem;
4use std::ptr::NonNull;
5
6use crate::{FastHash, FastHasher, HasherExt, StreamHasher};
7
8/// 64-bit hash functions for a byte array.
9///
10/// # Example
11///
12/// ```
13/// use fasthash::xxh3;
14///
15/// assert_eq!(xxh3::hash64("hello world"), 15296390279056496779);
16/// ```
17#[inline(always)]
18pub fn hash64<T: AsRef<[u8]>>(v: T) -> u64 {
19    Hash64::hash(v)
20}
21
22/// 64-bit hash function for a byte array.
23/// For convenience, a 64-bit seed is also hashed into the result.
24///
25/// # Example
26///
27/// ```
28/// use fasthash::xxh3;
29///
30/// assert_eq!(xxh3::hash64_with_seed("hello world", 123456789), 14779966986402262731);
31/// ```
32#[inline(always)]
33pub fn hash64_with_seed<T: AsRef<[u8]>>(v: T, seed: u64) -> u64 {
34    Hash64::hash_with_seed(v, seed)
35}
36
37/// 128-bit hash function for a byte array.
38///
39/// # Example
40///
41/// ```
42/// use fasthash::xxh3;
43///
44/// assert_eq!(
45///     xxh3::hash128("hello world"),
46///     297150157938599054391163723952090887879,
47/// );
48/// ```
49#[inline(always)]
50pub fn hash128<T: AsRef<[u8]>>(v: T) -> u128 {
51    Hash128::hash(v)
52}
53
54/// 128-bit hash function for a byte array.
55///
56/// For convenience, a 128-bit seed is also hashed into the result.
57///
58/// # Example
59///
60/// ```
61/// use fasthash::xxh3;
62///
63/// assert_eq!(
64///     xxh3::hash128_with_seed("hello world", 123456789),
65///     30898888592805294509478050770614222910,
66/// );
67/// ```
68#[inline(always)]
69pub fn hash128_with_seed<T: AsRef<[u8]>>(v: T, seed: u64) -> u128 {
70    Hash128::hash_with_seed(v, seed)
71}
72
73/// An implementation of `std::hash::Hasher`.
74///
75/// # Example
76///
77/// ```
78/// use std::hash::Hasher;
79/// use std::io::Cursor;
80///
81/// use fasthash::{xxh3::Hasher64, FastHasher, StreamHasher};
82///
83/// let mut h = Hasher64::new();
84///
85/// h.write(b"hello");
86/// assert_eq!(h.finish(), 10760762337991515389);
87///
88/// h.write(b"world");
89/// assert_eq!(h.finish(), 18436838148490100038);
90/// ```
91#[derive(Clone, Default)]
92pub struct Hash64;
93
94impl FastHash for Hash64 {
95    type Hash = u64;
96    type Seed = u64;
97
98    #[inline(always)]
99    fn hash<T: AsRef<[u8]>>(bytes: T) -> Self::Hash {
100        let bytes = bytes.as_ref();
101
102        unsafe { ffi::XXH3_64bits(bytes.as_ptr() as *const _, bytes.len()) }
103    }
104
105    #[inline(always)]
106    fn hash_with_seed<T: AsRef<[u8]>>(bytes: T, seed: Self::Seed) -> Self::Hash {
107        let bytes = bytes.as_ref();
108
109        unsafe { ffi::XXH3_64bits_withSeed(bytes.as_ptr() as *const _, bytes.len(), seed) }
110    }
111}
112
113/// An implementation of `std::hash::Hasher`.
114///
115/// # Example
116///
117/// ```
118/// use std::hash::Hasher;
119///
120/// use fasthash::{xxh3::Hasher64, FastHasher};
121///
122/// let mut h = Hasher64::new();
123///
124/// h.write(b"hello");
125/// assert_eq!(h.finish(), 10760762337991515389);
126///
127/// h.write(b"world");
128/// assert_eq!(h.finish(), 18436838148490100038);
129/// ```
130pub struct Hasher64(NonNull<ffi::XXH3_state_t>);
131
132impl Default for Hasher64 {
133    fn default() -> Self {
134        Hasher64(unsafe { NonNull::new_unchecked(ffi::XXH3_createState()) })
135    }
136}
137
138impl Clone for Hasher64 {
139    fn clone(&self) -> Self {
140        unsafe {
141            let state = ffi::XXH3_createState();
142
143            ffi::XXH3_copyState(state, self.0.as_ptr());
144
145            Hasher64(NonNull::new_unchecked(state))
146        }
147    }
148}
149
150impl Drop for Hasher64 {
151    fn drop(&mut self) {
152        unsafe {
153            ffi::XXH3_freeState(self.0.as_ptr());
154        }
155    }
156}
157
158impl Hasher for Hasher64 {
159    #[inline(always)]
160    fn finish(&self) -> u64 {
161        unsafe { ffi::XXH3_64bits_digest(self.0.as_ptr()) }
162    }
163
164    #[inline(always)]
165    fn write(&mut self, bytes: &[u8]) {
166        unsafe {
167            ffi::XXH3_64bits_update(self.0.as_ptr(), bytes.as_ptr() as *const _, bytes.len());
168        }
169    }
170}
171
172impl FastHasher for Hasher64 {
173    type Seed = u64;
174    type Output = u64;
175
176    #[inline(always)]
177    fn with_seed(seed: u64) -> Self {
178        unsafe {
179            let state = ffi::XXH3_createState();
180
181            ffi::XXH3_64bits_reset_withSeed(state, seed);
182
183            Hasher64(NonNull::new_unchecked(state))
184        }
185    }
186}
187
188impl StreamHasher for Hasher64 {}
189
190impl_build_hasher!(Hasher64, Hash64);
191
192/// An implementation of `std::hash::Hasher`.
193///
194/// # Example
195///
196/// ```
197/// use std::hash::Hasher;
198/// use std::io::Cursor;
199///
200/// use fasthash::{xxh3::Hasher128, FastHasher, HasherExt, StreamHasher};
201///
202/// let mut h = Hasher128::new();
203///
204/// h.write(b"hello");
205/// assert_eq!(h.finish_ext(), 241804000618833338782870102822322583576);
206///
207/// h.write(b"world");
208/// assert_eq!(h.finish_ext(), 295047064626328774025194411167141021551);
209/// ```
210#[derive(Clone, Default)]
211pub struct Hash128;
212
213impl FastHash for Hash128 {
214    type Hash = u128;
215    type Seed = u64;
216
217    #[inline(always)]
218    fn hash<T: AsRef<[u8]>>(bytes: T) -> Self::Hash {
219        let bytes = bytes.as_ref();
220
221        unsafe { mem::transmute(ffi::XXH3_128bits(bytes.as_ptr() as *const _, bytes.len())) }
222    }
223
224    #[inline(always)]
225    fn hash_with_seed<T: AsRef<[u8]>>(bytes: T, seed: Self::Seed) -> Self::Hash {
226        let bytes = bytes.as_ref();
227
228        unsafe {
229            mem::transmute(ffi::XXH3_128bits_withSeed(
230                bytes.as_ptr() as *const _,
231                bytes.len(),
232                seed,
233            ))
234        }
235    }
236}
237
238/// An implementation of `std::hash::Hasher`.
239///
240/// # Example
241///
242/// ```
243/// use std::hash::Hasher;
244///
245/// use fasthash::{xxh3::Hasher128, FastHasher, HasherExt};
246///
247/// let mut h = Hasher128::new();
248///
249/// h.write(b"hello");
250/// assert_eq!(h.finish_ext(), 241804000618833338782870102822322583576);
251///
252/// h.write(b"world");
253/// assert_eq!(h.finish_ext(), 295047064626328774025194411167141021551);
254/// ```
255pub struct Hasher128(NonNull<ffi::XXH3_state_t>);
256
257impl Default for Hasher128 {
258    fn default() -> Self {
259        Hasher128(unsafe { NonNull::new_unchecked(ffi::XXH3_createState()) })
260    }
261}
262
263impl Clone for Hasher128 {
264    fn clone(&self) -> Self {
265        unsafe {
266            let state = ffi::XXH3_createState();
267
268            ffi::XXH3_copyState(state, self.0.as_ptr());
269
270            Hasher128(NonNull::new_unchecked(state))
271        }
272    }
273}
274
275impl Drop for Hasher128 {
276    fn drop(&mut self) {
277        unsafe {
278            ffi::XXH3_freeState(self.0.as_ptr());
279        }
280    }
281}
282
283impl Hasher for Hasher128 {
284    #[inline(always)]
285    fn finish(&self) -> u64 {
286        unsafe { ffi::XXH3_128bits_digest(self.0.as_ptr()).low64 }
287    }
288
289    #[inline(always)]
290    fn write(&mut self, bytes: &[u8]) {
291        unsafe {
292            ffi::XXH3_128bits_update(self.0.as_ptr(), bytes.as_ptr() as *const _, bytes.len());
293        }
294    }
295}
296
297impl HasherExt for Hasher128 {
298    #[inline(always)]
299    fn finish_ext(&self) -> u128 {
300        let h = unsafe { ffi::XXH3_128bits_digest(self.0.as_ptr()) };
301
302        u128::from(h.low64) + (u128::from(h.high64) << 64)
303    }
304}
305
306impl FastHasher for Hasher128 {
307    type Seed = u64;
308    type Output = u128;
309
310    #[inline(always)]
311    fn with_seed(seed: u64) -> Self {
312        unsafe {
313            let state = ffi::XXH3_createState();
314
315            ffi::XXH3_128bits_reset_withSeed(state, seed);
316
317            Hasher128(NonNull::new_unchecked(state))
318        }
319    }
320}
321
322impl StreamHasher for Hasher128 {}
323
324impl_build_hasher!(Hasher128, Hash128);