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:
parent
82f57e36c5
commit
4a8f0e1db6
2 changed files with 39 additions and 11 deletions
18
src/lib.rs
18
src/lib.rs
|
|
@ -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
|
||||||
|
|
|
||||||
32
src/tests.rs
32
src/tests.rs
|
|
@ -2,11 +2,11 @@ use std::fs;
|
||||||
use super::*;
|
use super::*;
|
||||||
use test::Bencher;
|
use test::Bencher;
|
||||||
|
|
||||||
const BYTES: &'static[u8] = &[
|
const BYTES: &'static [u8] = &[
|
||||||
0b1011_0101, 0b0110_1010, 0b1010_1100, 0b1001_1001,
|
0b1011_0101, 0b0110_1010, 0b1010_1100, 0b1001_1001,
|
||||||
0b1001_1001, 0b1001_1001, 0b1001_1001, 0b1110_0111,
|
0b1001_1001, 0b1001_1001, 0b1001_1001, 0b1110_0111,
|
||||||
0b1001_1001, 0b1001_1001, 0b1001_1001, 0b1110_0111,
|
0b1001_1001, 0b1001_1001, 0b1001_1001, 0b1110_0111,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0 ,0
|
0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||||
];
|
];
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue