diff --git a/benches/deku.rs b/benches/deku.rs index bbaa2c3f..72106c36 100644 --- a/benches/deku.rs +++ b/benches/deku.rs @@ -21,6 +21,16 @@ enum DekuEnum { VariantA(u8), } +/// This is faster, because we go right to (endian, bytes) +#[derive(Debug, PartialEq, DekuRead, DekuWrite)] +struct DekuVecPerf { + #[deku(bytes = "1")] + count: u8, + #[deku(count = "count")] + #[deku(bytes = "1")] + data: Vec, +} + #[derive(Debug, PartialEq, DekuRead, DekuWrite)] struct DekuVec { count: u8, @@ -60,6 +70,14 @@ fn deku_write_vec(input: &DekuVec) { let _v = input.to_bytes().unwrap(); } +fn deku_read_vec_perf(input: &[u8]) { + let (_rest, _v) = DekuVecPerf::from_bytes((input, 0)).unwrap(); +} + +fn deku_write_vec_perf(input: &DekuVecPerf) { + let _v = input.to_bytes().unwrap(); +} + fn criterion_benchmark(c: &mut Criterion) { c.bench_function("deku_read_byte", |b| { b.iter(|| deku_read_byte(black_box([0x01].as_ref()))) @@ -71,7 +89,12 @@ fn criterion_benchmark(c: &mut Criterion) { b.iter(|| deku_read_bits(black_box([0xf1].as_ref()))) }); c.bench_function("deku_write_bits", |b| { - b.iter(|| deku_write_bits(black_box(&DekuBits { data_01: 0x0f, data_02: 0x01 }))) + b.iter(|| { + deku_write_bits(black_box(&DekuBits { + data_01: 0x0f, + data_02: 0x01, + })) + }) }); c.bench_function("deku_read_enum", |b| { @@ -96,6 +119,17 @@ fn criterion_benchmark(c: &mut Criterion) { c.bench_function("deku_write_vec", |b| { b.iter(|| deku_write_vec(black_box(&deku_write_vec_input))) }); + + let deku_write_vec_input = DekuVecPerf { + count: 100, + data: vec![0xFF; 100], + }; + c.bench_function("deku_read_vec_perf", |b| { + b.iter(|| deku_read_vec_perf(black_box(&deku_read_vec_input))) + }); + c.bench_function("deku_write_vec_perf", |b| { + b.iter(|| deku_write_vec_perf(black_box(&deku_write_vec_input))) + }); } criterion_group!(benches, criterion_benchmark); diff --git a/deku-derive/src/macros/deku_read.rs b/deku-derive/src/macros/deku_read.rs index 79e73600..6a4f4b43 100644 --- a/deku-derive/src/macros/deku_read.rs +++ b/deku-derive/src/macros/deku_read.rs @@ -597,27 +597,27 @@ fn emit_field_read( quote! { { use core::borrow::Borrow; - #type_as_deku_read::read(__deku_rest, (::#crate_::ctx::Limit::new_count(usize::try_from(*((#field_count).borrow()))?), (#read_args))) + #type_as_deku_read::::read(__deku_rest, (::#crate_::ctx::Limit::new_count(usize::try_from(*((#field_count).borrow()))?), (#read_args))) } } } else if let Some(field_bits) = &f.bits_read { quote! { { use core::borrow::Borrow; - #type_as_deku_read::read(__deku_rest, (::#crate_::ctx::Limit::new_size(::#crate_::ctx::Size::Bits(usize::try_from(*((#field_bits).borrow()))?)), (#read_args))) + #type_as_deku_read::::read(__deku_rest, (::#crate_::ctx::Limit::new_bit_size(::#crate_::ctx::BitSize(usize::try_from(*((#field_bits).borrow()))?)), (#read_args))) } } } else if let Some(field_bytes) = &f.bytes_read { quote! { { use core::borrow::Borrow; - #type_as_deku_read::read(__deku_rest, (::#crate_::ctx::Limit::new_size(::#crate_::ctx::Size::Bytes(usize::try_from(*((#field_bytes).borrow()))?)), (#read_args))) + #type_as_deku_read::::read(__deku_rest, (::#crate_::ctx::Limit::new_byte_size(::#crate_::ctx::ByteSize(usize::try_from(*((#field_bytes).borrow()))?)), (#read_args))) } } } else if let Some(field_until) = &f.until { // We wrap the input into another closure here to enforce that it is actually a callable // Otherwise, an incorrectly passed-in integer could unexpectedly convert into a `Count` limit - quote! {#type_as_deku_read::read(__deku_rest, (::#crate_::ctx::Limit::new_until(#field_until), (#read_args)))} + quote! {#type_as_deku_read::::read(__deku_rest, (::#crate_::ctx::Limit::new_until(#field_until), (#read_args)))} } else { quote! {#type_as_deku_read::read(__deku_rest, (#read_args))} } diff --git a/deku-derive/src/macros/mod.rs b/deku-derive/src/macros/mod.rs index f7b1067b..5cc34fda 100644 --- a/deku-derive/src/macros/mod.rs +++ b/deku-derive/src/macros/mod.rs @@ -204,7 +204,8 @@ fn gen_type_from_ctx_id( } /// Generate argument for `id`: -/// `#deku(endian = "big", bits = "1")` -> `Endian::Big, Size::Bits(1)` +/// `#deku(endian = "big", bits = "1")` -> `Endian::Big, BitSize(1)` +/// `#deku(endian = "big", bytes = "1")` -> `Endian::Big, ByteSize(1)` pub(crate) fn gen_id_args( endian: Option<&syn::LitStr>, bits: Option<&Num>, @@ -212,8 +213,8 @@ pub(crate) fn gen_id_args( ) -> syn::Result { let crate_ = get_crate_name(); let endian = endian.map(gen_endian_from_str).transpose()?; - let bits = bits.map(|n| quote! {::#crate_::ctx::Size::Bits(#n)}); - let bytes = bytes.map(|n| quote! {::#crate_::ctx::Size::Bytes(#n)}); + let bits = bits.map(|n| quote! {::#crate_::ctx::BitSize(#n)}); + let bytes = bytes.map(|n| quote! {::#crate_::ctx::ByteSize(#n)}); // FIXME: Should be `into_iter` here, see /~https://github.com/rust-lang/rust/issues/66145. let id_args = [endian.as_ref(), bits.as_ref(), bytes.as_ref()] @@ -229,7 +230,8 @@ pub(crate) fn gen_id_args( /// Generate argument for fields: /// -/// `#deku(endian = "big", bits = "1", ctx = "a")` -> `Endian::Big, Size::Bits(1), a` +/// `#deku(endian = "big", bits = "1", ctx = "a")` -> `Endian::Big, BitSize(1), a` +/// `#deku(endian = "big", bytes = "1", ctx = "a")` -> `Endian::Big, ByteSize(1), a` fn gen_field_args( endian: Option<&syn::LitStr>, bits: Option<&Num>, @@ -238,8 +240,8 @@ fn gen_field_args( ) -> syn::Result { let crate_ = get_crate_name(); let endian = endian.map(gen_endian_from_str).transpose()?; - let bits = bits.map(|n| quote! {::#crate_::ctx::Size::Bits(#n)}); - let bytes = bytes.map(|n| quote! {::#crate_::ctx::Size::Bytes(#n)}); + let bits = bits.map(|n| quote! {::#crate_::ctx::BitSize(#n)}); + let bytes = bytes.map(|n| quote! {::#crate_::ctx::ByteSize(#n)}); let ctx = ctx.map(|c| quote! {#c}); // FIXME: Should be `into_iter` here, see /~https://github.com/rust-lang/rust/issues/66145. diff --git a/examples/custom_reader_and_writer.rs b/examples/custom_reader_and_writer.rs index 8646d725..9d47adb3 100644 --- a/examples/custom_reader_and_writer.rs +++ b/examples/custom_reader_and_writer.rs @@ -1,12 +1,12 @@ use deku::bitvec::{BitSlice, BitVec, Msb0}; -use deku::ctx::Size; +use deku::ctx::BitSize; use deku::prelude::*; use std::convert::TryInto; fn bit_flipper_read( field_a: u8, rest: &BitSlice, - bit_size: Size, + bit_size: BitSize, ) -> Result<(&BitSlice, u8), DekuError> { // Access to previously read fields println!("field_a = 0x{:X}", field_a); @@ -30,7 +30,7 @@ fn bit_flipper_write( field_a: u8, field_b: u8, output: &mut BitVec, - bit_size: Size, + bit_size: BitSize, ) -> Result<(), DekuError> { // Access to previously written fields println!("field_a = 0x{:X}", field_a); @@ -52,8 +52,8 @@ struct DekuTest { field_a: u8, #[deku( - reader = "bit_flipper_read(*field_a, deku::rest, Size::Bits(8))", - writer = "bit_flipper_write(*field_a, *field_b, deku::output, Size::Bits(8))" + reader = "bit_flipper_read(*field_a, deku::rest, BitSize(8))", + writer = "bit_flipper_write(*field_a, *field_b, deku::output, BitSize(8))" )] field_b: u8, } diff --git a/src/attributes.rs b/src/attributes.rs index f0b6b474..2db9a244 100644 --- a/src/attributes.rs +++ b/src/attributes.rs @@ -855,7 +855,7 @@ struct Type1 { // is equivalent to struct Type1 { - #[deku(ctx = "Endian::Big, Size::Bits(1)")] + #[deku(ctx = "Endian::Big, BitSize(1)")] field: u8, } ``` @@ -874,7 +874,7 @@ struct Type1 { struct Type1 { #[deku(ctx = "Endian::Big")] field_a: u16, - #[deku(ctx = "Endian::Big, Size::Bits(5), *field_a")] // endian is prepended + #[deku(ctx = "Endian::Big, BitSize(5), *field_a")] // endian is prepended field_b: SubType, } ``` diff --git a/src/ctx.rs b/src/ctx.rs index ed99af89..5bace7ed 100644 --- a/src/ctx.rs +++ b/src/ctx.rs @@ -1,13 +1,9 @@ //! Types for context representation //! See [ctx attribute](super::attributes#ctx) for more information. -use crate::error::DekuError; use core::marker::PhantomData; use core::str::FromStr; -#[cfg(feature = "alloc")] -use alloc::format; - /// An endian #[derive(Debug, Copy, Clone, Eq, PartialEq)] pub enum Endian { @@ -85,8 +81,11 @@ pub enum Limit bool> { /// Read until a given predicate holds true Until(Predicate, PhantomData), + /// Read until a given quantity of bytes have been read + ByteSize(ByteSize), + /// Read until a given quantity of bits have been read - Size(Size), + BitSize(BitSize), } impl From for Limit bool> { @@ -101,9 +100,15 @@ impl FnMut(&'a T) -> bool> From for Limit From for Limit bool> { - fn from(size: Size) -> Self { - Limit::Size(size) +impl From for Limit bool> { + fn from(size: ByteSize) -> Self { + Limit::ByteSize(size) + } +} + +impl From for Limit bool> { + fn from(size: BitSize) -> Self { + Limit::BitSize(size) } } @@ -123,35 +128,39 @@ impl Limit bool> { } /// Constructs a new Limit that reads until the given size - pub fn new_size(size: Size) -> Self { + pub fn new_bit_size(size: BitSize) -> Self { + size.into() + } + + /// Constructs a new Limit that reads until the given size + pub fn new_byte_size(size: ByteSize) -> Self { size.into() } } -/// The size of a field +/// The size of field in bytes #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)] -pub enum Size { - /// bit size - Bits(usize), - /// byte size - Bytes(usize), -} +pub struct ByteSize(pub usize); -impl Size { +/// The size of field in bits +#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)] +pub struct BitSize(pub usize); + +impl BitSize { /// Convert the size in bytes to a bit size. /// /// # Panic /// Panic if `byte_size * 8` is greater than `usize::MAX`. fn bits_from_bytes(byte_size: usize) -> Self { - Self::Bits(byte_size.checked_mul(8).expect("bit size overflow")) + Self(byte_size.checked_mul(8).expect("bit size overflow")) } /// Returns the bit size of a type. /// # Examples /// ```rust - /// # use deku::ctx::Size; + /// # use deku::ctx::BitSize; /// - /// assert_eq!(Size::of::(), Size::Bits(4 * 8)); + /// assert_eq!(BitSize::of::(), BitSize(4 * 8)); /// ``` /// /// # Panics @@ -164,33 +173,4 @@ impl Size { pub fn of_val(val: &T) -> Self { Self::bits_from_bytes(core::mem::size_of_val(val)) } - - /// Returns the size in bits of a Size - /// - /// # Panics - /// Panic if the bit size of Size::Bytes(n) is greater than `usize::MAX` - pub fn bit_size(&self) -> usize { - match *self { - Size::Bits(size) => size, - Size::Bytes(size) => size.checked_mul(8).expect("bit size overflow"), - } - } - - /// Returns the size in bytes of a Size - pub fn byte_size(&self) -> Result { - match *self { - Size::Bits(size) => { - if size % 8 == 0 { - Ok(size / 8) - } else { - Err(DekuError::InvalidParam(format!( - "Bit size of {} is not a multiple of 8. - Cannot be represented in bytes", - size - ))) - } - } - Size::Bytes(size) => Ok(size), - } - } } diff --git a/src/impls/bool.rs b/src/impls/bool.rs index 7d18b55d..52fed530 100644 --- a/src/impls/bool.rs +++ b/src/impls/bool.rs @@ -72,7 +72,7 @@ mod tests { let input = &[0b01_000000]; let bit_slice = input.view_bits::(); - let (rest, res_read) = bool::read(bit_slice, crate::ctx::Size::Bits(2)).unwrap(); + let (rest, res_read) = bool::read(bit_slice, crate::ctx::BitSize(2)).unwrap(); assert_eq!(true, res_read); assert_eq!(6, rest.len()); diff --git a/src/impls/boxed.rs b/src/impls/boxed.rs index a499a4ac..35454e10 100644 --- a/src/impls/boxed.rs +++ b/src/impls/boxed.rs @@ -96,8 +96,8 @@ mod tests { case::normal_be([0xAA, 0xBB, 0xCC, 0xDD].as_ref(), Endian::Big, Some(16), 2.into(), vec![0xAABB, 0xCCDD].into_boxed_slice(), bits![Msb0, u8;], vec![0xAA, 0xBB, 0xCC, 0xDD]), case::predicate_le([0xAA, 0xBB, 0xCC, 0xDD].as_ref(), Endian::Little, Some(16), (|v: &u16| *v == 0xBBAA).into(), vec![0xBBAA].into_boxed_slice(), bits![Msb0, u8; 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1], vec![0xAA, 0xBB]), case::predicate_be([0xAA, 0xBB, 0xCC, 0xDD].as_ref(), Endian::Big, Some(16), (|v: &u16| *v == 0xAABB).into(), vec![0xAABB].into_boxed_slice(), bits![Msb0, u8; 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1], vec![0xAA, 0xBB]), - case::bytes_le([0xAA, 0xBB, 0xCC, 0xDD].as_ref(), Endian::Little, Some(16), Size::Bits(16).into(), vec![0xBBAA].into_boxed_slice(), bits![Msb0, u8; 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1], vec![0xAA, 0xBB]), - case::bytes_be([0xAA, 0xBB, 0xCC, 0xDD].as_ref(), Endian::Big, Some(16), Size::Bits(16).into(), vec![0xAABB].into_boxed_slice(), bits![Msb0, u8; 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1], vec![0xAA, 0xBB]), + case::bytes_le([0xAA, 0xBB, 0xCC, 0xDD].as_ref(), Endian::Little, Some(16), BitSize(16).into(), vec![0xBBAA].into_boxed_slice(), bits![Msb0, u8; 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1], vec![0xAA, 0xBB]), + case::bytes_be([0xAA, 0xBB, 0xCC, 0xDD].as_ref(), Endian::Big, Some(16), BitSize(16).into(), vec![0xAABB].into_boxed_slice(), bits![Msb0, u8; 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1], vec![0xAA, 0xBB]), )] fn test_boxed_slice bool>( input: &[u8], @@ -114,13 +114,13 @@ mod tests { let bit_size = bit_size.unwrap(); let (rest, res_read) = - >::read(bit_slice, (limit, (endian, Size::Bits(bit_size)))).unwrap(); + >::read(bit_slice, (limit, (endian, BitSize(bit_size)))).unwrap(); assert_eq!(expected, res_read); assert_eq!(expected_rest, rest); let mut res_write = bitvec![Msb0, u8;]; res_read - .write(&mut res_write, (endian, Size::Bits(bit_size))) + .write(&mut res_write, (endian, BitSize(bit_size))) .unwrap(); assert_eq!(expected_write, res_write.into_vec()); diff --git a/src/impls/hashmap.rs b/src/impls/hashmap.rs index 90b15619..a15d3a7b 100644 --- a/src/impls/hashmap.rs +++ b/src/impls/hashmap.rs @@ -92,8 +92,16 @@ impl< } // Read until a given quantity of bits have been read - Limit::Size(size) => { - let bit_size = size.bit_size(); + Limit::BitSize(size) => { + let bit_size = size.0; + read_hashmap_with_predicate(input, None, inner_ctx, move |read_bits, _| { + read_bits == bit_size + }) + } + + // Read until a given quantity of bits have been read + Limit::ByteSize(size) => { + let bit_size = size.0 * 8; read_hashmap_with_predicate(input, None, inner_ctx, move |read_bits, _| { read_bits == bit_size }) @@ -176,7 +184,7 @@ mod tests { case::count_1([0x01, 0xAA, 0x02, 0xBB].as_ref(), Endian::Little, Some(8), 1.into(), fxhashmap!{0x01 => 0xAA}, bits![Msb0, u8; 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1]), case::count_2([0x01, 0xAA, 0x02, 0xBB, 0xBB].as_ref(), Endian::Little, Some(8), 2.into(), fxhashmap!{0x01 => 0xAA, 0x02 => 0xBB}, bits![Msb0, u8; 1, 0, 1, 1, 1, 0, 1, 1]), case::until_null([0x01, 0xAA, 0, 0, 0xBB].as_ref(), Endian::Little, None, (|kv: &(u8, u8)| kv.0 == 0u8 && kv.1 == 0u8).into(), fxhashmap!{0x01 => 0xAA, 0 => 0}, bits![Msb0, u8; 1, 0, 1, 1, 1, 0, 1, 1]), - case::until_bits([0x01, 0xAA, 0xBB].as_ref(), Endian::Little, None, Size::Bits(16).into(), fxhashmap!{0x01 => 0xAA}, bits![Msb0, u8; 1, 0, 1, 1, 1, 0, 1, 1]), + case::until_bits([0x01, 0xAA, 0xBB].as_ref(), Endian::Little, None, BitSize(16).into(), fxhashmap!{0x01 => 0xAA}, bits![Msb0, u8; 1, 0, 1, 1, 1, 0, 1, 1]), case::bits_6([0b0000_0100, 0b1111_0000, 0b1000_0000].as_ref(), Endian::Little, Some(6), 2.into(), fxhashmap!{0x01 => 0x0F, 0x02 => 0}, bits![Msb0, u8;]), #[should_panic(expected = "Parse(\"too much data: container of 8 bits cannot hold 9 bits\")")] case::not_enough_data([].as_ref(), Endian::Little, Some(9), 1.into(), FxHashMap::default(), bits![Msb0, u8;]), @@ -187,7 +195,7 @@ mod tests { #[should_panic(expected = "Incomplete(NeedSize { bits: 8 })")] case::not_enough_data_until([0xAA].as_ref(), Endian::Little, Some(8), (|_: &(u8, u8)| false).into(), FxHashMap::default(), bits![Msb0, u8;]), #[should_panic(expected = "Incomplete(NeedSize { bits: 8 })")] - case::not_enough_data_bits([0xAA].as_ref(), Endian::Little, Some(8), (Size::Bits(16)).into(), FxHashMap::default(), bits![Msb0, u8;]), + case::not_enough_data_bits([0xAA].as_ref(), Endian::Little, Some(8), (BitSize(16)).into(), FxHashMap::default(), bits![Msb0, u8;]), #[should_panic(expected = "Parse(\"too much data: container of 8 bits cannot hold 9 bits\")")] case::too_much_data([0xAA, 0xBB].as_ref(), Endian::Little, Some(9), 1.into(), FxHashMap::default(), bits![Msb0, u8;]), )] @@ -203,8 +211,7 @@ mod tests { let (rest, res_read) = match bit_size { Some(bit_size) => { - FxHashMap::::read(bit_slice, (limit, (endian, Size::Bits(bit_size)))) - .unwrap() + FxHashMap::::read(bit_slice, (limit, (endian, BitSize(bit_size)))).unwrap() } None => FxHashMap::::read(bit_slice, (limit, (endian))).unwrap(), }; @@ -228,8 +235,8 @@ mod tests { case::normal_be([0xAA, 0xBB, 0, 0xCC, 0xDD, 0].as_ref(), Endian::Big, 2.into(), fxhashmap!{0xAABB => 0, 0xCCDD => 0}, bits![Msb0, u8;], vec![0xCC, 0xDD, 0, 0xAA, 0xBB, 0]), case::predicate_le([0xAA, 0xBB, 0, 0xCC, 0xDD, 0].as_ref(), Endian::Little, (|kv: &(u16, u8)| kv.0 == 0xBBAA && kv.1 == 0).into(), fxhashmap!{0xBBAA => 0}, bits![Msb0, u8; 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0], vec![0xAA, 0xBB, 0]), case::predicate_be([0xAA, 0xBB, 0, 0xCC, 0xDD, 0].as_ref(), Endian::Big, (|kv: &(u16, u8)| kv.0 == 0xAABB && kv.1 == 0).into(), fxhashmap!{0xAABB => 0}, bits![Msb0, u8; 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0], vec![0xAA, 0xBB, 0]), - case::bytes_le([0xAA, 0xBB, 0, 0xCC, 0xDD, 0].as_ref(), Endian::Little, Size::Bits(24).into(), fxhashmap!{0xBBAA => 0}, bits![Msb0, u8; 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0], vec![0xAA, 0xBB, 0]), - case::bytes_be([0xAA, 0xBB, 0, 0xCC, 0xDD, 0].as_ref(), Endian::Big, Size::Bits(24).into(), fxhashmap!{0xAABB => 0}, bits![Msb0, u8; 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0], vec![0xAA, 0xBB, 0]), + case::bytes_le([0xAA, 0xBB, 0, 0xCC, 0xDD, 0].as_ref(), Endian::Little, BitSize(24).into(), fxhashmap!{0xBBAA => 0}, bits![Msb0, u8; 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0], vec![0xAA, 0xBB, 0]), + case::bytes_be([0xAA, 0xBB, 0, 0xCC, 0xDD, 0].as_ref(), Endian::Big, BitSize(24).into(), fxhashmap!{0xAABB => 0}, bits![Msb0, u8; 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0], vec![0xAA, 0xBB, 0]), )] fn test_hashmap_read_write bool>( input: &[u8], diff --git a/src/impls/hashset.rs b/src/impls/hashset.rs index de0c7a3d..0d767840 100644 --- a/src/impls/hashset.rs +++ b/src/impls/hashset.rs @@ -91,8 +91,16 @@ impl< } // Read until a given quantity of bits have been read - Limit::Size(size) => { - let bit_size = size.bit_size(); + Limit::BitSize(size) => { + let bit_size = size.0; + read_hashset_with_predicate(input, None, inner_ctx, move |read_bits, _| { + read_bits == bit_size + }) + } + + // Read until a given quantity of bits have been read + Limit::ByteSize(size) => { + let bit_size = size.0 * 8; read_hashset_with_predicate(input, None, inner_ctx, move |read_bits, _| { read_bits == bit_size }) @@ -151,7 +159,7 @@ mod tests { case::count_1([0xAA, 0xBB].as_ref(), Endian::Little, Some(8), 1.into(), vec![0xAA].into_iter().collect(), bits![Msb0, u8; 1, 0, 1, 1, 1, 0, 1, 1]), case::count_2([0xAA, 0xBB, 0xCC].as_ref(), Endian::Little, Some(8), 2.into(), vec![0xAA, 0xBB].into_iter().collect(), bits![Msb0, u8; 1, 1, 0, 0, 1, 1, 0, 0]), case::until_null([0xAA, 0, 0xBB].as_ref(), Endian::Little, None, (|v: &u8| *v == 0u8).into(), vec![0xAA, 0].into_iter().collect(), bits![Msb0, u8; 1, 0, 1, 1, 1, 0, 1, 1]), - case::until_bits([0xAA, 0xBB].as_ref(), Endian::Little, None, Size::Bits(8).into(), vec![0xAA].into_iter().collect(), bits![Msb0, u8; 1, 0, 1, 1, 1, 0, 1, 1]), + case::until_bits([0xAA, 0xBB].as_ref(), Endian::Little, None, BitSize(8).into(), vec![0xAA].into_iter().collect(), bits![Msb0, u8; 1, 0, 1, 1, 1, 0, 1, 1]), case::bits_6([0b0110_1001, 0b1110_1001].as_ref(), Endian::Little, Some(6), 2.into(), vec![0b00_011010, 0b00_011110].into_iter().collect(), bits![Msb0, u8; 1, 0, 0, 1]), #[should_panic(expected = "Parse(\"too much data: container of 8 bits cannot hold 9 bits\")")] case::not_enough_data([].as_ref(), Endian::Little, Some(9), 1.into(), FxHashSet::default(), bits![Msb0, u8;]), @@ -162,7 +170,7 @@ mod tests { #[should_panic(expected = "Incomplete(NeedSize { bits: 8 })")] case::not_enough_data_until([0xAA].as_ref(), Endian::Little, Some(8), (|_: &u8| false).into(), FxHashSet::default(), bits![Msb0, u8;]), #[should_panic(expected = "Incomplete(NeedSize { bits: 8 })")] - case::not_enough_data_bits([0xAA].as_ref(), Endian::Little, Some(8), (Size::Bits(16)).into(), FxHashSet::default(), bits![Msb0, u8;]), + case::not_enough_data_bits([0xAA].as_ref(), Endian::Little, Some(8), (BitSize(16)).into(), FxHashSet::default(), bits![Msb0, u8;]), #[should_panic(expected = "Parse(\"too much data: container of 8 bits cannot hold 9 bits\")")] case::too_much_data([0xAA, 0xBB].as_ref(), Endian::Little, Some(9), 1.into(), FxHashSet::default(), bits![Msb0, u8;]), )] @@ -178,7 +186,7 @@ mod tests { let (rest, res_read) = match bit_size { Some(bit_size) => { - FxHashSet::::read(bit_slice, (limit, (endian, Size::Bits(bit_size)))).unwrap() + FxHashSet::::read(bit_slice, (limit, (endian, BitSize(bit_size)))).unwrap() } None => FxHashSet::::read(bit_slice, (limit, (endian))).unwrap(), }; @@ -202,8 +210,8 @@ mod tests { case::normal_be([0xAA, 0xBB, 0xCC, 0xDD].as_ref(), Endian::Big, Some(16), 2.into(), vec![0xAABB, 0xCCDD].into_iter().collect(), bits![Msb0, u8;], vec![0xCC, 0xDD, 0xAA, 0xBB]), case::predicate_le([0xAA, 0xBB, 0xCC, 0xDD].as_ref(), Endian::Little, Some(16), (|v: &u16| *v == 0xBBAA).into(), vec![0xBBAA].into_iter().collect(), bits![Msb0, u8; 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1], vec![0xAA, 0xBB]), case::predicate_be([0xAA, 0xBB, 0xCC, 0xDD].as_ref(), Endian::Big, Some(16), (|v: &u16| *v == 0xAABB).into(), vec![0xAABB].into_iter().collect(), bits![Msb0, u8; 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1], vec![0xAA, 0xBB]), - case::bytes_le([0xAA, 0xBB, 0xCC, 0xDD].as_ref(), Endian::Little, Some(16), Size::Bits(16).into(), vec![0xBBAA].into_iter().collect(), bits![Msb0, u8; 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1], vec![0xAA, 0xBB]), - case::bytes_be([0xAA, 0xBB, 0xCC, 0xDD].as_ref(), Endian::Big, Some(16), Size::Bits(16).into(), vec![0xAABB].into_iter().collect(), bits![Msb0, u8; 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1], vec![0xAA, 0xBB]), + case::bytes_le([0xAA, 0xBB, 0xCC, 0xDD].as_ref(), Endian::Little, Some(16), BitSize(16).into(), vec![0xBBAA].into_iter().collect(), bits![Msb0, u8; 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1], vec![0xAA, 0xBB]), + case::bytes_be([0xAA, 0xBB, 0xCC, 0xDD].as_ref(), Endian::Big, Some(16), BitSize(16).into(), vec![0xAABB].into_iter().collect(), bits![Msb0, u8; 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1], vec![0xAA, 0xBB]), )] fn test_hashset_read_write bool>( input: &[u8], @@ -220,13 +228,13 @@ mod tests { let bit_size = bit_size.unwrap(); let (rest, res_read) = - FxHashSet::::read(bit_slice, (limit, (endian, Size::Bits(bit_size)))).unwrap(); + FxHashSet::::read(bit_slice, (limit, (endian, BitSize(bit_size)))).unwrap(); assert_eq!(expected, res_read); assert_eq!(expected_rest, rest); let mut res_write = bitvec![Msb0, u8;]; res_read - .write(&mut res_write, (endian, Size::Bits(bit_size))) + .write(&mut res_write, (endian, BitSize(bit_size))) .unwrap(); assert_eq!(expected_write, res_write.into_vec()); } diff --git a/src/impls/nonzero.rs b/src/impls/nonzero.rs index 5157e23d..898b73c6 100644 --- a/src/impls/nonzero.rs +++ b/src/impls/nonzero.rs @@ -41,9 +41,9 @@ macro_rules! ImplDekuTraitsCtx { macro_rules! ImplDekuTraits { ($typ:ty, $readtype:ty) => { ImplDekuTraitsCtx!($typ, $readtype, (), ()); - ImplDekuTraitsCtx!($typ, $readtype, (endian, size), (Endian, Size)); + ImplDekuTraitsCtx!($typ, $readtype, (endian, bitsize), (Endian, BitSize)); + ImplDekuTraitsCtx!($typ, $readtype, (endian, bytesize), (Endian, ByteSize)); ImplDekuTraitsCtx!($typ, $readtype, endian, Endian); - ImplDekuTraitsCtx!($typ, $readtype, size, Size); }; } diff --git a/src/impls/primitive.rs b/src/impls/primitive.rs index 6d39679b..744cbb41 100644 --- a/src/impls/primitive.rs +++ b/src/impls/primitive.rs @@ -7,13 +7,13 @@ use alloc::format; macro_rules! ImplDekuRead { ($typ:ty) => { - impl DekuRead<'_, (Endian, Size)> for $typ { + impl DekuRead<'_, (Endian, BitSize)> for $typ { fn read( input: &BitSlice, - (endian, size): (Endian, Size), + (endian, size): (Endian, BitSize), ) -> Result<(&BitSlice, Self), DekuError> { - let max_type_bits: usize = Size::of::<$typ>().bit_size(); - let bit_size: usize = size.bit_size(); + let max_type_bits: usize = BitSize::of::<$typ>().0; + let bit_size: usize = size.0; let input_is_le = endian.is_le(); @@ -37,7 +37,6 @@ macro_rules! ImplDekuRead { && bit_slice.as_raw_slice().len() * 8 == max_type_bits { // if everything is aligned, just read the value - let bytes: &[u8] = bit_slice.as_raw_slice(); // Read value @@ -90,7 +89,41 @@ macro_rules! ImplDekuRead { <$typ>::from_be_bytes(bytes.try_into()?) } }; + Ok((rest, value)) + } + } + impl DekuRead<'_, (Endian, ByteSize)> for $typ { + fn read( + input: &BitSlice, + (endian, size): (Endian, ByteSize), + ) -> Result<(&BitSlice, Self), DekuError> { + let max_type_bits: usize = BitSize::of::<$typ>().0; + let bit_size: usize = size.0 * 8; + + let input_is_le = endian.is_le(); + + if bit_size > max_type_bits { + return Err(DekuError::Parse(format!( + "too much data: container of {} bits cannot hold {} bits", + max_type_bits, bit_size + ))); + } + + if input.len() < bit_size { + return Err(DekuError::Incomplete(crate::error::NeedSize::new(bit_size))); + } + + let (bit_slice, rest) = input.split_at(bit_size); + + let bytes: &[u8] = bit_slice.as_raw_slice(); + + // Read value + let value = if input_is_le { + <$typ>::from_le_bytes(bytes.try_into()?) + } else { + <$typ>::from_be_bytes(bytes.try_into()?) + }; Ok((rest, value)) } } @@ -99,16 +132,31 @@ macro_rules! ImplDekuRead { macro_rules! ImplDekuReadSignExtend { ($typ:ty, $inner:ty) => { - impl DekuRead<'_, (Endian, Size)> for $typ { + impl DekuRead<'_, (Endian, ByteSize)> for $typ { + fn read( + input: &BitSlice, + (endian, size): (Endian, ByteSize), + ) -> Result<(&BitSlice, Self), DekuError> { + let (rest, value) = + <$inner as DekuRead<'_, (Endian, ByteSize)>>::read(input, (endian, size))?; + + let max_type_bits = BitSize::of::<$typ>().0; + let bit_size = size.0 * 8; + let shift = max_type_bits - bit_size; + let value = (value as $typ) << shift >> shift; + Ok((rest, value)) + } + } + impl DekuRead<'_, (Endian, BitSize)> for $typ { fn read( input: &BitSlice, - (endian, size): (Endian, Size), + (endian, size): (Endian, BitSize), ) -> Result<(&BitSlice, Self), DekuError> { let (rest, value) = - <$inner as DekuRead<'_, (Endian, Size)>>::read(input, (endian, size))?; + <$inner as DekuRead<'_, (Endian, BitSize)>>::read(input, (endian, size))?; - let max_type_bits = Size::of::<$typ>().bit_size(); - let bit_size = size.bit_size(); + let max_type_bits = BitSize::of::<$typ>().0; + let bit_size = size.0; let shift = max_type_bits - bit_size; let value = (value as $typ) << shift >> shift; Ok((rest, value)) @@ -125,17 +173,34 @@ macro_rules! ForwardDekuRead { input: &BitSlice, endian: Endian, ) -> Result<(&BitSlice, Self), DekuError> { - let max_type_bits = Size::of::<$typ>(); + let bit_size = BitSize::of::<$typ>(); + + // Since we don't have a #[bits] or [bytes], check if we can use bytes for perf + if (bit_size.0 % 8) == 0 { + <$typ>::read(input, (endian, bit_size)) + } else { + <$typ>::read(input, (endian, ByteSize(bit_size.0 / 8))) + } + } + } + + // Only have `bit_size`, set `endian` to `Endian::default`. + impl DekuRead<'_, ByteSize> for $typ { + fn read( + input: &BitSlice, + byte_size: ByteSize, + ) -> Result<(&BitSlice, Self), DekuError> { + let endian = Endian::default(); - <$typ>::read(input, (endian, max_type_bits)) + <$typ>::read(input, (endian, byte_size)) } } // Only have `bit_size`, set `endian` to `Endian::default`. - impl DekuRead<'_, Size> for $typ { + impl DekuRead<'_, BitSize> for $typ { fn read( input: &BitSlice, - bit_size: Size, + bit_size: BitSize, ) -> Result<(&BitSlice, Self), DekuError> { let endian = Endian::default(); @@ -156,18 +221,63 @@ macro_rules! ForwardDekuRead { macro_rules! ImplDekuWrite { ($typ:ty) => { - impl DekuWrite<(Endian, Size)> for $typ { + impl DekuWrite<(Endian, BitSize)> for $typ { + fn write( + &self, + output: &mut BitVec, + (endian, size): (Endian, BitSize), + ) -> Result<(), DekuError> { + let input = match endian { + Endian::Little => self.to_le_bytes(), + Endian::Big => self.to_be_bytes(), + }; + + let bit_size: usize = size.0; + + let input_bits = input.view_bits::(); + + if bit_size > input_bits.len() { + return Err(DekuError::InvalidParam(format!( + "bit size {} is larger then input {}", + bit_size, + input_bits.len() + ))); + } + + if matches!(endian, Endian::Little) { + // Example read 10 bits u32 [0xAB, 0b11_000000] + // => [10101011, 00000011, 00000000, 00000000] + let mut remaining_bits = bit_size; + for chunk in input_bits.chunks(8) { + if chunk.len() > remaining_bits { + output.extend_from_bitslice(&chunk[chunk.len() - remaining_bits..]); + break; + } else { + output.extend_from_bitslice(chunk) + } + remaining_bits -= chunk.len(); + } + } else { + // Example read 10 bits u32 [0xAB, 0b11_000000] + // => [00000000, 00000000, 00000010, 10101111] + output.extend_from_bitslice(&input_bits[input_bits.len() - bit_size..]); + } + Ok(()) + } + } + + impl DekuWrite<(Endian, ByteSize)> for $typ { fn write( &self, output: &mut BitVec, - (endian, size): (Endian, Size), + (endian, size): (Endian, ByteSize), ) -> Result<(), DekuError> { let input = match endian { Endian::Little => self.to_le_bytes(), Endian::Big => self.to_be_bytes(), }; - let bit_size: usize = size.bit_size(); + let bit_size: usize = size.0 * 8; let input_bits = input.view_bits::(); @@ -222,11 +332,22 @@ macro_rules! ImplDekuWrite { macro_rules! ForwardDekuWrite { ($typ:ty) => { // Only have `bit_size`, set `endian` to `Endian::default`. - impl DekuWrite for $typ { + impl DekuWrite for $typ { + fn write( + &self, + output: &mut BitVec, + bit_size: BitSize, + ) -> Result<(), DekuError> { + <$typ>::write(self, output, (Endian::default(), bit_size)) + } + } + + // Only have `bit_size`, set `endian` to `Endian::default`. + impl DekuWrite for $typ { fn write( &self, output: &mut BitVec, - bit_size: Size, + bit_size: ByteSize, ) -> Result<(), DekuError> { <$typ>::write(self, output, (Endian::default(), bit_size)) } @@ -407,7 +528,7 @@ mod tests { let bit_slice = input.view_bits::(); let (rest, res_read) = match bit_size { - Some(bit_size) => u32::read(bit_slice, (endian, Size::Bits(bit_size))).unwrap(), + Some(bit_size) => u32::read(bit_slice, (endian, BitSize(bit_size))).unwrap(), None => u32::read(bit_slice, endian).unwrap(), }; @@ -427,7 +548,7 @@ mod tests { let mut res_write = bitvec![Msb0, u8;]; match bit_size { Some(bit_size) => input - .write(&mut res_write, (endian, Size::Bits(bit_size))) + .write(&mut res_write, (endian, BitSize(bit_size))) .unwrap(), None => input.write(&mut res_write, endian).unwrap(), }; @@ -448,7 +569,7 @@ mod tests { let bit_slice = input.view_bits::(); let (rest, res_read) = match bit_size { - Some(bit_size) => u32::read(bit_slice, (endian, Size::Bits(bit_size))).unwrap(), + Some(bit_size) => u32::read(bit_slice, (endian, BitSize(bit_size))).unwrap(), None => u32::read(bit_slice, endian).unwrap(), }; assert_eq!(expected, res_read); @@ -457,7 +578,7 @@ mod tests { let mut res_write = bitvec![Msb0, u8;]; match bit_size { Some(bit_size) => res_read - .write(&mut res_write, (endian, Size::Bits(bit_size))) + .write(&mut res_write, (endian, BitSize(bit_size))) .unwrap(), None => res_read.write(&mut res_write, endian).unwrap(), }; @@ -471,7 +592,7 @@ mod tests { fn $test_name() { let bit_slice = [0b10101_000].view_bits::(); - let (rest, res_read) = <$typ>::read(bit_slice, (Endian::Little, Size::Bits(5))).unwrap(); + let (rest, res_read) = <$typ>::read(bit_slice, (Endian::Little, BitSize(5))).unwrap(); assert_eq!(-11, res_read); assert_eq!(bits![Msb0, u8; 0, 0, 0], rest); diff --git a/src/impls/slice.rs b/src/impls/slice.rs index bb6670f8..e5447e3c 100644 --- a/src/impls/slice.rs +++ b/src/impls/slice.rs @@ -79,8 +79,16 @@ where } // Read until a given quantity of bits have been read - Limit::Size(size) => { - let bit_size = size.bit_size(); + Limit::BitSize(size) => { + let bit_size = size.0; + read_slice_with_predicate(input, inner_ctx, move |read_bits, _| { + read_bits == bit_size + }) + } + + // Read until a given quantity of bytes have been read + Limit::ByteSize(size) => { + let bit_size = size.0 * 8; read_slice_with_predicate(input, inner_ctx, move |read_bits, _| { read_bits == bit_size }) diff --git a/src/impls/vec.rs b/src/impls/vec.rs index 0c5719a1..61ad9f33 100644 --- a/src/impls/vec.rs +++ b/src/impls/vec.rs @@ -85,8 +85,16 @@ impl<'a, T: DekuRead<'a, Ctx>, Ctx: Copy, Predicate: FnMut(&T) -> bool> } // Read until a given quantity of bits have been read - Limit::Size(size) => { - let bit_size = size.bit_size(); + Limit::BitSize(size) => { + let bit_size = size.0; + read_vec_with_predicate(input, None, inner_ctx, move |read_bits, _| { + read_bits == bit_size + }) + } + + // Read until a given quantity of bits have been read + Limit::ByteSize(size) => { + let bit_size = size.0 * 8; read_vec_with_predicate(input, None, inner_ctx, move |read_bits, _| { read_bits == bit_size }) @@ -140,7 +148,7 @@ mod tests { case::count_1([0xAA, 0xBB].as_ref(), Endian::Little, Some(8), 1.into(), vec![0xAA], bits![Msb0, u8; 1, 0, 1, 1, 1, 0, 1, 1]), case::count_2([0xAA, 0xBB, 0xCC].as_ref(), Endian::Little, Some(8), 2.into(), vec![0xAA, 0xBB], bits![Msb0, u8; 1, 1, 0, 0, 1, 1, 0, 0]), case::until_null([0xAA, 0, 0xBB].as_ref(), Endian::Little, None, (|v: &u8| *v == 0u8).into(), vec![0xAA, 0], bits![Msb0, u8; 1, 0, 1, 1, 1, 0, 1, 1]), - case::until_bits([0xAA, 0xBB].as_ref(), Endian::Little, None, Size::Bits(8).into(), vec![0xAA], bits![Msb0, u8; 1, 0, 1, 1, 1, 0, 1, 1]), + case::until_bits([0xAA, 0xBB].as_ref(), Endian::Little, None, BitSize(8).into(), vec![0xAA], bits![Msb0, u8; 1, 0, 1, 1, 1, 0, 1, 1]), case::bits_6([0b0110_1001, 0b1110_1001].as_ref(), Endian::Little, Some(6), 2.into(), vec![0b00_011010, 0b00_011110], bits![Msb0, u8; 1, 0, 0, 1]), #[should_panic(expected = "Parse(\"too much data: container of 8 bits cannot hold 9 bits\")")] case::not_enough_data([].as_ref(), Endian::Little, Some(9), 1.into(), vec![], bits![Msb0, u8;]), @@ -151,7 +159,7 @@ mod tests { #[should_panic(expected = "Incomplete(NeedSize { bits: 8 })")] case::not_enough_data_until([0xAA].as_ref(), Endian::Little, Some(8), (|_: &u8| false).into(), vec![], bits![Msb0, u8;]), #[should_panic(expected = "Incomplete(NeedSize { bits: 8 })")] - case::not_enough_data_bits([0xAA].as_ref(), Endian::Little, Some(8), (Size::Bits(16)).into(), vec![], bits![Msb0, u8;]), + case::not_enough_data_bits([0xAA].as_ref(), Endian::Little, Some(8), (BitSize(16)).into(), vec![], bits![Msb0, u8;]), #[should_panic(expected = "Parse(\"too much data: container of 8 bits cannot hold 9 bits\")")] case::too_much_data([0xAA, 0xBB].as_ref(), Endian::Little, Some(9), 1.into(), vec![], bits![Msb0, u8;]), )] @@ -167,7 +175,7 @@ mod tests { let (rest, res_read) = match bit_size { Some(bit_size) => { - Vec::::read(bit_slice, (limit, (endian, Size::Bits(bit_size)))).unwrap() + Vec::::read(bit_slice, (limit, (endian, BitSize(bit_size)))).unwrap() } None => Vec::::read(bit_slice, (limit, (endian))).unwrap(), }; @@ -191,8 +199,8 @@ mod tests { case::normal_be([0xAA, 0xBB, 0xCC, 0xDD].as_ref(), Endian::Big, Some(16), 2.into(), vec![0xAABB, 0xCCDD], bits![Msb0, u8;], vec![0xAA, 0xBB, 0xCC, 0xDD]), case::predicate_le([0xAA, 0xBB, 0xCC, 0xDD].as_ref(), Endian::Little, Some(16), (|v: &u16| *v == 0xBBAA).into(), vec![0xBBAA], bits![Msb0, u8; 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1], vec![0xAA, 0xBB]), case::predicate_be([0xAA, 0xBB, 0xCC, 0xDD].as_ref(), Endian::Big, Some(16), (|v: &u16| *v == 0xAABB).into(), vec![0xAABB], bits![Msb0, u8; 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1], vec![0xAA, 0xBB]), - case::bytes_le([0xAA, 0xBB, 0xCC, 0xDD].as_ref(), Endian::Little, Some(16), Size::Bits(16).into(), vec![0xBBAA], bits![Msb0, u8; 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1], vec![0xAA, 0xBB]), - case::bytes_be([0xAA, 0xBB, 0xCC, 0xDD].as_ref(), Endian::Big, Some(16), Size::Bits(16).into(), vec![0xAABB], bits![Msb0, u8; 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1], vec![0xAA, 0xBB]), + case::bytes_le([0xAA, 0xBB, 0xCC, 0xDD].as_ref(), Endian::Little, Some(16), BitSize(16).into(), vec![0xBBAA], bits![Msb0, u8; 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1], vec![0xAA, 0xBB]), + case::bytes_be([0xAA, 0xBB, 0xCC, 0xDD].as_ref(), Endian::Big, Some(16), BitSize(16).into(), vec![0xAABB], bits![Msb0, u8; 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1], vec![0xAA, 0xBB]), )] fn test_vec_read_write bool>( input: &[u8], @@ -209,13 +217,13 @@ mod tests { let bit_size = bit_size.unwrap(); let (rest, res_read) = - Vec::::read(bit_slice, (limit, (endian, Size::Bits(bit_size)))).unwrap(); + Vec::::read(bit_slice, (limit, (endian, BitSize(bit_size)))).unwrap(); assert_eq!(expected, res_read); assert_eq!(expected_rest, rest); let mut res_write = bitvec![Msb0, u8;]; res_read - .write(&mut res_write, (endian, Size::Bits(bit_size))) + .write(&mut res_write, (endian, BitSize(bit_size))) .unwrap(); assert_eq!(expected_write, res_write.into_vec());