diff --git a/benches/deku.rs b/benches/deku.rs index 72106c36..f52791a8 100644 --- a/benches/deku.rs +++ b/benches/deku.rs @@ -105,13 +105,13 @@ fn criterion_benchmark(c: &mut Criterion) { }); let deku_read_vec_input = { - let mut v = [0xFFu8; 101].to_vec(); + let mut v = [0xffu8; 101].to_vec(); v[0] = 100u8; v }; let deku_write_vec_input = DekuVec { count: 100, - data: vec![0xFF; 100], + data: vec![0xff; 100], }; c.bench_function("deku_read_vec", |b| { b.iter(|| deku_read_vec(black_box(&deku_read_vec_input))) @@ -122,7 +122,7 @@ fn criterion_benchmark(c: &mut Criterion) { let deku_write_vec_input = DekuVecPerf { count: 100, - data: vec![0xFF; 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))) diff --git a/deku-derive/src/lib.rs b/deku-derive/src/lib.rs index f9dbde48..c499f157 100644 --- a/deku-derive/src/lib.rs +++ b/deku-derive/src/lib.rs @@ -4,13 +4,18 @@ Procedural macros that implement `DekuRead` and `DekuWrite` traits #![warn(missing_docs)] -use crate::macros::{deku_read::emit_deku_read, deku_write::emit_deku_write}; +use std::borrow::Cow; +use std::convert::TryFrom; + use darling::{ast, FromDeriveInput, FromField, FromMeta, FromVariant, ToTokens}; use proc_macro2::TokenStream; use quote::quote; -use std::borrow::Cow; -use std::convert::TryFrom; -use syn::{punctuated::Punctuated, spanned::Spanned, AttributeArgs}; +use syn::punctuated::Punctuated; +use syn::spanned::Spanned; +use syn::AttributeArgs; + +use crate::macros::deku_read::emit_deku_read; +use crate::macros::deku_write::emit_deku_write; mod macros; @@ -210,7 +215,7 @@ impl DekuData { } else { Ok(()) } - } + }, ast::Data::Enum(_) => { // Validate `type` or `id` is specified if data.id_type.is_none() && data.id.is_none() { @@ -251,7 +256,7 @@ impl DekuData { } Ok(()) - } + }, } } @@ -692,7 +697,7 @@ fn map_litstr_as_tokenstream( v.parse::() .expect("could not parse token stream"), ) - } + }, None => None, }) } @@ -709,7 +714,7 @@ fn gen_field_ident(ident: Option, index: usize, prefix: bool) -> let index = syn::Index::from(index); let prefix = if prefix { "field_" } else { "" }; format!("{}{}", prefix, quote! { #index }) - } + }, }; field_name.parse().unwrap() @@ -907,7 +912,7 @@ fn remove_deku_attrs(fields: &mut syn::Fields) { match fields { syn::Fields::Named(ref mut fields) => remove_deku_field_attrs(&mut fields.named), syn::Fields::Unnamed(ref mut fields) => remove_deku_field_attrs(&mut fields.unnamed), - syn::Fields::Unit => {} + syn::Fields::Unit => {}, } } @@ -915,7 +920,7 @@ fn remove_temp_fields(fields: &mut syn::Fields) { match fields { syn::Fields::Named(ref mut fields) => remove_deku_temp_fields(&mut fields.named), syn::Fields::Unnamed(ref mut fields) => remove_deku_temp_fields(&mut fields.unnamed), - syn::Fields::Unit => {} + syn::Fields::Unit => {}, } } @@ -941,7 +946,7 @@ pub fn deku_derive( Ok(v) => v, Err(e) => { return proc_macro::TokenStream::from(e.write_errors()); - } + }, }; // Parse item @@ -966,7 +971,7 @@ pub fn deku_derive( for variant in input_enum.variants.iter_mut() { remove_temp_fields(&mut variant.fields) } - } + }, _ => unimplemented!(), } @@ -982,13 +987,13 @@ pub fn deku_derive( syn::Data::Struct(ref mut input_struct) => { input.attrs.retain(is_not_deku); remove_deku_attrs(&mut input_struct.fields) - } + }, syn::Data::Enum(ref mut input_enum) => { for variant in input_enum.variants.iter_mut() { variant.attrs.retain(is_not_deku); remove_deku_attrs(&mut variant.fields) } - } + }, _ => unimplemented!(), } @@ -1006,10 +1011,11 @@ pub fn deku_derive( #[cfg(test)] mod tests { - use super::*; use rstest::rstest; use syn::parse_str; + use super::*; + #[rstest(input, // Valid struct case::struct_empty(r#"struct Test {}"#), diff --git a/deku-derive/src/macros/deku_read.rs b/deku-derive/src/macros/deku_read.rs index 5410608e..314d1918 100644 --- a/deku-derive/src/macros/deku_read.rs +++ b/deku-derive/src/macros/deku_read.rs @@ -1,16 +1,16 @@ +use std::convert::TryFrom; + +use darling::ast::{Data, Fields}; +use darling::ToTokens; +use proc_macro2::TokenStream; +use quote::quote; +use syn::spanned::Spanned; + use crate::macros::{ gen_ctx_types_and_arg, gen_field_args, gen_internal_field_ident, gen_internal_field_idents, gen_type_from_ctx_id, pad_bits, token_contains_string, wrap_default_ctx, }; use crate::{DekuData, DekuDataEnum, DekuDataStruct, FieldData, Id}; -use darling::{ - ast::{Data, Fields}, - ToTokens, -}; -use proc_macro2::TokenStream; -use quote::quote; -use std::convert::TryFrom; -use syn::spanned::Spanned; pub(crate) fn emit_deku_read(input: &DekuData) -> Result { match &input.data { @@ -64,19 +64,15 @@ fn emit_struct(input: &DekuData) -> Result { use core::convert::TryFrom; use ::#crate_::bitvec::BitView; let __deku_input_bits = __deku_input.0.view_bits::<::#crate_::bitvec::Msb0>(); - - let mut __deku_rest = __deku_input_bits; - __deku_rest = &__deku_rest[__deku_input.1..]; + let mut __deku_rest = &__deku_input_bits[__deku_input.1..]; + let mut __deku_total_read = 0; #magic_read #(#field_reads)* let __deku_value = #initialize_struct; - let __deku_pad = 8 * ((__deku_rest.len() + 7) / 8) - __deku_rest.len(); - let __deku_read_idx = __deku_input_bits.len() - (__deku_rest.len() + __deku_pad); - - Ok(((__deku_input_bits[__deku_read_idx..].domain().region().unwrap().1, __deku_pad), __deku_value)) + Ok((__deku_total_read, __deku_value)) }, &input.ctx, &input.ctx_default, @@ -98,18 +94,19 @@ fn emit_struct(input: &DekuData) -> Result { let read_body = quote! { use core::convert::TryFrom; let mut __deku_rest = __deku_input_bits; + let mut __deku_total_read = 0; #magic_read #(#field_reads)* let __deku_value = #initialize_struct; - Ok((__deku_rest, __deku_value)) + Ok((__deku_total_read, __deku_value)) }; tokens.extend(quote! { impl #imp ::#crate_::DekuRead<#lifetime, #ctx_types> for #ident #wher { - fn read(__deku_input_bits: &#lifetime ::#crate_::bitvec::BitSlice, #ctx_arg) -> core::result::Result<(&#lifetime ::#crate_::bitvec::BitSlice, Self), ::#crate_::DekuError> { + fn read(__deku_input_bits: &#lifetime ::#crate_::bitvec::BitSlice, #ctx_arg) -> core::result::Result<(usize, Self), ::#crate_::DekuError> { #read_body } } @@ -120,7 +117,7 @@ fn emit_struct(input: &DekuData) -> Result { tokens.extend(quote! { impl #imp ::#crate_::DekuRead<#lifetime> for #ident #wher { - fn read(__deku_input_bits: &#lifetime ::#crate_::bitvec::BitSlice, _: ()) -> core::result::Result<(&#lifetime ::#crate_::bitvec::BitSlice, Self), ::#crate_::DekuError> { + fn read(__deku_input_bits: &#lifetime ::#crate_::bitvec::BitSlice, _: ()) -> core::result::Result<(usize, Self), ::#crate_::DekuError> { #read_body } } @@ -229,7 +226,8 @@ fn emit_enum(input: &DekuData) -> Result { // if we're consuming an id, set the rest to new_rest before reading the variant let new_rest = if consume_id { quote! { - __deku_rest = __deku_new_rest; + __deku_rest = &__deku_rest[__deku_amt_read..]; + __deku_total_read += __deku_amt_read; } } else { quote! {} @@ -289,11 +287,11 @@ fn emit_enum(input: &DekuData) -> Result { let variant_id_read = if id.is_some() { quote! { - let (__deku_new_rest, __deku_variant_id) = (__deku_rest, (#id)); + let (__deku_amt_read, __deku_variant_id) = (0, (#id)); } } else if id_type.is_some() { quote! { - let (__deku_new_rest, __deku_variant_id) = <#id_type>::read(__deku_rest, (#id_args))?; + let (__deku_amt_read, __deku_variant_id) = <#id_type>::read(__deku_rest, (#id_args))?; } } else { // either `id` or `type` needs to be specified @@ -317,18 +315,14 @@ fn emit_enum(input: &DekuData) -> Result { use core::convert::TryFrom; use ::#crate_::bitvec::BitView; let __deku_input_bits = __deku_input.0.view_bits::<::#crate_::bitvec::Msb0>(); - - let mut __deku_rest = __deku_input_bits; - __deku_rest = &__deku_rest[__deku_input.1..]; + let mut __deku_rest = &__deku_input_bits[__deku_input.1..]; + let mut __deku_total_read = 0; #magic_read #variant_read - let __deku_pad = 8 * ((__deku_rest.len() + 7) / 8) - __deku_rest.len(); - let __deku_read_idx = __deku_input_bits.len() - (__deku_rest.len() + __deku_pad); - - Ok(((__deku_input_bits[__deku_read_idx..].domain().region().unwrap().1, __deku_pad), __deku_value)) + Ok((__deku_total_read, __deku_value)) }, &input.ctx, &input.ctx_default, @@ -349,18 +343,19 @@ fn emit_enum(input: &DekuData) -> Result { let read_body = quote! { use core::convert::TryFrom; let mut __deku_rest = __deku_input_bits; + let mut __deku_total_read = 0; #magic_read #variant_read - Ok((__deku_rest, __deku_value)) + Ok((__deku_total_read, __deku_value)) }; tokens.extend(quote! { #[allow(non_snake_case)] impl #imp ::#crate_::DekuRead<#lifetime, #ctx_types> for #ident #wher { - fn read(__deku_input_bits: &#lifetime ::#crate_::bitvec::BitSlice, #ctx_arg) -> core::result::Result<(&#lifetime ::#crate_::bitvec::BitSlice, Self), ::#crate_::DekuError> { + fn read(__deku_input_bits: &#lifetime ::#crate_::bitvec::BitSlice, #ctx_arg) -> core::result::Result<(usize, Self), ::#crate_::DekuError> { #read_body } } @@ -372,7 +367,7 @@ fn emit_enum(input: &DekuData) -> Result { tokens.extend(quote! { #[allow(non_snake_case)] impl #imp ::#crate_::DekuRead<#lifetime> for #ident #wher { - fn read(__deku_input_bits: &#lifetime ::#crate_::bitvec::BitSlice, _: ()) -> core::result::Result<(&#lifetime ::#crate_::bitvec::BitSlice, Self), ::#crate_::DekuError> { + fn read(__deku_input_bits: &#lifetime ::#crate_::bitvec::BitSlice, _: ()) -> core::result::Result<(usize, Self), ::#crate_::DekuError> { #read_body } } @@ -414,12 +409,13 @@ fn emit_magic_read(input: &DekuData) -> TokenStream { let __deku_magic = #magic; for __deku_byte in __deku_magic { - let (__deku_new_rest, __deku_read_byte) = u8::read(__deku_rest, ())?; + let (__deku_amt_read, __deku_read_byte) = u8::read(__deku_rest, ())?; if *__deku_byte != __deku_read_byte { return Err(::#crate_::DekuError::Parse(format!("Missing magic value {:?}", #magic))); } - __deku_rest = __deku_new_rest; + __deku_rest = &__deku_rest[__deku_amt_read..]; + __deku_total_read += __deku_amt_read; } } } else { @@ -497,6 +493,7 @@ fn emit_padding(bit_size: &TokenStream) -> TokenStream { if __deku_rest.len() >= __deku_pad { let (__deku_padded_bits, __deku_new_rest) = __deku_rest.split_at(__deku_pad); __deku_rest = __deku_new_rest; + __deku_total_read += __deku_pad; } else { return Err(::#crate_::DekuError::Incomplete(::#crate_::error::NeedSize::new(__deku_pad))); } @@ -655,10 +652,11 @@ fn emit_field_read( ); let field_read_normal = quote! { - let (__deku_new_rest, __deku_value) = #field_read_func?; + let (__deku_amt_read, __deku_value) = #field_read_func?; let __deku_value: #field_type = #field_map(__deku_value)?; - __deku_rest = __deku_new_rest; + __deku_rest = &__deku_rest[__deku_amt_read..]; + __deku_total_read += __deku_amt_read; __deku_value }; @@ -675,13 +673,13 @@ fn emit_field_read( #field_read_normal } } - } + }, (true, None) => { // #[deku(skip)] ==> `skip` quote! { #field_default } - } + }, (false, Some(field_cond)) => { // #[deku(cond = "...")] ==> read if `cond` quote! { @@ -691,12 +689,12 @@ fn emit_field_read( #field_default } } - } + }, (false, None) => { quote! { #field_read_normal } - } + }, }; let field_read = quote! { @@ -732,7 +730,7 @@ pub fn emit_from_bytes( quote! { impl #imp ::#crate_::DekuContainerRead<#lifetime> for #ident #wher { #[allow(non_snake_case)] - fn from_bytes(__deku_input: (&#lifetime [u8], usize)) -> core::result::Result<((&#lifetime [u8], usize), Self), ::#crate_::DekuError> { + fn from_bytes(__deku_input: (&#lifetime [u8], usize)) -> core::result::Result<(usize, Self), ::#crate_::DekuError> { #body } } @@ -752,8 +750,8 @@ pub fn emit_try_from( type Error = ::#crate_::DekuError; fn try_from(input: &#lifetime [u8]) -> core::result::Result { - let (rest, res) = ::from_bytes((input, 0))?; - if !rest.0.is_empty() { + let (amt_read, res) = ::from_bytes((input, 0))?; + if (amt_read / 8) != input.len() { return Err(::#crate_::DekuError::Parse(format!("Too much data"))); } Ok(res) diff --git a/deku-derive/src/macros/deku_write.rs b/deku-derive/src/macros/deku_write.rs index 331aea5d..76959bea 100644 --- a/deku-derive/src/macros/deku_write.rs +++ b/deku-derive/src/macros/deku_write.rs @@ -1,12 +1,14 @@ +use std::convert::TryFrom; + +use darling::ast::{Data, Fields}; +use proc_macro2::TokenStream; +use quote::quote; + use crate::macros::{ gen_ctx_types_and_arg, gen_field_args, gen_struct_destruction, pad_bits, token_contains_string, wrap_default_ctx, }; use crate::{DekuData, DekuDataEnum, DekuDataStruct, FieldData, Id}; -use darling::ast::{Data, Fields}; -use proc_macro2::TokenStream; -use quote::quote; -use std::convert::TryFrom; pub(crate) fn emit_deku_write(input: &DekuData) -> Result { match &input.data { @@ -200,13 +202,13 @@ fn emit_enum(input: &DekuData) -> Result { let mut __deku_variant_id: #id_type = #v; __deku_variant_id.write(__deku_output, (#id_args))?; } - } + }, Id::LitByteStr(v) => { quote! { let mut __deku_variant_id: #id_type = *#v; __deku_variant_id.write(__deku_output, (#id_args))?; } - } + }, } } else if variant.id_pat.is_some() { quote! {} @@ -570,18 +572,18 @@ fn emit_field_write( #field_write_normal } } - } + }, (true, None) => { // #[deku(skip)] ==> `skip` quote! { // skipping, no write } - } + }, (false, _) => { quote! { #field_write_normal } - } + }, }; let field_write = quote! { diff --git a/deku-derive/src/macros/mod.rs b/deku-derive/src/macros/mod.rs index eaae7a86..1fd3c00e 100644 --- a/deku-derive/src/macros/mod.rs +++ b/deku-derive/src/macros/mod.rs @@ -1,4 +1,3 @@ -use crate::Num; use proc_macro2::{Ident, Span, TokenStream}; use quote::{quote, ToTokens}; use syn::parse::Parser; @@ -6,6 +5,8 @@ use syn::punctuated::Punctuated; use syn::spanned::Spanned; use syn::token::Comma; +use crate::Num; + pub(crate) mod deku_read; pub(crate) mod deku_write; @@ -294,7 +295,7 @@ fn gen_endian_from_str(s: &syn::LitStr) -> syn::Result { // treat as variable, possibly from `ctx` let v: TokenStream = s.value().parse()?; Ok(quote! {#v}) - } + }, } } @@ -335,7 +336,7 @@ fn pad_bits( match (bits, bytes) { (Some(pad_bits), Some(pad_bytes)) => { emit_padding("e! { (#pad_bits) + ((#pad_bytes) * 8) }) - } + }, (Some(pad_bits), None) => emit_padding(pad_bits), (None, Some(pad_bytes)) => emit_padding("e! {((#pad_bytes) * 8)}), (None, None) => quote!(), diff --git a/examples/custom_reader_and_writer.rs b/examples/custom_reader_and_writer.rs index 29e35e58..099795c8 100644 --- a/examples/custom_reader_and_writer.rs +++ b/examples/custom_reader_and_writer.rs @@ -1,13 +1,14 @@ +use std::convert::TryInto; + use deku::bitvec::{BitSlice, BitVec, Msb0}; use deku::ctx::BitSize; use deku::prelude::*; -use std::convert::TryInto; fn bit_flipper_read( field_a: u8, rest: &BitSlice, bit_size: BitSize, -) -> Result<(&BitSlice, u8), DekuError> { +) -> Result<(usize, u8), DekuError> { // Access to previously read fields println!("field_a = 0x{:X}", field_a); @@ -18,12 +19,12 @@ fn bit_flipper_read( println!("bit_size: {:?}", bit_size); // read field_b, calling original func - let (rest, value) = u8::read(rest, bit_size)?; + let (amt_read, value) = u8::read(rest, bit_size)?; // flip the bits on value if field_a is 0x01 let value = if field_a == 0x01 { !value } else { value }; - Ok((rest, value)) + Ok((amt_read, value)) } fn bit_flipper_write( diff --git a/examples/enums.rs b/examples/enums.rs index f6a16a90..522b9801 100644 --- a/examples/enums.rs +++ b/examples/enums.rs @@ -1,6 +1,7 @@ +use std::convert::TryFrom; + use deku::prelude::*; use hexlit::hex; -use std::convert::TryFrom; #[derive(Debug, PartialEq, DekuRead, DekuWrite)] #[deku(type = "u8")] @@ -21,6 +22,8 @@ enum DekuTest { Var5 { id: u8 }, #[deku(id_pat = "&id if id > 6")] Var6 { id: u8 }, + #[deku(id_pat = "_")] + VarDefault { id: u8, value: u8 }, } fn main() { diff --git a/examples/enums_catch_all.rs b/examples/enums_catch_all.rs index b967ad86..8126d1e0 100644 --- a/examples/enums_catch_all.rs +++ b/examples/enums_catch_all.rs @@ -1,7 +1,7 @@ +use std::convert::{TryFrom, TryInto}; + use deku::prelude::*; use hexlit::hex; -use std::convert::TryFrom; -use std::convert::TryInto; #[derive(Clone, Copy, PartialEq, Eq, Debug, DekuWrite, DekuRead)] #[deku(type = "u8")] diff --git a/examples/example.rs b/examples/example.rs index 6e957d33..9f29414a 100644 --- a/examples/example.rs +++ b/examples/example.rs @@ -1,8 +1,9 @@ #![allow(clippy::unusual_byte_groupings)] -use deku::prelude::*; use std::convert::{TryFrom, TryInto}; +use deku::prelude::*; + #[derive(Debug, PartialEq, DekuRead, DekuWrite)] struct FieldF { #[deku(bits = "6")] @@ -15,7 +16,6 @@ struct FieldF { // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // | field_a | field_b |c| field_d | e | f | // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// #[derive(Debug, PartialEq, DekuRead, DekuWrite)] // #[deku(endian = "little")] // By default it uses the system endianness, but can be overwritten struct DekuTest { @@ -36,16 +36,16 @@ struct DekuTest { fn main() { let test_data: &[u8] = [ - 0xAB, + 0xab, 0b1010010_1, - 0xAB, - 0xCD, + 0xab, + 0xcd, 0b1100_0110, 0x02, - 0xBE, - 0xEF, - 0xC0, - 0xFE, + 0xbe, + 0xef, + 0xc0, + 0xfe, ] .as_ref(); @@ -53,14 +53,14 @@ fn main() { assert_eq!( DekuTest { - field_a: 0xAB, + field_a: 0xab, field_b: 0b0_1010010, field_c: 0b0000000_1, - field_d: 0xABCD, + field_d: 0xabcd, field_e: 0b0000_0011, field_f: FieldF { data: 0b00_000110 }, num_items: 2, - items: vec![0xBEEF, 0xC0FE], + items: vec![0xbeef, 0xc0fe], }, test_deku ); diff --git a/examples/ipv4.rs b/examples/ipv4.rs index 77052834..ff3cf589 100644 --- a/examples/ipv4.rs +++ b/examples/ipv4.rs @@ -1,8 +1,9 @@ -use deku::prelude::*; -use hexlit::hex; use std::convert::{TryFrom, TryInto}; use std::net::Ipv4Addr; +use deku::prelude::*; +use hexlit::hex; + /// Ipv4 Header /// ```text /// 0 1 2 3 @@ -42,9 +43,9 @@ pub struct Ipv4Header { pub protocol: u8, // Protocol pub checksum: u16, // Header checksum pub src: Ipv4Addr, // Source IP Address - pub dst: Ipv4Addr, // Destination IP Address - // options - // padding + pub dst: Ipv4Addr, /* Destination IP Address + * options + * padding */ } fn main() { diff --git a/src/attributes.rs b/src/attributes.rs index 45b70fc7..41e72580 100644 --- a/src/attributes.rs +++ b/src/attributes.rs @@ -810,9 +810,9 @@ impl DekuTest { /// Read and convert to String fn read( rest: &BitSlice, - ) -> Result<(&BitSlice, String), DekuError> { - let (rest, value) = u8::read(rest, ())?; - Ok((rest, value.to_string())) + ) -> Result<(usize, String), DekuError> { + let (amt_read, value) = u8::read(rest, ())?; + Ok((amt_read, value.to_string())) } /// Parse from String to u8 and write @@ -871,7 +871,7 @@ struct Test { let data: Vec = vec![0x01, 0x02]; -let (rest, value) = Test::from_bytes((&data[..], 0)).unwrap(); +let (amt_read, value) = Test::from_bytes((&data[..], 0)).unwrap(); assert_eq!(value.a, 0x01); assert_eq!(value.sub.b, 0x01 + 0x02) ``` @@ -937,7 +937,7 @@ struct Test { let data: Vec = vec![0x01, 0x02]; // Use with context from `Test` -let (rest, value) = Test::from_bytes((&data[..], 0)).unwrap(); +let (amt_Read, value) = Test::from_bytes((&data[..], 0)).unwrap(); assert_eq!(value.a, 0x01); assert_eq!(value.sub.b, 0x01 + 0x02); @@ -945,7 +945,7 @@ assert_eq!(value.sub.b, 0x01 + 0x02); // Note: `from_bytes` is now available on `SubType` let data: Vec = vec![0x02]; -let (rest, value) = Subtype::from_bytes((&data[..], 0)).unwrap(); +let (amt_read, value) = Subtype::from_bytes((&data[..], 0)).unwrap(); assert_eq!(value.b, 0x01 + 0x02) ``` @@ -1019,7 +1019,7 @@ enum DekuTest { let data: Vec = vec![0x01, 0xFF, 0x02, 0xAB, 0xEF, 0xBE]; -let (rest, value) = DekuTest::from_bytes((data.as_ref(), 0)).unwrap(); +let (amt_read, value) = DekuTest::from_bytes((data.as_ref(), 0)).unwrap(); assert_eq!( DekuTest::VariantA(0xFF), @@ -1029,7 +1029,7 @@ assert_eq!( let variant_bytes: Vec = value.try_into().unwrap(); assert_eq!(vec![0x01, 0xFF], variant_bytes); -let (rest, value) = DekuTest::from_bytes(rest).unwrap(); +let (amt_read, value) = DekuTest::from_bytes((data.as_ref(), amt_read)).unwrap(); assert_eq!( DekuTest::VariantB(0xAB, 0xBEEF), @@ -1053,7 +1053,7 @@ enum DekuTest { let data: Vec = vec![0x01, 0x02]; -let (rest, value) = DekuTest::from_bytes((data.as_ref(), 0)).unwrap(); +let (amt_read, value) = DekuTest::from_bytes((data.as_ref(), 0)).unwrap(); assert_eq!( DekuTest::VariantA, @@ -1063,7 +1063,7 @@ assert_eq!( let variant_bytes: Vec = value.try_into().unwrap(); assert_eq!(vec![0x01], variant_bytes); -let (rest, value) = DekuTest::from_bytes(rest).unwrap(); +let (rest, value) = DekuTest::from_bytes((data.as_ref(), amt_read)).unwrap(); assert_eq!( DekuTest::VariantB, @@ -1099,7 +1099,7 @@ enum DekuTest { let data: Vec = vec![0x03, 0xFF]; -let (rest, value) = DekuTest::from_bytes((data.as_ref(), 0)).unwrap(); +let (amt_read, value) = DekuTest::from_bytes((data.as_ref(), 0)).unwrap(); assert_eq!( DekuTest::VariantB { id: 0x03 }, @@ -1109,7 +1109,7 @@ assert_eq!( let variant_bytes: Vec = value.try_into().unwrap(); assert_eq!(vec![0x03], variant_bytes); -let (rest, value) = DekuTest::from_bytes(rest).unwrap(); +let (rest, value) = DekuTest::from_bytes((data.as_ref(), amt_read)).unwrap(); assert_eq!( DekuTest::VariantC(0xFF), @@ -1143,7 +1143,7 @@ enum DekuTest { let data: Vec = vec![0b1001_0110, 0xFF]; -let (rest, value) = DekuTest::from_bytes((&data, 0)).unwrap(); +let (amt_read, value) = DekuTest::from_bytes((&data, 0)).unwrap(); assert_eq!( DekuTest::VariantA(0b0110, 0xFF), diff --git a/src/ctx.rs b/src/ctx.rs index db2a1e04..84ad4dc6 100644 --- a/src/ctx.rs +++ b/src/ctx.rs @@ -58,6 +58,7 @@ impl FromStr for Endian { /// # Examples /// ```rust /// use std::str::FromStr; + /// /// use deku::ctx::Endian; /// assert_eq!(FromStr::from_str("little"), Ok(Endian::Little)); /// assert_eq!(FromStr::from_str("big"), Ok(Endian::Big)); diff --git a/src/error.rs b/src/error.rs index bfeabf96..061f58dc 100644 --- a/src/error.rs +++ b/src/error.rs @@ -2,7 +2,8 @@ #![cfg(feature = "alloc")] -use alloc::{format, string::String}; +use alloc::format; +use alloc::string::String; /// Number of bits needed to retry parsing #[derive(Debug, Clone, PartialEq, Eq)] diff --git a/src/impls/bool.rs b/src/impls/bool.rs index 478b5769..b413c417 100644 --- a/src/impls/bool.rs +++ b/src/impls/bool.rs @@ -1,9 +1,10 @@ -use crate::{DekuError, DekuRead, DekuWrite}; -use bitvec::prelude::*; - #[cfg(feature = "alloc")] use alloc::format; +use bitvec::prelude::*; + +use crate::{DekuError, DekuRead, DekuWrite}; + impl<'a, Ctx> DekuRead<'a, Ctx> for bool where Ctx: Copy, @@ -11,11 +12,8 @@ where { /// wrapper around u8::read with consideration to context, such as bit size /// true if the result of the read is `1`, false if `0` and error otherwise - fn read( - input: &'a BitSlice, - inner_ctx: Ctx, - ) -> Result<(&'a BitSlice, Self), DekuError> { - let (rest, val) = u8::read(input, inner_ctx)?; + fn read(input: &'a BitSlice, inner_ctx: Ctx) -> Result<(usize, Self), DekuError> { + let (amt_read, val) = u8::read(input, inner_ctx)?; let ret = match val { 0x01 => Ok(true), @@ -23,7 +21,7 @@ where _ => Err(DekuError::Parse(format!("cannot parse bool value: {val}",))), }?; - Ok((rest, ret)) + Ok((amt_read, ret)) } } @@ -42,10 +40,11 @@ where #[cfg(test)] mod tests { - use super::*; use hexlit::hex; use rstest::rstest; + use super::*; + #[rstest(input, expected, case(&hex!("00"), false), case(&hex!("01"), true), @@ -55,9 +54,9 @@ mod tests { )] fn test_bool(input: &[u8], expected: bool) { let bit_slice = input.view_bits::(); - let (rest, res_read) = bool::read(bit_slice, ()).unwrap(); + let (amt_read, res_read) = bool::read(bit_slice, ()).unwrap(); assert_eq!(expected, res_read); - assert!(rest.is_empty()); + assert_eq!(amt_read, 8); let mut res_write = bitvec![u8, Msb0;]; res_read.write(&mut res_write, ()).unwrap(); @@ -69,9 +68,9 @@ mod tests { let input = &[0b01_000000]; let bit_slice = input.view_bits::(); - let (rest, res_read) = bool::read(bit_slice, crate::ctx::BitSize(2)).unwrap(); + let (amt_read, res_read) = bool::read(bit_slice, crate::ctx::BitSize(2)).unwrap(); assert!(res_read); - assert_eq!(6, rest.len()); + assert_eq!(amt_read, 2); let mut res_write = bitvec![u8, Msb0;]; res_read.write(&mut res_write, ()).unwrap(); diff --git a/src/impls/boxed.rs b/src/impls/boxed.rs index 9ce5465e..74e798dc 100644 --- a/src/impls/boxed.rs +++ b/src/impls/boxed.rs @@ -1,22 +1,23 @@ -use crate::{ctx::Limit, DekuError, DekuRead, DekuWrite}; -use alloc::{boxed::Box, vec::Vec}; +use alloc::boxed::Box; +use alloc::vec::Vec; + use bitvec::prelude::*; +use crate::ctx::Limit; +use crate::{DekuError, DekuRead, DekuWrite}; + impl<'a, T, Ctx> DekuRead<'a, Ctx> for Box where T: DekuRead<'a, Ctx>, Ctx: Copy, { /// Read a T from input and store as Box - fn read( - input: &'a BitSlice, - inner_ctx: Ctx, - ) -> Result<(&'a BitSlice, Self), DekuError> + fn read(input: &'a BitSlice, inner_ctx: Ctx) -> Result<(usize, Self), DekuError> where Self: Sized, { - let (rest, val) = ::read(input, inner_ctx)?; - Ok((rest, Box::new(val))) + let (amt_read, val) = ::read(input, inner_ctx)?; + Ok((amt_read, Box::new(val))) } } @@ -41,13 +42,13 @@ where fn read( input: &'a BitSlice, (limit, inner_ctx): (Limit, Ctx), - ) -> Result<(&'a BitSlice, Self), DekuError> + ) -> Result<(usize, Self), DekuError> where Self: Sized, { // use Vec's implementation and convert to Box<[T]> - let (rest, val) = >::read(input, (limit, inner_ctx))?; - Ok((rest, val.into_boxed_slice())) + let (amt_read, val) = >::read(input, (limit, inner_ctx))?; + Ok((amt_read, val.into_boxed_slice())) } } @@ -67,10 +68,11 @@ where #[cfg(test)] mod tests { + use rstest::rstest; + use super::*; use crate::ctx::*; use crate::native_endian; - use rstest::rstest; #[rstest(input, expected, expected_rest, case( @@ -81,9 +83,9 @@ mod tests { )] fn test_boxed(input: &[u8], expected: Box, expected_rest: &BitSlice) { let bit_slice = input.view_bits::(); - let (rest, res_read) = >::read(bit_slice, ()).unwrap(); + let (amt_read, res_read) = >::read(bit_slice, ()).unwrap(); assert_eq!(expected, res_read); - assert_eq!(expected_rest, rest); + assert_eq!(expected_rest, bit_slice[amt_read..]); let mut res_write = bitvec![u8, Msb0;]; res_read.write(&mut res_write, ()).unwrap(); @@ -113,10 +115,10 @@ mod tests { // Unwrap here because all test cases are `Some`. let bit_size = bit_size.unwrap(); - let (rest, res_read) = + let (amt_read, res_read) = >::read(bit_slice, (limit, (endian, BitSize(bit_size)))).unwrap(); assert_eq!(expected, res_read); - assert_eq!(expected_rest, rest); + assert_eq!(expected_rest, bit_slice[amt_read..]); let mut res_write = bitvec![u8, Msb0;]; res_read diff --git a/src/impls/cow.rs b/src/impls/cow.rs index e685aac2..c48cb75f 100644 --- a/src/impls/cow.rs +++ b/src/impls/cow.rs @@ -1,22 +1,21 @@ -use crate::{DekuError, DekuRead, DekuWrite}; -use bitvec::prelude::*; use std::borrow::{Borrow, Cow}; +use bitvec::prelude::*; + +use crate::{DekuError, DekuRead, DekuWrite}; + impl<'a, T, Ctx> DekuRead<'a, Ctx> for Cow<'a, T> where T: DekuRead<'a, Ctx> + Clone, Ctx: Copy, { /// Read a T from input and store as Cow - fn read( - input: &'a BitSlice, - inner_ctx: Ctx, - ) -> Result<(&'a BitSlice, Self), DekuError> + fn read(input: &'a BitSlice, inner_ctx: Ctx) -> Result<(usize, Self), DekuError> where Self: Sized, { - let (rest, val) = ::read(input, inner_ctx)?; - Ok((rest, Cow::Owned(val))) + let (amt_read, val) = ::read(input, inner_ctx)?; + Ok((amt_read, Cow::Owned(val))) } } @@ -33,9 +32,10 @@ where #[cfg(test)] mod tests { + use rstest::rstest; + use super::*; use crate::native_endian; - use rstest::rstest; #[rstest(input, expected, expected_rest, case( @@ -46,9 +46,9 @@ mod tests { )] fn test_cow(input: &[u8], expected: Cow, expected_rest: &BitSlice) { let bit_slice = input.view_bits::(); - let (rest, res_read) = >::read(bit_slice, ()).unwrap(); + let (amt_read, res_read) = >::read(bit_slice, ()).unwrap(); assert_eq!(expected, res_read); - assert_eq!(expected_rest, rest); + assert_eq!(expected_rest, bit_slice[amt_read..]); let mut res_write = bitvec![u8, Msb0;]; res_read.write(&mut res_write, ()).unwrap(); diff --git a/src/impls/cstring.rs b/src/impls/cstring.rs index 692394fe..cddd943f 100644 --- a/src/impls/cstring.rs +++ b/src/impls/cstring.rs @@ -1,7 +1,10 @@ -use crate::{ctx::*, DekuError, DekuRead, DekuWrite}; -use bitvec::prelude::*; use std::ffi::CString; +use bitvec::prelude::*; + +use crate::ctx::*; +use crate::{DekuError, DekuRead, DekuWrite}; + impl DekuWrite for CString where u8: DekuWrite, @@ -16,14 +19,11 @@ impl<'a, Ctx: Copy> DekuRead<'a, Ctx> for CString where u8: DekuRead<'a, Ctx>, { - fn read( - input: &'a BitSlice, - ctx: Ctx, - ) -> Result<(&'a BitSlice, Self), DekuError> + fn read(input: &'a BitSlice, ctx: Ctx) -> Result<(usize, Self), DekuError> where Self: Sized, { - let (rest, mut bytes) = Vec::read(input, (Limit::from(|b: &u8| *b == 0x00), ctx))?; + let (amt_read, mut bytes) = Vec::read(input, (Limit::from(|b: &u8| *b == 0x00), ctx))?; // TODO: use from_vec_with_nul instead once stable @@ -36,15 +36,16 @@ where let value = CString::new(bytes) .map_err(|e| DekuError::Parse(format!("Failed to convert Vec to CString: {e}")))?; - Ok((rest, value)) + Ok((amt_read, value)) } } #[cfg(test)] mod tests { - use super::*; use rstest::rstest; + use super::*; + #[rstest(input, expected, expected_rest, case( &[b't', b'e', b's', b't', b'\0'], @@ -62,9 +63,9 @@ mod tests { )] fn test_cstring(input: &[u8], expected: CString, expected_rest: &BitSlice) { let bit_slice = input.view_bits::(); - let (rest, res_read) = CString::read(bit_slice, ()).unwrap(); + let (amt_read, res_read) = CString::read(bit_slice, ()).unwrap(); assert_eq!(expected, res_read); - assert_eq!(expected_rest, rest); + assert_eq!(expected_rest, bit_slice[amt_read..]); let mut res_write = bitvec![u8, Msb0;]; res_read.write(&mut res_write, ()).unwrap(); diff --git a/src/impls/hashmap.rs b/src/impls/hashmap.rs index 4a632755..331ac7c9 100644 --- a/src/impls/hashmap.rs +++ b/src/impls/hashmap.rs @@ -1,8 +1,11 @@ -use crate::{ctx::*, DekuError, DekuRead, DekuWrite}; -use bitvec::prelude::*; use std::collections::HashMap; use std::hash::{BuildHasher, Hash}; +use bitvec::prelude::*; + +use crate::ctx::*; +use crate::{DekuError, DekuRead, DekuWrite}; + /// Read `K, V`s into a hashmap until a given predicate returns true /// * `capacity` - an optional capacity to pre-allocate the hashmap with /// * `ctx` - The context required by `K, V`. It will be passed to every `K, V` when constructing. @@ -11,45 +14,47 @@ use std::hash::{BuildHasher, Hash}; /// and a borrow of the latest value to have been read. It should return `true` if reading /// should now stop, and `false` otherwise #[allow(clippy::type_complexity)] -fn read_hashmap_with_predicate< - 'a, +fn read_hashmap_with_predicate<'a, K, V, S, Ctx, Predicate>( + input: &'a BitSlice, + capacity: Option, + ctx: Ctx, + mut predicate: Predicate, +) -> Result<(usize, HashMap), DekuError> +where K: DekuRead<'a, Ctx> + Eq + Hash, V: DekuRead<'a, Ctx>, S: BuildHasher + Default, Ctx: Copy, Predicate: FnMut(usize, &(K, V)) -> bool, ->( - input: &'a BitSlice, - capacity: Option, - ctx: Ctx, - mut predicate: Predicate, -) -> Result<(&'a BitSlice, HashMap), DekuError> { +{ let mut res = HashMap::with_capacity_and_hasher(capacity.unwrap_or(0), S::default()); let mut rest = input; let mut found_predicate = false; + let mut total_read = 0; + while !found_predicate { - let (new_rest, kv) = <(K, V)>::read(rest, ctx)?; + let (amt_read, kv) = <(K, V)>::read(rest, ctx)?; + rest = &rest[amt_read..]; found_predicate = predicate( - unsafe { new_rest.as_bitptr().offset_from(input.as_bitptr()) } as usize, + unsafe { rest.as_bitptr().offset_from(input.as_bitptr()) } as usize, &kv, ); res.insert(kv.0, kv.1); - rest = new_rest; + total_read += amt_read; } - Ok((rest, res)) + Ok((total_read, res)) } -impl< - 'a, - K: DekuRead<'a, Ctx> + Eq + Hash, - V: DekuRead<'a, Ctx>, - S: BuildHasher + Default, - Ctx: Copy, - Predicate: FnMut(&(K, V)) -> bool, - > DekuRead<'a, (Limit<(K, V), Predicate>, Ctx)> for HashMap +impl<'a, K, V, S, Ctx, Predicate> DekuRead<'a, (Limit<(K, V), Predicate>, Ctx)> for HashMap +where + K: DekuRead<'a, Ctx> + Eq + Hash, + V: DekuRead<'a, Ctx>, + S: BuildHasher + Default, + Ctx: Copy, + Predicate: FnMut(&(K, V)) -> bool, { /// Read `K, V`s until the given limit /// * `limit` - the limiting factor on the amount of `K, V`s to read @@ -61,8 +66,9 @@ impl< /// # use deku::bitvec::BitView; /// # use std::collections::HashMap; /// let input: Vec = vec![100, 1, 2, 3, 4]; - /// let (rest, map) = HashMap::::read(input.view_bits(), (1.into(), Endian::Little)).unwrap(); - /// assert!(rest.is_empty()); + /// let (amt_read, map) = + /// HashMap::::read(input.view_bits(), (1.into(), Endian::Little)).unwrap(); + /// assert_eq!((amt_read / 8), 5); /// let mut expected = HashMap::::default(); /// expected.insert(100, 0x04030201); /// assert_eq!(expected, map) @@ -70,7 +76,7 @@ impl< fn read( input: &'a BitSlice, (limit, inner_ctx): (Limit<(K, V), Predicate>, Ctx), - ) -> Result<(&'a BitSlice, Self), DekuError> + ) -> Result<(usize, Self), DekuError> where Self: Sized, { @@ -79,7 +85,7 @@ impl< Limit::Count(mut count) => { // Handle the trivial case of reading an empty hashmap if count == 0 { - return Ok((input, HashMap::::default())); + return Ok((0, HashMap::::default())); } // Otherwise, read until we have read `count` elements @@ -87,12 +93,12 @@ impl< count -= 1; count == 0 }) - } + }, // Read until a given predicate returns true Limit::Until(mut predicate, _) => { read_hashmap_with_predicate(input, None, inner_ctx, move |_, kv| predicate(kv)) - } + }, // Read until a given quantity of bits have been read Limit::BitSize(size) => { @@ -100,32 +106,31 @@ impl< 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 + // Read until a given quantity of byte 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 }) - } + }, } } } -impl< - 'a, - K: DekuRead<'a> + Eq + Hash, - V: DekuRead<'a>, - S: BuildHasher + Default, - Predicate: FnMut(&(K, V)) -> bool, - > DekuRead<'a, Limit<(K, V), Predicate>> for HashMap +impl<'a, K, V, S, Predicate> DekuRead<'a, Limit<(K, V), Predicate>> for HashMap +where + K: DekuRead<'a> + Eq + Hash, + V: DekuRead<'a>, + S: BuildHasher + Default, + Predicate: FnMut(&(K, V)) -> bool, { /// Read `K, V`s until the given limit from input for types which don't require context. fn read( input: &'a BitSlice, limit: Limit<(K, V), Predicate>, - ) -> Result<(&'a BitSlice, Self), DekuError> + ) -> Result<(usize, Self), DekuError> where Self: Sized, { @@ -161,10 +166,11 @@ impl, V: DekuWrite, S, Ctx: Copy> DekuWrite for Hash #[cfg(test)] mod tests { - use super::*; use rstest::rstest; use rustc_hash::FxHashMap; + use super::*; + // Macro to create a deterministic HashMap for tests // This is needed for tests since the default HashMap Hasher // RandomState will Hash the keys different for each run of the test cases @@ -212,15 +218,15 @@ mod tests { ) { let bit_slice = input.view_bits::(); - let (rest, res_read) = match bit_size { + let (amt_read, res_read) = match bit_size { Some(bit_size) => { FxHashMap::::read(bit_slice, (limit, (endian, BitSize(bit_size)))).unwrap() - } + }, None => FxHashMap::::read(bit_slice, (limit, (endian))).unwrap(), }; assert_eq!(expected, res_read); - assert_eq!(expected_rest, rest); + assert_eq!(expected_rest, bit_slice[amt_read..]); } #[rstest(input, endian, expected, @@ -251,9 +257,9 @@ mod tests { ) { let bit_slice = input.view_bits::(); - let (rest, res_read) = FxHashMap::::read(bit_slice, (limit, endian)).unwrap(); + let (amt_read, res_read) = FxHashMap::::read(bit_slice, (limit, endian)).unwrap(); assert_eq!(expected, res_read); - assert_eq!(expected_rest, rest); + assert_eq!(expected_rest, bit_slice[amt_read..]); let mut res_write = bitvec![u8, Msb0;]; res_read.write(&mut res_write, endian).unwrap(); diff --git a/src/impls/hashset.rs b/src/impls/hashset.rs index eb21532e..ff99e772 100644 --- a/src/impls/hashset.rs +++ b/src/impls/hashset.rs @@ -1,8 +1,11 @@ -use crate::{ctx::*, DekuError, DekuRead, DekuWrite}; -use bitvec::prelude::*; use std::collections::HashSet; use std::hash::{BuildHasher, Hash}; +use bitvec::prelude::*; + +use crate::ctx::*; +use crate::{DekuError, DekuRead, DekuWrite}; + /// Read `T`s into a hashset until a given predicate returns true /// * `capacity` - an optional capacity to pre-allocate the hashset with /// * `ctx` - The context required by `T`. It will be passed to every `T` when constructing. @@ -11,43 +14,44 @@ use std::hash::{BuildHasher, Hash}; /// and a borrow of the latest value to have been read. It should return `true` if reading /// should now stop, and `false` otherwise #[allow(clippy::type_complexity)] -fn read_hashset_with_predicate< - 'a, - T: DekuRead<'a, Ctx> + Eq + Hash, - S: BuildHasher + Default, - Ctx: Copy, - Predicate: FnMut(usize, &T) -> bool, ->( +fn read_hashset_with_predicate<'a, T, S, Ctx, Predicate>( input: &'a BitSlice, capacity: Option, ctx: Ctx, mut predicate: Predicate, -) -> Result<(&'a BitSlice, HashSet), DekuError> { +) -> Result<(usize, HashSet), DekuError> +where + T: DekuRead<'a, Ctx> + Eq + Hash, + S: BuildHasher + Default, + Ctx: Copy, + Predicate: FnMut(usize, &T) -> bool, +{ let mut res = HashSet::with_capacity_and_hasher(capacity.unwrap_or(0), S::default()); let mut rest = input; let mut found_predicate = false; + let mut total_read = 0; while !found_predicate { - let (new_rest, val) = ::read(rest, ctx)?; + let (amt_read, val) = ::read(rest, ctx)?; + rest = &rest[amt_read..]; found_predicate = predicate( - unsafe { new_rest.as_bitptr().offset_from(input.as_bitptr()) } as usize, + unsafe { rest.as_bitptr().offset_from(input.as_bitptr()) } as usize, &val, ); res.insert(val); - rest = new_rest; + total_read += amt_read; } - Ok((rest, res)) + Ok((total_read, res)) } -impl< - 'a, - T: DekuRead<'a, Ctx> + Eq + Hash, - S: BuildHasher + Default, - Ctx: Copy, - Predicate: FnMut(&T) -> bool, - > DekuRead<'a, (Limit, Ctx)> for HashSet +impl<'a, T, S, Ctx, Predicate> DekuRead<'a, (Limit, Ctx)> for HashSet +where + T: DekuRead<'a, Ctx> + Eq + Hash, + S: BuildHasher + Default, + Ctx: Copy, + Predicate: FnMut(&T) -> bool, { /// Read `T`s until the given limit /// * `limit` - the limiting factor on the amount of `T`s to read @@ -60,14 +64,15 @@ impl< /// # use std::collections::HashSet; /// let input = vec![1u8, 2, 3, 4]; /// let expected: HashSet = vec![0x04030201].into_iter().collect(); - /// let (rest, set) = HashSet::::read(input.view_bits(), (1.into(), Endian::Little)).unwrap(); - /// assert!(rest.is_empty()); + /// let (amt_read, set) = + /// HashSet::::read(input.view_bits(), (1.into(), Endian::Little)).unwrap(); + /// assert_eq!(amt_read, 32); /// assert_eq!(expected, set) /// ``` fn read( input: &'a BitSlice, (limit, inner_ctx): (Limit, Ctx), - ) -> Result<(&'a BitSlice, Self), DekuError> + ) -> Result<(usize, Self), DekuError> where Self: Sized, { @@ -76,7 +81,7 @@ impl< Limit::Count(mut count) => { // Handle the trivial case of reading an empty hashset if count == 0 { - return Ok((input, HashSet::::default())); + return Ok((0, HashSet::::default())); } // Otherwise, read until we have read `count` elements @@ -84,14 +89,14 @@ impl< count -= 1; count == 0 }) - } + }, // Read until a given predicate returns true Limit::Until(mut predicate, _) => { read_hashset_with_predicate(input, None, inner_ctx, move |_, value| { predicate(value) }) - } + }, // Read until a given quantity of bits have been read Limit::BitSize(size) => { @@ -99,7 +104,7 @@ impl< 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) => { @@ -107,7 +112,7 @@ impl< read_hashset_with_predicate(input, None, inner_ctx, move |read_bits, _| { read_bits == bit_size }) - } + }, } } } @@ -119,7 +124,7 @@ impl<'a, T: DekuRead<'a> + Eq + Hash, S: BuildHasher + Default, Predicate: FnMut fn read( input: &'a BitSlice, limit: Limit, - ) -> Result<(&'a BitSlice, Self), DekuError> + ) -> Result<(usize, Self), DekuError> where Self: Sized, { @@ -153,10 +158,11 @@ impl, S, Ctx: Copy> DekuWrite for HashSet { #[cfg(test)] mod tests { - use super::*; use rstest::rstest; use rustc_hash::FxHashSet; + use super::*; + #[rstest(input, endian, bit_size, limit, expected, expected_rest, case::count_0([0xAA].as_ref(), Endian::Little, Some(8), 0.into(), FxHashSet::default(), bits![u8, Msb0; 1, 0, 1, 0, 1, 0, 1, 0]), case::count_1([0xAA, 0xBB].as_ref(), Endian::Little, Some(8), 1.into(), vec![0xAA].into_iter().collect(), bits![u8, Msb0; 1, 0, 1, 1, 1, 0, 1, 1]), @@ -187,15 +193,15 @@ mod tests { ) { let bit_slice = input.view_bits::(); - let (rest, res_read) = match bit_size { + let (amt_read, res_read) = match bit_size { Some(bit_size) => { FxHashSet::::read(bit_slice, (limit, (endian, BitSize(bit_size)))).unwrap() - } + }, None => FxHashSet::::read(bit_slice, (limit, (endian))).unwrap(), }; assert_eq!(expected, res_read); - assert_eq!(expected_rest, rest); + assert_eq!(expected_rest, bit_slice[amt_read..]); } #[rstest(input, endian, expected, @@ -230,10 +236,10 @@ mod tests { // Unwrap here because all test cases are `Some`. let bit_size = bit_size.unwrap(); - let (rest, res_read) = + let (amt_read, res_read) = FxHashSet::::read(bit_slice, (limit, (endian, BitSize(bit_size)))).unwrap(); assert_eq!(expected, res_read); - assert_eq!(expected_rest, rest); + assert_eq!(expected_rest, bit_slice[amt_read..]); let mut res_write = bitvec![u8, Msb0;]; res_read diff --git a/src/impls/ipaddr.rs b/src/impls/ipaddr.rs index 304ac8fd..63cc1882 100644 --- a/src/impls/ipaddr.rs +++ b/src/impls/ipaddr.rs @@ -1,20 +1,19 @@ -use crate::{DekuError, DekuRead, DekuWrite}; -use bitvec::prelude::*; use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; +use bitvec::prelude::*; + +use crate::{DekuError, DekuRead, DekuWrite}; + impl<'a, Ctx> DekuRead<'a, Ctx> for Ipv4Addr where u32: DekuRead<'a, Ctx>, { - fn read( - input: &'a BitSlice, - ctx: Ctx, - ) -> Result<(&'a BitSlice, Self), DekuError> + fn read(input: &'a BitSlice, ctx: Ctx) -> Result<(usize, Self), DekuError> where Self: Sized, { - let (rest, ip) = u32::read(input, ctx)?; - Ok((rest, ip.into())) + let (amt_read, ip) = u32::read(input, ctx)?; + Ok((amt_read, ip.into())) } } @@ -32,15 +31,12 @@ impl<'a, Ctx> DekuRead<'a, Ctx> for Ipv6Addr where u128: DekuRead<'a, Ctx>, { - fn read( - input: &'a BitSlice, - ctx: Ctx, - ) -> Result<(&'a BitSlice, Self), DekuError> + fn read(input: &'a BitSlice, ctx: Ctx) -> Result<(usize, Self), DekuError> where Self: Sized, { - let (rest, ip) = u128::read(input, ctx)?; - Ok((rest, ip.into())) + let (amt_read, ip) = u128::read(input, ctx)?; + Ok((amt_read, ip.into())) } } @@ -69,9 +65,10 @@ where #[cfg(test)] mod tests { + use rstest::rstest; + use super::*; use crate::ctx::Endian; - use rstest::rstest; #[rstest(input, endian, expected, expected_rest, case::normal_le([237, 160, 254, 145].as_ref(), Endian::Little, Ipv4Addr::new(145, 254, 160, 237), bits![u8, Msb0;]), @@ -85,9 +82,9 @@ mod tests { ) { let bit_slice = input.view_bits::(); - let (rest, res_read) = Ipv4Addr::read(bit_slice, endian).unwrap(); + let (amt_read, res_read) = Ipv4Addr::read(bit_slice, endian).unwrap(); assert_eq!(expected, res_read); - assert_eq!(expected_rest, rest); + assert_eq!(expected_rest, bit_slice[amt_read..]); let mut res_write = bitvec![u8, Msb0;]; res_read.write(&mut res_write, endian).unwrap(); @@ -106,9 +103,9 @@ mod tests { ) { let bit_slice = input.view_bits::(); - let (rest, res_read) = Ipv6Addr::read(bit_slice, endian).unwrap(); + let (amt_read, res_read) = Ipv6Addr::read(bit_slice, endian).unwrap(); assert_eq!(expected, res_read); - assert_eq!(expected_rest, rest); + assert_eq!(expected_rest, bit_slice[amt_read..]); let mut res_write = bitvec![u8, Msb0;]; res_read.write(&mut res_write, endian).unwrap(); @@ -127,7 +124,7 @@ mod tests { ip_addr.write(&mut ret_write, Endian::Little).unwrap(); assert_eq!( vec![ - 0xFF, 0x02, 0x0A, 0xC0, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0x02, 0x0a, 0xc0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ], ret_write.into_vec() diff --git a/src/impls/nonzero.rs b/src/impls/nonzero.rs index 33a5c2bf..d0e3f7ff 100644 --- a/src/impls/nonzero.rs +++ b/src/impls/nonzero.rs @@ -1,9 +1,11 @@ -use crate::{ctx::*, DekuError, DekuRead, DekuWrite}; -use bitvec::prelude::*; -use core::num::*; - #[cfg(feature = "alloc")] use alloc::format; +use core::num::*; + +use bitvec::prelude::*; + +use crate::ctx::*; +use crate::{DekuError, DekuRead, DekuWrite}; macro_rules! ImplDekuTraitsCtx { ($typ:ty, $readtype:ty, $ctx_arg:tt, $ctx_type:tt) => { @@ -11,16 +13,16 @@ macro_rules! ImplDekuTraitsCtx { fn read( input: &BitSlice, $ctx_arg: $ctx_type, - ) -> Result<(&BitSlice, Self), DekuError> + ) -> Result<(usize, Self), DekuError> where Self: Sized, { - let (rest, value) = <$readtype>::read(input, $ctx_arg)?; + let (amt_read, value) = <$readtype>::read(input, $ctx_arg)?; let value = <$typ>::new(value); match value { None => Err(DekuError::Parse(format!("NonZero assertion"))), - Some(v) => Ok((rest, v)), + Some(v) => Ok((amt_read, v)), } } } @@ -62,10 +64,11 @@ ImplDekuTraits!(NonZeroIsize, isize); #[cfg(test)] mod tests { - use super::*; use hexlit::hex; use rstest::rstest; + use super::*; + #[rstest(input, expected, case(&hex!("FF"), NonZeroU8::new(0xFF).unwrap()), @@ -74,9 +77,9 @@ mod tests { )] fn test_non_zero(input: &[u8], expected: NonZeroU8) { let bit_slice = input.view_bits::(); - let (rest, res_read) = NonZeroU8::read(bit_slice, ()).unwrap(); + let (amt_read, res_read) = NonZeroU8::read(bit_slice, ()).unwrap(); assert_eq!(expected, res_read); - assert!(rest.is_empty()); + assert!(bit_slice[amt_read..].is_empty()); let mut res_write = bitvec![u8, Msb0;]; res_read.write(&mut res_write, ()).unwrap(); diff --git a/src/impls/option.rs b/src/impls/option.rs index 24096071..a747b7c3 100644 --- a/src/impls/option.rs +++ b/src/impls/option.rs @@ -1,6 +1,7 @@ -use crate::{DekuError, DekuRead, DekuWrite}; use bitvec::prelude::*; +use crate::{DekuError, DekuRead, DekuWrite}; + impl<'a, T: DekuRead<'a, Ctx>, Ctx: Copy> DekuRead<'a, Ctx> for Option { /// Read a T from input and store as Some(T) /// * `inner_ctx` - The context required by `T`. It will be passed to every `T`s when constructing. @@ -10,19 +11,16 @@ impl<'a, T: DekuRead<'a, Ctx>, Ctx: Copy> DekuRead<'a, Ctx> for Option { /// # use deku::DekuRead; /// # use deku::bitvec::BitView; /// let input = vec![1u8, 2, 3, 4]; - /// let (rest, v) = Option::::read(input.view_bits(), Endian::Little).unwrap(); - /// assert!(rest.is_empty()); + /// let (amt_read, v) = Option::::read(input.view_bits(), Endian::Little).unwrap(); + /// assert_eq!(amt_read, 32); /// assert_eq!(v, Some(0x04030201)) /// ``` - fn read( - input: &'a BitSlice, - inner_ctx: Ctx, - ) -> Result<(&'a BitSlice, Self), DekuError> + fn read(input: &'a BitSlice, inner_ctx: Ctx) -> Result<(usize, Self), DekuError> where Self: Sized, { - let (rest, val) = ::read(input, inner_ctx)?; - Ok((rest, Some(val))) + let (amt_read, val) = ::read(input, inner_ctx)?; + Ok((amt_read, Some(val))) } } diff --git a/src/impls/primitive.rs b/src/impls/primitive.rs index 8dfdfd0d..7168b8ee 100644 --- a/src/impls/primitive.rs +++ b/src/impls/primitive.rs @@ -1,28 +1,27 @@ -use crate::{ctx::*, DekuError, DekuRead, DekuWrite}; -use bitvec::prelude::*; -use core::convert::TryInto; - #[cfg(feature = "alloc")] use alloc::format; +use core::convert::TryInto; + +use bitvec::prelude::*; + +use crate::ctx::*; +use crate::prelude::NeedSize; +use crate::{DekuError, DekuRead, DekuWrite}; // specialize u8 for ByteSize impl DekuRead<'_, (Endian, ByteSize)> for u8 { fn read( input: &BitSlice, (_, _): (Endian, ByteSize), - ) -> Result<(&BitSlice, Self), DekuError> { + ) -> Result<(usize, Self), DekuError> { const MAX_TYPE_BITS: usize = BitSize::of::().0; if input.len() < MAX_TYPE_BITS { - return Err(DekuError::Incomplete(crate::error::NeedSize::new( - MAX_TYPE_BITS, - ))); + return Err(DekuError::Incomplete(NeedSize::new(MAX_TYPE_BITS))); } - // SAFETY: We already check that input.len() < bit_size above - let (bit_slice, rest) = unsafe { input.split_at_unchecked(MAX_TYPE_BITS) }; - - let value = bit_slice.load::(); - Ok((rest, value)) + // PANIC: We already check that input.len() < bit_size above, so no panic will happen + let value = input[..MAX_TYPE_BITS].load::(); + Ok((MAX_TYPE_BITS, value)) } } @@ -32,7 +31,7 @@ macro_rules! ImplDekuReadBits { fn read( input: &BitSlice, (endian, size): (Endian, BitSize), - ) -> Result<(&BitSlice, Self), DekuError> { + ) -> Result<(usize, Self), DekuError> { const MAX_TYPE_BITS: usize = BitSize::of::<$typ>().0; let bit_size: usize = size.0; @@ -48,7 +47,8 @@ macro_rules! ImplDekuReadBits { return Err(DekuError::Incomplete(crate::error::NeedSize::new(bit_size))); } - let (bit_slice, rest) = input.split_at(bit_size); + // PANIC: We already check that input.len() < bit_size above, so no panic will happen + let bit_slice = &input[..bit_size]; let pad = 8 * ((bit_slice.len() + 7) / 8) - bit_slice.len(); @@ -63,53 +63,53 @@ macro_rules! ImplDekuReadBits { } else { <$typ>::from_be_bytes(bytes.try_into()?) }; - return Ok((rest, value)); + return Ok((bit_size, value)); } } - // Create a new BitVec from the slice and pad un-aligned chunks - // i.e. [10010110, 1110] -> [10010110, 00001110] - let bits: BitVec = { - let mut bits = BitVec::with_capacity(bit_slice.len() + pad); + // Create a new BitVec from the slice and pad un-aligned chunks + // i.e. [10010110, 1110] -> [10010110, 00001110] + let bits: BitVec = { + let mut bits = BitVec::with_capacity(bit_slice.len() + pad); - // Copy bits to new BitVec - bits.extend_from_bitslice(bit_slice); + // Copy bits to new BitVec + bits.extend_from_bitslice(&bit_slice); - // Force align - //i.e. [1110, 10010110] -> [11101001, 0110] - bits.force_align(); + // Force align + //i.e. [1110, 10010110] -> [11101001, 0110] + bits.force_align(); - // Some padding to next byte - let index = if input_is_le { - bits.len() - (8 - pad) - } else { - 0 - }; - for _ in 0..pad { - bits.insert(index, false); - } + // Some padding to next byte + let index = if input_is_le { + bits.len() - (8 - pad) + } else { + 0 + }; + for _ in 0..pad { + bits.insert(index, false); + } - // Pad up-to size of type - for _ in 0..(MAX_TYPE_BITS - bits.len()) { - if input_is_le { - bits.push(false); - } else { - bits.insert(0, false); - } + // Pad up-to size of type + for _ in 0..(MAX_TYPE_BITS - bits.len()) { + if input_is_le { + bits.push(false); + } else { + bits.insert(0, false); } + } - bits - }; + bits + }; - let bytes: &[u8] = bits.domain().region().unwrap().1; + let bytes: &[u8] = bits.domain().region().unwrap().1; - // 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)) + // Read value + let value = if input_is_le { + <$typ>::from_le_bytes(bytes.try_into()?) + } else { + <$typ>::from_be_bytes(bytes.try_into()?) + }; + Ok((bit_size, value)) } } }; @@ -121,7 +121,7 @@ macro_rules! ImplDekuReadBytes { fn read( input: &BitSlice, (endian, size): (Endian, ByteSize), - ) -> Result<(&BitSlice, Self), DekuError> { + ) -> Result<(usize, Self), DekuError> { const MAX_TYPE_BITS: usize = BitSize::of::<$typ>().0; let bit_size: usize = size.0 * 8; @@ -137,7 +137,7 @@ macro_rules! ImplDekuReadBytes { return Err(DekuError::Incomplete(crate::error::NeedSize::new(bit_size))); } - let (bit_slice, rest) = input.split_at(bit_size); + let bit_slice = &input[..bit_size]; let pad = 8 * ((bit_slice.len() + 7) / 8) - bit_slice.len(); @@ -156,7 +156,7 @@ macro_rules! ImplDekuReadBytes { let mut bits: BitVec = BitVec::with_capacity(bit_slice.len() + pad); // Copy bits to new BitVec - bits.extend_from_bitslice(bit_slice); + bits.extend_from_bitslice(&bit_slice); // Force align //i.e. [1110, 10010110] -> [11101001, 0110] @@ -180,7 +180,7 @@ macro_rules! ImplDekuReadBytes { res as $typ }; - Ok((rest, value)) + Ok((bit_size, value)) } } }; @@ -192,30 +192,30 @@ macro_rules! ImplDekuReadSignExtend { fn read( input: &BitSlice, (endian, size): (Endian, ByteSize), - ) -> Result<(&BitSlice, Self), DekuError> { - let (rest, value) = + ) -> Result<(usize, Self), DekuError> { + let (amt_read, value) = <$inner as DekuRead<'_, (Endian, ByteSize)>>::read(input, (endian, size))?; const MAX_TYPE_BITS: usize = 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)) + Ok((amt_read, value)) } } impl DekuRead<'_, (Endian, BitSize)> for $typ { fn read( input: &BitSlice, (endian, size): (Endian, BitSize), - ) -> Result<(&BitSlice, Self), DekuError> { - let (rest, value) = + ) -> Result<(usize, Self), DekuError> { + let (amt_read, value) = <$inner as DekuRead<'_, (Endian, BitSize)>>::read(input, (endian, size))?; const MAX_TYPE_BITS: usize = 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)) + Ok((amt_read, value)) } } }; @@ -228,7 +228,7 @@ macro_rules! ForwardDekuRead { fn read( input: &BitSlice, endian: Endian, - ) -> Result<(&BitSlice, Self), DekuError> { + ) -> Result<(usize, Self), DekuError> { let bit_size = BitSize::of::<$typ>(); // Since we don't have a #[bits] or [bytes], check if we can use bytes for perf @@ -245,7 +245,7 @@ macro_rules! ForwardDekuRead { fn read( input: &BitSlice, byte_size: ByteSize, - ) -> Result<(&BitSlice, Self), DekuError> { + ) -> Result<(usize, Self), DekuError> { let endian = Endian::default(); <$typ>::read(input, (endian, byte_size)) @@ -257,7 +257,7 @@ macro_rules! ForwardDekuRead { fn read( input: &BitSlice, bit_size: BitSize, - ) -> Result<(&BitSlice, Self), DekuError> { + ) -> Result<(usize, Self), DekuError> { let endian = Endian::default(); // check if we can use ByteSize for performance @@ -270,10 +270,7 @@ macro_rules! ForwardDekuRead { } impl DekuRead<'_> for $typ { - fn read( - input: &BitSlice, - _: (), - ) -> Result<(&BitSlice, Self), DekuError> { + fn read(input: &BitSlice, _: ()) -> Result<(usize, Self), DekuError> { <$typ>::read(input, Endian::default()) } } @@ -483,9 +480,10 @@ ImplDekuTraitsBytes!(f64, u64); #[cfg(test)] mod tests { + use rstest::rstest; + use super::*; use crate::native_endian; - use rstest::rstest; static ENDIAN: Endian = Endian::new(); @@ -505,87 +503,87 @@ mod tests { }; } - TestPrimitive!(test_u8, u8, vec![0xAAu8], 0xAAu8); + TestPrimitive!(test_u8, u8, vec![0xaau8], 0xaau8); TestPrimitive!( test_u16, u16, - vec![0xABu8, 0xCD], - native_endian!(0xCDAB_u16) + vec![0xabu8, 0xcd], + native_endian!(0xcdab_u16) ); TestPrimitive!( test_u32, u32, - vec![0xABu8, 0xCD, 0xEF, 0xBE], - native_endian!(0xBEEFCDAB_u32) + vec![0xabu8, 0xcd, 0xef, 0xbe], + native_endian!(0xbeefcdab_u32) ); TestPrimitive!( test_u64, u64, - vec![0xABu8, 0xCD, 0xEF, 0xBE, 0xAB, 0xCD, 0xFE, 0xC0], - native_endian!(0xC0FECDABBEEFCDAB_u64) + vec![0xabu8, 0xcd, 0xef, 0xbe, 0xab, 0xcd, 0xfe, 0xc0], + native_endian!(0xc0fecdabbeefcdab_u64) ); TestPrimitive!( test_u128, u128, vec![ - 0xABu8, 0xCD, 0xEF, 0xBE, 0xAB, 0xCD, 0xFE, 0xC0, 0xAB, 0xCD, 0xEF, 0xBE, 0xAB, 0xCD, - 0xFE, 0xC0 + 0xabu8, 0xcd, 0xef, 0xbe, 0xab, 0xcd, 0xfe, 0xc0, 0xab, 0xcd, 0xef, 0xbe, 0xab, 0xcd, + 0xfe, 0xc0 ], - native_endian!(0xC0FECDABBEEFCDABC0FECDABBEEFCDAB_u128) + native_endian!(0xc0fecdabbeefcdabc0fecdabbeefcdab_u128) ); TestPrimitive!( test_usize, usize, - vec![0xABu8, 0xCD, 0xEF, 0xBE, 0xAB, 0xCD, 0xFE, 0xC0], + vec![0xabu8, 0xcd, 0xef, 0xbe, 0xab, 0xcd, 0xfe, 0xc0], if core::mem::size_of::() == 8 { - native_endian!(0xC0FECDABBEEFCDAB_usize) + native_endian!(0xc0fecdabbeefcdab_usize) } else { - native_endian!(0xBEEFCDAB_usize) + native_endian!(0xbeefcdab_usize) } ); - TestPrimitive!(test_i8, i8, vec![0xFBu8], -5); - TestPrimitive!(test_i16, i16, vec![0xFDu8, 0xFE], native_endian!(-259_i16)); + TestPrimitive!(test_i8, i8, vec![0xfbu8], -5); + TestPrimitive!(test_i16, i16, vec![0xfdu8, 0xfe], native_endian!(-259_i16)); TestPrimitive!( test_i32, i32, - vec![0x02u8, 0x3F, 0x01, 0xEF], - native_endian!(-0x10FEC0FE_i32) + vec![0x02u8, 0x3f, 0x01, 0xef], + native_endian!(-0x10fec0fe_i32) ); TestPrimitive!( test_i64, i64, - vec![0x02u8, 0x3F, 0x01, 0xEF, 0x01, 0x3F, 0x01, 0xEF], - native_endian!(-0x10FEC0FE10FEC0FE_i64) + vec![0x02u8, 0x3f, 0x01, 0xef, 0x01, 0x3f, 0x01, 0xef], + native_endian!(-0x10fec0fe10fec0fe_i64) ); TestPrimitive!( test_i128, i128, vec![ - 0x02u8, 0x3F, 0x01, 0xEF, 0x01, 0x3F, 0x01, 0xEF, 0x01, 0x3F, 0x01, 0xEF, 0x01, 0x3F, - 0x01, 0xEF + 0x02u8, 0x3f, 0x01, 0xef, 0x01, 0x3f, 0x01, 0xef, 0x01, 0x3f, 0x01, 0xef, 0x01, 0x3f, + 0x01, 0xef ], - native_endian!(-0x10FEC0FE10FEC0FE10FEC0FE10FEC0FE_i128) + native_endian!(-0x10fec0fe10fec0fe10fec0fe10fec0fe_i128) ); TestPrimitive!( test_isize, isize, - vec![0x02u8, 0x3F, 0x01, 0xEF, 0x01, 0x3F, 0x01, 0xEF], + vec![0x02u8, 0x3f, 0x01, 0xef, 0x01, 0x3f, 0x01, 0xef], if core::mem::size_of::() == 8 { - native_endian!(-0x10FEC0FE10FEC0FE_isize) + native_endian!(-0x10fec0fe10fec0fe_isize) } else { - native_endian!(-0x10FEC0FE_isize) + native_endian!(-0x10fec0fe_isize) } ); TestPrimitive!( test_f32, f32, - vec![0xA6u8, 0x9B, 0xC4, 0xBB], + vec![0xa6u8, 0x9b, 0xc4, 0xbb], native_endian!(-0.006_f32) ); TestPrimitive!( test_f64, f64, - vec![0xFAu8, 0x7E, 0x6A, 0xBC, 0x74, 0x93, 0x78, 0xBF], + vec![0xfau8, 0x7e, 0x6a, 0xbc, 0x74, 0x93, 0x78, 0xbf], native_endian!(-0.006_f64) ); @@ -610,13 +608,13 @@ mod tests { ) { let bit_slice = input.view_bits::(); - let (rest, res_read) = match bit_size { + let (amt_read, res_read) = match bit_size { Some(bit_size) => u32::read(bit_slice, (endian, BitSize(bit_size))).unwrap(), None => u32::read(bit_slice, endian).unwrap(), }; assert_eq!(expected, res_read); - assert_eq!(expected_rest, rest); + assert_eq!(expected_rest, bit_slice[amt_read..]); } #[rstest(input, endian, bit_size, expected, @@ -651,12 +649,12 @@ mod tests { ) { let bit_slice = input.view_bits::(); - let (rest, res_read) = match bit_size { + let (amt_read, res_read) = match bit_size { Some(bit_size) => u32::read(bit_slice, (endian, BitSize(bit_size))).unwrap(), None => u32::read(bit_slice, endian).unwrap(), }; assert_eq!(expected, res_read); - assert_eq!(expected_rest, rest); + assert_eq!(expected_rest, bit_slice[amt_read..]); let mut res_write = bitvec![u8, Msb0;]; match bit_size { @@ -675,10 +673,10 @@ mod tests { fn $test_name() { let bit_slice = [0b10101_000].view_bits::(); - let (rest, res_read) = <$typ>::read(bit_slice, (Endian::Little, BitSize(5))).unwrap(); + let (amt_read, res_read) = <$typ>::read(bit_slice, (Endian::Little, BitSize(5))).unwrap(); assert_eq!(-11, res_read); - assert_eq!(bits![u8, Msb0; 0, 0, 0], rest); + assert_eq!(bits![u8, Msb0; 0, 0, 0], bit_slice[amt_read..]); } }; } diff --git a/src/impls/slice.rs b/src/impls/slice.rs index bd01b090..d5adb885 100644 --- a/src/impls/slice.rs +++ b/src/impls/slice.rs @@ -1,29 +1,35 @@ //! Implementations of DekuRead and DekuWrite for [T; N] where 0 < N <= 32 -use crate::{ctx::Limit, DekuError, DekuRead, DekuWrite}; use bitvec::prelude::*; pub use deku_derive::*; +use crate::ctx::Limit; +use crate::{DekuError, DekuRead, DekuWrite}; + /// Read `u8`s and returns a byte slice up until a given predicate returns true /// * `ctx` - The context required by `u8`. It will be passed to every `u8` when constructing. /// * `predicate` - the predicate that decides when to stop reading `u8`s /// The predicate takes two parameters: the number of bits that have been read so far, /// and a borrow of the latest value to have been read. It should return `true` if reading /// should now stop, and `false` otherwise -fn read_slice_with_predicate<'a, Ctx: Copy, Predicate: FnMut(usize, &u8) -> bool>( +fn read_slice_with_predicate<'a, Ctx, Predicate>( input: &'a BitSlice, ctx: Ctx, mut predicate: Predicate, -) -> Result<(&'a BitSlice, &[u8]), DekuError> +) -> Result<(usize, &[u8]), DekuError> where u8: DekuRead<'a, Ctx>, + Ctx: Copy, + Predicate: FnMut(usize, &u8) -> bool, { let mut rest = input; let mut value; + let mut total_read = 0; loop { - let (new_rest, val) = u8::read(rest, ctx)?; - rest = new_rest; + let (amt_read, val) = u8::read(rest, ctx)?; + rest = &rest[amt_read..]; + total_read += amt_read; let read_idx = unsafe { rest.as_bitptr().offset_from(input.as_bitptr()) } as usize; value = input[..read_idx].domain().region().unwrap().1; @@ -33,13 +39,14 @@ where } } - Ok((rest, value)) + Ok((total_read, value)) } -impl<'a, Ctx: Copy, Predicate: FnMut(&u8) -> bool> DekuRead<'a, (Limit, Ctx)> - for &'a [u8] +impl<'a, Ctx, Predicate> DekuRead<'a, (Limit, Ctx)> for &'a [u8] where u8: DekuRead<'a, Ctx>, + Ctx: Copy, + Predicate: FnMut(&u8) -> bool, { /// Read `u8`s until the given limit /// * `limit` - the limiting factor on the amount of `u8`s to read @@ -50,20 +57,20 @@ where /// # use deku::DekuRead; /// # use bitvec::view::BitView; /// let input = vec![1u8, 2, 3, 4]; - /// let (rest, v) = <&[u8]>::read(input.view_bits(), (4.into(), Endian::Little)).unwrap(); - /// assert!(rest.is_empty()); + /// let (amt_read, v) = <&[u8]>::read(input.view_bits(), (4.into(), Endian::Little)).unwrap(); + /// assert_eq!(amt_read, 32); /// assert_eq!(&[1u8, 2, 3, 4], v) /// ``` fn read( input: &'a BitSlice, (limit, inner_ctx): (Limit, Ctx), - ) -> Result<(&'a BitSlice, Self), DekuError> { + ) -> Result<(usize, Self), DekuError> { match limit { // Read a given count of elements Limit::Count(mut count) => { // Handle the trivial case of reading an empty slice if count == 0 { - return Ok((input, &input.domain().region().unwrap().1[..0])); + return Ok((0, &input.domain().region().unwrap().1[..0])); } // Otherwise, read until we have read `count` elements @@ -71,12 +78,12 @@ where count -= 1; count == 0 }) - } + }, // Read until a given predicate returns true Limit::Until(mut predicate, _) => { read_slice_with_predicate(input, inner_ctx, move |_, value| predicate(value)) - } + }, // Read until a given quantity of bits have been read Limit::BitSize(size) => { @@ -84,7 +91,7 @@ where 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) => { @@ -92,7 +99,7 @@ where read_slice_with_predicate(input, inner_ctx, move |read_bits, _| { read_bits == bit_size }) - } + }, } } } @@ -124,19 +131,21 @@ mod pre_const_generics_impl { fn read( input: &'a BitSlice, ctx: Ctx, - ) -> Result<(&'a BitSlice, Self), DekuError> + ) -> Result<(usize, Self), DekuError> where Self: Sized, { let mut slice: [$typ; $count] = Default::default(); let mut rest = input; + let mut total_read = 0; for i in 0..$count { - let (new_rest, value) = <$typ>::read(rest, ctx)?; + let (amt_read, value) = <$typ>::read(rest, ctx)?; slice[i] = value; - rest = new_rest; + rest = new_rest[amt_read..]; + total_read += amt_read; } - Ok((rest, slice)) + Ok((total_read, slice)) } } @@ -173,18 +182,15 @@ mod pre_const_generics_impl { #[cfg(feature = "const_generics")] mod const_generics_impl { - use super::*; - use core::mem::MaybeUninit; + use super::*; + impl<'a, Ctx: Copy, T, const N: usize> DekuRead<'a, Ctx> for [T; N] where T: DekuRead<'a, Ctx>, { - fn read( - input: &'a BitSlice, - ctx: Ctx, - ) -> Result<(&'a BitSlice, Self), DekuError> + fn read(input: &'a BitSlice, ctx: Ctx) -> Result<(usize, Self), DekuError> where Self: Sized, { @@ -193,8 +199,9 @@ mod const_generics_impl { // and never return it in case of error let mut slice: [MaybeUninit; N] = unsafe { MaybeUninit::uninit().assume_init() }; let mut rest = input; + let mut total_read = 0; for (n, item) in slice.iter_mut().enumerate() { - let (new_rest, value) = match T::read(rest, ctx) { + let (amt_read, value) = match T::read(rest, ctx) { Ok(it) => it, Err(err) => { // For each item in the array, drop if we allocated it. @@ -204,16 +211,18 @@ mod const_generics_impl { } } return Err(err); - } + }, }; item.write(value); - rest = new_rest; + rest = &rest[amt_read..]; + total_read += amt_read; } - Ok((rest, unsafe { + let val = unsafe { // TODO: array_assume_init: /~https://github.com/rust-lang/rust/issues/80908 (&slice as *const _ as *const [T; N]).read() - })) + }; + Ok((total_read, val)) } } @@ -244,10 +253,10 @@ mod const_generics_impl { #[cfg(test)] mod tests { - use super::*; + use rstest::rstest; + use super::*; use crate::ctx::Endian; - use rstest::rstest; #[rstest(input,endian,expected,expected_rest, case::normal_le([0xDD, 0xCC, 0xBB, 0xAA].as_ref(), Endian::Little, [0xCCDD, 0xAABB], bits![u8, Msb0;]), @@ -261,9 +270,9 @@ mod tests { ) { let bit_slice = input.view_bits::(); - let (rest, res_read) = <[u16; 2]>::read(bit_slice, endian).unwrap(); + let (amt_read, res_read) = <[u16; 2]>::read(bit_slice, endian).unwrap(); assert_eq!(expected, res_read); - assert_eq!(expected_rest, rest); + assert_eq!(expected_rest, bit_slice[amt_read..]); } #[rstest(input,endian,expected, @@ -305,9 +314,9 @@ mod tests { ) { let bit_slice = input.view_bits::(); - let (rest, res_read) = <[[u16; 2]; 2]>::read(bit_slice, endian).unwrap(); + let (amt_read, res_read) = <[[u16; 2]; 2]>::read(bit_slice, endian).unwrap(); assert_eq!(expected, res_read); - assert_eq!(expected_rest, rest); + assert_eq!(expected_rest, bit_slice[amt_read..]); } #[cfg(feature = "const_generics")] diff --git a/src/impls/tuple.rs b/src/impls/tuple.rs index 9872c77d..da0fe5be 100644 --- a/src/impls/tuple.rs +++ b/src/impls/tuple.rs @@ -1,8 +1,9 @@ //! Implementations of DekuRead and DekuWrite for tuples of length 1 to 11 -use crate::{DekuError, DekuRead, DekuWrite}; use bitvec::prelude::*; +use crate::{DekuError, DekuRead, DekuWrite}; + // Trait to help us build intermediate tuples while DekuRead'ing each element // from the tuple trait Append { @@ -39,18 +40,21 @@ macro_rules! ImplDekuTupleTraits { fn read( input: &'a BitSlice, ctx: Ctx, - ) -> Result<(&'a BitSlice, Self), DekuError> + ) -> Result<(usize, Self), DekuError> where Self: Sized, { let tuple = (); - let mut rest = input; + let mut _rest = input; + let mut total_read = 0; $( - let read = <$T>::read(rest, ctx)?; - rest = read.0; - let tuple = tuple.append(read.1); + let (amt_read, val) = <$T>::read(_rest, ctx)?; + let tuple = tuple.append(val); + + total_read += amt_read; + _rest = &_rest[amt_read..]; )+ - Ok((rest, tuple)) + Ok((total_read, tuple)) } } @@ -82,12 +86,13 @@ ImplDekuTupleTraits! { A, B, C, D, E, F, G, H, I, J, K, } #[cfg(test)] mod tests { - use super::*; - use crate::native_endian; use core::fmt::Debug; use rstest::rstest; + use super::*; + use crate::native_endian; + #[rstest(input, expected, expected_rest, case::length_1([0xef, 0xbe, 0xad, 0xde].as_ref(), (native_endian!(0xdeadbeef_u32),), bits![u8, Msb0;]), case::length_2([1, 0x24, 0x98, 0x82, 0].as_ref(), (true, native_endian!(0x829824_u32)), bits![u8, Msb0;]), @@ -99,9 +104,9 @@ mod tests { T: DekuRead<'a> + Sized + PartialEq + Debug, { let bit_slice = input.view_bits::(); - let (rest, res_read) = ::read(bit_slice, ()).unwrap(); + let (amt_read, res_read) = ::read(bit_slice, ()).unwrap(); assert_eq!(expected, res_read); - assert_eq!(expected_rest, rest); + assert_eq!(expected_rest, bit_slice[amt_read..]); } #[rstest(input, expected, diff --git a/src/impls/unit.rs b/src/impls/unit.rs index 710f3d72..ea7d999b 100644 --- a/src/impls/unit.rs +++ b/src/impls/unit.rs @@ -1,16 +1,14 @@ -use crate::{DekuError, DekuRead, DekuWrite}; use bitvec::prelude::*; +use crate::{DekuError, DekuRead, DekuWrite}; + impl DekuRead<'_, Ctx> for () { /// NOP on read - fn read( - input: &BitSlice, - _inner_ctx: Ctx, - ) -> Result<(&BitSlice, Self), DekuError> + fn read(_input: &BitSlice, _inner_ctx: Ctx) -> Result<(usize, Self), DekuError> where Self: Sized, { - Ok((input, ())) + Ok((0, ())) } } @@ -23,9 +21,10 @@ impl DekuWrite for () { #[cfg(test)] mod tests { - use super::*; use hexlit::hex; + use super::*; + #[test] #[allow(clippy::unit_arg)] #[allow(clippy::unit_cmp)] @@ -33,9 +32,9 @@ mod tests { let input = &hex!("FF"); let bit_slice = input.view_bits::(); - let (rest, res_read) = <()>::read(bit_slice, ()).unwrap(); + let (amt_read, res_read) = <()>::read(bit_slice, ()).unwrap(); assert_eq!((), res_read); - assert_eq!(bit_slice, rest); + assert_eq!(amt_read, 0); let mut res_write = bitvec![u8, Msb0;]; res_read.write(&mut res_write, ()).unwrap(); diff --git a/src/impls/vec.rs b/src/impls/vec.rs index 7f158f4a..9bf95ee8 100644 --- a/src/impls/vec.rs +++ b/src/impls/vec.rs @@ -1,9 +1,11 @@ -use crate::{ctx::*, DekuError, DekuRead, DekuWrite}; -use bitvec::prelude::*; - #[cfg(feature = "alloc")] use alloc::vec::Vec; +use bitvec::prelude::*; + +use crate::ctx::*; +use crate::{DekuError, DekuRead, DekuWrite}; + /// Read `T`s into a vec until a given predicate returns true /// * `capacity` - an optional capacity to pre-allocate the vector with /// * `ctx` - The context required by `T`. It will be passed to every `T` when constructing. @@ -11,25 +13,27 @@ use alloc::vec::Vec; /// The predicate takes two parameters: the number of bits that have been read so far, /// and a borrow of the latest value to have been read. It should return `true` if reading /// should now stop, and `false` otherwise -fn read_vec_with_predicate< - 'a, - T: DekuRead<'a, Ctx>, - Ctx: Copy, - Predicate: FnMut(usize, &T) -> bool, ->( +fn read_vec_with_predicate<'a, T, Ctx, Predicate>( input: &'a BitSlice, capacity: Option, ctx: Ctx, mut predicate: Predicate, -) -> Result<(&'a BitSlice, Vec), DekuError> { +) -> Result<(usize, Vec), DekuError> +where + T: DekuRead<'a, Ctx>, + Ctx: Copy, + Predicate: FnMut(usize, &T) -> bool, +{ let mut res = capacity.map_or_else(Vec::new, Vec::with_capacity); let mut rest = input; + let mut total_read = 0; loop { - let (new_rest, val) = ::read(rest, ctx)?; + let (amt_read, val) = ::read(rest, ctx)?; res.push(val); - rest = new_rest; + rest = &rest[amt_read..]; + total_read += amt_read; // This unwrap is safe as we are pushing to the vec immediately before it, // so there will always be a last element @@ -41,11 +45,14 @@ fn read_vec_with_predicate< } } - Ok((rest, res)) + Ok((total_read, res)) } -impl<'a, T: DekuRead<'a, Ctx>, Ctx: Copy, Predicate: FnMut(&T) -> bool> - DekuRead<'a, (Limit, Ctx)> for Vec +impl<'a, T, Ctx, Predicate> DekuRead<'a, (Limit, Ctx)> for Vec +where + T: DekuRead<'a, Ctx>, + Ctx: Copy, + Predicate: FnMut(&T) -> bool, { /// Read `T`s until the given limit /// * `limit` - the limiting factor on the amount of `T`s to read @@ -56,14 +63,14 @@ impl<'a, T: DekuRead<'a, Ctx>, Ctx: Copy, Predicate: FnMut(&T) -> bool> /// # use deku::DekuRead; /// # use deku::bitvec::BitView; /// let input = vec![1u8, 2, 3, 4]; - /// let (rest, v) = Vec::::read(input.view_bits(), (1.into(), Endian::Little)).unwrap(); - /// assert!(rest.is_empty()); + /// let (amt_read, v) = Vec::::read(input.view_bits(), (1.into(), Endian::Little)).unwrap(); + /// assert_eq!(amt_read, 32); /// assert_eq!(vec![0x04030201], v) /// ``` fn read( input: &'a BitSlice, (limit, inner_ctx): (Limit, Ctx), - ) -> Result<(&'a BitSlice, Self), DekuError> + ) -> Result<(usize, Self), DekuError> where Self: Sized, { @@ -72,7 +79,7 @@ impl<'a, T: DekuRead<'a, Ctx>, Ctx: Copy, Predicate: FnMut(&T) -> bool> Limit::Count(mut count) => { // Handle the trivial case of reading an empty vector if count == 0 { - return Ok((input, Vec::new())); + return Ok((0, Vec::new())); } // Otherwise, read until we have read `count` elements @@ -80,12 +87,12 @@ impl<'a, T: DekuRead<'a, Ctx>, Ctx: Copy, Predicate: FnMut(&T) -> bool> count -= 1; count == 0 }) - } + }, // Read until a given predicate returns true Limit::Until(mut predicate, _) => { read_vec_with_predicate(input, None, inner_ctx, move |_, value| predicate(value)) - } + }, // Read until a given quantity of bits have been read Limit::BitSize(size) => { @@ -93,7 +100,7 @@ impl<'a, T: DekuRead<'a, Ctx>, Ctx: Copy, Predicate: FnMut(&T) -> bool> 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) => { @@ -101,7 +108,7 @@ impl<'a, T: DekuRead<'a, Ctx>, Ctx: Copy, Predicate: FnMut(&T) -> bool> read_vec_with_predicate(input, None, inner_ctx, move |read_bits, _| { read_bits == bit_size }) - } + }, } } } @@ -113,7 +120,7 @@ impl<'a, T: DekuRead<'a>, Predicate: FnMut(&T) -> bool> DekuRead<'a, Limit, limit: Limit, - ) -> Result<(&'a BitSlice, Self), DekuError> + ) -> Result<(usize, Self), DekuError> where Self: Sized, { @@ -143,9 +150,10 @@ impl, Ctx: Copy> DekuWrite for Vec { #[cfg(test)] mod tests { - use super::*; use rstest::rstest; + use super::*; + #[rstest(input,endian,bit_size,limit,expected,expected_rest, case::count_0([0xAA].as_ref(), Endian::Little, Some(8), 0.into(), vec![], bits![u8, Msb0; 1, 0, 1, 0, 1, 0, 1, 0]), case::count_1([0xAA, 0xBB].as_ref(), Endian::Little, Some(8), 1.into(), vec![0xAA], bits![u8, Msb0; 1, 0, 1, 1, 1, 0, 1, 1]), @@ -176,15 +184,15 @@ mod tests { ) { let bit_slice = input.view_bits::(); - let (rest, res_read) = match bit_size { + let (amt_read, res_read) = match bit_size { Some(bit_size) => { Vec::::read(bit_slice, (limit, (endian, BitSize(bit_size)))).unwrap() - } + }, None => Vec::::read(bit_slice, (limit, (endian))).unwrap(), }; assert_eq!(expected, res_read); - assert_eq!(expected_rest, rest); + assert_eq!(expected_rest, bit_slice[amt_read..]); } #[rstest(input, endian, expected, @@ -219,10 +227,10 @@ mod tests { // Unwrap here because all test cases are `Some`. let bit_size = bit_size.unwrap(); - let (rest, res_read) = + let (amt_read, res_read) = Vec::::read(bit_slice, (limit, (endian, BitSize(bit_size)))).unwrap(); assert_eq!(expected, res_read); - assert_eq!(expected_rest, rest); + assert_eq!(expected_rest, bit_slice[amt_read..]); let mut res_write = bitvec![u8, Msb0;]; res_read diff --git a/src/lib.rs b/src/lib.rs index 39f341b1..97819920 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -42,7 +42,7 @@ struct DekuTest { } let data: Vec = vec![0b0110_1001, 0xBE, 0xEF]; -let (_rest, mut val) = DekuTest::from_bytes((data.as_ref(), 0)).unwrap(); +let (_amt_read, mut val) = DekuTest::from_bytes((data.as_ref(), 0)).unwrap(); assert_eq!(DekuTest { field_a: 0b0110, field_b: 0b1001, @@ -75,7 +75,7 @@ struct DekuHeader(u8); struct DekuData(u16); let data: Vec = vec![0xAA, 0xEF, 0xBE]; -let (_rest, mut val) = DekuTest::from_bytes((data.as_ref(), 0)).unwrap(); +let (_amt_read, mut val) = DekuTest::from_bytes((data.as_ref(), 0)).unwrap(); assert_eq!(DekuTest { header: DekuHeader(0xAA), data: DekuData(0xBEEF), @@ -109,7 +109,7 @@ struct DekuTest { } let data: Vec = vec![0x02, 0xBE, 0xEF, 0xFF, 0xFF]; -let (_rest, mut val) = DekuTest::from_bytes((data.as_ref(), 0)).unwrap(); +let (_amt_read, mut val) = DekuTest::from_bytes((data.as_ref(), 0)).unwrap(); assert_eq!(DekuTest { count: 0x02, data: vec![0xBE, 0xEF] @@ -176,10 +176,10 @@ enum DekuTest { let data: Vec = vec![0x01, 0x02, 0xEF, 0xBE]; -let (rest, val) = DekuTest::from_bytes((data.as_ref(), 0)).unwrap(); +let (amt_read, val) = DekuTest::from_bytes((data.as_ref(), 0)).unwrap(); assert_eq!(DekuTest::VariantA , val); -let (rest, val) = DekuTest::from_bytes(rest).unwrap(); +let (amt_read, val) = DekuTest::from_bytes((data.as_ref(), amt_read)).unwrap(); assert_eq!(DekuTest::VariantB(0xBEEF) , val); ``` @@ -210,7 +210,7 @@ struct Root { let data: Vec = vec![0x01, 0x02]; -let (rest, value) = Root::from_bytes((&data[..], 0)).unwrap(); +let (amt_read, value) = Root::from_bytes((&data[..], 0)).unwrap(); assert_eq!(value.a, 0x01); assert_eq!(value.sub.b, 0x01 + 0x02) ``` @@ -295,11 +295,11 @@ pub trait DekuRead<'a, Ctx = ()> { /// * **ctx** - A context required by context-sensitive reading. A unit type `()` means no context /// needed. /// - /// Returns the remaining bits after parsing in addition to Self. + /// Returns the amount of bits read after parsing in addition to Self. fn read( input: &'a bitvec::BitSlice, ctx: Ctx, - ) -> Result<(&'a bitvec::BitSlice, Self), DekuError> + ) -> Result<(usize, Self), DekuError> where Self: Sized; } @@ -310,8 +310,8 @@ pub trait DekuContainerRead<'a>: DekuRead<'a, ()> { /// Read bytes and construct type /// * **input** - Input given as data and bit offset /// - /// Returns the remaining bytes and bit offset after parsing in addition to Self. - fn from_bytes(input: (&'a [u8], usize)) -> Result<((&'a [u8], usize), Self), DekuError> + /// Returns the amount of bits read after parsing in addition to Self. + fn from_bytes(input: (&'a [u8], usize)) -> Result<(usize, Self), DekuError> where Self: Sized; } diff --git a/src/prelude.rs b/src/prelude.rs index 2511a0c6..3ac88025 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -2,7 +2,8 @@ [What is a prelude?](std::prelude) */ +pub use crate::error::{DekuError, NeedSize}; pub use crate::{ - deku_derive, error::DekuError, error::NeedSize, DekuContainerRead, DekuContainerWrite, - DekuEnumExt, DekuRead, DekuUpdate, DekuWrite, + deku_derive, DekuContainerRead, DekuContainerWrite, DekuEnumExt, DekuRead, DekuUpdate, + DekuWrite, }; diff --git a/tests/test_alloc.rs b/tests/test_alloc.rs index 83c8806e..e61294b5 100644 --- a/tests/test_alloc.rs +++ b/tests/test_alloc.rs @@ -45,10 +45,12 @@ struct TestDeku { } mod tests { - use super::*; + use std::convert::TryFrom; + use alloc_counter::count_alloc; use hexlit::hex; - use std::convert::TryFrom; + + use super::*; #[test] #[cfg_attr(miri, ignore)] diff --git a/tests/test_attributes/test_assert.rs b/tests/test_attributes/test_assert.rs index 134a9c13..51efeff3 100644 --- a/tests/test_attributes/test_assert.rs +++ b/tests/test_attributes/test_assert.rs @@ -1,7 +1,8 @@ +use std::convert::{TryFrom, TryInto}; + use deku::prelude::*; use hexlit::hex; use rstest::rstest; -use std::convert::{TryFrom, TryInto}; #[derive(Default, PartialEq, Debug, DekuRead, DekuWrite)] struct TestStruct { diff --git a/tests/test_attributes/test_assert_eq.rs b/tests/test_attributes/test_assert_eq.rs index cdab14be..6cb3ab59 100644 --- a/tests/test_attributes/test_assert_eq.rs +++ b/tests/test_attributes/test_assert_eq.rs @@ -1,7 +1,8 @@ +use std::convert::{TryFrom, TryInto}; + use deku::prelude::*; use hexlit::hex; use rstest::rstest; -use std::convert::{TryFrom, TryInto}; #[derive(Default, PartialEq, Debug, DekuRead, DekuWrite)] struct TestStruct { diff --git a/tests/test_attributes/test_cond.rs b/tests/test_attributes/test_cond.rs index feac39ea..0e27b13e 100644 --- a/tests/test_attributes/test_cond.rs +++ b/tests/test_attributes/test_cond.rs @@ -1,6 +1,7 @@ -use deku::prelude::*; use std::convert::{TryFrom, TryInto}; +use deku::prelude::*; + #[test] fn test_cond_deku() { #[derive(PartialEq, Debug, DekuRead, DekuWrite)] diff --git a/tests/test_attributes/test_ctx.rs b/tests/test_attributes/test_ctx.rs index 46f0c47e..abc1030c 100644 --- a/tests/test_attributes/test_ctx.rs +++ b/tests/test_attributes/test_ctx.rs @@ -1,7 +1,8 @@ +use std::convert::{TryFrom, TryInto}; + use bitvec::bitvec; use deku::bitvec::{BitView, Msb0}; use deku::prelude::*; -use std::convert::{TryFrom, TryInto}; /// General smoke tests for ctx /// TODO: These should be divided into smaller units @@ -60,8 +61,9 @@ fn test_top_level_ctx_enum() { } let test_data = [0x01_u8, 0x03]; - let (rest, ret_read) = TopLevelCtxEnum::read(test_data.view_bits(), (1, 2)).unwrap(); - assert!(rest.is_empty()); + let bit_slice = test_data.view_bits(); + let (amt_read, ret_read) = TopLevelCtxEnum::read(bit_slice, (1, 2)).unwrap(); + assert!(bit_slice[amt_read..].is_empty()); assert_eq!(ret_read, TopLevelCtxEnum::VariantA(0x06)); let mut ret_write = bitvec![u8, Msb0;]; @@ -94,8 +96,9 @@ fn test_top_level_ctx_enum_default() { assert_eq!(test_data.to_vec(), ret_write); // Use context - let (rest, ret_read) = TopLevelCtxEnumDefault::read(test_data.view_bits(), (1, 2)).unwrap(); - assert!(rest.is_empty()); + let bit_slice = test_data.view_bits(); + let (amt_read, ret_read) = TopLevelCtxEnumDefault::read(bit_slice, (1, 2)).unwrap(); + assert!(bit_slice[amt_read..].is_empty()); assert_eq!(ret_read, TopLevelCtxEnumDefault::VariantA(0x06)); let mut ret_write = bitvec![u8, Msb0;]; ret_read.write(&mut ret_write, (1, 2)).unwrap(); @@ -212,8 +215,9 @@ fn test_ctx_default_struct() { assert_eq!(ret_write, test_data); // Use context - let (rest, ret_read) = TopLevelCtxStructDefault::read(test_data.view_bits(), (1, 2)).unwrap(); - assert!(rest.is_empty()); + let bit_slice = test_data.view_bits(); + let (amt_read, ret_read) = TopLevelCtxStructDefault::read(bit_slice, (1, 2)).unwrap(); + assert_eq!(bit_slice.len(), amt_read); assert_eq!(expected, ret_read); let mut ret_write = bitvec![u8, Msb0;]; ret_read.write(&mut ret_write, (1, 2)).unwrap(); @@ -240,7 +244,7 @@ fn test_enum_endian_ctx() { assert_eq!( EnumTypeEndian { - t: EnumTypeEndianCtx::VarA(0xFF) + t: EnumTypeEndianCtx::VarA(0xff) }, ret_read ); diff --git a/tests/test_attributes/test_limits/test_bits_read.rs b/tests/test_attributes/test_limits/test_bits_read.rs index a23ddebd..3b9fb72a 100644 --- a/tests/test_attributes/test_limits/test_bits_read.rs +++ b/tests/test_attributes/test_limits/test_bits_read.rs @@ -1,6 +1,7 @@ +use std::convert::{TryFrom, TryInto}; + use deku::prelude::*; use rstest::rstest; -use std::convert::{TryFrom, TryInto}; mod test_slice { use super::*; @@ -13,7 +14,7 @@ mod test_slice { data: &'a [u8], } - let test_data: Vec = [0xAA, 0xBB].to_vec(); + let test_data: Vec = [0xaa, 0xbb].to_vec(); let ret_read = TestStruct::try_from(test_data.as_ref()).unwrap(); assert_eq!( @@ -45,7 +46,7 @@ mod test_slice { data: &'a [u8], } - let test_data: Vec = [input_bits, 0xAA, 0xBB].to_vec(); + let test_data: Vec = [input_bits, 0xaa, 0xbb].to_vec(); let ret_read = TestStruct::try_from(test_data.as_ref()).unwrap(); assert_eq!( @@ -72,14 +73,14 @@ mod test_vec { data: Vec, } - let test_data: Vec = [0xAA, 0xBB].to_vec(); + let test_data: Vec = [0xaa, 0xbb].to_vec(); let ret_read = TestStruct::try_from(test_data.as_ref()).unwrap(); assert_eq!( TestStruct { // We should read 16 bits, not 16 elements, // thus resulting in a single u16 element - data: vec![0xBBAA] + data: vec![0xbbaa] }, ret_read ); @@ -106,7 +107,7 @@ mod test_vec { data: Vec, } - let test_data: Vec = [input_bits, 0xAA, 0xBB].to_vec(); + let test_data: Vec = [input_bits, 0xaa, 0xbb].to_vec(); let ret_read = TestStruct::try_from(test_data.as_ref()).unwrap(); assert_eq!( @@ -115,7 +116,7 @@ mod test_vec { // We should read 16 bits, not 16 elements, // thus resulting in a single u16 element - data: vec![0xBBAA] + data: vec![0xbbaa] }, ret_read ); diff --git a/tests/test_attributes/test_limits/test_bytes_read.rs b/tests/test_attributes/test_limits/test_bytes_read.rs index 38ffa1c6..d107abce 100644 --- a/tests/test_attributes/test_limits/test_bytes_read.rs +++ b/tests/test_attributes/test_limits/test_bytes_read.rs @@ -1,6 +1,7 @@ +use std::convert::{TryFrom, TryInto}; + use deku::prelude::*; use rstest::rstest; -use std::convert::{TryFrom, TryInto}; mod test_slice { use super::*; @@ -13,7 +14,7 @@ mod test_slice { data: &'a [u8], } - let test_data: Vec = [0xAA, 0xBB].to_vec(); + let test_data: Vec = [0xaa, 0xbb].to_vec(); let ret_read = TestStruct::try_from(test_data.as_ref()).unwrap(); assert_eq!( @@ -42,7 +43,7 @@ mod test_slice { data: &'a [u8], } - let test_data: Vec = [input_bytes, 0xAA, 0xBB].to_vec(); + let test_data: Vec = [input_bytes, 0xaa, 0xbb].to_vec(); let ret_read = TestStruct::try_from(test_data.as_ref()).unwrap(); assert_eq!( @@ -69,14 +70,14 @@ mod test_vec { data: Vec, } - let test_data: Vec = [0xAA, 0xBB].to_vec(); + let test_data: Vec = [0xaa, 0xbb].to_vec(); let ret_read = TestStruct::try_from(test_data.as_ref()).unwrap(); assert_eq!( TestStruct { // We should read two bytes, not two elements, // thus resulting in a single u16 element - data: vec![0xBBAA] + data: vec![0xbbaa] }, ret_read ); @@ -100,7 +101,7 @@ mod test_vec { data: Vec, } - let test_data: Vec = [input_bytes, 0xAA, 0xBB].to_vec(); + let test_data: Vec = [input_bytes, 0xaa, 0xbb].to_vec(); let ret_read = TestStruct::try_from(test_data.as_ref()).unwrap(); assert_eq!( @@ -109,7 +110,7 @@ mod test_vec { // We should read two bytes, not two elements, // thus resulting in a single u16 element - data: vec![0xBBAA] + data: vec![0xbbaa] }, ret_read ); diff --git a/tests/test_attributes/test_limits/test_count.rs b/tests/test_attributes/test_limits/test_count.rs index 0eb8ef53..f950476e 100644 --- a/tests/test_attributes/test_limits/test_count.rs +++ b/tests/test_attributes/test_limits/test_count.rs @@ -1,6 +1,7 @@ -use deku::prelude::*; use std::convert::{TryFrom, TryInto}; +use deku::prelude::*; + mod test_slice { use super::*; @@ -12,7 +13,7 @@ mod test_slice { data: &'a [u8], } - let test_data: Vec = [0xAA, 0xBB].to_vec(); + let test_data: Vec = [0xaa, 0xbb].to_vec(); let ret_read = TestStruct::try_from(test_data.as_ref()).unwrap(); assert_eq!( @@ -35,7 +36,7 @@ mod test_slice { data: &'a [u8], } - let test_data: Vec = [0x02, 0xAA, 0xBB].to_vec(); + let test_data: Vec = [0x02, 0xaa, 0xbb].to_vec(); let ret_read = TestStruct::try_from(test_data.as_ref()).unwrap(); assert_eq!( @@ -60,7 +61,7 @@ mod test_slice { data: &'a [u8], } - let test_data: Vec = [0x03, 0xAA, 0xBB].to_vec(); + let test_data: Vec = [0x03, 0xaa, 0xbb].to_vec(); let _ret_read = TestStruct::try_from(test_data.as_ref()).unwrap(); } @@ -77,12 +78,12 @@ mod test_vec { data: Vec, } - let test_data: Vec = [0xAA, 0xBB].to_vec(); + let test_data: Vec = [0xaa, 0xbb].to_vec(); let ret_read = TestStruct::try_from(test_data.as_ref()).unwrap(); assert_eq!( TestStruct { - data: vec![0xAA, 0xBB] + data: vec![0xaa, 0xbb] }, ret_read ); @@ -100,13 +101,13 @@ mod test_vec { data: Vec, } - let test_data: Vec = [0x02, 0xAA, 0xBB].to_vec(); + let test_data: Vec = [0x02, 0xaa, 0xbb].to_vec(); let ret_read = TestStruct::try_from(test_data.as_ref()).unwrap(); assert_eq!( TestStruct { count: 0x02, - data: vec![0xAA, 0xBB] + data: vec![0xaa, 0xbb] }, ret_read ); @@ -125,7 +126,7 @@ mod test_vec { data: Vec, } - let test_data: Vec = [0x03, 0xAA, 0xBB].to_vec(); + let test_data: Vec = [0x03, 0xaa, 0xbb].to_vec(); let _ret_read = TestStruct::try_from(test_data.as_ref()).unwrap(); } diff --git a/tests/test_attributes/test_limits/test_until.rs b/tests/test_attributes/test_limits/test_until.rs index f88a3d5e..4285f588 100644 --- a/tests/test_attributes/test_limits/test_until.rs +++ b/tests/test_attributes/test_limits/test_until.rs @@ -1,6 +1,7 @@ -use deku::prelude::*; use std::convert::{TryFrom, TryInto}; +use deku::prelude::*; + mod test_slice { use super::*; @@ -12,7 +13,7 @@ mod test_slice { data: &'a [u8], } - let test_data: Vec = [0xAA, 0xBB].to_vec(); + let test_data: Vec = [0xaa, 0xbb].to_vec(); let ret_read = TestStruct::try_from(test_data.as_ref()).unwrap(); assert_eq!( @@ -36,12 +37,12 @@ mod test_slice { data: &'a [u8], } - let test_data: Vec = [0xBB, 0xAA, 0xBB].to_vec(); + let test_data: Vec = [0xbb, 0xaa, 0xbb].to_vec(); let ret_read = TestStruct::try_from(test_data.as_ref()).unwrap(); assert_eq!( TestStruct { - until: 0xBB, + until: 0xbb, data: &test_data[1..] }, ret_read @@ -62,7 +63,7 @@ mod test_slice { data: &'a [u8], } - let test_data: Vec = [0xCC, 0xAA, 0xBB].to_vec(); + let test_data: Vec = [0xcc, 0xaa, 0xbb].to_vec(); let _ret_read = TestStruct::try_from(test_data.as_ref()).unwrap(); } @@ -79,12 +80,12 @@ mod test_vec { data: Vec, } - let test_data: Vec = [0xAA, 0xBB].to_vec(); + let test_data: Vec = [0xaa, 0xbb].to_vec(); let ret_read = TestStruct::try_from(test_data.as_ref()).unwrap(); assert_eq!( TestStruct { - data: vec![0xAA, 0xBB] + data: vec![0xaa, 0xbb] }, ret_read ); @@ -103,13 +104,13 @@ mod test_vec { data: Vec, } - let test_data: Vec = [0xBB, 0xAA, 0xBB].to_vec(); + let test_data: Vec = [0xbb, 0xaa, 0xbb].to_vec(); let ret_read = TestStruct::try_from(test_data.as_ref()).unwrap(); assert_eq!( TestStruct { - until: 0xBB, - data: vec![0xAA, 0xBB] + until: 0xbb, + data: vec![0xaa, 0xbb] }, ret_read ); @@ -129,7 +130,7 @@ mod test_vec { data: Vec, } - let test_data: Vec = [0xCC, 0xAA, 0xBB].to_vec(); + let test_data: Vec = [0xcc, 0xaa, 0xbb].to_vec(); let _ret_read = TestStruct::try_from(test_data.as_ref()).unwrap(); } diff --git a/tests/test_attributes/test_map.rs b/tests/test_attributes/test_map.rs index 90329e59..e6d693e8 100644 --- a/tests/test_attributes/test_map.rs +++ b/tests/test_attributes/test_map.rs @@ -1,6 +1,7 @@ -use deku::prelude::*; use std::convert::TryFrom; +use deku::prelude::*; + #[test] fn test_map() { #[derive(PartialEq, Debug, DekuRead)] diff --git a/tests/test_attributes/test_padding/mod.rs b/tests/test_attributes/test_padding/mod.rs index a54bd259..8ac00f36 100644 --- a/tests/test_attributes/test_padding/mod.rs +++ b/tests/test_attributes/test_padding/mod.rs @@ -1,6 +1,7 @@ -use deku::prelude::*; use std::convert::{TryFrom, TryInto}; +use deku::prelude::*; + mod test_pad_bits_after; mod test_pad_bits_before; mod test_pad_bytes_after; @@ -17,20 +18,20 @@ fn test_pad_bits_before_and_pad_bytes_before() { field_b: u8, } - let data: Vec = vec![0b10_000000, 0xAA, 0xBB]; + let data: Vec = vec![0b10_000000, 0xaa, 0xbb]; let ret_read = TestStruct::try_from(data.as_ref()).unwrap(); assert_eq!( TestStruct { field_a: 0b10, - field_b: 0xBB, + field_b: 0xbb, }, ret_read ); let ret_write: Vec = ret_read.try_into().unwrap(); - assert_eq!(vec![0b10_000000, 0x00, 0xBB], ret_write); + assert_eq!(vec![0b10_000000, 0x00, 0xbb], ret_write); } #[test] @@ -42,18 +43,18 @@ fn test_pad_bits_after_and_pad_bytes_after() { field_b: u8, } - let data: Vec = vec![0b10_000000, 0xAA, 0xBB]; + let data: Vec = vec![0b10_000000, 0xaa, 0xbb]; let ret_read = TestStruct::try_from(data.as_ref()).unwrap(); assert_eq!( TestStruct { field_a: 0b10, - field_b: 0xBB, + field_b: 0xbb, }, ret_read ); let ret_write: Vec = ret_read.try_into().unwrap(); - assert_eq!(vec![0b10_000000, 0x00, 0xBB], ret_write); + assert_eq!(vec![0b10_000000, 0x00, 0xbb], ret_write); } diff --git a/tests/test_attributes/test_padding/test_pad_bits_after.rs b/tests/test_attributes/test_padding/test_pad_bits_after.rs index cea1887a..dc751e01 100644 --- a/tests/test_attributes/test_padding/test_pad_bits_after.rs +++ b/tests/test_attributes/test_padding/test_pad_bits_after.rs @@ -1,6 +1,7 @@ -use deku::prelude::*; use std::convert::{TryFrom, TryInto}; +use deku::prelude::*; + #[test] fn test_pad_bits_after() { #[derive(PartialEq, Debug, DekuRead, DekuWrite)] diff --git a/tests/test_attributes/test_padding/test_pad_bits_before.rs b/tests/test_attributes/test_padding/test_pad_bits_before.rs index 9c872aa7..a82150eb 100644 --- a/tests/test_attributes/test_padding/test_pad_bits_before.rs +++ b/tests/test_attributes/test_padding/test_pad_bits_before.rs @@ -1,6 +1,7 @@ -use deku::prelude::*; use std::convert::{TryFrom, TryInto}; +use deku::prelude::*; + #[test] fn test_pad_bits_before() { #[derive(PartialEq, Debug, DekuRead, DekuWrite)] diff --git a/tests/test_attributes/test_padding/test_pad_bytes_after.rs b/tests/test_attributes/test_padding/test_pad_bytes_after.rs index 787eb60d..c0ea0171 100644 --- a/tests/test_attributes/test_padding/test_pad_bytes_after.rs +++ b/tests/test_attributes/test_padding/test_pad_bytes_after.rs @@ -1,6 +1,7 @@ -use deku::prelude::*; use std::convert::{TryFrom, TryInto}; +use deku::prelude::*; + #[test] fn test_pad_bytes_after() { #[derive(PartialEq, Debug, DekuRead, DekuWrite)] @@ -10,20 +11,20 @@ fn test_pad_bytes_after() { field_b: u8, } - let data: Vec = vec![0xAA, 0xBB, 0xCC, 0xDD]; + let data: Vec = vec![0xaa, 0xbb, 0xcc, 0xdd]; let ret_read = TestStruct::try_from(data.as_ref()).unwrap(); assert_eq!( TestStruct { - field_a: 0xAA, - field_b: 0xDD, + field_a: 0xaa, + field_b: 0xdd, }, ret_read ); let ret_write: Vec = ret_read.try_into().unwrap(); - assert_eq!(vec![0xAA, 0x00, 0x00, 0xDD], ret_write); + assert_eq!(vec![0xaa, 0x00, 0x00, 0xdd], ret_write); } #[test] @@ -36,7 +37,7 @@ fn test_pad_bytes_after_not_enough() { field_b: u8, } - let data: Vec = vec![0xAA, 0xBB, 0xCC, 0xDD]; + let data: Vec = vec![0xaa, 0xbb, 0xcc, 0xdd]; let _ret_read = TestStruct::try_from(data.as_ref()).unwrap(); } @@ -53,7 +54,7 @@ fn test_pad_bytes_after_read_err() { field_b: u8, } - let data: Vec = vec![0xAA, 0xBB, 0xCC, 0xDD]; + let data: Vec = vec![0xaa, 0xbb, 0xcc, 0xdd]; let _ret_read = TestStruct::try_from(data.as_ref()).unwrap(); } @@ -71,8 +72,8 @@ fn test_pad_bytes_after_write_err() { } let data = TestStruct { - field_a: 0xAA, - field_b: 0xDD, + field_a: 0xaa, + field_b: 0xdd, }; let _ret_write: Vec = data.try_into().unwrap(); diff --git a/tests/test_attributes/test_padding/test_pad_bytes_before.rs b/tests/test_attributes/test_padding/test_pad_bytes_before.rs index 7d53d67a..636a73eb 100644 --- a/tests/test_attributes/test_padding/test_pad_bytes_before.rs +++ b/tests/test_attributes/test_padding/test_pad_bytes_before.rs @@ -1,6 +1,7 @@ -use deku::prelude::*; use std::convert::{TryFrom, TryInto}; +use deku::prelude::*; + #[test] fn test_pad_bytes_before() { #[derive(PartialEq, Debug, DekuRead, DekuWrite)] @@ -10,20 +11,20 @@ fn test_pad_bytes_before() { field_b: u8, } - let data: Vec = vec![0xAA, 0xBB, 0xCC, 0xDD]; + let data: Vec = vec![0xaa, 0xbb, 0xcc, 0xdd]; let ret_read = TestStruct::try_from(data.as_ref()).unwrap(); assert_eq!( TestStruct { - field_a: 0xAA, - field_b: 0xDD, + field_a: 0xaa, + field_b: 0xdd, }, ret_read ); let ret_write: Vec = ret_read.try_into().unwrap(); - assert_eq!(vec![0xAA, 0x00, 0x00, 0xDD], ret_write); + assert_eq!(vec![0xaa, 0x00, 0x00, 0xdd], ret_write); } #[test] @@ -36,7 +37,7 @@ fn test_pad_bytes_before_not_enough() { field_b: u8, } - let data: Vec = vec![0xAA]; + let data: Vec = vec![0xaa]; let _ret_read = TestStruct::try_from(data.as_ref()).unwrap(); } @@ -53,7 +54,7 @@ fn test_pad_bytes_before_read_err() { field_b: u8, } - let data: Vec = vec![0xAA, 0xBB, 0xCC, 0xDD]; + let data: Vec = vec![0xaa, 0xbb, 0xcc, 0xdd]; let _ret_read = TestStruct::try_from(data.as_ref()).unwrap(); } @@ -71,8 +72,8 @@ fn test_pad_bytes_before_write_err() { } let data = TestStruct { - field_a: 0xAA, - field_b: 0xDD, + field_a: 0xaa, + field_b: 0xdd, }; let _ret_write: Vec = data.try_into().unwrap(); diff --git a/tests/test_attributes/test_skip.rs b/tests/test_attributes/test_skip.rs index a554e9ac..e9dc0559 100644 --- a/tests/test_attributes/test_skip.rs +++ b/tests/test_attributes/test_skip.rs @@ -1,6 +1,7 @@ -use deku::prelude::*; use std::convert::{TryFrom, TryInto}; +use deku::prelude::*; + /// Skip #[test] fn test_skip() { diff --git a/tests/test_attributes/test_temp.rs b/tests/test_attributes/test_temp.rs index 3893ad96..e86e2f98 100644 --- a/tests/test_attributes/test_temp.rs +++ b/tests/test_attributes/test_temp.rs @@ -1,6 +1,7 @@ -use deku::prelude::*; use std::convert::{TryFrom, TryInto}; +use deku::prelude::*; + #[test] fn test_temp_field_write() { #[deku_derive(DekuRead, DekuWrite)] @@ -114,7 +115,7 @@ fn test_temp_enum_field() { }, } - let test_data: Vec = [0xAB, 0x01, 0x02].to_vec(); + let test_data: Vec = [0xab, 0x01, 0x02].to_vec(); let ret_read = TestEnum::try_from(test_data.as_ref()).unwrap(); assert_eq!( @@ -125,7 +126,7 @@ fn test_temp_enum_field() { ); let ret_write: Vec = ret_read.try_into().unwrap(); - assert_eq!(vec![0xAB, 0x02], ret_write); + assert_eq!(vec![0xab, 0x02], ret_write); } #[test] @@ -148,7 +149,7 @@ fn test_temp_enum_field_write() { VarB(u8), } - let test_data: Vec = [0xAB, 0x01, 0x02].to_vec(); + let test_data: Vec = [0xab, 0x01, 0x02].to_vec(); let ret_write: Vec = TestEnum::VarA { field_b: vec![0x02], } @@ -156,7 +157,7 @@ fn test_temp_enum_field_write() { .unwrap(); assert_eq!(test_data, ret_write); - let test_data: Vec = [0xBA, 0x10].to_vec(); + let test_data: Vec = [0xba, 0x10].to_vec(); let ret_write: Vec = TestEnum::VarB(0x10).to_bytes().unwrap(); assert_eq!(test_data, ret_write); } diff --git a/tests/test_attributes/test_update.rs b/tests/test_attributes/test_update.rs index 19dcb69d..1faf9df2 100644 --- a/tests/test_attributes/test_update.rs +++ b/tests/test_attributes/test_update.rs @@ -1,6 +1,7 @@ -use deku::prelude::*; use std::convert::{TryFrom, TryInto}; +use deku::prelude::*; + /// Update field value #[test] fn test_update() { @@ -36,20 +37,20 @@ fn test_update_from_field() { } // Update the value of `count` to the length of `data` - let test_data: Vec = [0x02, 0xAA, 0xBB].to_vec(); + let test_data: Vec = [0x02, 0xaa, 0xbb].to_vec(); // Read let mut ret_read = TestStruct::try_from(test_data.as_ref()).unwrap(); assert_eq!( TestStruct { count: 0x02, - data: vec![0xAA, 0xBB] + data: vec![0xaa, 0xbb] }, ret_read ); // Add an item to the vec - ret_read.data.push(0xFF); + ret_read.data.push(0xff); // `count` field should now be increased ret_read.update().unwrap(); @@ -57,7 +58,7 @@ fn test_update_from_field() { // Write let ret_write: Vec = ret_read.try_into().unwrap(); - assert_eq!([0x03, 0xAA, 0xBB, 0xFF].to_vec(), ret_write); + assert_eq!([0x03, 0xaa, 0xbb, 0xff].to_vec(), ret_write); } /// Update error diff --git a/tests/test_catch_all.rs b/tests/test_catch_all.rs index a068f86e..37946f22 100644 --- a/tests/test_catch_all.rs +++ b/tests/test_catch_all.rs @@ -1,8 +1,8 @@ #[cfg(test)] mod test { + use std::convert::{TryFrom, TryInto}; + use deku::prelude::*; - use std::convert::TryFrom; - use std::convert::TryInto; /// Basic test struct #[derive(Clone, Copy, PartialEq, Eq, Debug, DekuWrite, DekuRead)] diff --git a/tests/test_compile/cases/internal_variables.rs b/tests/test_compile/cases/internal_variables.rs index 5a78923a..4e5d1930 100644 --- a/tests/test_compile/cases/internal_variables.rs +++ b/tests/test_compile/cases/internal_variables.rs @@ -53,8 +53,8 @@ struct TestMap { fn dummy_reader( offset: usize, rest: &BitSlice, -) -> Result<(&BitSlice, usize), DekuError> { - Ok((rest, offset)) +) -> Result<(usize, usize), DekuError> { + Ok((0, offset)) } #[derive(DekuRead, DekuWrite)] struct TestReader { diff --git a/tests/test_compile/cases/unknown_endian.stderr b/tests/test_compile/cases/unknown_endian.stderr index f6277a95..bfb919e8 100644 --- a/tests/test_compile/cases/unknown_endian.stderr +++ b/tests/test_compile/cases/unknown_endian.stderr @@ -1,5 +1,5 @@ error[E0425]: cannot find value `variable` in this scope - --> $DIR/unknown_endian.rs:3:10 + --> tests/test_compile/cases/unknown_endian.rs:3:10 | 3 | #[derive(DekuRead)] | ^^^^^^^^ not found in this scope @@ -7,7 +7,7 @@ error[E0425]: cannot find value `variable` in this scope = note: this error originates in the derive macro `DekuRead` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0425]: cannot find value `variable` in this scope - --> $DIR/unknown_endian.rs:9:10 + --> tests/test_compile/cases/unknown_endian.rs:9:10 | 9 | #[derive(DekuRead)] | ^^^^^^^^ not found in this scope @@ -15,7 +15,7 @@ error[E0425]: cannot find value `variable` in this scope = note: this error originates in the derive macro `DekuRead` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0425]: cannot find value `variable` in this scope - --> $DIR/unknown_endian.rs:15:10 + --> tests/test_compile/cases/unknown_endian.rs:15:10 | 15 | #[derive(DekuRead)] | ^^^^^^^^ not found in this scope @@ -23,27 +23,15 @@ error[E0425]: cannot find value `variable` in this scope = note: this error originates in the derive macro `DekuRead` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0425]: cannot find value `variable` in this scope - --> $DIR/unknown_endian.rs:19:10 + --> tests/test_compile/cases/unknown_endian.rs:19:10 | 19 | #[derive(DekuRead)] | ^^^^^^^^ not found in this scope | = note: this error originates in the derive macro `DekuRead` (in Nightly builds, run with -Z macro-backtrace for more info) -warning: unreachable statement - --> $DIR/unknown_endian.rs:15:10 - | -15 | #[derive(DekuRead)] - | ^^^^^^^^ - | | - | unreachable statement - | any code following this `match` expression is unreachable, as all arms diverge - | - = note: `#[warn(unreachable_code)]` on by default - = note: this warning originates in the derive macro `DekuRead` (in Nightly builds, run with -Z macro-backtrace for more info) - warning: unreachable expression - --> $DIR/unknown_endian.rs:15:10 + --> tests/test_compile/cases/unknown_endian.rs:15:10 | 15 | #[derive(DekuRead)] | ^^^^^^^^ @@ -51,4 +39,5 @@ warning: unreachable expression | unreachable expression | any code following this `match` expression is unreachable, as all arms diverge | + = note: `#[warn(unreachable_code)]` on by default = note: this warning originates in the derive macro `DekuRead` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/test_deku_id.rs b/tests/test_deku_id.rs index 6d0bc1d2..1296bafa 100644 --- a/tests/test_deku_id.rs +++ b/tests/test_deku_id.rs @@ -58,7 +58,7 @@ fn test_ctx() { #[derive(Copy, Clone, PartialEq, Debug, DekuRead, DekuWrite)] #[deku(type = "u8")] enum Nice { - True = 0x00, + True = 0x00, False = 0x01, } diff --git a/tests/test_enum.rs b/tests/test_enum.rs index f652f298..5c9fd50c 100644 --- a/tests/test_enum.rs +++ b/tests/test_enum.rs @@ -1,7 +1,8 @@ +use std::convert::{TryFrom, TryInto}; + use deku::prelude::*; use hexlit::hex; use rstest::*; -use std::convert::{TryFrom, TryInto}; /// General smoke tests for enums /// TODO: These should be divided into smaller tests diff --git a/tests/test_from_bytes.rs b/tests/test_from_bytes.rs index dd14d587..88eaaa46 100644 --- a/tests/test_from_bytes.rs +++ b/tests/test_from_bytes.rs @@ -6,26 +6,26 @@ fn test_from_bytes_struct() { struct TestDeku(#[deku(bits = 4)] u8); let test_data: Vec = [0b0110_0110u8, 0b0101_1010u8].to_vec(); + let mut total_read = 0; - let ((rest, i), ret_read) = TestDeku::from_bytes((&test_data, 0)).unwrap(); + let (amt_read, ret_read) = TestDeku::from_bytes((&test_data, 0)).unwrap(); + total_read += amt_read; + assert_eq!(amt_read, 4); assert_eq!(TestDeku(0b0110), ret_read); - assert_eq!(2, rest.len()); - assert_eq!(4, i); - let ((rest, i), ret_read) = TestDeku::from_bytes((rest, i)).unwrap(); + let (amt_read, ret_read) = TestDeku::from_bytes((&test_data, total_read)).unwrap(); + total_read += amt_read; + assert_eq!(amt_read, 4); assert_eq!(TestDeku(0b0110), ret_read); - assert_eq!(1, rest.len()); - assert_eq!(0, i); - let ((rest, i), ret_read) = TestDeku::from_bytes((rest, i)).unwrap(); + let (amt_read, ret_read) = TestDeku::from_bytes((&test_data, total_read)).unwrap(); + total_read += amt_read; + assert_eq!(amt_read, 4); assert_eq!(TestDeku(0b0101), ret_read); - assert_eq!(1, rest.len()); - assert_eq!(4, i); - let ((rest, i), ret_read) = TestDeku::from_bytes((rest, i)).unwrap(); + let (amt_read, ret_read) = TestDeku::from_bytes((&test_data, total_read)).unwrap(); + assert_eq!(amt_read, 4); assert_eq!(TestDeku(0b1010), ret_read); - assert_eq!(0, rest.len()); - assert_eq!(0, i); } #[test] @@ -41,14 +41,11 @@ fn test_from_bytes_enum() { let test_data: Vec = [0b0110_0110u8, 0b0101_1010u8].to_vec(); - let ((rest, i), ret_read) = TestDeku::from_bytes((&test_data, 0)).unwrap(); + let (amt_read, ret_read) = TestDeku::from_bytes((&test_data, 0)).unwrap(); + assert_eq!(amt_read, 8); assert_eq!(TestDeku::VariantA(0b0110), ret_read); - assert_eq!(1, rest.len()); - assert_eq!(0, i); - let ((rest, i), ret_read) = TestDeku::from_bytes((rest, i)).unwrap(); + let (amt_read, ret_read) = TestDeku::from_bytes((&test_data, amt_read)).unwrap(); + assert_eq!(amt_read, 6); assert_eq!(TestDeku::VariantB(0b10), ret_read); - assert_eq!(1, rest.len()); - assert_eq!(6, i); - assert_eq!(0b0101_1010u8, rest[0]); } diff --git a/tests/test_generic.rs b/tests/test_generic.rs index 6151c223..4cdd2ff5 100644 --- a/tests/test_generic.rs +++ b/tests/test_generic.rs @@ -1,6 +1,7 @@ -use deku::prelude::*; use std::convert::{TryFrom, TryInto}; +use deku::prelude::*; + #[test] fn test_generic_struct() { #[derive(PartialEq, Debug, DekuRead, DekuWrite)] diff --git a/tests/test_magic.rs b/tests/test_magic.rs index dbf8240f..f3c8984d 100644 --- a/tests/test_magic.rs +++ b/tests/test_magic.rs @@ -1,7 +1,8 @@ +use std::convert::{TryFrom, TryInto}; + use deku::prelude::*; use hexlit::hex; use rstest::rstest; -use std::convert::{TryFrom, TryInto}; #[rstest(input, case(&hex!("64656b75")), diff --git a/tests/test_regression.rs b/tests/test_regression.rs index 4314414e..037d47ee 100644 --- a/tests/test_regression.rs +++ b/tests/test_regression.rs @@ -21,8 +21,8 @@ fn issue_224() { #[deku(type = "u8", bits = "2")] pub enum One { Start = 0, - Go = 1, - Stop = 2, + Go = 1, + Stop = 2, } #[derive(Debug, PartialEq, DekuRead, DekuWrite)] @@ -126,7 +126,7 @@ mod issue_282 { // /~https://github.com/sharksforarms/deku/issues/292 #[test] fn test_regression_292() { - let test_data: &[u8] = [0x0F, 0xF0].as_ref(); + let test_data: &[u8] = [0x0f, 0xf0].as_ref(); #[derive(Debug, PartialEq, DekuRead)] #[deku(endian = "little")] diff --git a/tests/test_struct.rs b/tests/test_struct.rs index c620af5d..69e03d79 100644 --- a/tests/test_struct.rs +++ b/tests/test_struct.rs @@ -1,8 +1,9 @@ #![allow(clippy::unusual_byte_groupings)] -use deku::prelude::*; use std::convert::{TryFrom, TryInto}; +use deku::prelude::*; + mod test_common; /// General smoke tests for structs @@ -53,18 +54,18 @@ fn test_unnamed_struct() { ); let test_data: Vec = [ - 0xFF, + 0xff, 0b1001_0110, - 0xAA, - 0xBB, - 0xCC, - 0xDD, + 0xaa, + 0xbb, + 0xcc, + 0xdd, 0b1001_0110, - 0xCC, - 0xDD, + 0xcc, + 0xdd, 0x02, - 0xBE, - 0xEF, + 0xbe, + 0xef, ] .to_vec(); @@ -72,20 +73,20 @@ fn test_unnamed_struct() { let ret_read = TestUnamedStruct::try_from(test_data.as_ref()).unwrap(); assert_eq!( TestUnamedStruct( - 0xFF, + 0xff, 0b0000_0010, 0b0001_0110, - native_endian!(0xBBAAu16), - 0xCCDDu16, + native_endian!(0xbbaau16), + 0xccddu16, NestedDeku { nest_a: 0b00_100101, nest_b: 0b10, inner: DoubleNestedDeku { - data: native_endian!(0xDDCCu16) + data: native_endian!(0xddccu16) } }, 0x02, - vec![0xBE, 0xEF], + vec![0xbe, 0xef], ), ret_read ); @@ -116,18 +117,18 @@ fn test_named_struct() { } let test_data: Vec = [ - 0xFF, + 0xff, 0b1001_0110, - 0xAA, - 0xBB, - 0xCC, - 0xDD, + 0xaa, + 0xbb, + 0xcc, + 0xdd, 0b1001_0110, - 0xCC, - 0xDD, + 0xcc, + 0xdd, 0x02, - 0xBE, - 0xEF, + 0xbe, + 0xef, ] .to_vec(); @@ -135,20 +136,20 @@ fn test_named_struct() { let ret_read = TestStruct::try_from(test_data.as_ref()).unwrap(); assert_eq!( TestStruct { - field_a: 0xFF, + field_a: 0xff, field_b: 0b0000_0010, field_c: 0b0001_0110, - field_d: native_endian!(0xBBAAu16), - field_e: 0xCCDDu16, + field_d: native_endian!(0xbbaau16), + field_e: 0xccddu16, field_f: NestedDeku { nest_a: 0b00_100101, nest_b: 0b10, inner: DoubleNestedDeku { - data: native_endian!(0xDDCCu16) + data: native_endian!(0xddccu16) } }, vec_len: 0x02, - vec_data: vec![0xBE, 0xEF] + vec_data: vec![0xbe, 0xef] }, ret_read ); @@ -165,11 +166,11 @@ fn test_raw_identifiers_struct() { pub r#type: u8, } - let test_data: Vec = [0xFF].to_vec(); + let test_data: Vec = [0xff].to_vec(); // Read let ret_read = TestStruct::try_from(test_data.as_ref()).unwrap(); - assert_eq!(TestStruct { r#type: 0xFF }, ret_read); + assert_eq!(TestStruct { r#type: 0xff }, ret_read); // Write let ret_write: Vec = ret_read.try_into().unwrap();