xxhash/xxhash.rs
1#![no_std]
2#![allow(unexpected_cfgs)]
3
4//! xxHash — extremely fast non-cryptographic hash algorithm.
5//!
6//! Provides four variants:
7//!
8//! | Struct | Bits | Description |
9//! |--------|------|-------------|
10//! | [`Xxh3_64`] | 64 | Recommended — XXH3 algorithm, faster on modern CPUs |
11//! | [`Xxh3_128`] | 128 | Recommended — XXH3 algorithm, 128-bit output |
12//! | [`Xxh32`] | 32 | Classic xxHash (XXH32) |
13//! | [`Xxh64`] | 64 | Classic xxHash (XXH64) |
14//!
15//! **Prefer [`Xxh3_64`] or [`Xxh3_128`] for new code.** XXH3 is the modern
16//! variant: ~2x faster on large inputs and >3x faster on small inputs
17//! compared to the classic XXH64, with better hash quality.
18//!
19//! All types implement the [`Checksum`] trait.
20//!
21//! # Const one-shot hashing
22//!
23//! Use the free functions [`xxh32`], [`xxh64`], [`xxh3_64`], and
24//! [`xxh3_128`] for `const`-compatible one-shot hashing:
25//!
26//! ```rust
27//! use xxhash::xxh3_64;
28//!
29//! const HASH: u64 = xxh3_64(b"hello");
30//! assert_eq!(HASH, 0x9555E8555C62DCFD);
31//! ```
32//!
33//! # Examples
34//!
35//! ## One-shot hashing (via trait)
36//!
37//! ```rust
38//! use xxhash::{Xxh3_64, Checksum};
39//!
40//! let hash: u64 = Xxh3_64::checksum(b"hello world");
41//! ```
42//!
43//! ## Incremental hashing
44//!
45//! ```rust
46//! use xxhash::{Xxh3_128, Checksum};
47//!
48//! let mut hasher = Xxh3_128::new();
49//! hasher.update(b"hello ");
50//! hasher.update(b"world");
51//! let hash: u128 = hasher.sum();
52//! ```
53//!
54//! ## Seeded hashing
55//!
56//! ```rust
57//! use xxhash::{Xxh3_64, Checksum};
58//!
59//! let mut hasher = Xxh3_64::with_seed(42);
60//! hasher.update(b"data");
61//! let hash: u64 = hasher.sum();
62//! ```
63//!
64//! ## XXH3 with a custom secret
65//!
66//! ```rust
67//! use xxhash::{Xxh3_64, Checksum};
68//!
69//! let secret = [0xAB; 192];
70//! let mut hasher = Xxh3_64::with_secret(secret);
71//! hasher.update(b"data");
72//! let hash: u64 = hasher.sum();
73//! ```
74
75use core::fmt;
76
77#[cfg(target_arch = "aarch64")]
78#[path = "xxh3_neon.rs"]
79mod xxh3_neon;
80
81#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
82#[path = "xxh3_avx2.rs"]
83mod xxh3_avx2;
84
85#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
86#[path = "xxh3_avx512.rs"]
87mod xxh3_avx512;
88
89#[cfg(all(target_arch = "wasm32", target_feature = "simd128"))]
90#[path = "xxh3_wasm_simd128.rs"]
91mod xxh3_wasm_simd128;
92
93mod xxh3;
94mod xxh32;
95mod xxh64;
96
97mod sealed {
98 pub trait Sealed {}
99 impl Sealed for u32 {}
100 impl Sealed for u64 {}
101 impl Sealed for u128 {}
102}
103
104/// Trait for types that can be used as xxHash outputs.
105///
106/// This trait is sealed and only implemented for `u32`, `u64`, and `u128`.
107pub trait ChecksumOutput: sealed::Sealed + Copy + Clone + fmt::Debug + PartialEq + 'static {}
108
109impl ChecksumOutput for u32 {}
110impl ChecksumOutput for u64 {}
111impl ChecksumOutput for u128 {}
112
113/// A trait for computing checksums.
114///
115/// Types implementing this trait can compute a hash incrementally via
116/// [`update`](Checksum::update) and [`sum`](Checksum::sum), or in a single
117/// call via [`checksum`](Checksum::checksum).
118pub trait Checksum {
119 /// The type of the resulting checksum value.
120 type Output: ChecksumOutput;
121
122 /// Create a new checksum instance with default settings (seed = 0,
123 /// default secret for XXH3 variants).
124 fn new() -> Self;
125
126 /// Compute the checksum of `data` in a single call.
127 fn checksum(data: &[u8]) -> Self::Output
128 where
129 Self: Sized,
130 {
131 let mut hasher = Self::new();
132 hasher.update(data);
133 hasher.sum()
134 }
135
136 /// Feed additional data into the checksum.
137 fn update(&mut self, data: &[u8]);
138
139 /// Finalize and return the computed checksum value.
140 fn sum(self) -> Self::Output;
141}
142
143pub use xxh3::{Xxh3_64, Xxh3_128, xxh3_64, xxh3_128};
144pub use xxh32::{Xxh32, xxh32};
145pub use xxh64::{Xxh64, xxh64};
146
147#[cfg(test)]
148mod test_helpers {
149 extern crate alloc;
150
151 /// Fills a buffer with pseudorandom data, exactly matching the C reference's
152 /// `XSUM_fillTestBuffer` from `xsum_sanity_check.c`.
153 ///
154 /// The PRNG uses:
155 /// - `byteGen` initialized to `PRIME32` (0x9E3779B1)
156 /// - Each iteration: `buf[i] = byteGen >> 56; byteGen *= PRIME64` where
157 /// `PRIME64` is the C test file's constant 0x9E3779B185EBCA8D (not the
158 /// hash PRIME64_1 constant).
159 pub(crate) fn fill_test_buffer(len: usize) -> alloc::vec::Vec<u8> {
160 const C_PRIME32: u64 = 0x9E3779B1;
161 const C_PRIME64: u64 = 0x9E3779B185EBCA8D;
162
163 let mut buf = alloc::vec::Vec::with_capacity(len);
164 let mut byte_gen = C_PRIME32;
165 for _ in 0..len {
166 buf.push((byte_gen >> 56) as u8);
167 byte_gen = byte_gen.wrapping_mul(C_PRIME64);
168 }
169 buf
170 }
171}