arc_mac/
stuffit_huffman.rs1use anyhow::{bail, Result};
12
13use super::bitreader_be::BitReaderBE;
14
15enum Node {
16 Leaf(u8),
17 Branch(Box<Node>, Box<Node>),
18}
19
20fn parse_tree(br: &mut BitReaderBE, depth: u32) -> Result<Node> {
23 if depth > 64 {
24 bail!("StuffIt Huffman: tree too deep");
25 }
26 if br.next_bit() == 1 {
27 Ok(Node::Leaf(br.next_bits(8) as u8))
28 } else {
29 let zero = parse_tree(br, depth + 1)?;
30 let one = parse_tree(br, depth + 1)?;
31 Ok(Node::Branch(Box::new(zero), Box::new(one)))
32 }
33}
34
35pub fn decompress(comp: &[u8], want: usize) -> Result<Vec<u8>> {
37 if want == 0 {
38 return Ok(Vec::new());
39 }
40 let mut br = BitReaderBE::new(comp);
41 let root = parse_tree(&mut br, 0)?;
42
43 let mut out = Vec::with_capacity(want);
44 while out.len() < want {
45 let mut node = &root;
46 loop {
47 match node {
48 Node::Leaf(b) => {
49 out.push(*b);
50 break;
51 }
52 Node::Branch(zero, one) => {
53 node = if br.next_bit() == 0 { zero } else { one };
55 }
56 }
57 }
58 }
59 Ok(out)
60}
61
62#[cfg(test)]
63mod tests {
64 use super::*;
65
66 #[test]
67 fn huffman_simple_tree() {
68 let mut bits: Vec<bool> = Vec::new();
72 let put_byte = |bits: &mut Vec<bool>, v: u8| {
73 for i in (0..8).rev() {
74 bits.push((v >> i) & 1 == 1);
75 }
76 };
77 bits.push(false); bits.push(true); put_byte(&mut bits, b'A');
80 bits.push(true); put_byte(&mut bits, b'B');
82 bits.push(false);
84 bits.push(true);
85 bits.push(false);
86 bits.push(false);
87
88 let mut bytes = Vec::new();
90 let mut acc = 0u8;
91 let mut n = 0;
92 for b in bits {
93 acc = (acc << 1) | (b as u8);
94 n += 1;
95 if n == 8 {
96 bytes.push(acc);
97 acc = 0;
98 n = 0;
99 }
100 }
101 if n > 0 {
102 bytes.push(acc << (8 - n));
103 }
104
105 let out = decompress(&bytes, 4).unwrap();
106 assert_eq!(&out, b"ABAA");
107 }
108}