mirror of
https://codeberg.org/icewind/bitbuffer.git
synced 2026-06-03 16:44:06 +02:00
unchecked api
This commit is contained in:
parent
f59dd94917
commit
92d23dc14f
2 changed files with 73 additions and 18 deletions
|
|
@ -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))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
|
||||||
if result.is_ok() {
|
|
||||||
self.pos += count;
|
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
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue