X-Git-Url: https://git.nihav.org/?a=blobdiff_plain;f=src%2Fio%2Fbitreader.rs;h=20753d1561263e788a8d21d6815280c184dc979b;hb=8ab3904ca48416131be683834f232175b8c76db5;hp=9c702ff62f975b78c559c22148799cd2871f20bf;hpb=90aa4e6be97ce0849901ce188b30773b2d6662ff;p=nihav.git diff --git a/src/io/bitreader.rs b/src/io/bitreader.rs index 9c702ff..20753d1 100644 --- a/src/io/bitreader.rs +++ b/src/io/bitreader.rs @@ -1,19 +1,21 @@ #[derive(Debug)] pub enum BitReaderMode { BE, - LE16, - LE32, + LE, + LE16MSB, + LE32MSB, } #[derive(Debug)] pub enum BitReaderError { BitstreamEnd, TooManyBitsRequested, + InvalidValue, } use self::BitReaderError::*; -type BitReaderResult = Result; +pub type BitReaderResult = Result; #[derive(Debug)] pub struct BitReader<'a> { @@ -48,21 +50,24 @@ impl<'a> BitReader<'a> { self.cache |= nw << (32 - self.bits); } - fn fill32le16(&mut self, src: &[u8], realbits: u8) { + fn fill32le16(&mut self, src: &[u8]) { let mut nw = (((src[1] as u32) << 24) | ((src[0] as u32) << 16) | ((src[3] as u32) << 8) | ((src[2] as u32) << 0)) as u64; - if realbits <= 16 { nw >>= 16; } - self.cache |= nw << self.bits; + self.cache |= nw << (32 - self.bits); } - fn fill32le32(&mut self, src: &[u8]) { + fn fill32le32(&mut self, src: &[u8], lsb: bool) { let nw = (((src[3] as u32) << 24) | ((src[2] as u32) << 16) | ((src[1] as u32) << 8) | ((src[0] as u32) << 0)) as u64; - self.cache |= nw << self.bits; + if lsb { + self.cache |= nw << self.bits; + } else { + self.cache |= nw << (32 - self.bits); + } } fn refill(&mut self) -> BitReaderResult<()> { @@ -71,9 +76,10 @@ impl<'a> BitReader<'a> { if self.pos + 4 <= self.end { let buf = &self.src[self.pos..]; match self.mode { - BitReaderMode::BE => self.fill32be (buf), - BitReaderMode::LE16 => self.fill32le16(buf, 32), - BitReaderMode::LE32 => self.fill32le32(buf), + BitReaderMode::BE => self.fill32be (buf), + BitReaderMode::LE16MSB => self.fill32le16(buf), + BitReaderMode::LE => self.fill32le32(buf, true), + BitReaderMode::LE32MSB => self.fill32le32(buf, false), } self.pos += 4; self.bits += 32; @@ -89,9 +95,10 @@ impl<'a> BitReader<'a> { } if newbits == 0 { break; } match self.mode { - BitReaderMode::BE => self.fill32be (&buf), - BitReaderMode::LE16 => self.fill32le16(&buf, newbits), - BitReaderMode::LE32 => self.fill32le32(&buf), + BitReaderMode::BE => self.fill32be (&buf), + BitReaderMode::LE16MSB => self.fill32le16(&buf), + BitReaderMode::LE => self.fill32le32(&buf, true), + BitReaderMode::LE32MSB => self.fill32le32(&buf, false), } self.bits += newbits; } @@ -101,16 +108,24 @@ impl<'a> BitReader<'a> { fn read_cache(&mut self, nbits: u8) -> u32 { let res = match self.mode { - BitReaderMode::BE => (self.cache as u64) >> (64 - nbits), - _ => ((1u64 << nbits) - 1) & self.cache, + BitReaderMode::LE => ((1u64 << nbits) - 1) & self.cache, + _ => (self.cache as u64) >> (64 - nbits), }; res as u32 } + fn read_cache_s(&mut self, nbits: u8) -> i32 { + let res = match self.mode { + BitReaderMode::LE => ((self.cache as i64) << (64 - nbits)) >> (64 - nbits), + _ => (self.cache as i64) >> (64 - nbits), + }; + res as i32 + } + fn skip_cache(&mut self, nbits: u8) { match self.mode { - BitReaderMode::BE => self.cache <<= nbits, - _ => self.cache >>= nbits, + BitReaderMode::LE => self.cache >>= nbits, + _ => self.cache <<= nbits, }; self.bits -= nbits; } @@ -121,6 +136,7 @@ impl<'a> BitReader<'a> { } pub fn read(&mut self, nbits: u8) -> BitReaderResult { + if nbits == 0 { return Ok(0) } if nbits > 32 { return Err(TooManyBitsRequested) } if self.bits < nbits { if let Err(err) = self.refill() { return Err(err) } @@ -128,7 +144,28 @@ impl<'a> BitReader<'a> { } let res = self.read_cache(nbits); self.skip_cache(nbits); - Ok(res as u32) + Ok(res) + } + + pub fn read_s(&mut self, nbits: u8) -> BitReaderResult { + if nbits == 0 || nbits > 32 { return Err(TooManyBitsRequested) } + if self.bits < nbits { + if let Err(err) = self.refill() { return Err(err) } + if self.bits < nbits { return Err(BitstreamEnd) } + } + let res = self.read_cache_s(nbits); + self.skip_cache(nbits); + Ok(res) + } + + pub fn read_bool(&mut self) -> BitReaderResult { + if self.bits < 1 { + if let Err(err) = self.refill() { return Err(err) } + if self.bits < 1 { return Err(BitstreamEnd) } + } + let res = self.read_cache(1); + self.skip_cache(1); + Ok(res == 1) } pub fn peek(&mut self, nbits: u8) -> u32 { @@ -169,10 +206,14 @@ mod test { fn br_works() { const DATA: [u8; 18] = [0b00011011; 18]; let src = &DATA; - let mut br = BitReader::new(src, src.len(), BitReaderMode::LE16); + let mut br = BitReader::new(src, src.len(), BitReaderMode::LE16MSB); for _ in 0..8 { assert_eq!(br.read(16).unwrap(), 0x1B1B); } + const DATA2: [u8; 1] = [ 0b00011011 ]; + let src = &DATA2; + let mut br = BitReader::new(src, src.len(), BitReaderMode::LE); + assert_eq!(br.read_s(5).unwrap(), -5); } }