tf_demo_parser/demo/
lzss.rs

1pub fn decompress(input: &[u8], output: &mut Vec<u8>) {
2    decompress_(input, output);
3}
4
5/// inner fn that returns an option so we can use ? for short circuiting return
6fn decompress_(input: &[u8], output: &mut Vec<u8>) -> Option<()> {
7    let mut len_bytes = [0; 4];
8    len_bytes.copy_from_slice(input.get(0..4)?);
9    let target_len = u32::from_le_bytes(len_bytes) as usize;
10
11    let mut read_pos = 4;
12    let mut read_byte = move || {
13        let byte = *input.get(read_pos)?;
14        read_pos += 1;
15        Some(byte)
16    };
17
18    loop {
19        let mut cmd_byte = read_byte()?;
20
21        for _ in 0..8 {
22            if cmd_byte & 0x01 == 0x01 {
23                let pos = (read_byte()? as usize) << 4;
24                let mixed = read_byte()? as usize;
25                let pos = pos | (mixed >> 4);
26                let count = (mixed & 0x0F) + 1;
27                if count == 1 {
28                    return None;
29                }
30
31                if output.len() + count > target_len {
32                    return None;
33                }
34
35                let start = output.len() - pos - 1;
36                // can't do extend_from_within since it start + count can be larger than output.len
37                for i in 0..count {
38                    output.push(*output.get(start + i)?);
39                }
40            } else {
41                output.push(read_byte()?);
42            }
43            cmd_byte >>= 1;
44        }
45    }
46}