rust 31 lines · 8 steps

Table-driven CRC32 with lazy init in Rust

A precomputed 256-entry lookup table, built once on first use, powers a fast byte-at-a-time CRC32 checksum.

Explained by highlit
1use std::sync::OnceLock;
2 
3static CRC_TABLE: OnceLock<[u32; 256]> = OnceLock::new();
4 
5fn table() -> &'static [u32; 256] {
6 CRC_TABLE.get_or_init(|| {
7 let mut table = [0u32; 256];
8 for (n, entry) in table.iter_mut().enumerate() {
9 let mut crc = n as u32;
10 for _ in 0..8 {
11 crc = if crc & 1 != 0 {
12 0xEDB8_8320 ^ (crc >> 1)
13 } else {
14 crc >> 1
15 };
16 }
17 *entry = crc;
18 }
19 table
20 })
21}
22 
23pub fn crc32(data: &[u8]) -> u32 {
24 let table = table();
25 let mut crc = 0xFFFF_FFFFu32;
26 for &byte in data {
27 let index = ((crc ^ byte as u32) & 0xFF) as usize;
28 crc = table[index] ^ (crc >> 8);
29 }
30 crc ^ 0xFFFF_FFFF
31}
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1Precomputing a lookup table trades a little memory for a big speedup by replacing per-bit work with a single table read per byte.
  2. 2OnceLock gives you thread-safe, compute-once initialization of expensive static data without unsafe code.
  3. 3The standard CRC32 uses the reflected polynomial 0xEDB88320 with an all-ones seed and a final XOR of all-ones.

Related explainers

Share this explainer

Here's the card — post it anywhere.

Table-driven CRC32 with lazy init in Rust — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code