use ::huffman_tree::{VorbisHuffmanTree, PeekedDataLookupResult};
pub struct BitpackCursor <'a> {
bit_cursor :u8,
byte_cursor :usize,
inner :&'a[u8],
}
macro_rules! sign_extend {
( $num:expr, $desttype:ident, $bit_cnt_large:expr, $bit_cnt_small:expr) => { {
let n = $num;
let res :$desttype = n as $desttype;
let k :u8 = $bit_cnt_large - $bit_cnt_small;
res << k >> k
} }
}
#[test]
fn test_sign_extend() {
assert_eq!(sign_extend!(0b00, i8, 8, 2), 0);
assert_eq!(sign_extend!(0b01, i8, 8, 2), 1);
assert_eq!(sign_extend!(0b11, i8, 8, 2), -1);
assert_eq!(sign_extend!(0b111, i8, 8, 3), -1);
assert_eq!(sign_extend!(0b101, i8, 8, 3), -3);
assert_eq!(sign_extend!(0b01111110, i16, 16, 8), 126);
assert_eq!(sign_extend!(0b10000010, i16, 16, 8), -126);
}
fn mask_bits(num : u8) -> u8 {
!((!0u8).wrapping_shl(num as u32)) | if num >= 8 { 0xff } else { 0 }
}
fn bmask_bits(num : u8) -> u8 {
(!0u8).wrapping_shr(8 - num as u32)
}
#[test]
fn test_mask_bits() {
assert_eq!(mask_bits(0), 0b00000000);
assert_eq!(mask_bits(1), 0b00000001);
assert_eq!(mask_bits(2), 0b00000011);
assert_eq!(mask_bits(3), 0b00000111);
assert_eq!(mask_bits(4), 0b00001111);
assert_eq!(mask_bits(5), 0b00011111);
assert_eq!(mask_bits(6), 0b00111111);
assert_eq!(mask_bits(7), 0b01111111);
assert_eq!(mask_bits(8), 0b11111111);
}
#[test]
fn test_bmask_bits() {
assert_eq!(bmask_bits(0), 0b11111111);
assert_eq!(bmask_bits(1), 0b00000001);
assert_eq!(bmask_bits(2), 0b00000011);
assert_eq!(bmask_bits(3), 0b00000111);
assert_eq!(bmask_bits(4), 0b00001111);
assert_eq!(bmask_bits(5), 0b00011111);
assert_eq!(bmask_bits(6), 0b00111111);
assert_eq!(bmask_bits(7), 0b01111111);
assert_eq!(bmask_bits(8), 0b11111111);
}
macro_rules! bpc_read_body {
( $rettype:ident, $bitnum:expr, $octetnum:expr, $selfarg:expr ) => { {
let last_octet_partial :usize = ($bitnum as i8 - $octetnum as i8 * 8 > 0) as usize;
let octetnum_rounded_up :usize = last_octet_partial + $octetnum;
let bit_cursor_after = ($selfarg.bit_cursor + $bitnum) % 8;
if ($selfarg.bit_cursor + $bitnum) as usize > 8 * octetnum_rounded_up {
if $selfarg.byte_cursor + 1 + octetnum_rounded_up > $selfarg.inner.len() {
return Err(());
}
let buf = &$selfarg.inner[$selfarg.byte_cursor
.. $selfarg.byte_cursor + 1 + octetnum_rounded_up];
let mut res :$rettype = buf[0] as $rettype;
res >>= $selfarg.bit_cursor;
let mut cur_bit_cursor = 8 - $selfarg.bit_cursor;
for i in 1 .. octetnum_rounded_up {
res |= (buf[i] as $rettype) << cur_bit_cursor;
cur_bit_cursor += 8;
}
let last_bits = buf[octetnum_rounded_up] & mask_bits(bit_cursor_after);
res |= (last_bits as $rettype) << cur_bit_cursor;
$selfarg.byte_cursor += octetnum_rounded_up;
$selfarg.bit_cursor = bit_cursor_after;
Ok(res)
} else {
if $selfarg.byte_cursor + octetnum_rounded_up > $selfarg.inner.len() {
return Err(());
}
let buf = &$selfarg.inner[$selfarg.byte_cursor ..
$selfarg.byte_cursor + octetnum_rounded_up];
let mut res :$rettype = buf[0] as $rettype;
res >>= $selfarg.bit_cursor;
if $bitnum <= 8 {
res &= mask_bits($bitnum) as $rettype;
}
let mut cur_bit_cursor = 8 - $selfarg.bit_cursor;
for i in 1 .. octetnum_rounded_up - 1 {
res |= (buf[i] as $rettype) << cur_bit_cursor;
cur_bit_cursor += 8;
}
if $bitnum > 8 {
let last_bits = buf[octetnum_rounded_up - 1] & bmask_bits(bit_cursor_after);
res |= (last_bits as $rettype) << cur_bit_cursor;
}
$selfarg.byte_cursor += $octetnum;
$selfarg.byte_cursor += ($selfarg.bit_cursor == 8 - ($bitnum % 8)) as usize;
$selfarg.bit_cursor = bit_cursor_after;
Ok(res)
}
} }
}
macro_rules! bpc_peek_body {
( $rettype:ident, $bitnum:expr, $octetnum:expr, $selfarg:expr ) => { {
let last_octet_partial :usize = ($bitnum as i8 - $octetnum as i8 * 8 > 0) as usize;
let octetnum_rounded_up :usize = last_octet_partial + $octetnum;
let bit_cursor_after = ($selfarg.bit_cursor + $bitnum) % 8;
if ($selfarg.bit_cursor + $bitnum) as usize > 8 * octetnum_rounded_up {
if $selfarg.byte_cursor + 1 + octetnum_rounded_up > $selfarg.inner.len() {
return Err(());
}
let buf = &$selfarg.inner[$selfarg.byte_cursor
.. $selfarg.byte_cursor + 1 + octetnum_rounded_up];
let mut res :$rettype = buf[0] as $rettype;
res >>= $selfarg.bit_cursor;
let mut cur_bit_cursor = 8 - $selfarg.bit_cursor;
for i in 1 .. octetnum_rounded_up {
res |= (buf[i] as $rettype) << cur_bit_cursor;
cur_bit_cursor += 8;
}
let last_bits = buf[octetnum_rounded_up] & mask_bits(bit_cursor_after);
res |= (last_bits as $rettype) << cur_bit_cursor;
Ok(res)
} else {
if $selfarg.byte_cursor + octetnum_rounded_up > $selfarg.inner.len() {
return Err(());
}
let buf = &$selfarg.inner[$selfarg.byte_cursor ..
$selfarg.byte_cursor + octetnum_rounded_up];
let mut res :$rettype = buf[0] as $rettype;
res >>= $selfarg.bit_cursor;
if $bitnum <= 8 {
res &= mask_bits($bitnum) as $rettype;
}
let mut cur_bit_cursor = 8 - $selfarg.bit_cursor;
for i in 1 .. octetnum_rounded_up - 1 {
res |= (buf[i] as $rettype) << cur_bit_cursor;
cur_bit_cursor += 8;
}
if $bitnum > 8 {
let last_bits = buf[octetnum_rounded_up - 1] & bmask_bits(bit_cursor_after);
res |= (last_bits as $rettype) << cur_bit_cursor;
}
Ok(res)
}
} }
}
macro_rules! bpc_advance_body {
( $bitnum:expr, $octetnum:expr, $selfarg:expr ) => { {
let last_octet_partial :usize = ($bitnum as i8 - $octetnum as i8 * 8 > 0) as usize;
let octetnum_rounded_up :usize = last_octet_partial + $octetnum;
let bit_cursor_after = ($selfarg.bit_cursor + $bitnum) % 8;
if ($selfarg.bit_cursor + $bitnum) as usize > 8 * octetnum_rounded_up {
$selfarg.byte_cursor += octetnum_rounded_up;
$selfarg.bit_cursor = bit_cursor_after;
Ok(())
} else {
$selfarg.byte_cursor += $octetnum;
$selfarg.byte_cursor += ($selfarg.bit_cursor == 8 - ($bitnum % 8)) as usize;
$selfarg.bit_cursor = bit_cursor_after;
Ok(())
}
} }
}
macro_rules! uk_reader {
( $fnname:ident, $rettype:ident, $bitnum:expr, $octetnum:expr) => {
#[inline]
pub fn $fnname(&mut self) -> Result<$rettype, ()> {
bpc_read_body!($rettype, $bitnum, $octetnum, self)
}
}
}
macro_rules! ik_reader {
( $fnname:ident, $rettype:ident, $bitnum_of_rettype:expr, $bitnum:expr, $octetnum:expr) => {
#[inline]
pub fn $fnname(&mut self) -> Result<$rettype, ()> {
Ok(sign_extend!(try!(
bpc_read_body!($rettype, $bitnum, $octetnum, self)),
$rettype, $bitnum_of_rettype, $bitnum))
}
}
}
macro_rules! ik_dynamic_reader {
( $fnname:ident, $rettype:ident, $bitnum_of_rettype:expr) => {
#[inline]
pub fn $fnname(&mut self, bit_num :u8) -> Result<$rettype, ()> {
let octet_num :usize = (bit_num / 8) as usize;
assert!(bit_num <= $bitnum_of_rettype);
Ok(sign_extend!(try!(
bpc_read_body!($rettype, bit_num, octet_num, self)),
$rettype, $bitnum_of_rettype, bit_num))
}
}
}
macro_rules! uk_dynamic_reader {
( $fnname:ident, $rettype:ident, $bit_num_max:expr) => {
#[inline]
pub fn $fnname(&mut self, bit_num :u8) -> Result<$rettype, ()> {
let octet_num :usize = (bit_num / 8) as usize;
if bit_num == 0 {
return Ok(0);
}
assert!(bit_num <= $bit_num_max);
bpc_read_body!($rettype, bit_num, octet_num, self)
}
}
}
fn float32_unpack(val :u32) -> f32 {
let sgn = val & 0x80000000;
let exp = (val & 0x7fe00000) >> 21;
let mantissa = (val & 0x1fffff) as f64;
let signed_mantissa = if sgn != 0 {
-mantissa
} else {
mantissa
};
return signed_mantissa as f32 * (exp as f32 - 788.0).exp2();
}
#[test]
fn test_float_32_unpack() {
assert_eq!(float32_unpack(1611661312), 1.000000);
assert_eq!(float32_unpack(1616117760), 5.000000);
assert_eq!(float32_unpack(1618345984), 11.000000);
assert_eq!(float32_unpack(1620115456), 17.000000);
assert_eq!(float32_unpack(1627381760), 255.000000);
assert_eq!(float32_unpack(3759144960), -1.000000);
assert_eq!(float32_unpack(3761242112), -2.000000);
assert_eq!(float32_unpack(3763339264), -4.000000);
assert_eq!(float32_unpack(3763601408), -5.000000);
assert_eq!(float32_unpack(3765436416), -8.000000);
assert_eq!(float32_unpack(3765829632), -11.000000);
assert_eq!(float32_unpack(3768451072), -30.000000);
assert_eq!(float32_unpack(3772628992), -119.000000);
assert_eq!(float32_unpack(3780634624), -1530.000000);
}
#[test]
fn test_float_32_unpack_issue_24() {
assert_eq!(float32_unpack(1628434432), 255.0);
assert_eq!(float32_unpack(1621655552), 17.0);
assert_eq!(float32_unpack(1619722240), 11.0);
assert_eq!(float32_unpack(1613234176), 1.0);
assert_eq!(float32_unpack(3760717824), -1.0);
assert_eq!(float32_unpack(3762814976), -2.0);
assert_eq!(float32_unpack(3764912128), -4.0);
assert_eq!(float32_unpack(3765043200), -5.0);
assert_eq!(float32_unpack(3767009280), -8.0);
assert_eq!(float32_unpack(3767205888), -11.0);
assert_eq!(float32_unpack(3769565184), -30.0);
assert_eq!(float32_unpack(3773751296), -119.0);
assert_eq!(float32_unpack(3781948416), -1530.0);
}
#[allow(dead_code)]
impl <'a> BitpackCursor <'a> {
pub fn new(arr : &'a[u8]) -> BitpackCursor {
return BitpackCursor::<'a> { bit_cursor: 0, byte_cursor: 0, inner: arr };
}
uk_reader!(read_u32, u32, 32, 4);
uk_reader!(read_u24, u32, 24, 3);
uk_reader!(read_u16, u16, 16, 2);
uk_reader!(read_u13, u16, 13, 1);
uk_reader!(read_u8, u8, 8, 1);
uk_reader!(read_u7, u8, 7, 0);
uk_reader!(read_u6, u8, 6, 0);
uk_reader!(read_u5, u8, 5, 0);
uk_reader!(read_u4, u8, 4, 0);
uk_reader!(read_u3, u8, 3, 0);
uk_reader!(read_u2, u8, 2, 0);
uk_reader!(read_u1, u8, 1, 0);
#[inline]
pub fn read_bit_flag(&mut self) -> Result<bool, ()> {
return Ok(try!(self.read_u1()) == 1);
}
uk_dynamic_reader!(read_dyn_u8, u8, 8);
uk_dynamic_reader!(read_dyn_u16, u16, 16);
uk_dynamic_reader!(read_dyn_u32, u32, 32);
uk_dynamic_reader!(read_dyn_u64, u64, 64);
ik_reader!(read_i32, i32, 32, 32, 4);
ik_reader!(read_i8, i8, 8, 8, 1);
ik_reader!(read_i7, i8, 8, 7, 0);
ik_dynamic_reader!(read_dyn_i8, i8, 8);
ik_dynamic_reader!(read_dyn_i16, i16, 16);
ik_dynamic_reader!(read_dyn_i32, i32, 32);
pub fn read_f32(&mut self) -> Result<f32, ()> {
let val = try!(self.read_u32());
Ok(float32_unpack(val))
}
#[inline]
pub fn peek_u8(&self) -> Result<u8, ()> {
bpc_peek_body!(u8, 8, 1, self)
}
pub fn advance_dyn_u8(&mut self, bit_num :u8) -> Result<(), ()> {
let octet_num :usize = (bit_num / 8) as usize;
if bit_num == 0 {
return Ok(());
}
assert!(bit_num <= 8);
bpc_advance_body!(bit_num, octet_num, self)
}
pub fn read_huffman(&mut self, tree :&VorbisHuffmanTree) -> Result<u32, ()> {
let mut iter = match self.peek_u8() {
Ok(data) => match tree.lookup_peeked_data(8, data as u32) {
PeekedDataLookupResult::Iter(advance, iter) => {
try!(self.advance_dyn_u8(advance));
iter
},
PeekedDataLookupResult::PayloadFound(advance, payload) => {
try!(self.advance_dyn_u8(advance));
return Ok(payload);
},
},
Err(_) => tree.iter(),
};
loop {
let b = try!(self.read_bit_flag());
match iter.next(b) {
Some(v) => return Ok(v),
None => (),
}
}
}
}
#[test]
fn test_bitpacking_reader_static() {
let test_arr = &[0b11111100, 0b01001000, 0b11001110, 0b00000110];
let mut cur = BitpackCursor::new(test_arr);
assert_eq!(cur.read_u4().unwrap(), 12);
assert_eq!(cur.read_u3().unwrap(), 7);
assert_eq!(cur.read_u7().unwrap(), 17);
assert_eq!(cur.read_u13().unwrap(), 6969);
}
#[test]
fn test_bitpacking_reader_dynamic() {
let test_arr = &[0b11111100, 0b01001000, 0b11001110, 0b00000110];
let mut cur = BitpackCursor::new(test_arr);
assert_eq!(cur.read_dyn_u8(4).unwrap(), 12);
assert_eq!(cur.read_dyn_u8(3).unwrap(), 7);
assert_eq!(cur.read_dyn_u16(7).unwrap(), 17);
assert_eq!(cur.read_dyn_u16(13).unwrap(), 6969);
let test_arr = &[93, 92];
let mut cur = BitpackCursor::new(test_arr);
assert_eq!(cur.read_dyn_u32(10).unwrap(), 93);
}
#[test]
fn test_bitpacking_reader_empty() {
let test_arr = &[0b11111100, 0b01001000, 0b11001110, 0b00000110];
let mut cur = BitpackCursor::new(test_arr);
assert_eq!(cur.read_dyn_u8(4).unwrap(), 12);
assert_eq!(cur.read_dyn_u8(0).unwrap(), 0);
assert_eq!(cur.read_dyn_u8(0).unwrap(), 0);
assert_eq!(cur.read_dyn_u8(3).unwrap(), 7);
assert_eq!(cur.read_dyn_u8(0).unwrap(), 0);
assert_eq!(cur.read_dyn_u16(7).unwrap(), 17);
assert_eq!(cur.read_dyn_u16(0).unwrap(), 0);
assert_eq!(cur.read_dyn_u16(0).unwrap(), 0);
assert_eq!(cur.read_dyn_u16(13).unwrap(), 6969);
assert_eq!(cur.read_dyn_u16(0).unwrap(), 0);
}
#[test]
fn test_bitpacking_reader_byte_aligned() {
let test_arr = &[0x00, 0x00, 0x00, 0x00, 0x01];
let mut cur = BitpackCursor::new(test_arr);
assert_eq!(cur.read_dyn_u32(32).unwrap(), 0);
assert_eq!(cur.read_dyn_u8(8).unwrap(), 1);
let test_arr = &[0x09, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01];
let mut cur = BitpackCursor::new(test_arr);
assert_eq!(cur.read_u1().unwrap(), 1);
assert_eq!(cur.read_u7().unwrap(), 4);
assert_eq!(cur.read_i8().unwrap(), 2);
assert_eq!(cur.read_u32().unwrap(), 0);
assert_eq!(cur.read_u8().unwrap(), 1);
}
#[test]
fn test_capture_pattern_nonaligned() {
let capture_pattern_arr = &[0x42, 0x43, 0x56];
let mut cur = BitpackCursor::new(capture_pattern_arr);
assert_eq!(cur.read_u24().unwrap(), 0x564342);
let test_arr = &[0x28, 0x81, 0xd0, 0x90, 0x55, 0x00, 0x00];
let mut cur = BitpackCursor::new(test_arr);
cur.read_u5().unwrap(); cur.read_u5().unwrap(); assert_eq!(cur.read_u4().unwrap(), 0);
assert_eq!(cur.read_u24().unwrap(), 0x564342);
assert_eq!(cur.read_u16().unwrap(), 1);
}