1extern crate bit_vec;
4extern crate byteorder;
5
6use bit_vec::BitVec;
7use byteorder::{BigEndian, ReadBytesExt};
8use std::io::{Error, ErrorKind, Read, Seek};
9use std::mem::transmute;
10
11pub fn decompress<T: Read + Seek>(data: &mut T) -> Result<Vec<u8>, Error> {
31 let lz_type = data.read_u8()?;
32 let mut data_size_tmp: [u8; 4] = [0; 4];
33 data.read_exact(&mut data_size_tmp[0..3])?;
34 let data_size = unsafe { transmute::<[u8; 4], u32>(data_size_tmp) };
35
36 match lz_type {
37 0x10 => decompress_lzss10(data, data_size as usize),
38 0x11 => decompress_lzss11(data, data_size as usize),
39 _ => Err(Error::new(ErrorKind::InvalidInput, "Invalid header")),
40 }
41}
42
43fn decompress_lzss10<T: Read + Seek>(data: &mut T, size: usize) -> Result<Vec<u8>, Error> {
44 let mut decompress_data: Vec<u8> = Vec::new();
45 let disp_extra = 1;
46 while decompress_data.len() < size {
47 let b = data.read_u8()?;
48 let bits = BitVec::from_bytes(&[b]);
49 for bit in bits.iter() {
50 if bit {
51 let val = data.read_u16::<BigEndian>()?;
52 let count = (val >> 0xC) + 3;
53 let disp = (val & 0xFFF) + disp_extra;
54 for _ in 0..count {
55 let len = decompress_data.len();
56 let copy_data = decompress_data[len - disp as usize];
57 decompress_data.push(copy_data);
58 }
59 } else {
60 decompress_data.push(data.read_u8()?);
61 }
62
63 if size <= decompress_data.len() {
64 break;
65 }
66 }
67 }
68
69 if size == decompress_data.len() {
70 Ok(decompress_data)
71 } else {
72 Err(Error::new(
73 ErrorKind::InvalidData,
74 "Decompressed size does not match expected size.",
75 ))
76 }
77}
78
79fn decompress_lzss11<T: Read + Seek>(data: &mut T, size: usize) -> Result<Vec<u8>, Error> {
80 let mut decompress_data: Vec<u8> = Vec::new();
81 while decompress_data.len() < size {
82 let b = data.read_u8()?;
83 let bits = BitVec::from_bytes(&[b]);
84 for bit in bits.iter() {
85 if bit {
86 let mut val = data.read_u8()?;
87 let indicator = val >> 4;
88 let mut count: u16;
89 match indicator {
90 0 => {
91 count = u16::from(val) << 4;
92 val = data.read_u8()?;
93 count += u16::from(val) >> 4;
94 count += 0x11
95 }
96 1 => {
97 count = (u16::from(val) & 0xF) << 12;
98 val = data.read_u8()?;
99 count += u16::from(val) << 4;
100 val = data.read_u8()?;
101 count += u16::from(val) >> 4;
102 count += 0x111;
103 }
104 _ => {
105 count = indicator.into();
106 count += 1;
107 }
108 }
109 let mut disp: u16 = (u16::from(val) & 0xF) << 8;
110 val = data.read_u8()?;
111 disp += u16::from(val) + 1;
112
113 for _ in 0..count {
114 let len = decompress_data.len();
115 let copy_data = decompress_data[len - disp as usize];
116 decompress_data.push(copy_data);
117 }
118 } else {
119 decompress_data.push(data.read_u8()?);
120 }
121
122 if size <= decompress_data.len() {
123 break;
124 }
125 }
126 }
127
128 if size == decompress_data.len() {
129 Ok(decompress_data)
130 } else {
131 Err(Error::new(
132 ErrorKind::InvalidData,
133 "Decompressed size does not match expected size.",
134 ))
135 }
136}
137
138#[cfg(test)]
139mod tests {
140 use super::*;
141 use std::io::Cursor;
142
143 #[test]
144 fn decompresses() {
145 let lzss10: [u8; 11] = [
146 0x10, 0x14, 0x00, 0x00, 0x08, 0x61, 0x62, 0x63, 0x64, 0xD0, 0x03,
147 ]; let lzss11: [u8; 11] = [
149 0x11, 0x14, 0x00, 0x00, 0x08, 0x61, 0x62, 0x63, 0x64, 0xF0, 0x03,
150 ]; let type_bad: [u8; 11] = [
152 0x13, 0x10, 0x00, 0x00, 0x08, 0x61, 0x62, 0x63, 0x64, 0xF0, 0x03,
153 ]; let mut result_lzss10: Vec<u8> = Vec::new();
156 let mut result_lzss11: Vec<u8> = Vec::new();
157 for _ in 0..5 {
158 result_lzss10.push(0x61);
159 result_lzss10.push(0x62);
160 result_lzss10.push(0x63);
161 result_lzss10.push(0x64);
162
163 result_lzss11.push(0x61);
164 result_lzss11.push(0x62);
165 result_lzss11.push(0x63);
166 result_lzss11.push(0x64);
167 }
168
169 assert_eq!(result_lzss10, decompress(&mut Cursor::new(lzss10)).unwrap());
170 assert_eq!(result_lzss11, decompress(&mut Cursor::new(lzss11)).unwrap());
171 assert!(
172 decompress(&mut Cursor::new(type_bad)).is_err(),
173 "Should error on invalid type header"
174 );
175 }
176
177 #[test]
178 fn decompresses_lzss10() {
179 let test1: [u8; 1] = [0x00];
180 let test2: [u8; 9] = [0x00, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68]; let test3: [u8; 7] = [0x08, 0x61, 0x62, 0x63, 0x64, 0xD0, 0x03]; let test4_bad: [u8; 11] = [
183 0x10, 0x10, 0x00, 0x00, 0x08, 0x61, 0x62, 0x63, 0x64, 0xD0, 0x03,
184 ]; let mut result3: Vec<u8> = Vec::new();
186 for _ in 0..5 {
187 result3.push(0x61);
188 result3.push(0x62);
189 result3.push(0x63);
190 result3.push(0x64);
191 }
192 assert_eq!(
193 0,
194 decompress_lzss10(&mut Cursor::new(test1), 0).unwrap().len()
195 );
196 assert_eq!(
197 &[0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68],
198 decompress_lzss10(&mut Cursor::new(test2), 8)
199 .unwrap()
200 .as_slice()
201 );
202 assert_eq!(
203 result3,
204 decompress_lzss10(&mut Cursor::new(test3), 20).unwrap()
205 );
206 assert!(
207 decompress(&mut Cursor::new(test4_bad)).is_err(),
208 "Should error on wrong size."
209 );
210 }
211
212 #[test]
213 fn decompresses_lzss11() {
214 let test1: [u8; 1] = [0x00];
215 let test2: [u8; 9] = [0x00, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68]; let test3: [u8; 7] = [0x08, 0x61, 0x62, 0x63, 0x64, 0xF0, 0x03]; let test4: [u8; 8] = [0x08, 0x61, 0x62, 0x63, 0x64, 0x01, 0x30, 0x03]; let test5: [u8; 9] = [0x08, 0x61, 0x62, 0x63, 0x64, 0x10, 0x07, 0xB0, 0x03]; let test6_bad: [u8; 11] = [
220 0x11, 0x10, 0x00, 0x00, 0x08, 0x61, 0x62, 0x63, 0x64, 0xF0, 0x03,
221 ]; let mut result3: Vec<u8> = Vec::new();
223 let mut result4: Vec<u8> = Vec::new();
224 let mut result5: Vec<u8> = Vec::new();
225
226 for _ in 0..5 {
227 result3.push(0x61);
228 result3.push(0x62);
229 result3.push(0x63);
230 result3.push(0x64);
231 }
232 for _ in 0..10 {
233 result4.push(0x61);
234 result4.push(0x62);
235 result4.push(0x63);
236 result4.push(0x64);
237 }
238 for _ in 0..100 {
239 result5.push(0x61);
240 result5.push(0x62);
241 result5.push(0x63);
242 result5.push(0x64);
243 }
244
245 assert_eq!(
246 0,
247 decompress_lzss11(&mut Cursor::new(test1), 0).unwrap().len()
248 );
249 assert_eq!(
250 &[0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68],
251 decompress_lzss11(&mut Cursor::new(test2), 8)
252 .unwrap()
253 .as_slice()
254 );
255 assert_eq!(
256 result3,
257 decompress_lzss11(&mut Cursor::new(test3), 20).unwrap()
258 );
259 assert_eq!(
260 result4,
261 decompress_lzss11(&mut Cursor::new(test4), 40).unwrap()
262 );
263 assert_eq!(
264 result5,
265 decompress_lzss11(&mut Cursor::new(test5), 400).unwrap()
266 );
267 assert!(
268 decompress(&mut Cursor::new(test6_bad)).is_err(),
269 "Should error on wrong size."
270 );
271 }
272}