| use std::env; |
| use std::fs::File; |
| use std::io::{self, Write}; |
| use std::path::{Path, PathBuf}; |
| |
| const CASTAGNOLI_POLY: u32 = 0x82f63b78; |
| |
| type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>; |
| |
| 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 = b as u16; |
| match b & 0b00000011 { |
| 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.iter() { |
| writeln!(out, " {},", x)?; |
| } |
| writeln!(out, "];\n")?; |
| |
| writeln!(out, "pub const TABLE16: [[u32; 256]; 16] = [")?; |
| for table in table16.iter() { |
| writeln!(out, " [")?; |
| for &x in table.iter() { |
| writeln!(out, " {},", x)?; |
| } |
| writeln!(out, " ],")?; |
| } |
| writeln!(out, "];")?; |
| |
| out.flush()?; |
| |
| Ok(()) |
| } |
| |
| 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 |
| } |