const POLY: u64 = 0xad93d23594c935a9;
const CRC64_TABLE: [u64; 256] = {
let mut table = [0u64; 256];
let mut i = 0usize;
while i < 256 {
let mut crc = (i as u64) << 56;
let mut round = 0;
while round < 8 {
let bit_set = (crc & 0x8000_0000_0000_0000) != 0;
crc <<= 1;
if bit_set {
crc ^= POLY;
}
round += 1;
}
table[i] = crc;
i += 1;
}
table
};
#[inline]
fn reflect64(mut data: u64) -> u64 {
data = ((data >> 1) & 0x5555_5555_5555_5555) | ((data & 0x5555_5555_5555_5555) << 1);
data = ((data >> 2) & 0x3333_3333_3333_3333) | ((data & 0x3333_3333_3333_3333) << 2);
data = ((data >> 4) & 0x0F0F_0F0F_0F0F_0F0F) | ((data & 0x0F0F_0F0F_0F0F_0F0F) << 4);
data.swap_bytes()
}
fn crc64_table(data: &[u8]) -> u64 {
let mut crc: u64 = 0;
for &c in data {
crc = (crc << 8) ^ CRC64_TABLE[(((crc >> 56) as u8) ^ c.reverse_bits()) as usize];
}
reflect64(crc)
}
pub fn hash(data: &[u8]) -> [u8; 8] {
crc64_table(data).to_le_bytes()
}
#[cfg(test)]
mod tests {
use super::*;
fn crc64_bitwise(data: &[u8]) -> u64 {
let mut crc: u64 = 0;
for &c in data {
let mut i: u8 = 1;
while i != 0 {
let mut bit_set = (crc & 0x8000_0000_0000_0000) != 0;
if (c & i) != 0 {
bit_set = !bit_set;
}
crc <<= 1;
if bit_set {
crc ^= POLY;
}
i <<= 1;
}
}
reflect64(crc)
}
#[test]
fn 查表实现与逐位参考对拍() {
let samples: [&[u8]; 9] = [
b"",
b"1",
b"123456789",
b"\x00",
b"\xff\xff\xff\xff\xff\xff\xff\xff",
b"12345678",
b"1234567890123456",
b"The quick brown fox jumps over the lazy dog",
&[0x80u8, 0x7f, 0x01, 0xfe, 0x55, 0xaa, 0x00, 0xff, 0x10, 0x20],
];
for s in samples {
assert_eq!(crc64_table(s), crc64_bitwise(s), "输入 {s:?} 不一致");
}
}
}