//! Checksum functions. // Accumulator for CRC function. fn crc_accum(a: u32, _: u32) -> u32 { if a & 1 == 1 { ISO_3309_POLYNOMIAL ^ a >> 1 } else { a >> 1 } } // Initializes a CRC array. // FIXME: use const fn when stabilized fn crc_init() -> [u32; 256] { let mut t = [0; 256]; for (n, v) in t.iter_mut().enumerate() { *v = (0..8).fold(n as u32, crc_accum); } t } /// Creates an ADLER32 of all bytes in `b`. /// /// # Examples /// /// ``` /// use maraiah::cksum::adler32; /// /// assert_eq!(adler32(b"Lorem ipsum dolor sit amet"), 0x83D5_09C5); /// ``` pub fn adler32(b: &[u8]) -> u32 { let mut x = 1; let mut y = 0; for &z in b { let z = u32::from(z); x = (x + z) % ADLER32_MODULO; y = (y + x) % ADLER32_MODULO; } (y << 16) | x } /// Creates a CRC-32 of all bytes in `b` with the starting sum `s`. The /// polynomial used is the one from ISO-3309. /// /// # Examples /// /// ``` /// use maraiah::cksum::crc32; /// /// assert_eq!(crc32(b"Lorem ipsum dolor sit amet", !0), 0x5F29_D461); /// ``` pub fn crc32(b: &[u8], s: u32) -> u32 { let t = crc_init(); !b.iter().fold(s, |a, &o| a >> 8 ^ t[usize::from(a as u8 ^ o)]) } const ISO_3309_POLYNOMIAL: u32 = 0xEDB8_8320; const ADLER32_MODULO: u32 = 0xFFF1; // EOF