Skip to content

Commit 4200177

Browse files
committed
fix irregular256 encoding and roundtrip tests for deflate readwrite
1 parent 5f9b868 commit 4200177

File tree

2 files changed

+80
-22
lines changed

2 files changed

+80
-22
lines changed

src/deflate/deflate_token.rs

+10-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,15 @@ pub enum DeflateToken {
1818
Reference(DeflateTokenReference),
1919
}
2020

21+
impl DeflateToken {
22+
pub fn new_ref(len: u32, dist: u32, irregular258: bool) -> DeflateToken {
23+
DeflateToken::Reference(DeflateTokenReference::new(len, dist, irregular258))
24+
}
25+
pub fn new_lit(lit: u8) -> DeflateToken {
26+
DeflateToken::Literal(lit)
27+
}
28+
}
29+
2130
/// In the case of a distance and length, the length is the number of bytes to copy from the
2231
/// previous bytes, and the distance is the number of bytes back to start copying from.
2332
///
@@ -70,7 +79,7 @@ pub enum DeflateHuffmanType {
7079
},
7180
}
7281

73-
#[derive(Debug)]
82+
#[derive(Debug, PartialEq)]
7483
pub enum DeflateTokenBlock {
7584
Huffman {
7685
tokens: Vec<DeflateToken>,

src/deflate/deflate_writer.rs

+70-21
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ impl DeflateWriter {
6666
DeflateHuffmanType::Static { .. } => {
6767
self.bitwriter.write(1, 2, &mut self.output);
6868
let huffman_writer = HuffmanWriter::start_fixed_huffman_table();
69-
self.encode_block_with_decoder(tokens, &huffman_writer);
69+
self.encode_huffman(tokens, &huffman_writer);
7070
}
7171
DeflateHuffmanType::Dynamic {
7272
huffman_encoding, ..
@@ -77,7 +77,7 @@ impl DeflateWriter {
7777
&mut self.output,
7878
)?;
7979

80-
self.encode_block_with_decoder(tokens, &huffman_writer);
80+
self.encode_huffman(tokens, &huffman_writer);
8181
}
8282
},
8383
}
@@ -90,11 +90,7 @@ impl DeflateWriter {
9090
self.bitwriter.flush_whole_bytes(&mut self.output);
9191
}
9292

93-
fn encode_block_with_decoder(
94-
&mut self,
95-
tokens: &Vec<DeflateToken>,
96-
huffman_writer: &HuffmanWriter,
97-
) {
93+
fn encode_huffman(&mut self, tokens: &Vec<DeflateToken>, huffman_writer: &HuffmanWriter) {
9894
for token in tokens {
9995
match token {
10096
DeflateToken::Literal(lit) => {
@@ -111,7 +107,7 @@ impl DeflateWriter {
111107
&mut self.output,
112108
LITLEN_CODE_COUNT as u16 - 2,
113109
);
114-
self.bitwriter.write(5, 31, &mut self.output);
110+
self.bitwriter.write(31, 5, &mut self.output);
115111
} else {
116112
let lencode = quantize_length(reference.len());
117113
huffman_writer.write_literal(
@@ -128,22 +124,22 @@ impl DeflateWriter {
128124
&mut self.output,
129125
);
130126
}
127+
}
131128

132-
let distcode = quantize_distance(reference.dist());
133-
huffman_writer.write_distance(
134-
&mut self.bitwriter,
129+
let distcode = quantize_distance(reference.dist());
130+
huffman_writer.write_distance(
131+
&mut self.bitwriter,
132+
&mut self.output,
133+
distcode as u16,
134+
);
135+
136+
let distextra = DIST_EXTRA_TABLE[distcode];
137+
if distextra > 0 {
138+
self.bitwriter.write(
139+
reference.dist() - 1 - DIST_BASE_TABLE[distcode] as u32,
140+
distextra.into(),
135141
&mut self.output,
136-
distcode as u16,
137142
);
138-
139-
let distextra = DIST_EXTRA_TABLE[distcode];
140-
if distextra > 0 {
141-
self.bitwriter.write(
142-
reference.dist() - 1 - DIST_BASE_TABLE[distcode] as u32,
143-
distextra.into(),
144-
&mut self.output,
145-
);
146-
}
147143
}
148144
}
149145
}
@@ -152,3 +148,56 @@ impl DeflateWriter {
152148
huffman_writer.write_literal(&mut self.bitwriter, &mut self.output, 256);
153149
}
154150
}
151+
152+
/// Create a set of blocks and read them back to see if they are identical
153+
#[test]
154+
fn roundtrip_deflate_writer() {
155+
use super::deflate_reader::DeflateReader;
156+
use std::io::Cursor;
157+
158+
let mut w = DeflateWriter::new();
159+
160+
let blocks = [
161+
DeflateTokenBlock::Huffman {
162+
tokens: vec![DeflateToken::Literal(0), DeflateToken::Literal(1)],
163+
huffman_type: DeflateHuffmanType::Static { incomplete: false },
164+
},
165+
DeflateTokenBlock::Stored {
166+
uncompressed: vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
167+
padding_bits: 0b101, // there are 3 bits of padding
168+
},
169+
DeflateTokenBlock::Huffman {
170+
tokens: vec![
171+
DeflateToken::Literal(0),
172+
DeflateToken::Literal(1),
173+
DeflateToken::new_ref(100, 1, false),
174+
DeflateToken::new_ref(258, 1, true),
175+
DeflateToken::Literal(3),
176+
],
177+
huffman_type: DeflateHuffmanType::Static { incomplete: false },
178+
},
179+
];
180+
181+
for i in 0..blocks.len() {
182+
w.encode_block(&blocks[i], i == blocks.len() - 1).unwrap();
183+
}
184+
w.flush_with_padding(0);
185+
186+
let output = w.detach_output();
187+
188+
let mut r = DeflateReader::new(Cursor::new(output));
189+
190+
let mut newcontent = Vec::new();
191+
loop {
192+
let mut last = false;
193+
newcontent.push(r.read_block(&mut last).unwrap());
194+
if last {
195+
break;
196+
}
197+
}
198+
199+
assert_eq!(blocks.len(), newcontent.len());
200+
for i in 0..blocks.len() {
201+
assert_eq!(blocks[i], newcontent[i], "block {}", i);
202+
}
203+
}

0 commit comments

Comments
 (0)