DevCore/
code.rs

1// Constants.
2pub const END_OF_BLOCK: u16 = 256;
3pub const FIXED_LITERAL_BIT_CODE_TABLE: [(std::ops::Range<u16>, u8, u16); 4] = [
4    (000..144, 8, 0b0_0011_0000),
5    (144..256, 9, 0b1_1001_0000),
6    (256..280, 7, 0b0_0000_0000),
7    (280..288, 8, 0b0_1100_0000),
8];
9pub const LENGTH_TABLE: [(u8, u8); 29] = [
10    (0, 0),
11    (1, 0),
12    (2, 0),
13    (3, 0),
14    (4, 0),
15    (5, 0),
16    (6, 0),
17    (7, 0),
18    (8, 1),
19    (10, 1),
20    (12, 1),
21    (14, 1),
22    (16, 2),
23    (20, 2),
24    (24, 2),
25    (28, 2),
26    (32, 3),
27    (40, 3),
28    (48, 3),
29    (56, 3),
30    (64, 4),
31    (80, 4),
32    (96, 4),
33    (112, 4),
34    (128, 5),
35    (160, 5),
36    (192, 5),
37    (224, 5),
38    (255, 0),
39];
40pub const DISTANCE_TABLE: [(u16, u8); 30] = [
41    (1, 0),
42    (2, 0),
43    (3, 0),
44    (4, 0),
45    (5, 1),
46    (7, 1),
47    (9, 2),
48    (13, 2),
49    (17, 3),
50    (25, 3),
51    (33, 4),
52    (49, 4),
53    (65, 5),
54    (97, 5),
55    (129, 6),
56    (193, 6),
57    (257, 7),
58    (385, 7),
59    (513, 8),
60    (769, 8),
61    (1025, 9),
62    (1537, 9),
63    (2049, 10),
64    (3073, 10),
65    (4097, 11),
66    (6145, 11),
67    (8193, 12),
68    (12_289, 12),
69    (16_385, 13),
70    (24_577, 13),
71];
72// Structures.
73#[derive(Debug, Clone, Copy)]
74pub enum Code {
75    EndOfBlock,
76    Literal(u8),
77    Pointer { distance: u16, length: u8 },
78}
79// Implementations.
80impl Code {
81    pub fn literal_code(&self) -> u16 {
82        match *self {
83            Code::Literal(x) => x as u16,
84            Code::EndOfBlock => END_OF_BLOCK,
85            Code::Pointer { length: l, .. } => match l {
86                0x00..=0x07 => 257 + l as u16,
87                0x08..=0x0F => 265 + (l as u16 - 0x08) / 0x02,
88                0x10..=0x1F => 269 + (l as u16 - 0x10) / 0x04,
89                0x20..=0x3F => 273 + (l as u16 - 0x20) / 0x08,
90                0x40..=0x7F => 277 + (l as u16 - 0x40) / 0x10,
91                0x80..=0xFE => 281 + (l as u16 - 0x80) / 0x20,
92                0xFF => 285,
93            },
94        }
95    }
96    pub fn extra_length(&self) -> Option<(u8, u16)> {
97        if let Code::Pointer { length: l, .. } = *self {
98            match l {
99                0x00..=0x07 | 0xFF => None,
100                0x08..=0x0F => Some((1, (l as u16 - 0x08) % 0x02)),
101                0x10..=0x1F => Some((2, (l as u16 - 0x10) % 0x04)),
102                0x20..=0x3F => Some((3, (l as u16 - 0x20) % 0x08)),
103                0x40..=0x7F => Some((4, (l as u16 - 0x40) % 0x10)),
104                0x80..=0xFE => Some((5, (l as u16 - 0x80) % 0x20)),
105            }
106        } else {
107            None
108        }
109    }
110    pub fn distance_code(&self) -> Option<(u16, u8, u16)> {
111        if let Code::Pointer { distance: d, .. } = *self {
112            let d = d - 1;
113            match d {
114                0x0000..=0x0003 => Some((d, 0, 0)),
115                0x0004..=0x0007 => {
116                    let (div, rem) = div_rem(d - 0x0004, 0x0002);
117                    Some((4 + div, 1, rem))
118                }
119                0x0008..=0x000F => {
120                    let (div, rem) = div_rem(d - 0x0008, 0x0004);
121                    Some((6 + div, 2, rem))
122                }
123                0x0010..=0x001F => {
124                    let (div, rem) = div_rem(d - 0x0010, 0x0008);
125                    Some((8 + div, 3, rem))
126                }
127                0x0020..=0x003F => {
128                    let (div, rem) = div_rem(d - 0x0020, 0x0010);
129                    Some((10 + div, 4, rem))
130                }
131                0x0040..=0x007F => {
132                    let (div, rem) = div_rem(d - 0x0040, 0x0020);
133                    Some((12 + div, 5, rem))
134                }
135                0x0080..=0x00FF => {
136                    let (div, rem) = div_rem(d - 0x0080, 0x0040);
137                    Some((14 + div, 6, rem))
138                }
139                0x0100..=0x01FF => {
140                    let (div, rem) = div_rem(d - 0x0100, 0x0080);
141                    Some((16 + div, 7, rem))
142                }
143                0x0200..=0x03FF => {
144                    let (div, rem) = div_rem(d - 0x0200, 0x0100);
145                    Some((18 + div, 8, rem))
146                }
147                0x0400..=0x07FF => {
148                    let (div, rem) = div_rem(d - 0x0400, 0x0200);
149                    Some((20 + div, 9, rem))
150                }
151                0x0800..=0x0FFF => {
152                    let (div, rem) = div_rem(d - 0x0800, 0x0400);
153                    Some((22 + div, 10, rem))
154                }
155                0x1000..=0x1FFF => {
156                    let (div, rem) = div_rem(d - 0x1000, 0x0800);
157                    Some((24 + div, 11, rem))
158                }
159                0x2000..=0x3FFF => {
160                    let (div, rem) = div_rem(d - 0x2000, 0x1000);
161                    Some((26 + div, 12, rem))
162                }
163                0x4000..=0x7FFF => {
164                    let (div, rem) = div_rem(d - 0x4000, 0x2000);
165                    Some((28 + div, 13, rem))
166                }
167                _ => unimplemented!(),
168            }
169        } else {
170            None
171        }
172    }
173}
174// Functions.
175fn div_rem(a: u16, b: u16) -> (u16, u16) {
176    (a / b, a % b)
177}