mirror of
https://codeberg.org/icewind/bitbuffer.git
synced 2026-06-03 16:44:06 +02:00
read for NoZero ints
This commit is contained in:
parent
b723dee23b
commit
71823f22ec
6 changed files with 100 additions and 67 deletions
|
|
@ -8,10 +8,10 @@ use std::rc::Rc;
|
|||
|
||||
use num_traits::{Float, PrimInt};
|
||||
|
||||
use crate::{ReadError, Result};
|
||||
use crate::endianness::Endianness;
|
||||
use crate::is_signed::IsSigned;
|
||||
use crate::unchecked_primitive::{UncheckedPrimitiveFloat, UncheckedPrimitiveInt};
|
||||
use crate::{ReadError, Result};
|
||||
|
||||
const USIZE_SIZE: usize = size_of::<usize>();
|
||||
|
||||
|
|
@ -35,8 +35,8 @@ const USIZE_SIZE: usize = size_of::<usize>();
|
|||
/// # }
|
||||
/// ```
|
||||
pub struct BitBuffer<E>
|
||||
where
|
||||
E: Endianness,
|
||||
where
|
||||
E: Endianness,
|
||||
{
|
||||
bytes: Rc<Vec<u8>>,
|
||||
bit_len: usize,
|
||||
|
|
@ -46,8 +46,8 @@ pub struct BitBuffer<E>
|
|||
}
|
||||
|
||||
impl<E> BitBuffer<E>
|
||||
where
|
||||
E: Endianness,
|
||||
where
|
||||
E: Endianness,
|
||||
{
|
||||
/// Create a new BitBuffer from a byte vector
|
||||
///
|
||||
|
|
@ -75,8 +75,8 @@ impl<E> BitBuffer<E>
|
|||
}
|
||||
|
||||
impl<E> BitBuffer<E>
|
||||
where
|
||||
E: Endianness,
|
||||
where
|
||||
E: Endianness,
|
||||
{
|
||||
/// The available number of bits in the buffer
|
||||
pub fn bit_len(&self) -> usize {
|
||||
|
|
@ -147,9 +147,7 @@ impl<E> BitBuffer<E>
|
|||
});
|
||||
}
|
||||
|
||||
let byte = unsafe {
|
||||
self.bytes.get_unchecked(byte_index)
|
||||
};
|
||||
let byte = unsafe { self.bytes.get_unchecked(byte_index) };
|
||||
let shifted = byte >> bit_offset;
|
||||
Ok(shifted & 1u8 == 1)
|
||||
}
|
||||
|
|
@ -183,8 +181,8 @@ impl<E> BitBuffer<E>
|
|||
/// [`ReadError::TooManyBits`]: enum.ReadError.html#variant.TooManyBits
|
||||
#[inline]
|
||||
pub fn read_int<T>(&self, position: usize, count: usize) -> Result<T>
|
||||
where
|
||||
T: PrimInt + BitOrAssign + IsSigned + UncheckedPrimitiveInt,
|
||||
where
|
||||
T: PrimInt + BitOrAssign + IsSigned + UncheckedPrimitiveInt,
|
||||
{
|
||||
let type_bit_size = size_of::<T>() * 8;
|
||||
let usize_bit_size = size_of::<usize>() * 8;
|
||||
|
|
@ -228,8 +226,8 @@ impl<E> BitBuffer<E>
|
|||
|
||||
#[inline]
|
||||
fn read_fit_usize<T>(&self, position: usize, count: usize) -> T
|
||||
where
|
||||
T: PrimInt + BitOrAssign + IsSigned + UncheckedPrimitiveInt,
|
||||
where
|
||||
T: PrimInt + BitOrAssign + IsSigned + UncheckedPrimitiveInt,
|
||||
{
|
||||
let type_bit_size = size_of::<T>() * 8;
|
||||
let raw = self.read_usize(position, count);
|
||||
|
|
@ -242,8 +240,8 @@ impl<E> BitBuffer<E>
|
|||
}
|
||||
|
||||
fn read_no_fit_usize<T>(&self, position: usize, count: usize) -> T
|
||||
where
|
||||
T: PrimInt + BitOrAssign + IsSigned + UncheckedPrimitiveInt,
|
||||
where
|
||||
T: PrimInt + BitOrAssign + IsSigned + UncheckedPrimitiveInt,
|
||||
{
|
||||
let mut left_to_read = count;
|
||||
let mut acc = T::zero();
|
||||
|
|
@ -269,8 +267,8 @@ impl<E> BitBuffer<E>
|
|||
}
|
||||
|
||||
fn make_signed<T>(&self, value: T, count: usize) -> T
|
||||
where
|
||||
T: PrimInt + BitOrAssign + IsSigned + UncheckedPrimitiveInt,
|
||||
where
|
||||
T: PrimInt + BitOrAssign + IsSigned + UncheckedPrimitiveInt,
|
||||
{
|
||||
if T::is_signed() {
|
||||
let sign_bit = value >> (count - 1) & T::one();
|
||||
|
|
@ -400,9 +398,7 @@ impl<E> BitBuffer<E>
|
|||
Some(byte_len) => {
|
||||
let bytes = self.read_bytes(position, byte_len)?;
|
||||
let raw_string = if cfg!(feature = "unchecked_utf8") {
|
||||
unsafe {
|
||||
String::from_utf8_unchecked(bytes)
|
||||
}
|
||||
unsafe { String::from_utf8_unchecked(bytes) }
|
||||
} else {
|
||||
String::from_utf8(bytes)?
|
||||
};
|
||||
|
|
@ -411,9 +407,7 @@ impl<E> BitBuffer<E>
|
|||
None => {
|
||||
let bytes = self.read_string_bytes(position);
|
||||
if cfg!(feature = "unchecked_utf8") {
|
||||
unsafe {
|
||||
Ok(String::from_utf8_unchecked(bytes))
|
||||
}
|
||||
unsafe { Ok(String::from_utf8_unchecked(bytes)) }
|
||||
} else {
|
||||
String::from_utf8(bytes).map_err(ReadError::from)
|
||||
}
|
||||
|
|
@ -454,8 +448,8 @@ impl<E> BitBuffer<E>
|
|||
|
||||
#[cfg(feature = "simd")]
|
||||
fn read_string_bytes(&self, position: usize) -> Vec<u8> {
|
||||
use packed_simd::u8x16;
|
||||
use packed_simd::u128x1;
|
||||
use packed_simd::u8x16;
|
||||
use packed_simd::IntoBits;
|
||||
|
||||
let bit_index = position & 7;
|
||||
|
|
@ -465,7 +459,8 @@ impl<E> BitBuffer<E>
|
|||
let bit_index_simd = u128x1::new(bit_index as u128);
|
||||
|
||||
loop {
|
||||
let raw_value: u128x1 = u8x16::from_slice_unaligned(&self.bytes[byte_index..byte_index + 16]).into_bits();
|
||||
let raw_value: u128x1 =
|
||||
u8x16::from_slice_unaligned(&self.bytes[byte_index..byte_index + 16]).into_bits();
|
||||
let shifted = raw_value.rotate_right(bit_index_simd);
|
||||
let input_bytes: u8x16 = shifted.into_bits();
|
||||
let has_zero = ZEROS.eq(input_bytes).any();
|
||||
|
|
@ -513,8 +508,8 @@ impl<E> BitBuffer<E>
|
|||
///
|
||||
/// [`ReadError::NotEnoughData`]: enum.ReadError.html#variant.NotEnoughData
|
||||
pub fn read_float<T>(&self, position: usize) -> Result<T>
|
||||
where
|
||||
T: Float + UncheckedPrimitiveFloat,
|
||||
where
|
||||
T: Float + UncheckedPrimitiveFloat,
|
||||
{
|
||||
let type_bit_size = size_of::<T>() * 8;
|
||||
if position + type_bit_size > self.bit_len {
|
||||
|
|
|
|||
|
|
@ -62,7 +62,9 @@ pub use std::string::FromUtf8Error;
|
|||
pub use bitstream_reader_derive::{BitRead, BitReadSized, BitSize, BitSizeSized};
|
||||
pub use buffer::BitBuffer;
|
||||
pub use endianness::*;
|
||||
pub use read::{BitRead, BitReadSized, BitSize, BitSizeSized, LazyBitRead, LazyBitReadSized, BitSkip};
|
||||
pub use read::{
|
||||
BitRead, BitReadSized, BitSize, BitSizeSized, BitSkip, LazyBitRead, LazyBitReadSized,
|
||||
};
|
||||
pub use stream::BitStream;
|
||||
|
||||
mod buffer;
|
||||
|
|
|
|||
59
src/read.rs
59
src/read.rs
|
|
@ -1,8 +1,10 @@
|
|||
use crate::endianness::{BigEndian, LittleEndian};
|
||||
use crate::{BitStream, Endianness, Result};
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
use std::hash::Hash;
|
||||
use std::marker::PhantomData;
|
||||
use std::mem::size_of;
|
||||
|
||||
/// Trait for types that can be read from a stream without requiring the size to be configured
|
||||
///
|
||||
|
|
@ -112,33 +114,64 @@ impl<T: BitRead<E> + BitSize, E: Endianness> BitSkip<E> for T {
|
|||
}
|
||||
|
||||
macro_rules! impl_read_int {
|
||||
($type:ty, $len:expr) => {
|
||||
($type:ty) => {
|
||||
impl<E: Endianness> BitRead<E> for $type {
|
||||
#[inline]
|
||||
fn read(stream: &mut BitStream<E>) -> Result<$type> {
|
||||
stream.read_int::<$type>($len)
|
||||
stream.read_int::<$type>(size_of::<$type>() * 8)
|
||||
}
|
||||
}
|
||||
|
||||
impl BitSize for $type {
|
||||
#[inline]
|
||||
fn bit_size() -> usize {
|
||||
$len
|
||||
size_of::<$type>() * 8
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl_read_int!(u8, 8);
|
||||
impl_read_int!(u16, 16);
|
||||
impl_read_int!(u32, 32);
|
||||
impl_read_int!(u64, 64);
|
||||
impl_read_int!(u128, 128);
|
||||
impl_read_int!(i8, 8);
|
||||
impl_read_int!(i16, 16);
|
||||
impl_read_int!(i32, 32);
|
||||
impl_read_int!(i64, 64);
|
||||
impl_read_int!(i128, 128);
|
||||
macro_rules! impl_read_int_nonzero {
|
||||
($type:ty) => {
|
||||
impl BitRead<LittleEndian> for Option<$type> {
|
||||
#[inline]
|
||||
fn read(stream: &mut BitStream<LittleEndian>) -> Result<Self> {
|
||||
Ok(<$type>::new(stream.read()?))
|
||||
}
|
||||
}
|
||||
|
||||
impl BitRead<BigEndian> for Option<$type> {
|
||||
#[inline]
|
||||
fn read(stream: &mut BitStream<BigEndian>) -> Result<Self> {
|
||||
Ok(<$type>::new(stream.read()?))
|
||||
}
|
||||
}
|
||||
|
||||
impl BitSize for $type {
|
||||
#[inline]
|
||||
fn bit_size() -> usize {
|
||||
size_of::<$type>() * 8
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl_read_int!(u8);
|
||||
impl_read_int!(u16);
|
||||
impl_read_int!(u32);
|
||||
impl_read_int!(u64);
|
||||
impl_read_int!(u128);
|
||||
impl_read_int!(i8);
|
||||
impl_read_int!(i16);
|
||||
impl_read_int!(i32);
|
||||
impl_read_int!(i64);
|
||||
impl_read_int!(i128);
|
||||
|
||||
impl_read_int_nonzero!(std::num::NonZeroU8);
|
||||
impl_read_int_nonzero!(std::num::NonZeroU16);
|
||||
impl_read_int_nonzero!(std::num::NonZeroU32);
|
||||
impl_read_int_nonzero!(std::num::NonZeroU64);
|
||||
impl_read_int_nonzero!(std::num::NonZeroU128);
|
||||
|
||||
impl<E: Endianness> BitRead<E> for f32 {
|
||||
#[inline]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue