varta-vlp 0.2.0

Varta Lifeline Protocol — 32-byte fixed-layout health frame.
Documentation
//! CRC-32C (Castagnoli) — wire-frame integrity check.
//!
//! Used by [`crate::Frame::encode`] to stamp bytes 28..32 of every emitted
//! frame, and by [`crate::Frame::decode`] to gate every field-range check
//! on a verified payload. CRC-32C is provably stronger than CRC-32 (IEEE
//! 802.3) on short (≤ 128 byte) messages and is the standard for iSCSI,
//! SCTP, ext4, and Btrfs.
//!
//! Parameters (Koopman notation `CRC-32C/iSCSI`):
//!
//! * width: 32
//! * polynomial: `0x1EDC6F41` (reflected form `0x82F63B78`)
//! * init: `0xFFFFFFFF`
//! * reflect-input: yes
//! * reflect-output: yes
//! * output-XOR: `0xFFFFFFFF`
//!
//! Implementation is a byte-at-a-time table lookup. The 256-entry table is
//! generated at compile time via `const fn`; no static initialisation cost,
//! no runtime allocation, no `unsafe`. Per-frame cost on Apple Silicon is
//! ~28 cycles (~9 ns), well below the 900 ns p99 beat-path budget.
//!
//! Hardware CRC-32C is available on every shipping x86_64 (SSE 4.2) and
//! ARMv8.1+ CPU; a future PR can opt in via `core::arch` intrinsics behind
//! a `target_feature` cfg without changing the wire format.

/// Reflected form of the Castagnoli polynomial `0x1EDC6F41`.
const POLY_REFLECTED: u32 = 0x82F63B78;

/// Precomputed lookup table — one entry per input byte.
const TABLE: [u32; 256] = build_table();

const fn build_table() -> [u32; 256] {
    let mut table = [0u32; 256];
    let mut i = 0;
    while i < 256 {
        let mut c = i as u32;
        let mut j = 0;
        while j < 8 {
            c = if c & 1 != 0 {
                (c >> 1) ^ POLY_REFLECTED
            } else {
                c >> 1
            };
            j += 1;
        }
        table[i] = c;
        i += 1;
    }
    table
}

/// Compute CRC-32C over `bytes`.
///
/// Wire-format primitive — downstream tooling (debuggers, packet sniffers,
/// fuzz harnesses) needs this entry point to construct or verify the
/// 4-byte trailer of a VLP frame.
///
/// # Examples
///
/// ```
/// use varta_vlp::crc32c;
/// // Standard CRC-32C reference vector (RFC 3720 appendix B).
/// assert_eq!(crc32c::compute(b"123456789"), 0xE3069283);
/// ```
pub const fn compute(bytes: &[u8]) -> u32 {
    let mut crc = 0xFFFF_FFFFu32;
    let mut i = 0;
    while i < bytes.len() {
        let idx = ((crc ^ bytes[i] as u32) & 0xFF) as usize;
        crc = TABLE[idx] ^ (crc >> 8);
        i += 1;
    }
    !crc
}

#[cfg(test)]
mod tests {
    use super::compute;

    // RFC 3720 appendix B + iSCSI test vectors. These are the canonical
    // Castagnoli-CRC reference values; if the table or the algorithm
    // regresses, this test catches it before any frame round-trip does.
    #[test]
    fn empty_input() {
        assert_eq!(compute(b""), 0x0000_0000);
    }

    #[test]
    fn single_byte_a() {
        assert_eq!(compute(b"a"), 0xC1D0_4330);
    }

    #[test]
    fn check_sequence_123456789() {
        assert_eq!(compute(b"123456789"), 0xE306_9283);
    }

    #[test]
    fn thirty_two_zero_bytes() {
        assert_eq!(compute(&[0u8; 32]), 0x8A91_36AA);
    }

    #[test]
    fn thirty_two_all_ones_bytes() {
        assert_eq!(compute(&[0xFFu8; 32]), 0x62A8_AB43);
    }

    // `compute` is `const fn` — these const-asserts prove the table is
    // useable at compile time. Any regression in `const`-eligibility will
    // surface as a compile error here, before any runtime test runs.
    const _: () = assert!(compute(b"") == 0x0000_0000);
    const _: () = assert!(compute(b"123456789") == 0xE306_9283);
}