Skip to content

Commit dc77163

Browse files
committed
Make huffman decoder/encoder building function return io::Result<_>
This resolve RazrFalcon/usvg#22
1 parent 6157daa commit dc77163

File tree

3 files changed

+36
-28
lines changed

3 files changed

+36
-28
lines changed

src/deflate/encode.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -400,7 +400,7 @@ where
400400
{
401401
self.lz77.flush(&mut self.buf);
402402
self.buf.push(symbol::Symbol::EndOfBlock);
403-
let symbol_encoder = self.huffman.build(&self.buf);
403+
let symbol_encoder = self.huffman.build(&self.buf)?;
404404
self.huffman.save(writer, &symbol_encoder)?;
405405
for s in self.buf.drain(..) {
406406
symbol_encoder.encode(writer, &s)?;

src/deflate/symbol.rs

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ impl Decoder {
232232
}
233233

234234
pub trait HuffmanCodec {
235-
fn build(&self, symbols: &[Symbol]) -> Encoder;
235+
fn build(&self, symbols: &[Symbol]) -> io::Result<Encoder>;
236236
fn save<W>(&self, writer: &mut bit::BitWriter<W>, codec: &Encoder) -> io::Result<()>
237237
where
238238
W: io::Write;
@@ -245,27 +245,27 @@ pub trait HuffmanCodec {
245245
pub struct FixedHuffmanCodec;
246246
impl HuffmanCodec for FixedHuffmanCodec {
247247
#[allow(unused_variables)]
248-
fn build(&self, symbols: &[Symbol]) -> Encoder {
248+
fn build(&self, symbols: &[Symbol]) -> io::Result<Encoder> {
249249
let mut literal_builder = huffman::EncoderBuilder::new(288);
250250
for &(bitwidth, ref symbols, code_base) in &FIXED_LITERAL_OR_LENGTH_CODE_TABLE {
251251
for (code, symbol) in symbols
252252
.clone()
253253
.enumerate()
254254
.map(|(i, s)| (code_base + i as u16, s))
255255
{
256-
literal_builder.set_mapping(symbol, huffman::Code::new(bitwidth, code));
256+
literal_builder.set_mapping(symbol, huffman::Code::new(bitwidth, code))?;
257257
}
258258
}
259259

260260
let mut distance_builder = huffman::EncoderBuilder::new(30);
261261
for i in 0..30 {
262-
distance_builder.set_mapping(i, huffman::Code::new(5, i));
262+
distance_builder.set_mapping(i, huffman::Code::new(5, i))?;
263263
}
264264

265-
Encoder {
265+
Ok(Encoder {
266266
literal: literal_builder.finish(),
267267
distance: distance_builder.finish(),
268-
}
268+
})
269269
}
270270
#[allow(unused_variables)]
271271
fn save<W>(&self, writer: &mut bit::BitWriter<W>, codec: &Encoder) -> io::Result<()>
@@ -286,13 +286,13 @@ impl HuffmanCodec for FixedHuffmanCodec {
286286
.enumerate()
287287
.map(|(i, s)| (code_base + i as u16, s))
288288
{
289-
literal_builder.set_mapping(symbol, huffman::Code::new(bitwidth, code));
289+
literal_builder.set_mapping(symbol, huffman::Code::new(bitwidth, code))?;
290290
}
291291
}
292292

293293
let mut distance_builder = huffman::DecoderBuilder::new(5, None);
294294
for i in 0..30 {
295-
distance_builder.set_mapping(i, huffman::Code::new(5, i));
295+
distance_builder.set_mapping(i, huffman::Code::new(5, i))?;
296296
}
297297

298298
Ok(Decoder {
@@ -305,7 +305,7 @@ impl HuffmanCodec for FixedHuffmanCodec {
305305
#[derive(Debug)]
306306
pub struct DynamicHuffmanCodec;
307307
impl HuffmanCodec for DynamicHuffmanCodec {
308-
fn build(&self, symbols: &[Symbol]) -> Encoder {
308+
fn build(&self, symbols: &[Symbol]) -> io::Result<Encoder> {
309309
let mut literal_counts = [0; 286];
310310
let mut distance_counts = [0; 30];
311311
for s in symbols {
@@ -314,10 +314,10 @@ impl HuffmanCodec for DynamicHuffmanCodec {
314314
distance_counts[d as usize] += 1;
315315
}
316316
}
317-
Encoder {
318-
literal: huffman::EncoderBuilder::from_frequencies(&literal_counts, 15),
319-
distance: huffman::EncoderBuilder::from_frequencies(&distance_counts, 15),
320-
}
317+
Ok(Encoder {
318+
literal: huffman::EncoderBuilder::from_frequencies(&literal_counts, 15)?,
319+
distance: huffman::EncoderBuilder::from_frequencies(&distance_counts, 15)?,
320+
})
321321
}
322322
fn save<W>(&self, writer: &mut bit::BitWriter<W>, codec: &Encoder) -> io::Result<()>
323323
where
@@ -331,7 +331,7 @@ impl HuffmanCodec for DynamicHuffmanCodec {
331331
for x in &codes {
332332
code_counts[x.0 as usize] += 1;
333333
}
334-
let bitwidth_encoder = huffman::EncoderBuilder::from_frequencies(&code_counts, 7);
334+
let bitwidth_encoder = huffman::EncoderBuilder::from_frequencies(&code_counts, 7)?;
335335

336336
let bitwidth_code_count = cmp::max(
337337
4,
@@ -379,7 +379,7 @@ impl HuffmanCodec for DynamicHuffmanCodec {
379379
bitwidth_code_bitwidthes[i] = reader.read_bits(3)? as u8;
380380
}
381381
let bitwidth_decoder =
382-
huffman::DecoderBuilder::from_bitwidthes(&bitwidth_code_bitwidthes, None);
382+
huffman::DecoderBuilder::from_bitwidthes(&bitwidth_code_bitwidthes, None)?;
383383

384384
let mut literal_code_bitwidthes = Vec::with_capacity(literal_code_count as usize);
385385
while literal_code_bitwidthes.len() < literal_code_count as usize {
@@ -412,8 +412,8 @@ impl HuffmanCodec for DynamicHuffmanCodec {
412412
literal: huffman::DecoderBuilder::from_bitwidthes(
413413
&literal_code_bitwidthes,
414414
Some(END_OF_BLOCK),
415-
),
416-
distance: huffman::DecoderBuilder::from_bitwidthes(&distance_code_bitwidthes, None),
415+
)?,
416+
distance: huffman::DecoderBuilder::from_bitwidthes(&distance_code_bitwidthes, None)?,
417417
})
418418
}
419419
}

src/huffman.rs

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,9 @@ impl Code {
3434

3535
pub trait Builder: Sized {
3636
type Instance;
37-
fn set_mapping(&mut self, symbol: u16, code: Code);
37+
fn set_mapping(&mut self, symbol: u16, code: Code) -> io::Result<()>;
3838
fn finish(self) -> Self::Instance;
39-
fn restore_canonical_huffman_codes(mut self, bitwidthes: &[u8]) -> Self::Instance {
39+
fn restore_canonical_huffman_codes(mut self, bitwidthes: &[u8]) -> io::Result<Self::Instance> {
4040
debug_assert!(!bitwidthes.is_empty());
4141

4242
let mut symbols = bitwidthes
@@ -51,11 +51,11 @@ pub trait Builder: Sized {
5151
let mut prev_width = 0;
5252
for (symbol, bitwidth) in symbols {
5353
code <<= bitwidth - prev_width;
54-
self.set_mapping(symbol, Code::new(bitwidth, code));
54+
self.set_mapping(symbol, Code::new(bitwidth, code))?;
5555
code += 1;
5656
prev_width = bitwidth;
5757
}
58-
self.finish()
58+
Ok(self.finish())
5959
}
6060
}
6161

@@ -75,14 +75,14 @@ impl DecoderBuilder {
7575
max_bitwidth: max_bitwidth,
7676
}
7777
}
78-
pub fn from_bitwidthes(bitwidthes: &[u8], eob_symbol: Option<u16>) -> Decoder {
78+
pub fn from_bitwidthes(bitwidthes: &[u8], eob_symbol: Option<u16>) -> io::Result<Decoder> {
7979
let builder = Self::new(bitwidthes.iter().cloned().max().unwrap_or(0), eob_symbol);
8080
builder.restore_canonical_huffman_codes(bitwidthes)
8181
}
8282
}
8383
impl Builder for DecoderBuilder {
8484
type Instance = Decoder;
85-
fn set_mapping(&mut self, symbol: u16, code: Code) {
85+
fn set_mapping(&mut self, symbol: u16, code: Code) -> io::Result<()> {
8686
debug_assert!(code.width <= self.max_bitwidth);
8787
if Some(symbol) == self.eob_symbol {
8888
self.eob_bitwidth = code.width;
@@ -95,11 +95,18 @@ impl Builder for DecoderBuilder {
9595
let code_be = code.inverse_endian();
9696
for padding in 0..(1 << (self.max_bitwidth - code.width)) {
9797
let i = ((padding << code.width) | code_be.bits) as usize;
98-
debug_assert_eq!(self.table[i], u16::from(MAX_BITWIDTH) + 1);
98+
if self.table[i] != u16::from(MAX_BITWIDTH) + 1 {
99+
let message = format!(
100+
"Bit region conflict: i={}, old_value={}, new_value={}, symbol={}, code={:?}",
101+
i, self.table[i], value, symbol, code
102+
);
103+
return Err(io::Error::new(io::ErrorKind::InvalidData, message));
104+
}
99105
unsafe {
100106
*self.table.get_unchecked_mut(i) = value;
101107
}
102108
}
109+
Ok(())
103110
}
104111
fn finish(self) -> Self::Instance {
105112
Decoder {
@@ -158,7 +165,7 @@ impl EncoderBuilder {
158165
table: vec![Code::new(0, 0); symbol_count],
159166
}
160167
}
161-
pub fn from_bitwidthes(bitwidthes: &[u8]) -> Encoder {
168+
pub fn from_bitwidthes(bitwidthes: &[u8]) -> io::Result<Encoder> {
162169
let symbol_count = bitwidthes
163170
.iter()
164171
.enumerate()
@@ -168,7 +175,7 @@ impl EncoderBuilder {
168175
let builder = Self::new(symbol_count);
169176
builder.restore_canonical_huffman_codes(bitwidthes)
170177
}
171-
pub fn from_frequencies(symbol_frequencies: &[usize], max_bitwidth: u8) -> Encoder {
178+
pub fn from_frequencies(symbol_frequencies: &[usize], max_bitwidth: u8) -> io::Result<Encoder> {
172179
let max_bitwidth = cmp::min(
173180
max_bitwidth,
174181
ordinary_huffman_codes::calc_optimal_max_bitwidth(symbol_frequencies),
@@ -179,9 +186,10 @@ impl EncoderBuilder {
179186
}
180187
impl Builder for EncoderBuilder {
181188
type Instance = Encoder;
182-
fn set_mapping(&mut self, symbol: u16, code: Code) {
189+
fn set_mapping(&mut self, symbol: u16, code: Code) -> io::Result<()> {
183190
debug_assert_eq!(self.table[symbol as usize], Code::new(0, 0));
184191
self.table[symbol as usize] = code.inverse_endian();
192+
Ok(())
185193
}
186194
fn finish(self) -> Self::Instance {
187195
Encoder { table: self.table }

0 commit comments

Comments
 (0)