tomolib 1.1.1

Library for reading, modifying, and extracting Tomodachi Life data formats.
Documentation
#[must_use]
pub(crate) fn murmur3_x86_32_seed0(bytes: &[u8]) -> u32 {
    const C1: u32 = 0xCC9E_2D51;
    const C2: u32 = 0x1B87_3593;

    let mut h: u32 = 0;
    let mut chunks = bytes.chunks_exact(4);
    for chunk in &mut chunks {
        let mut k = u32::from_le_bytes([chunk[0], chunk[1], chunk[2], chunk[3]]);
        k = k.wrapping_mul(C1).rotate_left(15).wrapping_mul(C2);
        h ^= k;
        h = h.rotate_left(13).wrapping_mul(5).wrapping_add(0xE654_6B64);
    }

    let tail = chunks.remainder();
    let mut k1: u32 = 0;
    if tail.len() >= 3 {
        k1 ^= u32::from(tail[2]) << 16;
    }
    if tail.len() >= 2 {
        k1 ^= u32::from(tail[1]) << 8;
    }
    if let Some(&b) = tail.first() {
        k1 ^= u32::from(b);
        k1 = k1.wrapping_mul(C1).rotate_left(15).wrapping_mul(C2);
        h ^= k1;
    }

    let len_u32 = u32::try_from(bytes.len()).unwrap_or(u32::MAX);
    h ^= len_u32;
    h ^= h >> 16;
    h = h.wrapping_mul(0x85EB_CA6B);
    h ^= h >> 13;
    h = h.wrapping_mul(0xC2B2_AE35);
    h ^= h >> 16;
    h
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn known_vectors() {
        assert_eq!(murmur3_x86_32_seed0(b""), 0);
        assert_eq!(murmur3_x86_32_seed0(b"Accessory"), 0xA320_6403);
        assert_eq!(murmur3_x86_32_seed0(b"Action"), 0xF59B_6FEA);
        assert_eq!(murmur3_x86_32_seed0(b"Actor"), 0x9610_D708);
        assert_eq!(murmur3_x86_32_seed0(b"ActorKey"), 0xB12B_1C59);
    }
}