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

add traits for determining the number of bits required to read a type

This commit is contained in:
Robin Appelman 2019-03-03 16:46:47 +01:00
commit fe95592d57

View file

@ -87,6 +87,12 @@ pub trait BitRead<E: Endianness>: Sized {
fn read(stream: &mut BitStream<E>) -> Result<Self>;
}
/// Trait to get the number of bits needed to read types that can be read from a stream without requiring the size to be configured.
pub trait BitSize {
/// How many bits are required to read this type
fn bit_size() -> usize;
}
macro_rules! impl_read_int {
($type:ty, $len:expr) => {
impl<E: Endianness> BitRead<E> for $type {
@ -95,6 +101,13 @@ macro_rules! impl_read_int {
stream.read_int::<$type>($len)
}
}
impl BitSize for $type {
#[inline(always)]
fn bit_size() -> usize {
$len
}
}
};
}
@ -116,6 +129,13 @@ impl<E: Endianness> BitRead<E> for f32 {
}
}
impl BitSize for f32 {
#[inline(always)]
fn bit_size() -> usize {
32
}
}
impl<E: Endianness> BitRead<E> for f64 {
#[inline(always)]
fn read(stream: &mut BitStream<E>) -> Result<f64> {
@ -123,6 +143,13 @@ impl<E: Endianness> BitRead<E> for f64 {
}
}
impl BitSize for f64 {
#[inline(always)]
fn bit_size() -> usize {
64
}
}
impl<E: Endianness> BitRead<E> for bool {
#[inline(always)]
fn read(stream: &mut BitStream<E>) -> Result<bool> {
@ -130,6 +157,13 @@ impl<E: Endianness> BitRead<E> for bool {
}
}
impl BitSize for bool {
#[inline(always)]
fn bit_size() -> usize {
1
}
}
impl<E: Endianness> BitRead<E> for String {
#[inline(always)]
fn read(stream: &mut BitStream<E>) -> Result<String> {
@ -206,6 +240,12 @@ pub trait BitReadSized<E: Endianness>: Sized {
fn read(stream: &mut BitStream<E>, size: usize) -> Result<Self>;
}
/// Trait to get the number of bits needed to read types that can be read from a stream requiring the size to be configured.
pub trait BitSizeSized {
/// How many bits are required to read this type
fn bit_size(size: usize) -> usize;
}
macro_rules! impl_read_int_sized {
($type:ty) => {
impl<E: Endianness> BitReadSized<E> for $type {
@ -214,6 +254,13 @@ macro_rules! impl_read_int_sized {
stream.read_int::<$type>(size)
}
}
impl BitSizeSized for $type {
#[inline(always)]
fn bit_size(size: usize) -> usize {
size
}
}
};
}
@ -235,6 +282,13 @@ impl<E: Endianness> BitReadSized<E> for String {
}
}
impl BitSizeSized for String {
#[inline(always)]
fn bit_size(size: usize) -> usize {
8 * size
}
}
/// Read a boolean, if true, read `T`, else return `None`
impl<E: Endianness, T: BitRead<E>> BitRead<E> for Option<T> {
fn read(stream: &mut BitStream<E>) -> Result<Self> {
@ -246,6 +300,13 @@ impl<E: Endianness, T: BitRead<E>> BitRead<E> for Option<T> {
}
}
impl<T: BitSize> BitSize for Option<T> {
#[inline(always)]
fn bit_size() -> usize {
1 + T::bit_size()
}
}
impl<E: Endianness, T: BitReadSized<E>> BitReadSized<E> for Option<T> {
fn read(stream: &mut BitStream<E>, size: usize) -> Result<Self> {
if stream.read()? {
@ -256,6 +317,13 @@ impl<E: Endianness, T: BitReadSized<E>> BitReadSized<E> for Option<T> {
}
}
impl<T: BitSizeSized> BitSizeSized for Option<T> {
#[inline(always)]
fn bit_size(size: usize) -> usize {
1 + T::bit_size(size)
}
}
impl<E: Endianness> BitReadSized<E> for BitStream<E> {
#[inline(always)]
fn read(stream: &mut BitStream<E>, size: usize) -> Result<Self> {
@ -263,6 +331,13 @@ impl<E: Endianness> BitReadSized<E> for BitStream<E> {
}
}
impl<E: Endianness> BitSizeSized for BitStream<E> {
#[inline(always)]
fn bit_size(size: usize) -> usize {
size
}
}
/// Read `T` `size` times and return as `Vec<T>`
impl<E: Endianness, T: BitRead<E>> BitReadSized<E> for Vec<T> {
fn read(stream: &mut BitStream<E>, size: usize) -> Result<Self> {
@ -274,6 +349,13 @@ impl<E: Endianness, T: BitRead<E>> BitReadSized<E> for Vec<T> {
}
}
impl<T: BitSize> BitSizeSized for Vec<T> {
#[inline(always)]
fn bit_size(size: usize) -> usize {
size * T::bit_size()
}
}
// Once we have something like https://github.com/rust-lang/rfcs/issues/1053 we can do this optimization
//impl<E: Endianness> ReadSized<E> for Vec<u8> {
// #[inline(always)]
@ -294,3 +376,10 @@ impl<E: Endianness, K: BitRead<E> + Eq + Hash, T: BitRead<E>> BitReadSized<E> fo
Ok(map)
}
}
impl<K: BitSize, T: BitSize> BitSizeSized for HashMap<K, T> {
#[inline(always)]
fn bit_size(size: usize) -> usize {
size * (K::bit_size() + T::bit_size())
}
}