#![forbid(unsafe_code)]
#[must_use]
pub fn stable_hash_u64_slice(sorted_values: &[u64]) -> u64 {
const HASH_PRIME: u64 = 1_099_511_628_211; const HASH_OFFSET: u64 = 14_695_981_039_346_656_037;
if sorted_values.is_empty() {
return 0;
}
let mut hash = HASH_OFFSET;
for &value in sorted_values {
hash = hash.wrapping_mul(HASH_PRIME).wrapping_add(value);
}
hash ^= hash >> 33;
hash = hash.wrapping_mul(0xff51_afd7_ed55_8ccd);
hash ^= hash >> 33;
hash = hash.wrapping_mul(0xc4ce_b9fe_1a85_ec53);
hash ^= hash >> 33;
hash
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_stable_hash_u64_slice_comprehensive() {
let values = vec![1u64, 2u64, 3u64];
let hash1 = stable_hash_u64_slice(&values);
let mut reversed = values.clone();
reversed.reverse();
let hash2 = stable_hash_u64_slice(&reversed);
assert_ne!(
hash1, hash2,
"Different order should produce different hash"
);
let mut sorted1 = values;
sorted1.sort_unstable();
let mut sorted2 = reversed;
sorted2.sort_unstable();
assert_eq!(
stable_hash_u64_slice(&sorted1),
stable_hash_u64_slice(&sorted2),
"Same sorted input should produce same hash"
);
let empty: Vec<u64> = vec![];
assert_eq!(
stable_hash_u64_slice(&empty),
0,
"Empty slice should produce hash 0"
);
let single = vec![42u64];
let single_copy = vec![42u64];
assert_eq!(
stable_hash_u64_slice(&single),
stable_hash_u64_slice(&single_copy),
"Same single value should produce same hash"
);
let different_single = vec![43u64];
assert_ne!(
stable_hash_u64_slice(&single),
stable_hash_u64_slice(&different_single),
"Different single values should produce different hashes"
);
let test_values = vec![100u64, 200u64, 300u64, 400u64];
let hash_a = stable_hash_u64_slice(&test_values);
let hash_b = stable_hash_u64_slice(&test_values);
let hash_c = stable_hash_u64_slice(&test_values);
assert_eq!(hash_a, hash_b, "Multiple calls should be deterministic");
assert_eq!(hash_b, hash_c, "Multiple calls should be deterministic");
let short = vec![1u64, 2u64];
let long = vec![1u64, 2u64, 3u64];
assert_ne!(
stable_hash_u64_slice(&short),
stable_hash_u64_slice(&long),
"Different lengths should produce different hashes"
);
let large_values = vec![u64::MAX, u64::MAX - 1, u64::MAX - 2];
let hash_large1 = stable_hash_u64_slice(&large_values);
let hash_large2 = stable_hash_u64_slice(&large_values);
assert_eq!(
hash_large1, hash_large2,
"Large values should be handled consistently"
);
let different_large = vec![u64::MAX - 3, u64::MAX - 4, u64::MAX - 5];
assert_ne!(
hash_large1,
stable_hash_u64_slice(&different_large),
"Different large values should produce different hashes"
);
}
}