1
0
Fork 0
mirror of https://codeberg.org/icewind/bitbuffer.git synced 2026-06-03 16:44:06 +02:00

fix reads that dont fit in usize

This commit is contained in:
Robin Appelman 2019-02-17 13:57:59 +01:00
commit 4a8f0e1db6
2 changed files with 39 additions and 11 deletions

View file

@ -49,7 +49,7 @@ macro_rules! array_ref {
}} }}
} }
const USIZE_SIZE: usize = std::mem::size_of::<usize>(); const USIZE_SIZE: usize = size_of::<usize>();
impl<'a> BitBuffer<'a> { impl<'a> BitBuffer<'a> {
pub fn from_padded_slice(bytes: &'a [u8], byte_len: usize) -> BitBuffer<'a> { pub fn from_padded_slice(bytes: &'a [u8], byte_len: usize) -> BitBuffer<'a> {
@ -109,15 +109,16 @@ impl<'a> BitBuffer<'a> {
{ {
let value = { let value = {
let type_bit_size = size_of::<T>() * 8; let type_bit_size = size_of::<T>() * 8;
let usize_bit_size = size_of::<usize>() * 8;
if type_bit_size < count { if type_bit_size < count {
return Err(ReadError::TooManyBits { return Err(ReadError::TooManyBits {
requested: count, requested: count,
max: size_of::<T>() * 8, max: type_bit_size,
}); });
} }
if size_of::<usize>() > size_of::<T>() || (count / 8) < size_of::<usize>() { if size_of::<usize>() > size_of::<T>() || count < usize_bit_size - 8 {
let raw = self.read_usize(position, count)?; let raw = self.read_usize(position, count)?;
let max_signed_value = (1 << (type_bit_size - 1)) - 1; let max_signed_value = (1 << (type_bit_size - 1)) - 1;
if T::is_signed() && raw > max_signed_value { if T::is_signed() && raw > max_signed_value {
@ -126,17 +127,18 @@ impl<'a> BitBuffer<'a> {
T::from(raw).unwrap() T::from(raw).unwrap()
} }
} else { } else {
let mut bits_left = count; let mut left_to_read = count;
let mut partial = T::zero(); let mut partial = T::zero();
let max_read = size_of::<usize>() - 1 * 8; let max_read = (size_of::<usize>() - 1) * 8;
let mut read_pos = position; let mut read_pos = position;
let mut bit_offset = 0; let mut bit_offset = 0;
while bits_left > 0 { while left_to_read > 0 {
let read = min(min(bits_left, max_read), self.bit_len - read_pos); let bits_left = self.bit_len - read_pos;
let read = min(min(left_to_read, max_read), bits_left);
partial |= T::from(self.read_usize(read_pos, read)?).unwrap() << bit_offset; partial |= T::from(self.read_usize(read_pos, read)?).unwrap() << bit_offset;
bit_offset += read; bit_offset += read;
read_pos += read; read_pos += read;
bits_left -= read; left_to_read -= read;
} }
partial partial

View file

@ -40,7 +40,8 @@ fn read_u64() {
let buffer = BitBuffer::from_padded_slice(BYTES, 12); let buffer = BitBuffer::from_padded_slice(BYTES, 12);
assert_eq!(buffer.read::<u64>(6, 34).unwrap(), 0b1001_1001_1001_1001_1010_1100_0110_1010_10); assert_eq!(buffer.read::<u64>(6, 34).unwrap(), 0b1001_1001_1001_1001_1010_1100_0110_1010_10);
assert_eq!(buffer.read::<u64>(6, 60).unwrap(), 0b00_1110_01111001_1001_1001_1001_1001_1001_1001_1001_1010_1100_0110_1010_10); assert_eq!(buffer.read::<u64>(6, 60).unwrap(), 0b01_1110_0111_1001_1001_1001_1001_1001_1001_1001_1001_1010_1100_0110_1010_10);
assert_eq!(buffer.read::<u64>(6, 64).unwrap(), 0b01_1001_1110_0111_1001_1001_1001_1001_1001_1001_1001_1001_1010_1100_0110_1010_10);
} }
#[test] #[test]
@ -51,6 +52,31 @@ fn read_i8() {
assert_eq!(buffer.read::<i8>(0, 8).unwrap(), -0b011_0101); assert_eq!(buffer.read::<i8>(0, 8).unwrap(), -0b011_0101);
} }
#[test]
fn read_i16() {
let buffer = BitBuffer::from_padded_slice(BYTES, 12);
assert_eq!(buffer.read::<i16>(6, 12).unwrap(), 0b0_0110_1010_10);
assert_eq!(buffer.read::<i16>(6, 13).unwrap(), -0b00_0110_1010_10);
}
#[test]
fn read_i32() {
let buffer = BitBuffer::from_padded_slice(BYTES, 12);
assert_eq!(buffer.read::<i32>(6, 24).unwrap(), 0b1_1001_1010_1100_0110_1010_10);
assert_eq!(buffer.read::<i32>(6, 26).unwrap(), -0b001_1001_1010_1100_0110_1010_10);
}
#[test]
fn read_i64() {
let buffer = BitBuffer::from_padded_slice(BYTES, 12);
assert_eq!(buffer.read::<i64>(6, 34).unwrap(), -0b001_1001_1001_1001_1010_1100_0110_1010_10);
assert_eq!(buffer.read::<i64>(6, 59).unwrap(), -0b1110_01111001_1001_1001_1001_1001_1001_1001_1001_1010_1100_0110_1010_10);
assert_eq!(buffer.read::<i64>(1, 64).unwrap(), -0b1110_01111001_1001_1001_1001_1001_1001_1001_1001_1010_1100_0110_1010_1011_010);
}
fn read_perf(buffer: BitBuffer) -> u16 { fn read_perf(buffer: BitBuffer) -> u16 {
let size = 5; let size = 5;
let mut pos = 0; let mut pos = 0;