const CRC32_LE_LUT_LN: [u32; 16] = [
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832,
0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
];
const CRC32_LE_LUT_HN: [u32; 16] = [
0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c, 0xedb88320,
0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c,
];
const fn snb_u8(data: u8) -> u8 {
let t0 = (data ^ (data >> 1)) & 0x55;
let t1 = t0 << 1;
data ^ t0 ^ t1
}
const fn snb_u32(data: u32) -> u32 {
let t0 = (data ^ (data >> 1)) & 0x55555555u32;
let t1 = t0 << 1;
data ^ t0 ^ t1
}
pub const fn crc32le_init() -> u32 {
!0
}
pub const fn crc32le_finish_send(crc: u32) -> u32 {
!crc
}
pub const fn crc32le_finish_receive(computed_crc: u32, received_crc: u32) -> bool {
crc32le_finish_send(computed_crc) == received_crc
}
#[allow(unused)]
pub const fn crc32le_update_u8(crc: u32, data: u8) -> u32 {
let mut crc = crc ^ data as u32;
crc = (crc >> 8) ^ CRC32_LE_LUT_LN[(crc & 0xf) as usize] ^ CRC32_LE_LUT_HN[((crc >> 4) & 0xf) as usize];
crc
}
#[allow(unused)]
pub const fn crc32le_update_u8_snb(crc: u32, data: u8) -> u32 {
crc32le_update_u8(crc, snb_u8(data))
}
#[allow(unused)]
pub const fn crc32le_update_u32le(crc: u32, data_from_le: u32) -> u32 {
let mut crc = crc ^ data_from_le;
let mut j = 4;
while j > 0 {
crc = (crc >> 8) ^ CRC32_LE_LUT_LN[(crc & 0xf) as usize] ^ CRC32_LE_LUT_HN[((crc >> 4) & 0xf) as usize];
j -= 1;
}
crc
}
#[allow(unused)]
pub const fn crc32le_update_u32le_snb(crc: u32, data_from_le: u32) -> u32 {
crc32le_update_u32le(crc, snb_u32(data_from_le))
}
#[allow(unused)]
pub const fn crc32le_update_u64le(crc: u32, data_from_le: u64) -> u32 {
let crc = crc32le_update_u32le(crc, data_from_le as u32);
crc32le_update_u32le(crc, (data_from_le >> 32) as u32)
}
#[allow(unused)]
pub const fn crc32le_update_u64le_snb(crc: u32, data_from_le: u64) -> u32 {
let crc = crc32le_update_u32le_snb(crc, data_from_le as u32);
crc32le_update_u32le_snb(crc, (data_from_le >> 32) as u32)
}
#[allow(unused)]
pub fn crc32le_update_data(mut crc: u32, data: &[u8]) -> u32 {
let (head, middle_ne_u32, tail) = unsafe { data.align_to::<u32>() };
for b in head.iter() {
crc = crc32le_update_u8(crc, *b);
}
for v_ne in middle_ne_u32.iter() {
let v_le = v_ne.to_le();
crc = crc32le_update_u32le(crc, v_le);
}
for b in tail.iter() {
crc = crc32le_update_u8(crc, *b);
}
crc
}
#[allow(unused)]
pub fn crc32le_update_data_snb(mut crc: u32, data: &[u8]) -> u32 {
let (head, middle_ne_u32, tail) = unsafe { data.align_to::<u32>() };
for b in head.iter() {
crc = crc32le_update_u8_snb(crc, *b);
}
for v_ne in middle_ne_u32.iter() {
let v_le = v_ne.to_le();
crc = crc32le_update_u32le_snb(crc, v_le);
}
for b in tail.iter() {
crc = crc32le_update_u8_snb(crc, *b);
}
crc
}
#[test]
fn test_crc32le() {
let send_crc = crc32le_init();
let send_crc = crc32le_update_u32le(send_crc, 0xabbccdde);
let send_crc = crc32le_update_u64le(send_crc, 0xabbccddeeff00112);
let send_crc = crc32le_update_u8(send_crc, 0x23);
let send_crc = crc32le_finish_send(send_crc);
assert_eq!(
crc32le_finish_send(crc32le_update_data(
crc32le_init(),
&[
0xdeu8, 0xcd, 0xbc, 0xab, 0x12, 0x01, 0xf0, 0xef, 0xde, 0xcd, 0xbc, 0xab, 0x23
]
)),
send_crc
);
assert_ne!(
crc32le_finish_send(crc32le_update_data(
crc32le_init(),
&[
0xdeu8, 0xcd, 0xbc, 0xab, 0x12, 0x01, 0xf0, 0xef, 0xde, 0xcd, 0xbc, 0xab, 0x23, 0x00,
]
)),
send_crc
);
let computed_crc = crc32le_init();
let computed_crc = crc32le_update_u8(computed_crc, 0xde);
let computed_crc = crc32le_update_u64le(computed_crc, 0xdeeff00112abbccd);
let computed_crc = crc32le_update_u32le(computed_crc, 0x23abbccd);
assert!(crc32le_finish_receive(computed_crc, send_crc));
}
#[test]
fn test_crc32le_snb() {
let send_crc = crc32le_init();
let send_crc = crc32le_update_u32le_snb(send_crc, 0xabbccdde);
let send_crc = crc32le_update_u64le_snb(send_crc, 0xabbccddeeff00112);
let send_crc = crc32le_update_u8_snb(send_crc, 0x23);
let send_crc = crc32le_finish_send(send_crc);
assert_eq!(
crc32le_finish_send(crc32le_update_data_snb(
crc32le_init(),
&[
0xdeu8, 0xcd, 0xbc, 0xab, 0x12, 0x01, 0xf0, 0xef, 0xde, 0xcd, 0xbc, 0xab, 0x23
]
)),
send_crc
);
assert_ne!(
crc32le_finish_send(crc32le_update_data_snb(
crc32le_init(),
&[
0xdeu8, 0xcd, 0xbc, 0xab, 0x12, 0x01, 0xf0, 0xef, 0xde, 0xcd, 0xbc, 0xab, 0x23, 0x00,
]
)),
send_crc
);
let computed_crc = crc32le_init();
let computed_crc = crc32le_update_u8_snb(computed_crc, 0xde);
let computed_crc = crc32le_update_u64le_snb(computed_crc, 0xdeeff00112abbccd);
let computed_crc = crc32le_update_u32le_snb(computed_crc, 0x23abbccd);
assert!(crc32le_finish_receive(computed_crc, send_crc));
}