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

unchecked api

This commit is contained in:
Robin Appelman 2020-01-07 19:19:01 +01:00
commit 92d23dc14f
2 changed files with 73 additions and 18 deletions

View file

@ -172,6 +172,15 @@ where
}) })
} }
pub unsafe fn read_bool_unchecked(&self, position: usize) -> bool {
let byte_index = position / 8;
let bit_offset = position & 7;
let byte = self.bytes.get_unchecked(byte_index);
let shifted = byte >> bit_offset;
shifted & 1u8 == 1
}
/// Read a sequence of bits from the buffer as integer /// Read a sequence of bits from the buffer as integer
/// ///
/// # Errors /// # Errors
@ -205,7 +214,6 @@ where
T: PrimInt + BitOrAssign + IsSigned + UncheckedPrimitiveInt + BitXor, T: PrimInt + BitOrAssign + IsSigned + UncheckedPrimitiveInt + BitXor,
{ {
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 {
@ -215,19 +223,30 @@ where
} }
if position + count > self.bit_len() { if position + count > self.bit_len() {
if position > self.bit_len() { return if position > self.bit_len() {
return Err(ReadError::IndexOutOfBounds { Err(ReadError::IndexOutOfBounds {
pos: position, pos: position,
size: self.bit_len(), size: self.bit_len(),
}); })
} else { } else {
return Err(ReadError::NotEnoughData { Err(ReadError::NotEnoughData {
requested: count, requested: count,
bits_left: self.bit_len() - position, bits_left: self.bit_len() - position,
}); })
} };
} }
Ok(unsafe { self.read_int_unchecked(position, count) })
}
#[inline]
pub unsafe fn read_int_unchecked<T>(&self, position: usize, count: usize) -> T
where
T: PrimInt + BitOrAssign + IsSigned + UncheckedPrimitiveInt + BitXor,
{
let type_bit_size = size_of::<T>() * 8;
let usize_bit_size = size_of::<usize>() * 8;
let bit_offset = position & 7; let bit_offset = position & 7;
let fit_usize = count + bit_offset < usize_bit_size; let fit_usize = count + bit_offset < usize_bit_size;
@ -238,9 +257,9 @@ where
}; };
if count == type_bit_size { if count == type_bit_size {
Ok(value) value
} else { } else {
Ok(self.make_signed(value, count)) self.make_signed(value, count)
} }
} }
@ -340,11 +359,16 @@ where
} }
} }
Ok(unsafe { self.read_bytes_unchecked(position, byte_count) })
}
#[inline]
pub unsafe fn read_bytes_unchecked(&self, position: usize, byte_count: usize) -> Vec<u8> {
let shift = position & 7; let shift = position & 7;
if shift == 0 { if shift == 0 {
let byte_pos = position / 8; let byte_pos = position / 8;
return Ok(self.bytes[byte_pos..byte_pos + byte_count].to_vec()); return self.bytes[byte_pos..byte_pos + byte_count].to_vec();
} }
let mut data = Vec::with_capacity(byte_count); let mut data = Vec::with_capacity(byte_count);
@ -364,7 +388,7 @@ where
let usable_bytes = &bytes[0..byte_left]; let usable_bytes = &bytes[0..byte_left];
data.extend_from_slice(usable_bytes); data.extend_from_slice(usable_bytes);
Ok(data) data
} }
/// Read a series of bytes from the buffer as string /// Read a series of bytes from the buffer as string
@ -503,16 +527,23 @@ where
} }
} }
Ok(unsafe { self.read_float_unchecked(position) })
}
pub unsafe fn read_float_unchecked<T>(&self, position: usize) -> T
where
T: Float + UncheckedPrimitiveFloat,
{
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_fit_usize::<u32>(position, 32) self.read_fit_usize::<u32>(position, 32)
} else { } else {
self.read_no_fit_usize::<u32>(position, 32) self.read_no_fit_usize::<u32>(position, 32)
}; };
Ok(T::from_f32_unchecked(f32::from_bits(int))) T::from_f32_unchecked(f32::from_bits(int))
} else { } else {
let int = self.read_no_fit_usize::<u64>(position, 64); let int = self.read_no_fit_usize::<u64>(position, 64);
Ok(T::from_f64_unchecked(f64::from_bits(int))) T::from_f64_unchecked(f64::from_bits(int))
} }
} }

View file

@ -133,11 +133,19 @@ where
where where
T: PrimInt + BitOrAssign + IsSigned + UncheckedPrimitiveInt, T: PrimInt + BitOrAssign + IsSigned + UncheckedPrimitiveInt,
{ {
let result = self.buffer.read_int(self.pos, count); self.pos += count;
if result.is_ok() {
self.pos += count; self.buffer.read_int(self.pos, count)
} }
result
#[inline]
pub unsafe fn read_int_unchecked<T>(&mut self, count: usize) -> T
where
T: PrimInt + BitOrAssign + IsSigned + UncheckedPrimitiveInt,
{
self.pos += count;
self.buffer.read_int_unchecked(self.pos, count)
} }
/// Read a sequence of bits from the stream as float /// Read a sequence of bits from the stream as float
@ -179,6 +187,16 @@ where
result result
} }
pub unsafe fn read_float_unchecked<T>(&mut self) -> T
where
T: Float + UncheckedPrimitiveFloat,
{
let count = size_of::<T>() * 8;
self.pos += count;
self.buffer.read_float_unchecked(self.pos)
}
/// Read a series of bytes from the stream /// Read a series of bytes from the stream
/// ///
/// # Errors /// # Errors
@ -215,6 +233,12 @@ where
result result
} }
pub unsafe fn read_bytes_unchecked(&mut self, byte_count: usize) -> Vec<u8> {
let count = byte_count * 8;
self.pos += count;
self.buffer.read_bytes_unchecked(self.pos, byte_count)
}
/// Read a series of bytes from the stream as utf8 string /// Read a series of bytes from the stream as utf8 string
/// ///
/// You can either read a fixed number of bytes, or a dynamic length null-terminated string /// You can either read a fixed number of bytes, or a dynamic length null-terminated string