//! Small streaming hashes ported from `hashing/portableHashes.js` (MurmurHash3, SipHash-2-4, //! FNV). Output byte order matches 0.1.0 (big-endian integers). /// Block buffer shared by the block-based hashes. struct Blocks { tail: [u8; N], used: usize, length: u64, } impl Blocks { fn new() -> Self { Self { tail: [0; N], used: 0, length: 0 } } fn feed(&mut self, mut input: &[u8], mut block: impl FnMut(&[u8; N])) { self.length = self.length.wrapping_add(input.len() as u64); if self.used > 0 { let take = (N - self.used).min(input.len()); self.tail[self.used..self.used + take].copy_from_slice(&input[..take]); self.used += take; input = &input[take..]; if self.used < N { return; } let full = self.tail; block(&full); self.used = 0; } let mut chunks = input.chunks_exact(N); for chunk in &mut chunks { block(chunk.try_into().unwrap()); } let rest = chunks.remainder(); self.tail[..rest.len()].copy_from_slice(rest); self.used = rest.len(); } fn tail(&self) -> &[u8] { &self.tail[..self.used] } } fn fmix32(mut h: u32) -> u32 { h ^= h >> 16; h = h.wrapping_mul(0x85ebca6b); h ^= h >> 13; h = h.wrapping_mul(0xc2b2ae35); h ^ (h >> 16) } fn fmix64(mut k: u64) -> u64 { k ^= k >> 33; k = k.wrapping_mul(0xff51afd7ed558ccd); k ^= k >> 33; k = k.wrapping_mul(0xc4ceb9fe1a85ec53); k ^ (k >> 33) } fn le32(b: &[u8]) -> u32 { u32::from_le_bytes(b[..4].try_into().unwrap()) } fn le64(b: &[u8]) -> u64 { u64::from_le_bytes(b[..8].try_into().unwrap()) } pub struct Murmur32 { blocks: Blocks<4>, h1: u32, } impl Murmur32 { pub fn new(seed: u32) -> Self { Self { blocks: Blocks::new(), h1: seed } } pub fn update(&mut self, input: &[u8]) { let h1 = &mut self.h1; self.blocks.feed(input, |b| { let k1 = le32(b).wrapping_mul(0xcc9e2d51).rotate_left(15).wrapping_mul(0x1b873593); *h1 ^= k1; *h1 = h1.rotate_left(13).wrapping_mul(5).wrapping_add(0xe6546b64); }); } pub fn finish(mut self) -> Vec { let tail = self.blocks.tail(); let mut k1 = 0u32; for (i, byte) in tail.iter().enumerate() { k1 ^= (*byte as u32) << (i * 8); } if !tail.is_empty() { self.h1 ^= k1.wrapping_mul(0xcc9e2d51).rotate_left(15).wrapping_mul(0x1b873593); } fmix32(self.h1 ^ self.blocks.length as u32).to_be_bytes().to_vec() } } pub struct Murmur128x86 { blocks: Blocks<16>, h: [u32; 4], } const X86_C: [u32; 4] = [0x239b961b, 0xab0e9789, 0x38b34ae5, 0xa1e38b93]; impl Murmur128x86 { pub fn new(seed: u32) -> Self { Self { blocks: Blocks::new(), h: [seed; 4] } } fn mix(k: u32, i: usize) -> u32 { let rot = [15, 16, 17, 18][i]; k.wrapping_mul(X86_C[i]).rotate_left(rot).wrapping_mul(X86_C[(i + 1) % 4]) } pub fn update(&mut self, input: &[u8]) { let h = &mut self.h; self.blocks.feed(input, |b| { let rots = [19, 17, 15, 13]; let adds = [0x561ccd1b, 0x0bcaa747, 0x96cd1c35, 0x32ac3b17]; for i in 0..4 { h[i] ^= Self::mix(le32(&b[i * 4..]), i); h[i] = h[i].rotate_left(rots[i]).wrapping_add(h[(i + 1) % 4]); h[i] = h[i].wrapping_mul(5).wrapping_add(adds[i]); } }); } pub fn finish(mut self) -> Vec { let tail = self.blocks.tail().to_vec(); let mut k = [0u32; 4]; for (i, byte) in tail.iter().enumerate() { k[i / 4] ^= (*byte as u32) << ((i % 4) * 8); } for i in (0..4).rev() { if tail.len() > i * 4 { self.h[i] ^= Self::mix(k[i], i); } } let length = self.blocks.length as u32; let h = &mut self.h; for v in h.iter_mut() { *v ^= length; } let sum = |h: &mut [u32; 4]| { h[0] = h[0].wrapping_add(h[1]).wrapping_add(h[2]).wrapping_add(h[3]); h[1] = h[1].wrapping_add(h[0]); h[2] = h[2].wrapping_add(h[0]); h[3] = h[3].wrapping_add(h[0]); }; sum(h); for v in h.iter_mut() { *v = fmix32(*v); } sum(h); h.iter().flat_map(|v| v.to_be_bytes()).collect() } } pub struct Murmur128x64 { blocks: Blocks<16>, h1: u64, h2: u64, } const X64_C1: u64 = 0x87c37b91114253d5; const X64_C2: u64 = 0x4cf5ad432745937f; impl Murmur128x64 { pub fn new(seed: u64) -> Self { Self { blocks: Blocks::new(), h1: seed, h2: seed } } pub fn update(&mut self, input: &[u8]) { let (h1, h2) = (&mut self.h1, &mut self.h2); self.blocks.feed(input, |b| { let k1 = le64(b).wrapping_mul(X64_C1).rotate_left(31).wrapping_mul(X64_C2); *h1 ^= k1; *h1 = h1.rotate_left(27).wrapping_add(*h2).wrapping_mul(5).wrapping_add(0x52dce729); let k2 = le64(&b[8..]).wrapping_mul(X64_C2).rotate_left(33).wrapping_mul(X64_C1); *h2 ^= k2; *h2 = h2.rotate_left(31).wrapping_add(*h1).wrapping_mul(5).wrapping_add(0x38495ab5); }); } pub fn finish(mut self) -> Vec { let tail = self.blocks.tail().to_vec(); let (mut k1, mut k2) = (0u64, 0u64); for (i, byte) in tail.iter().enumerate() { if i >= 8 { k2 ^= (*byte as u64) << ((i - 8) * 8); } else { k1 ^= (*byte as u64) << (i * 8); } } if tail.len() > 8 { self.h2 ^= k2.wrapping_mul(X64_C2).rotate_left(33).wrapping_mul(X64_C1); } if !tail.is_empty() { self.h1 ^= k1.wrapping_mul(X64_C1).rotate_left(31).wrapping_mul(X64_C2); } let length = self.blocks.length; self.h1 ^= length; self.h2 ^= length; self.h1 = self.h1.wrapping_add(self.h2); self.h2 = self.h2.wrapping_add(self.h1); self.h1 = fmix64(self.h1); self.h2 = fmix64(self.h2); self.h1 = self.h1.wrapping_add(self.h2); self.h2 = self.h2.wrapping_add(self.h1); [self.h1.to_be_bytes(), self.h2.to_be_bytes()].concat() } } pub struct SipHash24 { blocks: Blocks<8>, v: [u64; 4], } impl SipHash24 { pub fn new(key: &[u8]) -> Self { let (k0, k1) = (le64(key), le64(&key[8..])); Self { blocks: Blocks::new(), v: [0x736f6d6570736575 ^ k0, 0x646f72616e646f6d ^ k1, 0x6c7967656e657261 ^ k0, 0x7465646279746573 ^ k1] } } fn round(v: &mut [u64; 4]) { v[0] = v[0].wrapping_add(v[1]); v[1] = v[1].rotate_left(13) ^ v[0]; v[0] = v[0].rotate_left(32); v[2] = v[2].wrapping_add(v[3]); v[3] = v[3].rotate_left(16) ^ v[2]; v[0] = v[0].wrapping_add(v[3]); v[3] = v[3].rotate_left(21) ^ v[0]; v[2] = v[2].wrapping_add(v[1]); v[1] = v[1].rotate_left(17) ^ v[2]; v[2] = v[2].rotate_left(32); } fn compress(v: &mut [u64; 4], m: u64) { v[3] ^= m; Self::round(v); Self::round(v); v[0] ^= m; } pub fn update(&mut self, input: &[u8]) { let v = &mut self.v; self.blocks.feed(input, |b| Self::compress(v, le64(b))); } pub fn finish(mut self) -> Vec { let mut last = (self.blocks.length & 0xff) << 56; for (i, byte) in self.blocks.tail().iter().enumerate() { last |= (*byte as u64) << (i * 8); } Self::compress(&mut self.v, last); self.v[2] ^= 0xff; for _ in 0..4 { Self::round(&mut self.v); } (self.v[0] ^ self.v[1] ^ self.v[2] ^ self.v[3]).to_be_bytes().to_vec() } } pub struct Fnv { bits: u32, alternate: bool, value: u64, } impl Fnv { pub fn new(bits: u32, alternate: bool) -> Self { Self { bits, alternate, value: if bits == 32 { 0x811c9dc5 } else { 0xcbf29ce484222325 } } } pub fn update(&mut self, input: &[u8]) { if self.bits == 32 { let mut v = self.value as u32; for b in input { if self.alternate { v = (v ^ *b as u32).wrapping_mul(0x01000193); } else { v = v.wrapping_mul(0x01000193) ^ *b as u32; } } self.value = v as u64; } else { let mut v = self.value; for b in input { if self.alternate { v = (v ^ *b as u64).wrapping_mul(0x100000001b3); } else { v = v.wrapping_mul(0x100000001b3) ^ *b as u64; } } self.value = v; } } pub fn finish(self) -> Vec { if self.bits == 32 { (self.value as u32).to_be_bytes().to_vec() } else { self.value.to_be_bytes().to_vec() } } }