1use crate::ext::io::*;
3use std::io::{Read, Result};
4
5pub struct LzssReader<T: Read> {
7 reader: T,
8 buf: Vec<u8>,
9 buf_pos: usize,
10 frame: Vec<u8>,
11 frame_mask: usize,
12 frame_pos: usize,
13 tmp: u8,
14 tmp_used: bool,
15}
16
17impl<T: Read> LzssReader<T> {
18 pub fn new(reader: T) -> Self {
19 Self::new2(reader, 0x1000, 0, 0xfee)
20 }
21 pub fn new2(reader: T, frame_size: usize, frame_fill: u8, frame_init_pos: usize) -> Self {
22 Self {
23 reader,
24 buf: Vec::new(),
25 buf_pos: 0,
26 frame: vec![frame_fill; frame_size],
27 frame_mask: frame_size - 1,
28 frame_pos: frame_init_pos,
29 tmp: 0,
30 tmp_used: false,
31 }
32 }
33 fn push(&mut self, buf: &mut MemWriterRef, data: u8) -> Result<()> {
34 if buf.is_eof() {
35 self.buf.push(data);
36 } else {
37 buf.write_u8(data)?;
38 }
39 Ok(())
40 }
41 fn unpack(&mut self, buf: &mut MemWriterRef) -> Result<()> {
42 let mut bu = [0; 1];
43 let mut readed = if self.tmp_used {
44 bu[0] = self.tmp;
45 self.tmp_used = false;
46 1
47 } else {
48 self.reader.read(&mut bu)?
49 };
50 if readed == 0 {
51 return Ok(());
53 }
54 let ctl = bu[0];
55 let mut bit = 1;
56 readed = self.reader.read(&mut bu)?;
57 while bit != 0x100 && readed > 0 {
58 if ((ctl as u32) & bit) != 0 {
59 let b = bu[0];
60 self.frame[self.frame_pos] = b;
61 self.frame_pos += 1;
62 self.frame_pos &= self.frame_mask;
63 self.push(buf, b)?;
64 } else {
65 let lo = bu[0];
66 readed = self.reader.read(&mut bu)?;
67 if readed == 0 {
68 return Ok(());
69 }
70 let hi = bu[0];
71 let mut offset = (((hi as usize) & 0xF0) << 4) | (lo as usize);
72 let mut count = 3 + (hi & 0xF);
73 while count != 0 {
74 let v = self.frame[offset];
75 offset += 1;
76 offset &= self.frame_mask;
77 self.frame[self.frame_pos] = v;
78 self.frame_pos += 1;
79 self.frame_pos &= self.frame_mask;
80 self.push(buf, v)?;
81 count -= 1;
82 }
83 }
84 bit <<= 1;
85 readed = self.reader.read(&mut bu)?;
86 }
87 if readed > 0 {
88 self.tmp = bu[0];
89 self.tmp_used = true;
90 }
91 Ok(())
92 }
93}
94
95impl<R: Read> Read for LzssReader<R> {
96 fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
97 if !self.buf.is_empty() && self.buf_pos < self.buf.len() {
98 let readed = buf.len().min(self.buf.len() - self.buf_pos);
99 buf[..readed].copy_from_slice(&self.buf[self.buf_pos..self.buf_pos + readed]);
100 self.buf_pos += readed;
101 if self.buf_pos == self.buf.len() {
102 self.buf.clear();
103 self.buf_pos = 0;
104 }
105 return Ok(readed);
106 }
107 let mut writer = MemWriterRef::new(buf);
108 self.unpack(&mut writer)?;
109 Ok(writer.pos)
110 }
111}
112
113#[cfg(test)]
114mod tests {
115 use super::*;
116
117 #[test]
118 fn test_literal_only() {
119 let data = [0xFF, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80];
120 let mut reader = LzssReader::new(&data[..]);
121 let mut result = Vec::new();
122 reader.read_to_end(&mut result).unwrap();
123 assert_eq!(result, vec![0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80]);
124 }
125
126 #[test]
127 fn test_back_ref() {
128 let data = [0x07, b'A', b'B', b'C', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
130 let mut reader = LzssReader::new2(&data[..], 256, 0, 0);
131 let mut result = Vec::new();
132 reader.read_to_end(&mut result).unwrap();
133 assert_eq!(result, b"ABCABCABCABCABCABC");
134 }
135
136 #[test]
137 fn test_chunked_read() {
138 let data = [0x07, b'A', b'B', b'C', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
139 let mut reader = LzssReader::new2(&data[..], 256, 0, 0);
140 let mut buf = [0u8; 5];
141 let mut result = Vec::new();
142 loop {
143 let n = reader.read(&mut buf).unwrap();
144 if n == 0 {
145 break;
146 }
147 result.extend_from_slice(&buf[..n]);
148 }
149 assert_eq!(result, b"ABCABCABCABCABCABC");
150 }
151
152 #[test]
153 fn test_run_length() {
154 let data = [0x01, b'A', 0, 0x01];
156 let mut reader = LzssReader::new2(&data[..], 256, 0, 0);
157 let mut result = Vec::new();
158 reader.read_to_end(&mut result).unwrap();
159 assert_eq!(result, b"AAAAA");
160 }
161
162 #[test]
163 fn test_back_ref_offset() {
164 let data = [
166 0xFF, b'X', b'X', b'X', b'X', b'X', b'A', b'B', b'C', 0x03, b'D', b'E', 0x05, 0x02,
167 ];
168 let mut reader = LzssReader::new2(&data[..], 256, 0, 0);
169 let mut result = Vec::new();
170 reader.read_to_end(&mut result).unwrap();
171 assert_eq!(result, b"XXXXXABCDEABCDE");
172 }
173
174 #[test]
175 fn test_multi_control_byte() {
176 let data = [
178 0xFF, b'A', b'B', b'C', b'D', b'E', b'F', b'G', b'H', 0xFF, b'I', b'J', b'K', b'L',
179 b'M', b'N', b'O', b'P',
180 ];
181 let mut reader = LzssReader::new(&data[..]);
182 let mut result = Vec::new();
183 reader.read_to_end(&mut result).unwrap();
184 assert_eq!(result, b"ABCDEFGHIJKLMNOP");
185 }
186}