unarj_rs/
decode_fastest.rs

1use bitstream_io::{BigEndian, BitRead, BitReader};
2use std::io;
3
4pub fn decode_val(r: &mut BitReader<&[u8], BigEndian>, from: u32, to: u32) -> io::Result<u16> {
5    let mut res = 0;
6    let mut add = 0;
7    let mut exp = 1 << from;
8    let mut bit = from;
9    while bit < to {
10        res = r.read::<u16>(1)?;
11        if res == 0 {
12            break;
13        }
14        add += exp;
15        exp <<= 1;
16        bit += 1;
17    }
18    if bit != 0 {
19        res = r.read::<u16>(bit)?;
20    }
21    res += add;
22    Ok(res)
23}
24
25const THRESHOLD: usize = 3;
26
27pub fn decode_fastest(data: &[u8], original_size: usize) -> io::Result<Vec<u8>> {
28    let mut res = Vec::with_capacity(original_size);
29    let mut r = BitReader::endian(data, BigEndian);
30    while res.len() < original_size {
31        let len = decode_val(&mut r, 0, 7)?;
32        if len == 0 {
33            let next_char = r.read::<u8>(8)?;
34            res.push(next_char);
35        } else {
36            let rep_count = len as usize + THRESHOLD - 1;
37            let back_ptr = decode_val(&mut r, 9, 13)? as usize;
38            if back_ptr > res.len() - 1 {
39                return Err(io::Error::new(
40                    io::ErrorKind::InvalidData,
41                    "Invalid back_ptr",
42                ));
43            }
44            let mut i = res.len() - 1 - back_ptr;
45            for _ in 0..rep_count {
46                res.push(res[i]);
47                i += 1;
48            }
49        }
50    }
51    Ok(res)
52}