1
0
Fork 0
mirror of https://codeberg.org/icewind/bitbuffer.git synced 2026-06-04 00:54:07 +02:00

implement read for Option<T> and Vec<T>

This commit is contained in:
Robin Appelman 2019-02-27 13:59:15 +01:00
commit 8d09284040
4 changed files with 67 additions and 7 deletions

View file

@ -8,7 +8,7 @@
pub use buffer::{BitBuffer, IsPadded, NonPadded, Padded};
pub use endianness::*;
pub use read::{Read, ReadSize};
pub use read::{Read, ReadSized};
pub use std::string::FromUtf8Error;
pub use stream::BitStream;

View file

@ -57,14 +57,14 @@ impl<'a, E: Endianness, P: IsPadded> Read<'a, E, P> for String {
}
/// 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 {
pub trait ReadSized<'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 {
impl<'a, E: Endianness, P: IsPadded> ReadSized<'a, E, P> for $type {
#[inline(always)]
fn read(stream: &mut BitStream<'a, E, P>, size: usize) -> Result<$type> {
stream.read_int::<$type>(size)
@ -84,9 +84,38 @@ 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 {
impl<'a, E: Endianness, P: IsPadded> ReadSized<'a, E, P> for String {
#[inline(always)]
fn read(stream: &mut BitStream<'a, E, P>, size: usize) -> Result<String> {
stream.read_string(Some(size))
}
}
/// Read a boolean, if true, read the value, else return None
impl<'a, E: Endianness, P: IsPadded, T: Read<'a, E, P>> Read<'a, E, P> for Option<T> {
fn read(stream: &mut BitStream<'a, E, P>) -> Result<Self> {
if stream.read()? {
Ok(Some(stream.read()?))
} else {
Ok(None)
}
}
}
impl<'a, E: Endianness, P: IsPadded, T: Read<'a, E, P>> ReadSized<'a, E, P> for Vec<T> {
fn read(stream: &mut BitStream<'a, E, P>, size: usize) -> Result<Self> {
let mut vec = Vec::with_capacity(size);
for _ in 0..size {
vec.push(stream.read()?)
}
Ok(vec)
}
}
// Once we have something like https://github.com/rust-lang/rfcs/issues/1053 we can do this optimization
//impl<'a, E: Endianness, P: IsPadded> ReadSized<'a, E, P> for Vec<u8> {
// #[inline(always)]
// fn read(stream: &mut BitStream<'a, E, P>, size: usize) -> Result<Self> {
// stream.read_bytes(size)
// }
//}

View file

@ -7,7 +7,7 @@ use crate::buffer::IsPadded;
use crate::endianness::Endianness;
use crate::is_signed::IsSigned;
use crate::BitBuffer;
use crate::{Read, ReadError, ReadSize, Result};
use crate::{Read, ReadError, ReadSized, Result};
/// Stream that provides an easy way to iterate trough a BitBuffer
///
@ -416,7 +416,7 @@ where
}
/// 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> {
pub fn read_sized<T: ReadSized<'a, E, S>>(&mut self, size: usize) -> Result<T> {
T::read(self, size)
}
}

View file

@ -236,16 +236,47 @@ fn read_trait() {
assert_eq!(-0b0010_1100_1001_1001, c);
let d: bool = stream.read().unwrap();
assert_eq!(true, d);
let e: Option<u8> = stream.read().unwrap();
assert_eq!(None, e);
stream.set_pos(0).unwrap();
let f: Option<u8> = stream.read().unwrap();
assert_eq!(Some(0b011_0101_0), f);
}
#[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();
let a: u8 = stream.read_sized(4).unwrap();
assert_eq!(0b1011, a);
stream.set_pos(0).unwrap();
let vec: Vec<u16> = stream.read_sized(3).unwrap();
assert_eq!(
vec![
0b1011_0101_0110_1010,
0b1010_1100_1001_1001,
0b1001_1001_1001_1001
],
vec
);
stream.set_pos(0).unwrap();
let vec: Vec<u8> = stream.read_sized(3).unwrap();
assert_eq!(vec![0b1011_0101, 0b0110_1010, 0b1010_1100], vec);
}
//0b1011_0101,
// 0b0110_1010,
// 0b1010_1100,
// 0b1001_1001,
// 0b1001_1001,
// 0b1001_1001,
// 0b1001_1001,
// 0b1110_0111,
// 0b1001_1001,
// 0b1001_1001,
// 0b1001_1001,
// 0b1110_0111,
// for bench on nightly
//fn read_perf<P: IsPadded>(buffer: BitBuffer<LittleEndian, P>) -> u16 {
// let size = 5;