Programmieren in Rust

Fehlererkennung

Inhaltsverzeichnis

  1. Zyklische Redundanzprüfung

Zyklische Redundanzprüfung

pub mod crc32 {
    const POLYNOMIAL: u32 = 0xEDB88320;

    pub struct CRC32 {
        lookup: [u32; 256]
    }

    impl CRC32 {
        pub fn new() -> Self {
            let mut lookup = [0; 256];
            for i in 0..lookup.len() {
                let mut crc = i as u32;
                for _ in 0..8 {
                    let a = (!(crc & 1)).wrapping_add(1);
                    crc = (crc >> 1) ^ (a & POLYNOMIAL);
                }
                lookup[i] = crc;
            }
            Self {lookup}
        }
        pub fn hash(&self, data: &[u8], previous: u32) -> u32 {
            let mut crc: u32 = !previous;
            for byte in data {
                let index = ((crc as u8) ^ byte) as usize;
                crc = (crc >> 8) ^ self.lookup[index];
            }
            !crc
        }    
    }
}

#[cfg(test)]
mod crc32_test {
    // Die Werte sind geprüft mit binascii.crc32
    // aus der Python-Standardbibliothek.
    const TEST_VECTORS: [(u32, &[u8]); 14] = [
        (0x00000000, b""),
        (0xd202ef8d, b"\x00"),
        (0x41d912ff, b"\x00\x00"),
        (0xff000000, b"\xff"),
        (0xffff0000, b"\xff\xff"),
        (0xffffff00, b"\xff\xff\xff"),
        (0xffffffff, b"\xff\xff\xff\xff"),
        (0xd2fd1072, b"\xff\xff\xff\xff\xff"),
        (0xe8b7be43, b"a"),
        (0x078a19d7, b"aa"),
        (0x9e83486d, b"ab"),
        (0x2ca74a14, b"ba"),
        (0x8587d865, b"abcde"),
        (0xaeef2a50, b"abcdefgh")
    ];

    #[test]
    fn test() {
        let crc = crate::crc32::CRC32::new();
        for (expected, data) in TEST_VECTORS {
            assert_eq!(crc.hash(data, 0), expected);
        }
        assert_eq!(0x9e83486d, crc.hash(b"", crc.hash(b"ab", 0)));
        assert_eq!(0x9e83486d, crc.hash(b"b", crc.hash(b"a", 0)));
        assert_eq!(0x8587d865, crc.hash(b"e", crc.hash(b"abcd", 0)));
        assert_eq!(0x8587d865, crc.hash(b"de", crc.hash(b"abc", 0)));
        assert_eq!(0xaeef2a50, crc.hash(b"efgh", crc.hash(b"abcd", 0)));
        assert_eq!(0xaeef2a50, crc.hash(b"fgh", crc.hash(b"abcde", 0)));
        let mut value = 0;
        for x in 0..u16::MAX {
            value = crc.hash(&u16::to_le_bytes(x), value);
        }
        assert_eq!(0xc7624fe6, value);
    }
}

fn main() {
    let crc = crc32::CRC32::new();
    let data = b"Tee";
    println!("{:08x}", crc.hash(data, 0));
}