struct HuffTree {
even_childs :bool,
payload :Option<u32>,
l :Option<Box<HuffTree>>,
r :Option<Box<HuffTree>>,
}
impl HuffTree {
pub fn insert_rec(&mut self, payload :u32, depth :u8) -> bool {
if self.payload.is_some() {
return false;
}
if depth == 0 {
if !(self.l.is_none() && self.r.is_none()) {
return false;
}
self.payload = Some(payload);
return true;
}
if self.even_childs {
match &mut self.l {
&mut Some(_) => return false,
&mut None => {
let mut new_node = HuffTree { even_childs :true, payload :None, l :None, r :None };
new_node.insert_rec(payload, depth - 1);
self.l = Some(Box::new(new_node));
self.even_childs = false;
return true;
}
}
} else {
let left = self.l.as_mut().unwrap();
if !left.even_childs {
if left.insert_rec(payload, depth - 1) {
self.even_childs = left.even_childs &&
if let &mut Some(ref mut right) = &mut self.r.as_mut() { right.even_childs } else { false };
return true;
}
}
return match self.r {
Some(ref mut right) => {
let success = right.insert_rec(payload, depth - 1);
self.even_childs = left.even_childs && right.even_childs;
success
},
None => {
let mut new_node = HuffTree { even_childs :true, payload :None, l :None, r :None };
let success = new_node.insert_rec(payload, depth - 1);
self.even_childs = left.even_childs && new_node.even_childs;
self.r = Some(Box::new(new_node));
success
}
};
}
}
}
#[derive(Debug)]
pub enum HuffmanError {
Overspecified,
Underpopulated,
InvalidSingleEntry,
}
#[derive(Clone, Copy)]
enum UnrolledLookupEntry {
HasEntry(u8, u32),
InconclusiveWithHint(u32),
Inconclusive,
}
pub enum PeekedDataLookupResult<'l> {
Iter(u8, VorbisHuffmanIter<'l>),
PayloadFound(u8, u32),
}
pub struct VorbisHuffmanTree {
desc_prog :Vec<u32>,
unrolled_entries :[UnrolledLookupEntry; 256],
}
impl VorbisHuffmanTree {
pub fn load_from_array(codebook_codeword_lengths :&[u8]) -> Result<VorbisHuffmanTree, HuffmanError> {
let mut simple_tree = HuffTree { even_childs :true, payload :None, l :None, r :None };
let mut cnt :usize = 0;
let mut last_valid_idx = None;
for (i, &codeword_length) in codebook_codeword_lengths.iter().enumerate() {
if codeword_length == 0 {
continue;
}
cnt += 1;
last_valid_idx = Some(i);
if !simple_tree.insert_rec(i as u32, codeword_length) {
try!(Err(HuffmanError::Overspecified))
}
}
if cnt == 1 {
let decoded = last_valid_idx.unwrap();
let encoded_len = codebook_codeword_lengths[decoded];
if encoded_len == 1 {
return Ok(VorbisHuffmanTree {
desc_prog :vec![1u32 << 31, 3, 3, decoded as u32],
unrolled_entries :[
UnrolledLookupEntry::HasEntry(1, decoded as u32); 256
],
});
} else {
try!(Err(HuffmanError::InvalidSingleEntry))
}
}
if !simple_tree.even_childs {
try!(Err(HuffmanError::Underpopulated));
}
let mut desc_prog = Vec::with_capacity(cnt);
fn traverse(tree :& HuffTree, desc_prog :&mut Vec<u32>) -> u32 {
let cur_pos = desc_prog.len() as u32;
let has_children = tree.l.is_some() || tree.r.is_some();
let entry = ((has_children as u32) << 31) | tree.payload.unwrap_or(0);
desc_prog.push(entry);
if has_children {
desc_prog.push(0);
desc_prog.push(0);
desc_prog[cur_pos as usize + 1] =
traverse(tree.l.as_ref().unwrap(), desc_prog);
desc_prog[cur_pos as usize + 2] =
traverse(tree.r.as_ref().unwrap(), desc_prog);
}
return cur_pos;
}
assert_eq!(traverse(&simple_tree, &mut desc_prog), 0);
let mut unrolled_entries = [UnrolledLookupEntry::Inconclusive; 256];
fn uroll_traverse(tree :& HuffTree,
unrolled_entries :&mut [UnrolledLookupEntry; 256],
prefix :u32, prefix_idx :u8,
desc_prog :&[u32], desc_prog_idx :u32) {
let has_children = tree.l.is_some() || tree.r.is_some();
if has_children {
if prefix_idx == 8 {
unrolled_entries[prefix as usize] =
UnrolledLookupEntry::InconclusiveWithHint(desc_prog_idx);
} else {
uroll_traverse(tree.l.as_ref().unwrap(),
unrolled_entries,
prefix + (0 << prefix_idx), prefix_idx + 1,
desc_prog, desc_prog[desc_prog_idx as usize + 1]);
uroll_traverse(tree.r.as_ref().unwrap(),
unrolled_entries,
prefix + (1 << prefix_idx), prefix_idx + 1,
desc_prog, desc_prog[desc_prog_idx as usize + 2]);
}
} else {
let payload = tree.payload.unwrap();
let it = 1 << prefix_idx;
let mut i = prefix as usize;
for _ in 1 .. (1u16 << (8 - prefix_idx)) {
unrolled_entries[i] =
UnrolledLookupEntry::HasEntry(prefix_idx, payload);
i += it;
}
}
}
if cnt > 0 {
uroll_traverse(&simple_tree,
&mut unrolled_entries, 0, 0, &desc_prog, 0);
}
return Ok(VorbisHuffmanTree {
desc_prog,
unrolled_entries,
});
}
pub fn iter<'l>(&'l self) -> VorbisHuffmanIter<'l> {
return VorbisHuffmanIter { desc_prog :&self.desc_prog, pos :0 };
}
pub fn lookup_peeked_data<'l>(&'l self, bit_count :u8, peeked_data :u32)
-> PeekedDataLookupResult<'l> {
if bit_count > 8 {
panic!("Bit count {} larger than allowed 8", bit_count);
}
use self::UnrolledLookupEntry::*;
use self::PeekedDataLookupResult::*;
return match self.unrolled_entries[peeked_data as usize] {
HasEntry(cnt_to_remove, payload) if cnt_to_remove <= bit_count
=> PayloadFound(cnt_to_remove, payload),
InconclusiveWithHint(hint)
=> Iter(8, VorbisHuffmanIter { desc_prog : &self.desc_prog, pos : hint }),
_
=> Iter(0, VorbisHuffmanIter { desc_prog : &self.desc_prog, pos : 0 }),
};
}
}
pub struct VorbisHuffmanIter<'a> {
desc_prog :&'a Vec<u32>,
pos :u32,
}
impl<'a> VorbisHuffmanIter<'a> {
pub fn next(&mut self, bit :bool) -> Option<u32> {
self.pos = self.desc_prog[self.pos as usize + 1 + bit as usize];
let child = self.desc_prog[self.pos as usize];
if (child & (1u32 << 31)) != 0 {
return None;
} else {
self.pos = 0;
return Some(child);
}
}
}
#[cfg(test)]
impl VorbisHuffmanTree {
fn iter_test(&self, path :u32, path_len :u8, expected_val :u32) {
let mut itr = self.iter();
for i in 1 .. path_len {
assert_eq!(itr.next((path & (1 << (path_len - i))) != 0), None);
}
assert_eq!(itr.next((path & 1) != 0), Some(expected_val));
}
}
#[test]
fn test_huffman_tree() {
let tree = VorbisHuffmanTree::load_from_array(&[2, 4, 4, 4, 4, 2, 3, 3]).unwrap();
tree.iter_test(0b00, 2, 0);
tree.iter_test(0b0100, 4, 1);
tree.iter_test(0b0101, 4, 2);
tree.iter_test(0b0110, 4, 3);
tree.iter_test(0b0111, 4, 4);
tree.iter_test(0b10, 2, 5);
tree.iter_test(0b110, 3, 6);
tree.iter_test(0b111, 3, 7);
VorbisHuffmanTree::load_from_array(&[
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 32]).unwrap();
}
#[test]
fn test_issue_8() {
let _ = VorbisHuffmanTree::load_from_array(&[0; 625]);
}
#[test]
fn test_under_over_spec() {
let tree = VorbisHuffmanTree::load_from_array(&[2, 4, 4, 4, 4, 2, 3]);
assert!(tree.is_err());
let tree = VorbisHuffmanTree::load_from_array(&[2, 4, 4, 4, 2, 3, 3]);
assert!(tree.is_err());
let tree = VorbisHuffmanTree::load_from_array(&[2, 4, 4, 4, 4, 2, 3, 3,3]);
assert!(tree.is_err());
}
#[test]
fn test_single_entry_huffman_tree() {
let tree = VorbisHuffmanTree::load_from_array(&[1]).unwrap();
tree.iter_test(0b0, 1, 0);
tree.iter_test(0b1, 1, 0);
let tree = VorbisHuffmanTree::load_from_array(&[0, 0, 1, 0]).unwrap();
tree.iter_test(0b0, 1, 2);
tree.iter_test(0b1, 1, 2);
let tree = VorbisHuffmanTree::load_from_array(&[2]);
assert!(tree.is_err());
}
#[test]
fn test_unordered_huffman_tree() {
let tree = VorbisHuffmanTree::load_from_array(&[2, 4, 4, 2, 4, 4, 3, 3]).unwrap();
tree.iter_test(0b00, 2, 0);
tree.iter_test(0b0100, 4, 1);
tree.iter_test(0b0101, 4, 2);
tree.iter_test(0b10, 2, 3);
tree.iter_test(0b0110, 4, 4);
tree.iter_test(0b0111, 4, 5);
tree.iter_test(0b110, 3, 6);
tree.iter_test(0b111, 3, 7);
}
#[test]
fn test_extracted_huffman_tree() {
VorbisHuffmanTree::load_from_array(&[
5, 6, 11, 11, 11, 11, 10, 10, 12, 11, 5, 2, 11, 5, 6, 6,
7, 9, 11, 13, 13, 10, 7, 11, 6, 7, 8, 9, 10, 12, 11, 5,
11, 6, 8, 7, 9, 11, 14, 15, 11, 6, 6, 8, 4, 5, 7, 8,
10,13, 10, 5, 7, 7, 5, 5, 6, 8, 10, 11, 10, 7, 7, 8,
6, 5, 5, 7, 9, 9, 11, 8, 8, 11, 8, 7, 6, 6, 7, 9,
12,11, 10, 13, 9, 9, 7, 7, 7, 9, 11, 13, 12, 15, 12, 11,
9, 8, 8, 8]).unwrap();
}