qualia_core_db/container_10d/
crc32c.rs1use std::sync::OnceLock;
25
26#[inline]
28pub fn crc32c(data: &[u8]) -> u32 {
29 !crc32c_update(0xFFFF_FFFF, data)
30}
31
32#[inline]
37pub fn crc32c_update(mut crc: u32, data: &[u8]) -> u32 {
38 let table = crc32c_table();
39 for &byte in data {
40 let idx = ((crc ^ byte as u32) & 0xFF) as usize;
41 crc = table[idx] ^ (crc >> 8);
42 }
43 crc
44}
45
46fn crc32c_table() -> &'static [u32; 256] {
47 static TABLE: OnceLock<[u32; 256]> = OnceLock::new();
48 TABLE.get_or_init(|| {
49 let mut t = [0u32; 256];
50 for i in 0..256 {
51 let mut crc = i as u32;
52 for _ in 0..8 {
53 crc = (crc >> 1) ^ (0x82F6_3B78 & 0u32.wrapping_sub(crc & 1));
54 }
55 t[i] = crc;
56 }
57 t
58 })
59}
60
61#[cfg(test)]
63fn crc32c_update_tableless(mut crc: u32, data: &[u8]) -> u32 {
64 for &byte in data {
65 crc ^= byte as u32;
66 for _ in 0..8 {
67 crc = (crc >> 1) ^ (0x82F6_3B78 & 0u32.wrapping_sub(crc & 1));
68 }
69 }
70 crc
71}
72
73#[cfg(test)]
74mod tests {
75 use super::*;
76
77 #[test]
78 fn crc32c_check_value_123456789_is_e3069283() {
79 assert_eq!(crc32c(b"123456789"), 0xE306_9283);
80 }
81
82 #[test]
83 fn crc32c_empty_input_is_final_xor_of_init() {
84 assert_eq!(crc32c(&[]), 0x0000_0000);
85 }
86
87 #[test]
88 fn crc32c_incremental_matches_one_shot() {
89 let data = b"The quick brown fox jumps over the lazy dog";
90 let one_shot = crc32c(data);
91 let mut state = crc32c_update(0xFFFF_FFFF, &data[..10]);
92 state = crc32c_update(state, &data[10..20]);
93 state = crc32c_update(state, &data[20..]);
94 assert_eq!(!state, one_shot);
95 }
96
97 #[test]
98 fn crc32c_table_matches_tableless_bit_identical() {
99 let samples: &[&[u8]] = &[
100 b"",
101 b"123456789",
102 b"The quick brown fox jumps over the lazy dog",
103 &[0u8; 4096],
104 ];
105 for s in samples {
106 let table = !crc32c_update(0xFFFF_FFFF, s);
107 let ref_ = !crc32c_update_tableless(0xFFFF_FFFF, s);
108 assert_eq!(table, ref_, "mismatch on sample len={}", s.len());
109 }
110 let all: Vec<u8> = (0u8..=255).collect();
111 assert_eq!(
112 !crc32c_update(0xFFFF_FFFF, &all),
113 !crc32c_update_tableless(0xFFFF_FFFF, &all)
114 );
115 }
116
117 #[test]
118 fn crc32c_is_deterministic() {
119 let data = b"deterministic input";
120 assert_eq!(crc32c(data), crc32c(data));
121 }
122}