use xxhash_rust::xxh64::xxh64;
#[inline]
pub fn compute_xxh64(data: &[u8]) -> u64 {
xxh64(data, 0)
}
#[inline]
pub fn verify_xxh64(data: &[u8], expected: u64) -> bool {
compute_xxh64(data) == expected
}
#[cfg(feature = "xxh3")]
#[inline]
pub fn compute_xxh3(data: &[u8]) -> u64 {
xxhash_rust::xxh3::xxh3_64(data)
}
#[cfg(feature = "xxh3")]
#[inline]
pub fn verify_xxh3(data: &[u8], expected: u64) -> bool {
compute_xxh3(data) == expected
}
#[cfg(feature = "compat-crc32")]
#[inline]
pub fn compute_crc32(data: &[u8]) -> u64 {
crc32fast::hash(data) as u64
}
#[cfg(feature = "compat-crc32")]
#[inline]
pub fn verify_crc32(data: &[u8], expected: u64) -> bool {
compute_crc32(data) == expected
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
pub enum ChecksumAlgo {
Xxh64 = 0,
Xxh3 = 1,
Crc32 = 2,
}
impl ChecksumAlgo {
#[inline]
pub fn compute(self, data: &[u8]) -> u64 {
match self {
ChecksumAlgo::Xxh64 => compute_xxh64(data),
#[cfg(feature = "xxh3")]
ChecksumAlgo::Xxh3 => compute_xxh3(data),
#[cfg(not(feature = "xxh3"))]
ChecksumAlgo::Xxh3 => compute_xxh64(data), #[cfg(feature = "compat-crc32")]
ChecksumAlgo::Crc32 => compute_crc32(data),
#[cfg(not(feature = "compat-crc32"))]
ChecksumAlgo::Crc32 => compute_xxh64(data), }
}
#[inline]
pub fn verify(self, data: &[u8], expected: u64) -> bool {
self.compute(data) == expected
}
#[inline]
pub fn default_algo() -> Self {
#[cfg(feature = "xxh3")]
{
ChecksumAlgo::Xxh3
}
#[cfg(not(feature = "xxh3"))]
{
ChecksumAlgo::Xxh64
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn checksum_deterministic() {
let data = b"The quick brown fox jumps over the lazy dog";
let h1 = compute_xxh64(data);
let h2 = compute_xxh64(data);
assert_eq!(h1, h2);
}
#[test]
fn checksum_differs_for_different_data() {
let h1 = compute_xxh64(b"aaa");
let h2 = compute_xxh64(b"aab");
assert_ne!(h1, h2);
}
#[test]
fn verify_works() {
let data = b"test data";
let hash = compute_xxh64(data);
assert!(verify_xxh64(data, hash));
assert!(!verify_xxh64(data, hash.wrapping_add(1)));
}
#[test]
fn algo_api() {
let data = b"checksum algo test";
let algo = ChecksumAlgo::Xxh64;
let hash = algo.compute(data);
assert!(algo.verify(data, hash));
assert!(!algo.verify(data, hash ^ 1));
}
#[test]
fn default_algo_works() {
let data = b"default algo";
let algo = ChecksumAlgo::default_algo();
let hash = algo.compute(data);
assert!(algo.verify(data, hash));
}
}