From 49b4b56aeae9f870f1093b1c3d24419bec717707 Mon Sep 17 00:00:00 2001 From: Marrub Date: Tue, 12 Mar 2019 02:28:51 -0400 Subject: [PATCH] fix read_bits API (bits should come right to left) --- source/durandal/bin.rs | 3 +- source/durandal/bit.rs | 182 +++++++++++++++++++++-------------------- 2 files changed, 95 insertions(+), 90 deletions(-) diff --git a/source/durandal/bin.rs b/source/durandal/bin.rs index 6a12bc4..e8cc534 100644 --- a/source/durandal/bin.rs +++ b/source/durandal/bin.rs @@ -351,8 +351,7 @@ pub fn rd_array_num(b: &[u8], n: usize, read: F) /// /// # Panics /// -/// A panic will occur if the `read` function returns a disjoint index or -/// otherwise panics (by an out of bounds index to `b` or otherwise.) +/// A panic will occur if the `read` function panics. /// /// # Errors /// diff --git a/source/durandal/bit.rs b/source/durandal/bit.rs index a23289d..f20b64d 100644 --- a/source/durandal/bit.rs +++ b/source/durandal/bit.rs @@ -7,53 +7,57 @@ use crate::durandal::err::*; /// /// # Errors /// -/// The function will return an error if `width` is 0 or more than 64, or if +/// The function will return an error if `width` is more than 64, or if /// `(cr_bit + width - 1) / 8` would overflow an index into `b`. -pub fn read_bits_b(b: &[u8], cr_bit: usize, width: u8) -> ResultS<(usize, u64)> +pub fn read_bits_b(b: &[u8], cr_bit: usize, width: u8) -> ResultS { - if width < 1 || width > 64 { + if width == 0 { + return Ok(0); + } + + if width > 64 { bail!("invalid number of bits"); } - let nx_bit = cr_bit + usize::from(width); - let ed_bit = nx_bit - 1; + let last = (cr_bit + usize::from(width) - 1) / 8; - 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)) + if last >= b.len() { + bail!("not enough data"); } + + let mut byte_ptr = cr_bit / 8; + let mut bits_ptr = cr_bit % 8; + + let mut res = 0; + + for _ in 0..width { + res <<= 1; + + if b[byte_ptr] & (1 << bits_ptr) != 0 { + res |= 1; + } + + bits_ptr += 1; + + if bits_ptr > 7 { + bits_ptr = 0; + byte_ptr += 1; + } + } + + Ok(res) } /// The same as `read_bits_b`, but least-significant bit first. -pub fn read_bits_l(b: &[u8], cr_bit: usize, width: u8) -> ResultS<(usize, u64)> +pub fn read_bits_l(b: &[u8], cr_bit: usize, width: u8) -> ResultS { - let (nx_bit, res) = read_bits_b(b, cr_bit, width)?; + if width == 0 { + Ok(0) + } else { + let res = read_bits_b(b, cr_bit, width)?; - Ok((nx_bit, reverse_bits(res) >> (64 - width))) + Ok(reverse_bits(res) >> (64 - width)) + } } fn reverse_bits(v: u64) -> u64 @@ -65,56 +69,48 @@ fn reverse_bits(v: u64) -> u64 v.swap_bytes() } -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]; + const INPUT: &[u8] = &[0b01100101, 0b10101010, 0b00010000, 0b00000000, + 0b11111111, 0b11100001, 0b10101100, 0b00110011, + 0b10100101, 0b11100000, 0b00000111, 0b00000001, + 0b11001010, 0b10101111, 0b00101011, 0b01101010, + 0b11010101, 0b10100011, 0b01010101, 0b11000001]; - let (p, n) = read_bits_b(INPUT, 0, 3).unwrap(); - assert_eq!(n, 0b011); + let mut p = 0; - let (p, n) = read_bits_b(INPUT, p, 63).unwrap(); - assert_eq!(n, 0b001011010101000010000000000001111111111100001101011000011001110); + let n = read_bits_b(INPUT, p, 3).unwrap(); + assert_eq!(n, 0b101); + p += 3; - let (p, n) = read_bits_b(INPUT, p, 4).unwrap(); + let n = read_bits_b(INPUT, p, 63).unwrap(); + assert_eq!(n, 0b001100101010100001000000000001111111110000111001101011100110010); + p += 63; + + let n = read_bits_b(INPUT, p, 4).unwrap(); assert_eq!(n, 0b1001); + p += 4; - let (p, n) = read_bits_b(INPUT, p, 7).unwrap(); - assert_eq!(n, 0b0111100); + let n = read_bits_b(INPUT, p, 7).unwrap(); + assert_eq!(n, 0b0100000); + p += 7; - let (p, n) = read_bits_b(INPUT, p, 17).unwrap(); - assert_eq!(n, 0b00000000111000000); + let n = read_bits_b(INPUT, p, 17).unwrap(); + assert_eq!(n, 0b11111100000100000); + p += 17; - let (p, n) = read_bits_b(INPUT, p, 27).unwrap(); - assert_eq!(n, 0b011100101010101111001010110); + let n = read_bits_b(INPUT, p, 27).unwrap(); + assert_eq!(n, 0b000101001111110101110101000); + p += 27; - let (p, n) = read_bits_b(INPUT, p, 33).unwrap(); - assert_eq!(n, 0b110101011010101101000110101010111); + let n = read_bits_b(INPUT, p, 33).unwrap(); + assert_eq!(n, 0b101011010101011110001011010101010); + p += 33; - let (p, n) = read_bits_b(INPUT, p, 6).unwrap(); - assert_eq!(n, 0b000001); + let n = read_bits_b(INPUT, p, 6).unwrap(); + assert_eq!(n, 0b000011); + p += 6; let e = read_bits_b(INPUT, p, 1); assert!(if let Err(_) = e {true} else {false}); @@ -122,29 +118,39 @@ fn bit_tests() let e = read_bits_b(INPUT, p, 2); assert!(if let Err(_) = e {true} else {false}); - let (p, n) = read_bits_l(INPUT, 0, 3).unwrap(); - assert_eq!(n, 0b110); + let mut p = 0; - let (p, n) = read_bits_l(INPUT, p, 63).unwrap(); - assert_eq!(n, 0b011100110000110101100001111111111100000000000010000101010110100); + let n = read_bits_l(INPUT, 0, 3).unwrap(); + assert_eq!(n, 0b101); + p += 3; - let (p, n) = read_bits_l(INPUT, p, 4).unwrap(); + let n = read_bits_l(INPUT, p, 63).unwrap(); + assert_eq!(n, 0b010011001110101100111000011111111100000000000100001010101001100); + p += 63; + + let n = read_bits_l(INPUT, p, 4).unwrap(); assert_eq!(n, 0b1001); + p += 4; - let (p, n) = read_bits_l(INPUT, p, 7).unwrap(); - assert_eq!(n, 0b0011110); + let n = read_bits_l(INPUT, p, 7).unwrap(); + assert_eq!(n, 0b0000010); + p += 7; - let (p, n) = read_bits_l(INPUT, p, 17).unwrap(); - assert_eq!(n, 0b00000011100000000); + let n = read_bits_l(INPUT, p, 17).unwrap(); + assert_eq!(n, 0b00000100000111111); + p += 17; - let (p, n) = read_bits_l(INPUT, p, 27).unwrap(); - assert_eq!(n, 0b011010100111101010101001110); + let n = read_bits_l(INPUT, p, 27).unwrap(); + assert_eq!(n, 0b000101011101011111100101000); + p += 27; - let (p, n) = read_bits_l(INPUT, p, 33).unwrap(); - assert_eq!(n, 0b111010101011000101101010110101011); + let n = read_bits_l(INPUT, p, 33).unwrap(); + assert_eq!(n, 0b010101010110100011110101010110101); + p += 33; - let (p, n) = read_bits_l(INPUT, p, 6).unwrap(); - assert_eq!(n, 0b100000); + let n = read_bits_l(INPUT, p, 6).unwrap(); + assert_eq!(n, 0b110000); + p += 6; let e = read_bits_l(INPUT, p, 1); assert!(if let Err(_) = e {true} else {false});