1use std::hash::Hasher as StdHasher;
2
3pub use ::fnv::FnvHasher;
4use digest::typenum::U8;
5use digest::{FixedOutput, HashMarker, Output, OutputSizeUser, Update};
6
7use crate::common::{impl_hash_wrapper, HashWrapper};
8
9#[derive(Default)]
10pub struct Fnv(FnvHasher);
11
12impl_hash_wrapper!(Fnv, FnvHasher, U8);
13
14impl Clone for Fnv {
15 fn clone(&self) -> Self {
16 Self(FnvHasher::with_key(self.0.finish()))
17 }
18}
19
20impl Update for Fnv {
21 fn update(&mut self, data: &[u8]) {
22 self.0.write(data);
23 }
24}
25
26impl FixedOutput for Fnv {
27 fn finalize_into(self, out: &mut Output<Self>) {
28 let result = self.0.finish();
29 let bytes = result.to_be_bytes();
30 out.copy_from_slice(&bytes);
31 }
32}
33
34#[cfg(test)]
35mod tests {
36 use insta::assert_snapshot;
37
38 use super::*;
39 use crate::tests::hash;
40
41 #[test]
42 fn test_fnv() {
43 let default = FnvHasher::default().finish();
44 assert_eq!(hash::<Fnv>(""), format!("{default:X}"));
45 assert_snapshot!(hash::<Fnv>(""), @"CBF29CE484222325");
46 assert_snapshot!(hash::<Fnv>("hello"), @"A430D84680AABD0B");
47 }
48}