mirror of
https://codeberg.org/icewind/bitbuffer.git
synced 2026-06-04 00:54:07 +02:00
add traits that allow for reading arbitrary types from stream
This commit is contained in:
parent
deafc90b74
commit
ad56d05dbe
4 changed files with 127 additions and 1 deletions
|
|
@ -8,12 +8,14 @@
|
|||
|
||||
pub use buffer::{BitBuffer, IsPadded, NonPadded, Padded};
|
||||
pub use endianness::*;
|
||||
pub use read::{Read, ReadSize};
|
||||
pub use std::string::FromUtf8Error;
|
||||
pub use stream::BitStream;
|
||||
|
||||
mod buffer;
|
||||
mod endianness;
|
||||
mod is_signed;
|
||||
mod read;
|
||||
mod stream;
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
|
|
|||
92
src/read.rs
Normal file
92
src/read.rs
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
use crate::{BitStream, Endianness, IsPadded, Result};
|
||||
|
||||
/// Trait for types that can be read from a stream without requiring the size to be configured
|
||||
pub trait Read<'a, E: Endianness, P: IsPadded>: Sized {
|
||||
/// Read the type from stream
|
||||
fn read(stream: &mut BitStream<'a, E, P>) -> Result<Self>;
|
||||
}
|
||||
|
||||
macro_rules! impl_read_int {
|
||||
($type:ty, $len:expr) => {
|
||||
impl<'a, E: Endianness, P: IsPadded> Read<'a, E, P> for $type {
|
||||
#[inline(always)]
|
||||
fn read(stream: &mut BitStream<'a, E, P>) -> Result<$type> {
|
||||
stream.read_int::<$type>($len)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
impl<'a, E: Endianness, P: IsPadded> Read<'a, E, P> for f32 {
|
||||
#[inline(always)]
|
||||
fn read(stream: &mut BitStream<'a, E, P>) -> Result<f32> {
|
||||
stream.read_float::<f32>()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, E: Endianness, P: IsPadded> Read<'a, E, P> for f64 {
|
||||
#[inline(always)]
|
||||
fn read(stream: &mut BitStream<'a, E, P>) -> Result<f64> {
|
||||
stream.read_float::<f64>()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, E: Endianness, P: IsPadded> Read<'a, E, P> for bool {
|
||||
#[inline(always)]
|
||||
fn read(stream: &mut BitStream<'a, E, P>) -> Result<bool> {
|
||||
stream.read_bool()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, E: Endianness, P: IsPadded> Read<'a, E, P> for String {
|
||||
#[inline(always)]
|
||||
fn read(stream: &mut BitStream<'a, E, P>) -> Result<String> {
|
||||
stream.read_string(None)
|
||||
}
|
||||
}
|
||||
|
||||
/// Trait for types that can be read from a stream wit requiring the size to be configured
|
||||
pub trait ReadSize<'a, E: Endianness, P: IsPadded>: Sized {
|
||||
/// Read the type from stream
|
||||
fn read(stream: &mut BitStream<'a, E, P>, size: usize) -> Result<Self>;
|
||||
}
|
||||
|
||||
macro_rules! impl_read_int_sized {
|
||||
($type:ty) => {
|
||||
impl<'a, E: Endianness, P: IsPadded> ReadSize<'a, E, P> for $type {
|
||||
#[inline(always)]
|
||||
fn read(stream: &mut BitStream<'a, E, P>, size: usize) -> Result<$type> {
|
||||
stream.read_int::<$type>(size)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl_read_int_sized!(u8);
|
||||
impl_read_int_sized!(u16);
|
||||
impl_read_int_sized!(u32);
|
||||
impl_read_int_sized!(u64);
|
||||
impl_read_int_sized!(u128);
|
||||
impl_read_int_sized!(i8);
|
||||
impl_read_int_sized!(i16);
|
||||
impl_read_int_sized!(i32);
|
||||
impl_read_int_sized!(i64);
|
||||
impl_read_int_sized!(i128);
|
||||
|
||||
impl<'a, E: Endianness, P: IsPadded> ReadSize<'a, E, P> for String {
|
||||
#[inline(always)]
|
||||
fn read(stream: &mut BitStream<'a, E, P>, size: usize) -> Result<String> {
|
||||
stream.read_string(Some(size))
|
||||
}
|
||||
}
|
||||
|
|
@ -7,7 +7,7 @@ use crate::buffer::IsPadded;
|
|||
use crate::endianness::Endianness;
|
||||
use crate::is_signed::IsSigned;
|
||||
use crate::BitBuffer;
|
||||
use crate::{ReadError, Result};
|
||||
use crate::{Read, ReadError, ReadSize, Result};
|
||||
|
||||
/// Stream that provides an easy way to iterate trough a BitBuffer
|
||||
///
|
||||
|
|
@ -409,4 +409,14 @@ where
|
|||
pub fn bits_left(&self) -> usize {
|
||||
self.bit_len - self.pos()
|
||||
}
|
||||
|
||||
/// Read a value based on the provided type
|
||||
pub fn read<T: Read<'a, E, S>>(&mut self) -> Result<T> {
|
||||
T::read(self)
|
||||
}
|
||||
|
||||
/// Read a value based on the provided type and size
|
||||
pub fn read_size<T: ReadSize<'a, E, S>>(&mut self, size: usize) -> Result<T> {
|
||||
T::read(self, size)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
22
src/tests.rs
22
src/tests.rs
|
|
@ -224,6 +224,28 @@ fn read_f64_le() {
|
|||
assert_eq!(buffer.read_float::<f64>(6).unwrap(), 135447455835963910000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn read_trait() {
|
||||
let buffer = BitBuffer::new(BYTES, BigEndian);
|
||||
let mut stream = BitStream::new(buffer, None, None);
|
||||
let a: u8 = stream.read().unwrap();
|
||||
assert_eq!(0b1011_0101, a);
|
||||
let b: i8 = stream.read().unwrap();
|
||||
assert_eq!(0b110_1010, b);
|
||||
let c: i16 = stream.read().unwrap();
|
||||
assert_eq!(-0b0010_1100_1001_1001, c);
|
||||
let d: bool = stream.read().unwrap();
|
||||
assert_eq!(true, d);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn read_sized_trait() {
|
||||
let buffer = BitBuffer::new(BYTES, BigEndian);
|
||||
let mut stream = BitStream::new(buffer, None, None);
|
||||
let a: u8 = stream.read_size(4).unwrap();
|
||||
assert_eq!(0b1011, a);
|
||||
}
|
||||
|
||||
// for bench on nightly
|
||||
//fn read_perf<P: IsPadded>(buffer: BitBuffer<LittleEndian, P>) -> u16 {
|
||||
// let size = 5;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue