mirror of
https://codeberg.org/icewind/bitbuffer.git
synced 2026-06-03 16:44:06 +02:00
some docs
This commit is contained in:
parent
aeec13ceec
commit
f54d8748ad
3 changed files with 91 additions and 44 deletions
12
src/lib.rs
12
src/lib.rs
|
|
@ -5,7 +5,7 @@
|
|||
//!
|
||||
//! Once you have a BitStream, there are 2 different approaches of reading data
|
||||
//!
|
||||
//! - read primitives, Strings and byte arrays, using [`read_bool`], [`read_int`], [`read_float`], [`read_byes`] and [`read_string`]
|
||||
//! - read primitives, Strings and byte arrays, using [`read_bool`], [`read_int`], [`read_float`], [`read_bytes`] and [`read_string`]
|
||||
//! - read any type implementing the [`BitRead`] or [`BitReadSized`] traits using [`read`] and [`read_sized`]
|
||||
//! - [`BitRead`] is for types that can be read without requiring any size info (e.g. null-terminal strings, floats, whole integers, etc)
|
||||
//! - [`BitReadSized`] is for types that require external sizing information to be read (fixed length strings, arbitrary length integers
|
||||
|
|
@ -45,16 +45,14 @@
|
|||
//! [`read_bool`]: struct.BitStream.html#method.read_bool
|
||||
//! [`read_int`]: struct.BitStream.html#method.read_int
|
||||
//! [`read_float`]: struct.BitStream.html#method.read_float
|
||||
//! [`read_byes`]: struct.BitStream.html#method.read_bytes
|
||||
//! [`read_bytes`]: struct.BitStream.html#method.read_bytes
|
||||
//! [`read_string`]: struct.BitStream.html#method.read_string
|
||||
//! [`read`]: struct.BitStream.html#method.read
|
||||
//! [`read_sized`]: struct.BitStream.html#method.read_sized
|
||||
//! [`BitRead`]: trait.BitRead.html
|
||||
//! [`BitReadSized`]: trait.BitReadSized.html
|
||||
|
||||
#![warn(missing_docs)]
|
||||
//#![feature(test)]
|
||||
|
||||
// for bench on nightly
|
||||
//extern crate test;
|
||||
|
||||
use std::error::Error;
|
||||
use std::fmt;
|
||||
|
|
@ -153,4 +151,4 @@ pub fn bit_size_of<T: BitSize>() -> usize {
|
|||
#[inline(always)]
|
||||
pub fn bit_size_of_sized<T: BitSizeSized>(size: usize) -> usize {
|
||||
T::bit_size(size)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
70
src/read.rs
70
src/read.rs
|
|
@ -1,8 +1,8 @@
|
|||
use crate::{BitStream, Endianness, Result};
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
use std::hash::Hash;
|
||||
use std::marker::PhantomData;
|
||||
use std::cell::RefCell;
|
||||
|
||||
/// Trait for types that can be read from a stream without requiring the size to be configured
|
||||
///
|
||||
|
|
@ -18,7 +18,7 @@ use std::cell::RefCell;
|
|||
/// The size for a field can be set using 3 different methods
|
||||
/// - set the size as an integer using the `size` attribute,
|
||||
/// - use a previously defined field as the size using the `size` attribute
|
||||
/// - read a set number of bits as an integer, using the resulting value as size using the `read_bits` attribute
|
||||
/// - read a set number of bits as an integer, using the resulting value as size using the `size_bits` attribute
|
||||
///
|
||||
/// ## Examples
|
||||
///
|
||||
|
|
@ -98,14 +98,14 @@ pub trait BitSize {
|
|||
macro_rules! impl_read_int {
|
||||
($type:ty, $len:expr) => {
|
||||
impl<E: Endianness> BitRead<E> for $type {
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
fn read(stream: &mut BitStream<E>) -> Result<$type> {
|
||||
stream.read_int::<$type>($len)
|
||||
}
|
||||
}
|
||||
|
||||
impl BitSize for $type {
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
fn bit_size() -> usize {
|
||||
$len
|
||||
}
|
||||
|
|
@ -125,49 +125,49 @@ impl_read_int!(i64, 64);
|
|||
impl_read_int!(i128, 128);
|
||||
|
||||
impl<E: Endianness> BitRead<E> for f32 {
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
fn read(stream: &mut BitStream<E>) -> Result<f32> {
|
||||
stream.read_float::<f32>()
|
||||
}
|
||||
}
|
||||
|
||||
impl BitSize for f32 {
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
fn bit_size() -> usize {
|
||||
32
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Endianness> BitRead<E> for f64 {
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
fn read(stream: &mut BitStream<E>) -> Result<f64> {
|
||||
stream.read_float::<f64>()
|
||||
}
|
||||
}
|
||||
|
||||
impl BitSize for f64 {
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
fn bit_size() -> usize {
|
||||
64
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Endianness> BitRead<E> for bool {
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
fn read(stream: &mut BitStream<E>) -> Result<bool> {
|
||||
stream.read_bool()
|
||||
}
|
||||
}
|
||||
|
||||
impl BitSize for bool {
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
fn bit_size() -> usize {
|
||||
1
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Endianness> BitRead<E> for String {
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
fn read(stream: &mut BitStream<E>) -> Result<String> {
|
||||
stream.read_string(None)
|
||||
}
|
||||
|
|
@ -189,7 +189,7 @@ impl<E: Endianness> BitRead<E> for String {
|
|||
/// - set the size as an integer using the `size` attribute,
|
||||
/// - use a previously defined field as the size using the `size` attribute
|
||||
/// - based on the input size by setting `size` attribute to `"input_size"`
|
||||
/// - read a set number of bits as an integer, using the resulting value as size using the `read_bits` attribute
|
||||
/// - read a set number of bits as an integer, using the resulting value as size using the `size_bits` attribute
|
||||
///
|
||||
/// ## Examples
|
||||
///
|
||||
|
|
@ -251,14 +251,14 @@ pub trait BitSizeSized {
|
|||
macro_rules! impl_read_int_sized {
|
||||
($type:ty) => {
|
||||
impl<E: Endianness> BitReadSized<E> for $type {
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
fn read(stream: &mut BitStream<E>, size: usize) -> Result<$type> {
|
||||
stream.read_int::<$type>(size)
|
||||
}
|
||||
}
|
||||
|
||||
impl BitSizeSized for $type {
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
fn bit_size(size: usize) -> usize {
|
||||
size
|
||||
}
|
||||
|
|
@ -278,14 +278,14 @@ impl_read_int_sized!(i64);
|
|||
impl_read_int_sized!(i128);
|
||||
|
||||
impl<E: Endianness> BitReadSized<E> for String {
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
fn read(stream: &mut BitStream<E>, size: usize) -> Result<String> {
|
||||
stream.read_string(Some(size))
|
||||
}
|
||||
}
|
||||
|
||||
impl BitSizeSized for String {
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
fn bit_size(size: usize) -> usize {
|
||||
8 * size
|
||||
}
|
||||
|
|
@ -303,7 +303,7 @@ impl<E: Endianness, T: BitRead<E>> BitRead<E> for Option<T> {
|
|||
}
|
||||
|
||||
impl<T: BitSize> BitSize for Option<T> {
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
fn bit_size() -> usize {
|
||||
1 + T::bit_size()
|
||||
}
|
||||
|
|
@ -320,21 +320,21 @@ impl<E: Endianness, T: BitReadSized<E>> BitReadSized<E> for Option<T> {
|
|||
}
|
||||
|
||||
impl<T: BitSizeSized> BitSizeSized for Option<T> {
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
fn bit_size(size: usize) -> usize {
|
||||
1 + T::bit_size(size)
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Endianness> BitReadSized<E> for BitStream<E> {
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
fn read(stream: &mut BitStream<E>, size: usize) -> Result<Self> {
|
||||
stream.read_bits(size)
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Endianness> BitSizeSized for BitStream<E> {
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
fn bit_size(size: usize) -> usize {
|
||||
size
|
||||
}
|
||||
|
|
@ -352,7 +352,7 @@ impl<E: Endianness, T: BitRead<E>> BitReadSized<E> for Vec<T> {
|
|||
}
|
||||
|
||||
impl<T: BitSize> BitSizeSized for Vec<T> {
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
fn bit_size(size: usize) -> usize {
|
||||
size * T::bit_size()
|
||||
}
|
||||
|
|
@ -360,7 +360,7 @@ impl<T: BitSize> BitSizeSized for Vec<T> {
|
|||
|
||||
// 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)]
|
||||
// #[inline]
|
||||
// fn read(stream: &mut BitStream<E>, size: usize) -> Result<Self> {
|
||||
// stream.read_bytes(size)
|
||||
// }
|
||||
|
|
@ -380,7 +380,7 @@ impl<E: Endianness, K: BitRead<E> + Eq + Hash, T: BitRead<E>> BitReadSized<E> fo
|
|||
}
|
||||
|
||||
impl<K: BitSize, T: BitSize> BitSizeSized for HashMap<K, T> {
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
fn bit_size(size: usize) -> usize {
|
||||
size * (K::bit_size() + T::bit_size())
|
||||
}
|
||||
|
|
@ -394,11 +394,11 @@ impl<K: BitSize, T: BitSize> BitSizeSized for HashMap<K, T> {
|
|||
/// [`BitSize`]: trait.BitSize.html
|
||||
pub struct LazyBitRead<T: BitRead<E> + BitSize, E: Endianness> {
|
||||
source: RefCell<BitStream<E>>,
|
||||
inner_type: PhantomData<T>
|
||||
inner_type: PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<T: BitRead<E> + BitSize, E: Endianness> LazyBitRead<T, E> {
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
/// Get the contents of the lazy struct
|
||||
pub fn read(self) -> Result<T> {
|
||||
self.source.borrow_mut().read::<T>()
|
||||
|
|
@ -406,18 +406,18 @@ impl<T: BitRead<E> + BitSize, E: Endianness> LazyBitRead<T, E> {
|
|||
}
|
||||
|
||||
impl<T: BitRead<E> + BitSize, E: Endianness> BitRead<E> for LazyBitRead<T, E> {
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
fn read(stream: &mut BitStream<E>) -> Result<Self> {
|
||||
let bit_size = T::bit_size();
|
||||
Ok(LazyBitRead {
|
||||
source: RefCell::new(stream.read_bits(bit_size)?),
|
||||
inner_type: PhantomData
|
||||
source: RefCell::new(stream.read_bits(bit_size)?),
|
||||
inner_type: PhantomData,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: BitRead<E> + BitSize, E: Endianness> BitSize for LazyBitRead<T, E> {
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
fn bit_size() -> usize {
|
||||
T::bit_size()
|
||||
}
|
||||
|
|
@ -432,11 +432,11 @@ impl<T: BitRead<E> + BitSize, E: Endianness> BitSize for LazyBitRead<T, E> {
|
|||
pub struct LazyBitReadSized<T: BitReadSized<E> + BitSizeSized, E: Endianness> {
|
||||
source: RefCell<BitStream<E>>,
|
||||
size: usize,
|
||||
inner_type: PhantomData<T>
|
||||
inner_type: PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<T: BitReadSized<E> + BitSizeSized, E: Endianness> LazyBitReadSized<T, E> {
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
/// Get the contents of the lazy struct
|
||||
pub fn value(self) -> Result<T> {
|
||||
self.source.borrow_mut().read_sized::<T>(self.size)
|
||||
|
|
@ -444,20 +444,20 @@ impl<T: BitReadSized<E> + BitSizeSized, E: Endianness> LazyBitReadSized<T, E> {
|
|||
}
|
||||
|
||||
impl<T: BitReadSized<E> + BitSizeSized, E: Endianness> BitReadSized<E> for LazyBitReadSized<T, E> {
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
fn read(stream: &mut BitStream<E>, size: usize) -> Result<Self> {
|
||||
let bit_size = T::bit_size(size);
|
||||
Ok(LazyBitReadSized {
|
||||
source: RefCell::new(stream.read_bits(bit_size)?),
|
||||
inner_type: PhantomData,
|
||||
size
|
||||
size,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: BitReadSized<E> + BitSizeSized, E: Endianness> BitSizeSized for LazyBitReadSized<T, E> {
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
fn bit_size(size: usize) -> usize {
|
||||
T::bit_size(size)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -472,13 +472,45 @@ where
|
|||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
/// #[inline(always)]
|
||||
///
|
||||
/// ```
|
||||
/// # use bitstream_reader::{BitBuffer, BitStream, LittleEndian, Result};
|
||||
/// use bitstream_reader::BitRead;
|
||||
/// #
|
||||
/// #[derive(BitRead, Debug, PartialEq)]
|
||||
/// struct ComplexType {
|
||||
/// first: u8,
|
||||
/// #[size = 15]
|
||||
/// second: u16,
|
||||
/// third: bool,
|
||||
/// }
|
||||
/// #
|
||||
/// # fn main() -> Result<()> {
|
||||
/// # let bytes = vec![
|
||||
/// # 0b1011_0101, 0b0110_1010, 0b1010_1100, 0b1001_1001,
|
||||
/// # 0b1001_1001, 0b1001_1001, 0b1001_1001, 0b1110_0111
|
||||
/// # ];
|
||||
/// # let buffer = BitBuffer::new(bytes, LittleEndian);
|
||||
/// # let mut stream = BitStream::new(buffer);
|
||||
/// let data: ComplexType = stream.read()?;
|
||||
/// assert_eq!(data, ComplexType {
|
||||
/// first: 0b1011_0101,
|
||||
/// second: 0b010_1100_0110_1010,
|
||||
/// third: true,
|
||||
/// });
|
||||
/// #
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn read<T: BitRead<E>>(&mut self) -> Result<T> {
|
||||
T::read(self)
|
||||
}
|
||||
|
||||
/// Read a value based on the provided type and size
|
||||
///
|
||||
/// The meaning of the size parameter differs depending on the type that is being read
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
|
|
@ -497,7 +529,24 @@ where
|
|||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
///
|
||||
/// ```
|
||||
/// # use bitstream_reader::{BitBuffer, BitStream, LittleEndian, Result};
|
||||
/// #
|
||||
/// # fn main() -> Result<()> {
|
||||
/// # let bytes = vec![
|
||||
/// # 0b1011_0101, 0b0110_1010, 0b1010_1100, 0b1001_1001,
|
||||
/// # 0b1001_1001, 0b1001_1001, 0b1001_1001, 0b1110_0111
|
||||
/// # ];
|
||||
/// # let buffer = BitBuffer::new(bytes, LittleEndian);
|
||||
/// # let mut stream = BitStream::new(buffer);
|
||||
/// let data: Vec<u16> = stream.read_sized(3)?;
|
||||
/// assert_eq!(data, vec![0b0110_1010_1011_0101, 0b1001_1001_1010_1100, 0b1001_1001_1001_1001]);
|
||||
/// #
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn read_sized<T: BitReadSized<E>>(&mut self, size: usize) -> Result<T> {
|
||||
T::read(self, size)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue