const CRC32_POLYNOMIAL: u32 = 0x04C11DB7;
static CRC32_TABLE: [u32; 256] = generate_crc32_table();
const fn generate_crc32_table() -> [u32; 256] {
let mut table = [0u32; 256];
let mut i = 0;
while i < 256 {
let mut crc = (i as u32) << 24;
let mut j = 0;
while j < 8 {
if crc & 0x80000000 != 0 {
crc = (crc << 1) ^ CRC32_POLYNOMIAL;
} else {
crc <<= 1;
}
j += 1;
}
table[i] = crc;
i += 1;
}
table
}
#[inline]
pub fn calculate_crc32(data: &[u8]) -> u32 {
let mut crc: u32 = 0xFFFFFFFF;
for &byte in data {
let index = ((crc >> 24) ^ (byte as u32)) as u8;
crc = (crc << 8) ^ CRC32_TABLE[index as usize];
}
crc ^ 0xFFFFFFFF
}
#[inline]
pub fn verify_crc32(data: &[u8], expected_crc: u32) -> bool {
calculate_crc32(data) == expected_crc
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_crc32_calculation() {
let empty_data: &[u8] = &[];
let empty_crc = calculate_crc32(empty_data);
assert_eq!(calculate_crc32(empty_data), empty_crc);
assert!(verify_crc32(empty_data, empty_crc));
let simple_data = b"Hello, world!";
let simple_crc = calculate_crc32(simple_data);
assert_eq!(calculate_crc32(simple_data), simple_crc);
assert!(verify_crc32(simple_data, simple_crc));
let different_data = b"123456789";
let different_crc = calculate_crc32(different_data);
assert_eq!(calculate_crc32(different_data), different_crc);
assert!(verify_crc32(different_data, different_crc));
assert_ne!(simple_crc, different_crc);
assert_ne!(empty_crc, simple_crc);
assert_ne!(empty_crc, different_crc);
}
#[test]
fn test_crc32_verification() {
let data = b"test data";
let crc = calculate_crc32(data);
assert!(verify_crc32(data, crc));
assert!(!verify_crc32(data, crc + 1));
assert!(!verify_crc32(data, crc - 1));
}
}