1
0
Fork 0
mirror of https://codeberg.org/icewind/bitbuffer.git synced 2026-06-04 00:54:07 +02:00

move bounds check to higher functions

This commit is contained in:
Robin Appelman 2019-03-03 02:16:03 +01:00
commit 589928921e

View file

@ -7,10 +7,10 @@ use std::ops::BitOrAssign;
use num_traits::{Float, PrimInt}; use num_traits::{Float, PrimInt};
use crate::{ReadError, Result};
use crate::endianness::Endianness; use crate::endianness::Endianness;
use crate::is_signed::IsSigned; use crate::is_signed::IsSigned;
use crate::unchecked_primitive::{UncheckedPrimitiveFloat, UncheckedPrimitiveInt}; use crate::unchecked_primitive::{UncheckedPrimitiveFloat, UncheckedPrimitiveInt};
use crate::{ReadError, Result};
const USIZE_SIZE: usize = size_of::<usize>(); const USIZE_SIZE: usize = size_of::<usize>();
@ -34,7 +34,7 @@ const USIZE_SIZE: usize = size_of::<usize>();
/// # } /// # }
/// ``` /// ```
pub struct BitBuffer<E> pub struct BitBuffer<E>
where where
E: Endianness, E: Endianness,
{ {
bytes: Vec<u8>, bytes: Vec<u8>,
@ -44,7 +44,7 @@ where
} }
impl<E> BitBuffer<E> impl<E> BitBuffer<E>
where where
E: Endianness, E: Endianness,
{ {
/// Create a new BitBuffer from a byte vector /// Create a new BitBuffer from a byte vector
@ -72,7 +72,7 @@ where
} }
impl<E> BitBuffer<E> impl<E> BitBuffer<E>
where where
E: Endianness, E: Endianness,
{ {
/// The available number of bits in the buffer /// The available number of bits in the buffer
@ -86,19 +86,6 @@ where
} }
fn read_usize(&self, position: usize, count: usize) -> Result<usize> { fn read_usize(&self, position: usize, count: usize) -> Result<usize> {
if position + count > self.bit_len {
if position > self.bit_len {
return Err(ReadError::IndexOutOfBounds {
pos: position,
size: self.bit_len,
});
} else {
return Err(ReadError::NotEnoughData {
requested: count,
bits_left: self.bit_len - position,
});
}
}
let byte_index = min(position / 8, self.byte_len - USIZE_SIZE); let byte_index = min(position / 8, self.byte_len - USIZE_SIZE);
let bit_offset = position - byte_index * 8; let bit_offset = position - byte_index * 8;
let raw_container: &usize = unsafe { let raw_container: &usize = unsafe {
@ -206,6 +193,20 @@ where
}); });
} }
if position + count > self.bit_len {
if position > self.bit_len {
return Err(ReadError::IndexOutOfBounds {
pos: position,
size: self.bit_len,
});
} else {
return Err(ReadError::NotEnoughData {
requested: count,
bits_left: self.bit_len - position,
});
}
}
let bit_offset = position & 7; let bit_offset = position & 7;
if size_of::<usize>() > size_of::<T>() || count + bit_offset < usize_bit_size { if size_of::<usize>() > size_of::<T>() || count + bit_offset < usize_bit_size {
let raw = self.read_usize(position, count)?; let raw = self.read_usize(position, count)?;
@ -280,6 +281,20 @@ where
/// ///
/// [`ReadError::NotEnoughData`]: enum.ReadError.html#variant.NotEnoughData /// [`ReadError::NotEnoughData`]: enum.ReadError.html#variant.NotEnoughData
pub fn read_bytes(&self, position: usize, byte_count: usize) -> Result<Vec<u8>> { pub fn read_bytes(&self, position: usize, byte_count: usize) -> Result<Vec<u8>> {
if position + byte_count * 8 > self.bit_len {
if position > self.bit_len {
return Err(ReadError::IndexOutOfBounds {
pos: position,
size: self.bit_len,
});
} else {
return Err(ReadError::NotEnoughData {
requested: byte_count * 8,
bits_left: self.bit_len - position,
});
}
}
let mut data = Vec::with_capacity(byte_count); let mut data = Vec::with_capacity(byte_count);
let mut byte_left = byte_count; let mut byte_left = byte_count;
let max_read = size_of::<usize>() - 1; let max_read = size_of::<usize>() - 1;
@ -403,6 +418,20 @@ where
where where
T: Float + UncheckedPrimitiveFloat, T: Float + UncheckedPrimitiveFloat,
{ {
if position + size_of::<T>() * 8 > self.bit_len {
if position > self.bit_len {
return Err(ReadError::IndexOutOfBounds {
pos: position,
size: self.bit_len,
});
} else {
return Err(ReadError::NotEnoughData {
requested: size_of::<T>() * 8,
bits_left: self.bit_len - position,
});
}
}
if size_of::<T>() == 4 { if size_of::<T>() == 4 {
let int = if size_of::<T>() < USIZE_SIZE { let int = if size_of::<T>() < USIZE_SIZE {
self.read_usize(position, 32)? as u32 self.read_usize(position, 32)? as u32