use std::io::{Read, Result as IoResult}; const TABLE: [u32; 256] = generate_table(); const fn generate_table() -> [u32; 256] { let mut table = [0; 256]; let mut i = 0; while i <= 255 { let mut t = i as u32; let mut j = 0; while j < 8 { if (t & 1) > 0 { t = (t >> 1) ^ 0xEDB88320 } else { t >>= 1 } j += 1; } table[i] = t; i += 1 } table } fn crc32(byte: u8, crc: u32) -> u32 { (crc >> 8) ^ TABLE[((crc & 0xFF) as u8 ^ byte) as usize] } pub struct Keys { key0: u32, key1: u32, key2: u32, } impl Keys { pub fn new() -> Self { Self { key0: 305419896, key1: 591751049, key2: 878082192, } } pub fn update(&mut self, byte: u8) { self.key0 = crc32(byte, self.key0); self.key1 = self .key1 .wrapping_add(self.key0 & 0xFF) .wrapping_mul(134775813) .wrapping_add(1); self.key2 = crc32((self.key1 >> 24) as u8, self.key2); } #[allow(dead_code)] pub fn encode_bytes(&mut self, byte: u8) -> u8 { let key = self.key2 | 2; self.update(byte); byte ^ ((key.wrapping_mul(key ^ 1)) >> 8) as u8 } pub fn decode_byte(&mut self, byte: u8) -> u8 { let key = self.key2 | 2; let byte = byte ^ ((key.wrapping_mul(key ^ 1)) >> 8) as u8; self.update(byte); byte } } pub struct WeakDecoder { io: Io, keys: Keys, } impl WeakDecoder { pub fn new(io: Io, keys: Keys) -> Self { WeakDecoder { io, keys } } } impl Read for WeakDecoder { fn read(&mut self, buf: &mut [u8]) -> IoResult { let bytes = self.io.read(buf)?; for i in 0..bytes { buf[i] = self.keys.decode_byte(buf[i]); } Ok(bytes) } }