1 use std::env;
2 use std::fs::File;
3 use std::io::{self, Write};
4 use std::path::{Path, PathBuf};
5
6 const CASTAGNOLI_POLY: u32 = 0x82f63b78;
7
8 type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;
9
main()10 fn main() {
11 if let Err(err) = try_main() {
12 panic!("{}", err);
13 }
14 }
15
try_main() -> Result<()>16 fn try_main() -> Result<()> {
17 let out_dir = match env::var_os("OUT_DIR") {
18 None => {
19 return Err(From::from("OUT_DIR environment variable not defined"))
20 }
21 Some(out_dir) => PathBuf::from(out_dir),
22 };
23 write_tag_lookup_table(&out_dir)?;
24 write_crc_tables(&out_dir)?;
25 Ok(())
26 }
27
write_tag_lookup_table(out_dir: &Path) -> Result<()>28 fn write_tag_lookup_table(out_dir: &Path) -> Result<()> {
29 let out_path = out_dir.join("tag.rs");
30 let mut out = io::BufWriter::new(File::create(out_path)?);
31
32 writeln!(out, "pub const TAG_LOOKUP_TABLE: [u16; 256] = [")?;
33 for b in 0u8..=255 {
34 writeln!(out, " {},", tag_entry(b))?;
35 }
36 writeln!(out, "];")?;
37 Ok(())
38 }
39
tag_entry(b: u8) -> u1640 fn tag_entry(b: u8) -> u16 {
41 let b = b as u16;
42 match b & 0b00000011 {
43 0b00 => {
44 let lit_len = (b >> 2) + 1;
45 if lit_len <= 60 {
46 lit_len
47 } else {
48 assert!(lit_len <= 64);
49 (lit_len - 60) << 11
50 }
51 }
52 0b01 => {
53 let len = 4 + ((b >> 2) & 0b111);
54 let offset = (b >> 5) & 0b111;
55 (1 << 11) | (offset << 8) | len
56 }
57 0b10 => {
58 let len = 1 + (b >> 2);
59 (2 << 11) | len
60 }
61 0b11 => {
62 let len = 1 + (b >> 2);
63 (4 << 11) | len
64 }
65 _ => unreachable!(),
66 }
67 }
68
write_crc_tables(out_dir: &Path) -> Result<()>69 fn write_crc_tables(out_dir: &Path) -> Result<()> {
70 let out_path = out_dir.join("crc32_table.rs");
71 let mut out = io::BufWriter::new(File::create(out_path)?);
72
73 let table = make_table(CASTAGNOLI_POLY);
74 let table16 = make_table16(CASTAGNOLI_POLY);
75
76 writeln!(out, "pub const TABLE: [u32; 256] = [")?;
77 for &x in table.iter() {
78 writeln!(out, " {},", x)?;
79 }
80 writeln!(out, "];\n")?;
81
82 writeln!(out, "pub const TABLE16: [[u32; 256]; 16] = [")?;
83 for table in table16.iter() {
84 writeln!(out, " [")?;
85 for &x in table.iter() {
86 writeln!(out, " {},", x)?;
87 }
88 writeln!(out, " ],")?;
89 }
90 writeln!(out, "];")?;
91
92 out.flush()?;
93
94 Ok(())
95 }
96
make_table16(poly: u32) -> [[u32; 256]; 16]97 fn make_table16(poly: u32) -> [[u32; 256]; 16] {
98 let mut tab = [[0; 256]; 16];
99 tab[0] = make_table(poly);
100 for i in 0..256 {
101 let mut crc = tab[0][i];
102 for j in 1..16 {
103 crc = (crc >> 8) ^ tab[0][crc as u8 as usize];
104 tab[j][i] = crc;
105 }
106 }
107 tab
108 }
109
make_table(poly: u32) -> [u32; 256]110 fn make_table(poly: u32) -> [u32; 256] {
111 let mut tab = [0; 256];
112 for i in 0u32..256u32 {
113 let mut crc = i;
114 for _ in 0..8 {
115 if crc & 1 == 1 {
116 crc = (crc >> 1) ^ poly;
117 } else {
118 crc >>= 1;
119 }
120 }
121 tab[i as usize] = crc;
122 }
123 tab
124 }
125