//! Bit streams. use crate::durandal::err::*; /// Reads `width` bits from `b` starting at bit `cr_bit` into an integer. /// /// # Errors /// /// The function will return an error if `width` is 0 or more than 64, or if /// `(cr_bit + width - 1) / 8` would overflow an index into `b`. pub fn read_bits(b: &[u8], cr_bit: usize, width: u8) -> ResultS<(usize, u64)> { if width < 1 || width > 64 { bail!("invalid number of bits"); } let nx_bit = cr_bit + usize::from(width); let ed_bit = nx_bit - 1; let cr_byte = cr_bit / 8; let ed_byte = ed_bit / 8; check_data!(ed_byte + 1, b); let cr_bits = cr_bit as u32 % 8; let nx_bits = nx_bit as u32 % 8; let nx_mask = ((1_u128 << nx_bits) - 1) as u64; let num_bytes = ed_byte - cr_byte; let bytes = get_bytes(b, num_bytes, cr_byte); let bits = u64::from_be_bytes(bytes); let bits = bits.wrapping_shl(cr_bits); let bits = bits >> (64 - width); // special case for over byte boundary if num_bytes == 8 { let lbyt = u64::from(b[ed_byte]); let lbyt = lbyt >> (8 - nx_bits); let lbyt = lbyt & nx_mask; Ok((nx_bit, bits & !nx_mask | lbyt)) } else { Ok((nx_bit, bits)) } } fn get_bytes(b: &[u8], num_bytes: usize, f: usize) -> [u8; 8] { match num_bytes { 8 | 7 => [b[f], b[f+1], b[f+2], b[f+3], b[f+4], b[f+5], b[f+6], b[f+7]], 6 => [b[f], b[f+1], b[f+2], b[f+3], b[f+4], b[f+5], b[f+6], 0], 5 => [b[f], b[f+1], b[f+2], b[f+3], b[f+4], b[f+5], 0, 0], 4 => [b[f], b[f+1], b[f+2], b[f+3], b[f+4], 0, 0, 0], 3 => [b[f], b[f+1], b[f+2], b[f+3], 0, 0, 0, 0], 2 => [b[f], b[f+1], b[f+2], 0, 0, 0, 0, 0], 1 => [b[f], b[f+1], 0, 0, 0, 0, 0, 0], 0 => [b[f], 0, 0, 0, 0, 0, 0, 0], _ => panic!("invalid number of bytes to read ({})", num_bytes), } } #[test] fn bit_tests() { const INPUT: &[u8] = &[0b011_00101, 0b10101010, 0b00010000, 0b00000000, 0b11111111, 0b11100001, 0b10101100, 0b00110011, 0b10_1001_01, 0b11100_000, 0b00000111, 0b000000_01, 0b11001010, 0b10101111, 0b00101011, 0b0_1101010, 0b11010101, 0b10100011, 0b01010101, 0b11_000001]; let (p, n) = read_bits(INPUT, 0, 3).unwrap(); assert_eq!(n, 0b011); let (p, n) = read_bits(INPUT, p, 63).unwrap(); assert_eq!(n, 0x16A8_4003_FF86_B0CE); let (p, n) = read_bits(INPUT, p, 4).unwrap(); assert_eq!(n, 0b1001); let (p, n) = read_bits(INPUT, p, 7).unwrap(); assert_eq!(n, 0b0111100); let (p, n) = read_bits(INPUT, p, 17).unwrap(); assert_eq!(n, 0b00000000111000000); let (p, n) = read_bits(INPUT, p, 27).unwrap(); assert_eq!(n, 0b011100101010101111001010110); let (p, n) = read_bits(INPUT, p, 33).unwrap(); assert_eq!(n, 0b110101011010101101000110101010111); let (p, n) = read_bits(INPUT, p, 6).unwrap(); assert_eq!(n, 1); let e = read_bits(INPUT, p, 1); assert!(if let Err(_) = e {true} else {false}); let e = read_bits(INPUT, p, 2); assert!(if let Err(_) = e {true} else {false}); } // EOF