--- /dev/null
+use io::bitreader::BitReader;
+
+#[derive(Debug)]
+pub enum CodebookError {
+ InvalidCodebook,
+ MemoryError,
+ InvalidCode,
+}
+
+type CodebookResult<T> = Result<T, CodebookError>;
+
+pub struct FullCodebookDesc<S> {
+ code: u32,
+ bits: u8,
+ sym: S,
+}
+
+pub struct ShortCodebookDesc {
+ code: u32,
+ bits: u8,
+}
+
+pub trait CodebookDescReader<S> {
+ fn bits(&mut self, idx: usize) -> u8;
+ fn code(&mut self, idx: usize) -> u32;
+ fn sym (&mut self, idx: usize) -> S;
+ fn len (&mut self) -> usize;
+}
+
+#[allow(dead_code)]
+pub struct Codebook<S> {
+ table: Vec<u32>,
+ syms: Vec<S>,
+ lut_bits: u8,
+}
+
+pub trait CodebookReader<S> {
+ fn read_cb(&mut self, cb: &Codebook<S>) -> CodebookResult<S>;
+}
+
+impl<S: Copy> Codebook<S> {
+//todo allow add escapes
+ pub fn new(cb: &mut CodebookDescReader<S>) -> CodebookResult<Self> {
+ let mut maxbits = 0;
+ let mut nnz = 0;
+ for i in 0..cb.len() {
+ let bits = cb.bits(i);
+ if bits > 0 { nnz = nnz + 1; }
+ if bits > maxbits {
+ maxbits = bits;
+ }
+ }
+ if maxbits == 0 { return Err(CodebookError::InvalidCodebook); }
+
+ let mut table: Vec<u32> = Vec::new();
+ let mut syms: Vec<S> = Vec::new();
+ let tab_len = 1 << maxbits;
+ table.reserve(tab_len);
+ if table.capacity() < tab_len { return Err(CodebookError::MemoryError); }
+ table.resize(tab_len, 0xFF);
+ syms.reserve(nnz);
+ if syms.capacity() < nnz { return Err(CodebookError::MemoryError); }
+
+ let mut symidx: u32 = 0;
+ for i in 0..cb.len() {
+ let bits = cb.bits(i);
+ if bits == 0 { continue; }
+ let code = cb.code(i) << (maxbits - bits);
+ let fill_len = 1 << (maxbits - bits);
+ for j in 0..fill_len {
+ let idx = (code + j) as usize;
+ table[idx] = (symidx << 8) | (bits as u32);
+ }
+ symidx = symidx + 1;
+ }
+
+ for i in 0..cb.len() {
+ if cb.bits(i) > 0 {
+ syms.push(cb.sym(i));
+ }
+ }
+
+ Ok(Codebook { table: table, syms: syms, lut_bits: maxbits })
+ }
+}
+
+impl<'a, S: Copy> CodebookReader<S> for BitReader<'a> {
+ #[allow(unused_variables)]
+ fn read_cb(&mut self, cb: &Codebook<S>) -> CodebookResult<S> {
+ let lut_idx = self.peek(cb.lut_bits) as usize;
+ let bits = cb.table[lut_idx] & 0xFF;
+ let idx = (cb.table[lut_idx] >> 8) as usize;
+ if bits == 0xFF || (bits as isize) > self.left() {
+ return Err(CodebookError::InvalidCode);
+ }
+ if let Err(_) = self.skip(bits) {}
+ let sym = cb.syms[idx];
+ return Ok(sym)
+ }
+}
+
+pub struct FullCodebookDescReader<S> {
+ data: Vec<FullCodebookDesc<S>>,
+}
+
+impl<S> FullCodebookDescReader<S> {
+ pub fn new(data: Vec<FullCodebookDesc<S>>) -> Self {
+ FullCodebookDescReader { data: data }
+ }
+}
+
+impl<S: Copy> CodebookDescReader<S> for FullCodebookDescReader<S> {
+ fn bits(&mut self, idx: usize) -> u8 { self.data[idx].bits }
+ fn code(&mut self, idx: usize) -> u32 { self.data[idx].code }
+ fn sym (&mut self, idx: usize) -> S { self.data[idx].sym }
+ fn len(&mut self) -> usize { self.data.len() }
+}
+
+pub struct ShortCodebookDescReader {
+ data: Vec<ShortCodebookDesc>,
+}
+
+impl ShortCodebookDescReader {
+ pub fn new(data: Vec<ShortCodebookDesc<>>) -> Self {
+ ShortCodebookDescReader { data: data }
+ }
+}
+
+impl CodebookDescReader<u32> for ShortCodebookDescReader {
+ fn bits(&mut self, idx: usize) -> u8 { self.data[idx].bits }
+ fn code(&mut self, idx: usize) -> u32 { self.data[idx].code }
+ fn sym (&mut self, idx: usize) -> u32 { idx as u32 }
+ fn len(&mut self) -> usize { self.data.len() }
+}
+
+#[cfg(test)]
+mod test {
+ use super::*;
+ use io::bitreader::*;
+
+ #[test]
+ fn test_cb() {
+ const BITS: [u8; 2] = [0b01011011, 0b10111100];
+ let cb_desc: Vec<FullCodebookDesc<i8>> = vec!(
+ FullCodebookDesc { code: 0b0, bits: 1, sym: 16 },
+ FullCodebookDesc { code: 0b10, bits: 2, sym: -3 },
+ FullCodebookDesc { code: 0b110, bits: 3, sym: 42 },
+ FullCodebookDesc { code: 0b1110, bits: 4, sym: -42 }
+ );
+ let buf = &BITS;
+ let mut br = BitReader::new(buf, buf.len(), BitReaderMode::BE);
+ let mut cfr = FullCodebookDescReader::new(cb_desc);
+ let cb = Codebook::new(&mut cfr).unwrap();
+ assert_eq!(br.read_cb(&cb).unwrap(), 16);
+ assert_eq!(br.read_cb(&cb).unwrap(), -3);
+ assert_eq!(br.read_cb(&cb).unwrap(), 42);
+ assert_eq!(br.read_cb(&cb).unwrap(), -42);
+ let ret = br.read_cb(&cb);
+ if let Err(e) = ret {
+ assert_eq!(e as i32, CodebookError::InvalidCode as i32);
+ } else {
+ assert_eq!(0, 1);
+ }
+
+ let scb_desc: Vec<ShortCodebookDesc> = vec!(
+ ShortCodebookDesc { code: 0b0, bits: 1 },
+ ShortCodebookDesc { code: 0, bits: 0 },
+ ShortCodebookDesc { code: 0b10, bits: 2 },
+ ShortCodebookDesc { code: 0, bits: 0 },
+ ShortCodebookDesc { code: 0, bits: 0 },
+ ShortCodebookDesc { code: 0b110, bits: 3 },
+ ShortCodebookDesc { code: 0, bits: 0 },
+ ShortCodebookDesc { code: 0b1110, bits: 4 }
+ );
+ let mut br2 = BitReader::new(buf, buf.len(), BitReaderMode::BE);
+ let mut cfr = ShortCodebookDescReader::new(scb_desc);
+ let cb = Codebook::new(&mut cfr).unwrap();
+ assert_eq!(br2.read_cb(&cb).unwrap(), 0);
+ assert_eq!(br2.read_cb(&cb).unwrap(), 2);
+ assert_eq!(br2.read_cb(&cb).unwrap(), 5);
+ assert_eq!(br2.read_cb(&cb).unwrap(), 7);
+ }
+}