compression/deflate/
mod.rs

1//! rust-compression
2//!
3//! # Licensing
4//! This Source Code is subject to the terms of the Mozilla Public License
5//! version 2.0 (the "License"). You can obtain a copy of the License at
6//! <http://mozilla.org/MPL/2.0/>.
7#![cfg(feature = "deflate")]
8
9pub(crate) mod decoder;
10pub(crate) mod encoder;
11
12use crate::bitio::small_bit_vec::SmallBitVec;
13use crate::core::u16;
14#[cfg(not(feature = "std"))]
15#[allow(unused_imports)]
16use alloc::vec;
17#[cfg(not(feature = "std"))]
18use alloc::vec::Vec;
19
20fn fix_symbol_table() -> Vec<u8> {
21    let mut r = vec![8; 144];
22    r.append(&mut vec![9; 112]);
23    r.append(&mut vec![7; 24]);
24    r.append(&mut vec![8; 8]);
25    r
26}
27
28fn fix_offset_table() -> &'static [u8; 32] {
29    &[5; 32]
30}
31
32#[derive(Debug)]
33struct CodeTable {
34    codes: Vec<u8>,
35    offsets: Vec<u16>,
36    ext_bits: Vec<u8>,
37}
38
39impl CodeTable {
40    fn convert(&self, value: u16) -> (u8, SmallBitVec<u16>) {
41        let pos = self.codes[value as usize];
42        (
43            pos,
44            SmallBitVec::new(
45                value - self.offsets[pos as usize],
46                self.ext_bits(pos as usize),
47            ),
48        )
49    }
50
51    fn ext_bits(&self, pos: usize) -> usize {
52        self.ext_bits[pos] as usize
53    }
54
55    fn convert_back(&self, pos: usize, ext: u16) -> u16 {
56        self.offsets[pos] + ext
57    }
58}
59
60fn gen_codes(len: usize, offsets: &[u16]) -> Vec<u8> {
61    let mut codes = Vec::with_capacity(len);
62    let mut j = 0;
63    for i in 0..(len as u16) {
64        while offsets[j as usize + 1] <= i {
65            j += 1;
66        }
67        codes.push(j);
68    }
69    codes
70}
71
72fn gen_len_tab() -> CodeTable {
73    let mut offsets = Vec::with_capacity(30);
74    let mut ext_bits = Vec::with_capacity(29);
75    for i in 0..8 {
76        offsets.push(i);
77        ext_bits.push(0);
78    }
79
80    for i in 8..28 {
81        let n = (i >> 2) - 1;
82        offsets.push(u16::from(i & 3 | 4) << n);
83        ext_bits.push(n);
84    }
85
86    // 28
87    offsets.push(255);
88    ext_bits.push(0);
89
90    // 29
91    offsets.push(u16::MAX);
92
93    let codes = gen_codes(256, &offsets);
94
95    CodeTable {
96        codes,
97        offsets,
98        ext_bits,
99    }
100}
101
102fn gen_off_tab() -> CodeTable {
103    let mut offsets = Vec::with_capacity(31);
104    let mut ext_bits = Vec::with_capacity(30);
105    for i in 0..4 {
106        offsets.push(i);
107        ext_bits.push(0);
108    }
109
110    for i in 4..30 {
111        let n = (i >> 1) - 1;
112        offsets.push(u16::from(i & 1 | 2) << n);
113        ext_bits.push(n);
114    }
115
116    // 30
117    offsets.push(u16::MAX);
118
119    let codes = gen_codes(0x8000, &offsets);
120
121    CodeTable {
122        codes,
123        offsets,
124        ext_bits,
125    }
126}
127
128#[cfg(test)]
129mod tests {
130    use crate::action::Action;
131    use crate::deflate::decoder::Deflater;
132    use crate::deflate::encoder::Inflater;
133    use crate::traits::decoder::DecodeExt;
134    use crate::traits::encoder::EncodeExt;
135    #[cfg(not(feature = "std"))]
136    use alloc::vec::Vec;
137    use rand::distributions::Standard;
138    use rand::{thread_rng, Rng};
139
140    fn check(testarray: &[u8]) {
141        let encoded = testarray
142            .to_vec()
143            .encode(&mut Inflater::new(), Action::Finish)
144            .collect::<Result<Vec<_>, _>>();
145        let decoded = encoded
146            .unwrap()
147            .decode(&mut Deflater::new())
148            .collect::<Result<Vec<_>, _>>()
149            .unwrap();
150
151        assert_eq!(testarray.to_vec(), decoded);
152    }
153
154    #[test]
155    fn test_empty() {
156        check(&[]);
157    }
158
159    #[test]
160    fn test_unit() {
161        check(b"a");
162    }
163
164    #[test]
165    fn test_arr() {
166        check(b"aaaaaaaaaaa");
167    }
168
169    #[test]
170    fn test_std() {
171        check(b"aabbaabbaaabbbaaabbbaabbaabb");
172    }
173
174    #[test]
175    fn test_long() {
176        check(&(b"a".iter().cycle().take(260).cloned().collect::<Vec<u8>>()));
177    }
178
179    #[test]
180    fn test_long2() {
181        check(
182            &((144..256)
183                .cycle()
184                .take(224)
185                .map(|x| x as u8)
186                .collect::<Vec<u8>>()),
187        )
188    }
189
190    #[test]
191    fn test_multiblocks() {
192        let rng = thread_rng();
193
194        check(&(rng.sample_iter(&Standard).take(323_742).collect::<Vec<_>>()));
195    }
196
197    #[test]
198    fn test_multiblocks2() {
199        let rng = thread_rng();
200
201        check(&(rng.sample_iter(&Standard).take(323_742).collect::<Vec<_>>()));
202    }
203
204    #[test]
205    fn test_multiblocks3() {
206        let rng = thread_rng();
207
208        check(
209            &(rng
210                .sample_iter(&Standard)
211                .take(0xF_FFFF)
212                .collect::<Vec<_>>()),
213        );
214    }
215
216    fn test_rand_with_len(len: usize) {
217        let rng = thread_rng();
218
219        check(&(rng.sample_iter(&Standard).take(len).collect::<Vec<_>>()));
220    }
221
222    #[test]
223    fn test_multiblocks6() {
224        test_rand_with_len(6);
225    }
226
227    #[test]
228    fn test_multiblocks4() {
229        test_rand_with_len(0x10_000);
230    }
231
232    #[test]
233    fn test_multiblocks5() {
234        test_rand_with_len(0x10_0001);
235    }
236}