1use crate::bitstream::BackwardBits;
2use crate::fse::Table as FseTable;
3use crate::DecodeError;
4
5const MAX_BITS: u8 = 11;
6
7#[derive(Clone, Copy, Debug, Default)]
9pub struct Entry {
10 symbol: u8,
11 bits: u8,
12}
13
14impl Entry {
15 pub const fn new() -> Self {
17 Self { symbol: 0, bits: 0 }
18 }
19}
20
21pub(crate) struct Table<'a> {
22 entries: &'a mut [Entry],
23 scratch: FseTable<'a>,
24 table_bits: u8,
25 valid: bool,
26}
27
28impl<'a> Table<'a> {
29 pub(crate) fn new(entries: &'a mut [Entry], scratch: FseTable<'a>) -> Self {
30 Self {
31 entries,
32 scratch,
33 table_bits: 0,
34 valid: false,
35 }
36 }
37
38 pub(crate) fn reset(&mut self) {
39 self.table_bits = 0;
40 self.valid = false;
41 self.scratch.reset();
42 }
43
44 pub(crate) fn is_valid(&self) -> bool {
45 self.valid
46 }
47
48 pub(crate) fn read_description(
49 &mut self,
50 input: &[u8],
51 fse_scratch: &mut [i16],
52 ) -> Result<usize, DecodeError> {
53 let header = *input.first().ok_or(DecodeError::InvalidEntropyTable)?;
54 let mut weights = [0u8; 256];
55 let (weight_count, consumed) = if header < 128 {
56 let compressed_size = header as usize;
57 if compressed_size == 0 || input.len() < 1 + compressed_size {
58 return Err(DecodeError::InvalidEntropyTable);
59 }
60 let count = decode_compressed_weights(
61 &input[1..1 + compressed_size],
62 &mut weights,
63 &mut self.scratch,
64 fse_scratch,
65 )?;
66 (count, 1 + compressed_size)
67 } else {
68 let count = header as usize - 127;
69 let bytes = count.div_ceil(2);
70 if input.len() < 1 + bytes {
71 return Err(DecodeError::InvalidEntropyTable);
72 }
73 for (index, weight) in weights[..count].iter_mut().enumerate() {
74 let packed = input[1 + index / 2];
75 *weight = if index % 2 == 0 {
76 packed >> 4
77 } else {
78 packed & 0x0f
79 };
80 }
81 (count, 1 + bytes)
82 };
83 self.build(&weights[..weight_count])?;
84 Ok(consumed)
85 }
86
87 pub(crate) fn decode(
88 &self,
89 input: &[u8],
90 output: &mut [u8],
91 strict: bool,
92 ) -> Result<(), DecodeError> {
93 if !self.valid {
94 return Err(DecodeError::InvalidEntropyTable);
95 }
96 let mut bits = BackwardBits::new(input)?;
97 for byte in output {
98 let index = bits.peek_padded(self.table_bits) as usize;
99 let entry = self.entries[index];
100 if entry.bits == 0 {
101 return Err(DecodeError::InvalidEntropyTable);
102 }
103 if strict {
104 bits.consume(entry.bits)?;
109 } else {
110 let consumed = core::cmp::min(entry.bits as usize, bits.remaining()) as u8;
111 bits.consume(consumed)?;
112 }
113 *byte = entry.symbol;
114 }
115 if bits.remaining() != 0 {
116 return Err(DecodeError::InvalidBitstream);
117 }
118 Ok(())
119 }
120
121 pub(crate) fn decode_four(
122 &self,
123 input: &[u8],
124 output: &mut [u8],
125 strict: bool,
126 ) -> Result<(), DecodeError> {
127 if input.len() < 6 {
128 return Err(DecodeError::InvalidBitstream);
129 }
130 let sizes = [
131 u16::from_le_bytes([input[0], input[1]]) as usize,
132 u16::from_le_bytes([input[2], input[3]]) as usize,
133 u16::from_le_bytes([input[4], input[5]]) as usize,
134 ];
135 let starts = [
136 6,
137 6usize
138 .checked_add(sizes[0])
139 .ok_or(DecodeError::ArithmeticOverflow)?,
140 6usize
141 .checked_add(sizes[0])
142 .and_then(|value| value.checked_add(sizes[1]))
143 .ok_or(DecodeError::ArithmeticOverflow)?,
144 6usize
145 .checked_add(sizes[0])
146 .and_then(|value| value.checked_add(sizes[1]))
147 .and_then(|value| value.checked_add(sizes[2]))
148 .ok_or(DecodeError::ArithmeticOverflow)?,
149 ];
150 if starts[3] > input.len() {
151 return Err(DecodeError::InvalidBitstream);
152 }
153 let ends = [starts[1], starts[2], starts[3], input.len()];
154 let segment = output.len().div_ceil(4);
155 for stream in 0..4 {
156 let output_start = core::cmp::min(stream * segment, output.len());
157 let output_end = core::cmp::min(output_start + segment, output.len());
158 if output_start != output_end {
159 self.decode(
160 &input[starts[stream]..ends[stream]],
161 &mut output[output_start..output_end],
162 strict,
163 )?;
164 }
165 }
166 Ok(())
167 }
168
169 fn build(&mut self, weights: &[u8]) -> Result<(), DecodeError> {
170 if weights.is_empty() || weights.len() >= 256 {
171 return Err(DecodeError::InvalidEntropyTable);
172 }
173 let mut sum = 0u32;
174 for weight in weights {
175 if *weight > MAX_BITS {
176 return Err(DecodeError::InvalidEntropyTable);
177 }
178 if *weight != 0 {
179 sum = sum
180 .checked_add(1u32 << (*weight - 1))
181 .ok_or(DecodeError::InvalidEntropyTable)?;
182 }
183 }
184 if sum == 0 {
185 return Err(DecodeError::InvalidEntropyTable);
186 }
187 let table_bits = 32 - sum.leading_zeros();
188 if table_bits > MAX_BITS as u32 {
189 return Err(DecodeError::InvalidEntropyTable);
190 }
191 let remainder = (1u32 << table_bits)
192 .checked_sub(sum)
193 .ok_or(DecodeError::InvalidEntropyTable)?;
194 if !remainder.is_power_of_two() {
195 return Err(DecodeError::InvalidEntropyTable);
196 }
197 let implied_weight = 32 - remainder.leading_zeros();
198 let table_bits = table_bits as u8;
199
200 let mut code_bits = [0u8; 256];
201 for (index, weight) in weights.iter().enumerate() {
202 code_bits[index] = if *weight == 0 {
203 0
204 } else {
205 table_bits + 1 - *weight
206 };
207 }
208 code_bits[weights.len()] = table_bits + 1 - implied_weight as u8;
209
210 let mut ranks = [0usize; MAX_BITS as usize + 1];
211 for bits in &code_bits[..=weights.len()] {
212 ranks[*bits as usize] += 1;
213 }
214 let mut starts = [0usize; MAX_BITS as usize + 1];
215 for bits in (1..=table_bits as usize).rev() {
216 starts[bits - 1] =
217 starts[bits] + ranks[bits] * (1usize << (table_bits as usize - bits));
218 }
219 let used = 1usize << table_bits;
220 if starts[0] != used {
221 return Err(DecodeError::InvalidEntropyTable);
222 }
223 self.entries[..used].fill(Entry::default());
224 for (symbol, bits) in code_bits[..=weights.len()].iter().enumerate() {
225 if *bits == 0 {
226 continue;
227 }
228 let width = 1usize << (table_bits - *bits);
229 let start = starts[*bits as usize];
230 let end = start
231 .checked_add(width)
232 .ok_or(DecodeError::InvalidEntropyTable)?;
233 if end > used {
234 return Err(DecodeError::InvalidEntropyTable);
235 }
236 self.entries[start..end].fill(Entry {
237 symbol: symbol as u8,
238 bits: *bits,
239 });
240 starts[*bits as usize] = end;
241 }
242 self.table_bits = table_bits;
243 self.valid = true;
244 Ok(())
245 }
246}
247
248fn decode_compressed_weights(
249 input: &[u8],
250 output: &mut [u8; 256],
251 table: &mut FseTable<'_>,
252 scratch: &mut [i16],
253) -> Result<usize, DecodeError> {
254 table.reset();
255 let description_size = table.read_description(input, 12, 6, scratch)?;
256 if description_size >= input.len() {
257 return Err(DecodeError::InvalidEntropyTable);
258 }
259 let mut bits = BackwardBits::new(&input[description_size..])?;
260 let mut first = bits.read(table.log())?;
261 let mut second = bits.read(table.log())?;
262 let mut count = 0usize;
263 loop {
264 if count >= 255 {
265 return Err(DecodeError::InvalidEntropyTable);
266 }
267 output[count] = table.symbol(first)?;
268 count += 1;
269 let entry = table.entry(first)?;
270 if bits.remaining() < entry.bits as usize {
271 if count >= 255 {
272 return Err(DecodeError::InvalidEntropyTable);
273 }
274 output[count] = table.symbol(second)?;
275 return Ok(count + 1);
276 }
277 table.update(&mut first, &mut bits)?;
278
279 if count >= 255 {
280 return Err(DecodeError::InvalidEntropyTable);
281 }
282 output[count] = table.symbol(second)?;
283 count += 1;
284 let entry = table.entry(second)?;
285 if bits.remaining() < entry.bits as usize {
286 if count >= 255 {
287 return Err(DecodeError::InvalidEntropyTable);
288 }
289 output[count] = table.symbol(first)?;
290 return Ok(count + 1);
291 }
292 table.update(&mut second, &mut bits)?;
293 }
294}
295
296#[cfg(test)]
297mod tests {
298 use super::*;
299
300 #[test]
301 fn truncated_literal_symbol_is_rejected() {
302 let mut entries = std::vec![Entry::new(); crate::HUFFMAN_ENTRIES];
303 let mut scratch = std::vec![crate::FseEntry::new(); 512];
304 let mut table = Table::new(&mut entries, FseTable::new(&mut scratch));
305 table.build(&[1]).unwrap();
306 let mut output = [0; 1];
307 assert!(table.decode(&[1], &mut output, true).is_err());
308 assert!(table.decode(&[2], &mut output, true).is_ok());
309 assert_eq!(output, [0]);
310 }
311}