1pub 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#[derive(Debug, Clone, Copy)]
74pub enum Code {
75 EndOfBlock,
76 Literal(u8),
77 Pointer { distance: u16, length: u8 },
78}
79impl 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}
174fn div_rem(a: u16, b: u16) -> (u16, u16) {
176 (a / b, a % b)
177}