use std::env; use std::fs::File; use std::io::{self, Write}; use std::path::{Path, PathBuf}; const CASTAGNOLI_POLY: u32 = 0x82f6_3b78; type Result = std::result::Result>; fn main() { if let Err(err) = try_main() { panic!("{}", err); } } fn try_main() -> Result<()> { let out_dir = match env::var_os("OUT_DIR") { None => { return Err(From::from("OUT_DIR environment variable not defined")) } Some(out_dir) => PathBuf::from(out_dir), }; write_tag_lookup_table(&out_dir)?; write_crc_tables(&out_dir)?; Ok(()) } fn write_tag_lookup_table(out_dir: &Path) -> Result<()> { let out_path = out_dir.join("tag.rs"); let mut out = io::BufWriter::new(File::create(out_path)?); writeln!(out, "pub const TAG_LOOKUP_TABLE: [u16; 256] = [")?; for b in 0u8..=255 { writeln!(out, " {},", tag_entry(b))?; } writeln!(out, "];")?; Ok(()) } fn tag_entry(b: u8) -> u16 { let b = u16::from(b); match b & 0b0000_0011 { 0b00 => { let lit_len = (b >> 2) + 1; if lit_len <= 60 { lit_len } else { assert!(lit_len <= 64); (lit_len - 60) << 11 } } 0b01 => { let len = 4 + ((b >> 2) & 0b111); let offset = (b >> 5) & 0b111; (1 << 11) | (offset << 8) | len } 0b10 => { let len = 1 + (b >> 2); (2 << 11) | len } 0b11 => { let len = 1 + (b >> 2); (4 << 11) | len } _ => unreachable!(), } } fn write_crc_tables(out_dir: &Path) -> Result<()> { let out_path = out_dir.join("crc32_table.rs"); let mut out = io::BufWriter::new(File::create(out_path)?); let table = make_table(CASTAGNOLI_POLY); let table16 = make_table16(CASTAGNOLI_POLY); writeln!(out, "pub const TABLE: [u32; 256] = [")?; for &x in &table { writeln!(out, " {x},")?; } writeln!(out, "];\n")?; writeln!(out, "pub const TABLE16: [[u32; 256]; 16] = [")?; for table in &table16 { writeln!(out, " [")?; for &x in table { writeln!(out, " {x},")?; } writeln!(out, " ],")?; } writeln!(out, "];")?; out.flush()?; Ok(()) } #[allow(clippy::cast_possible_truncation)] fn make_table16(poly: u32) -> [[u32; 256]; 16] { let mut tab = [[0; 256]; 16]; tab[0] = make_table(poly); for i in 0..256 { let mut crc = tab[0][i]; for j in 1..16 { crc = (crc >> 8) ^ tab[0][crc as u8 as usize]; tab[j][i] = crc; } } tab } fn make_table(poly: u32) -> [u32; 256] { let mut tab = [0; 256]; for i in 0u32..256u32 { let mut crc = i; for _ in 0..8 { if crc & 1 == 1 { crc = (crc >> 1) ^ poly; } else { crc >>= 1; } } tab[i as usize] = crc; } tab }