pub trait HashFinalize {
#[inline(always)]
fn finalize_hash(raw: u64, storage_bytes: usize) -> u64 {
let _ = storage_bytes;
raw
}
}
impl HashFinalize for fxhash::FxBuildHasher {
#[inline(always)]
fn finalize_hash(raw: u64, storage_bytes: usize) -> u64 {
if storage_bytes <= std::mem::size_of::<u64>() {
raw ^ (raw >> 32)
} else {
raw
}
}
}
#[cfg(all(
feature = "gxhash",
target_feature = "aes",
any(target_arch = "x86_64", target_arch = "aarch64")
))]
impl HashFinalize for gxhash::GxBuildHasher {}
#[cfg(test)]
mod tests {
use super::*;
const RAW: u64 = 0xDEAD_BEEF_0000_0001;
#[test]
fn fxhash_folds_narrow_storage() {
for width in [1, 2, 4, 8] {
assert_eq!(
<fxhash::FxBuildHasher as HashFinalize>::finalize_hash(RAW, width),
RAW ^ (RAW >> 32),
"fxhash should fold at width {width}"
);
}
}
#[test]
fn fxhash_passes_wide_storage_through() {
for width in [16, 32, 64] {
assert_eq!(
<fxhash::FxBuildHasher as HashFinalize>::finalize_hash(RAW, width),
RAW,
"fxhash should not fold at width {width}"
);
}
}
#[cfg(all(
feature = "gxhash",
target_feature = "aes",
any(target_arch = "x86_64", target_arch = "aarch64")
))]
#[test]
fn gxhash_never_folds() {
for width in [1, 2, 4, 8, 16, 32, 64] {
assert_eq!(
<gxhash::GxBuildHasher as HashFinalize>::finalize_hash(RAW, width),
RAW,
"gxhash should never fold (width {width})"
);
}
}
}