Skip to main content

open_wal/
crc.rs

1//! CRC-32C (Castagnoli) checksum.
2//!
3//! All CRCs in the on-disk format are **CRC-32C (Castagnoli)**, the same choice
4//! as ext4/RocksDB/iSCSI (§5 of `docs/wal_design_v6.md`). This module is the
5//! single chokepoint so every caller (record codec, segment header) uses one
6//! function and the polynomial is asserted in exactly one place's tests.
7//!
8//! Castagnoli polynomial (`0x1EDC6F41` reflected), **not** the ISO-HDLC/zlib
9//! polynomial used by `crc32fast` — getting that wrong is silent and
10//! catastrophic.
11
12/// Compute the CRC-32C (Castagnoli) checksum of `data`.
13#[inline]
14#[must_use]
15pub fn crc32c(data: &[u8]) -> u32 {
16    crc32c::crc32c(data)
17}
18
19#[cfg(test)]
20mod tests {
21    use super::crc32c;
22
23    /// Canonical CRC-32C check value of the string "123456789".
24    const CHECK_123456789: u32 = 0xE306_9283;
25
26    /// Check value the ISO-HDLC/zlib polynomial (`crc32fast`) would produce for
27    /// "123456789". Used as a negative control.
28    const ISO_HDLC_123456789: u32 = 0xCBF4_3926;
29
30    #[test]
31    fn empty_input_is_zero() {
32        assert_eq!(crc32c(b""), 0x0000_0000);
33    }
34
35    #[test]
36    fn canonical_check_vector() {
37        // §14.1: CRC-32C vs published Castagnoli vector.
38        assert_eq!(crc32c(b"123456789"), CHECK_123456789);
39    }
40
41    #[test]
42    fn is_castagnoli_not_iso_hdlc() {
43        // §14.1: assert it is Castagnoli, NOT ISO-HDLC (the crc32fast/zlib
44        // polynomial). If this ever passes by equalling the ISO value, the
45        // wrong crate is wired in and the on-disk format is silently corrupt.
46        assert_ne!(crc32c(b"123456789"), ISO_HDLC_123456789);
47    }
48
49    #[test]
50    fn known_answer_all_zeros() {
51        // 32 bytes of 0x00. Guards the table/HW path against the empty case.
52        assert_eq!(crc32c(&[0x00u8; 32]), 0x8A91_36AA);
53    }
54
55    #[test]
56    fn known_answer_all_ones() {
57        // 32 bytes of 0xFF.
58        assert_eq!(crc32c(&[0xFFu8; 32]), 0x62A8_AB43);
59    }
60
61    #[test]
62    fn detects_single_bit_flip() {
63        let a = crc32c(b"the quick brown fox");
64        let b = crc32c(b"the quick brown gox");
65        assert_ne!(a, b);
66    }
67}