diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 4e3fd019..81684c51 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -22,6 +22,8 @@ jobs: - run: cargo test --all # run examples - run: cargo run --example 2>&1 | grep -P ' ' | awk '{print $1}' | xargs -i cargo run --example {} + # test with no bits feature (don't test docs) + - run: cargo test --lib --examples --tests --features std --no-default-features # Only build on MSRV, since trybuild will fail on older version build-msrv: diff --git a/Cargo.toml b/Cargo.toml index 65a46711..9a871510 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -56,3 +56,31 @@ workspace = true # Triggers in macro generated code of darling # https://github.com/rust-lang/rust-clippy/issues/12643 manual-unwrap-or-default = "allow" + +[[example]] +name = "custom_reader_and_writer" +required-features = ["bits"] + +[[example]] +name = "deku_input" + +[[example]] +name = "enums_catch_all" +required-features = ["bits"] + +[[example]] +name = "enums" + +[[example]] +name = "example" +required-features = ["bits"] + +[[example]] +name = "ipv4" +required-features = ["bits"] + +[[example]] +name = "many" + +[[example]] +name = "read_all" diff --git a/deku-derive/src/lib.rs b/deku-derive/src/lib.rs index fea289b7..8a45fcf7 100644 --- a/deku-derive/src/lib.rs +++ b/deku-derive/src/lib.rs @@ -136,6 +136,7 @@ struct DekuData { id_type: Option, /// enum only: bit size of the enum `id` + #[cfg(feature = "bits")] bits: Option, /// enum only: byte size of the enum `id` @@ -198,6 +199,7 @@ impl DekuData { magic: receiver.magic, id: receiver.id, id_type: receiver.id_type?, + #[cfg(feature = "bits")] bits: receiver.bits, bytes: receiver.bytes, seek_rewind: receiver.seek_rewind, @@ -224,7 +226,7 @@ impl DekuData { match data.data { ast::Data::Struct(_) => { // Validate id_* attributes are being used on an enum - if data.id_type.is_some() { + let ret = if data.id_type.is_some() { Err(cerror( data.id_type.span(), "`id_type` only supported on enum", @@ -233,11 +235,16 @@ impl DekuData { Err(cerror(data.id.span(), "`id` only supported on enum")) } else if data.bytes.is_some() { Err(cerror(data.bytes.span(), "`bytes` only supported on enum")) - } else if data.bits.is_some() { - Err(cerror(data.bits.span(), "`bits` only supported on enum")) } else { Ok(()) + }; + + #[cfg(feature = "bits")] + if ret.is_ok() && data.bits.is_some() { + return Err(cerror(data.bits.span(), "`bits` only supported on enum")); } + + ret } ast::Data::Enum(_) => { // Validate `id_type` or `id` is specified @@ -257,6 +264,7 @@ impl DekuData { } // Validate `id_*` used correctly + #[cfg(feature = "bits")] if data.id.is_some() && data.bits.is_some() { return Err(cerror( data.ident.span(), @@ -271,6 +279,7 @@ impl DekuData { } // Validate either `bits` or `bytes` is specified + #[cfg(feature = "bits")] if data.bits.is_some() && data.bytes.is_some() { return Err(cerror( data.bits.span(), @@ -336,7 +345,10 @@ impl<'a> TryFrom<&'a DekuData> for DekuDataEnum<'a> { let id_args = crate::macros::gen_id_args( deku_data.endian.as_ref(), + #[cfg(feature = "bits")] deku_data.bits.as_ref(), + #[cfg(not(feature = "bits"))] + None, deku_data.bytes.as_ref(), )?; @@ -393,6 +405,7 @@ struct FieldData { endian: Option, /// field bit size + #[cfg(feature = "bits")] bits: Option, /// field byte size @@ -402,6 +415,7 @@ struct FieldData { count: Option, /// tokens providing the number of bits for the length of the container + #[cfg(feature = "bits")] bits_read: Option, /// tokens providing the number of bytes for the length of the container @@ -432,12 +446,14 @@ struct FieldData { skip: bool, /// pad a number of bits before + #[cfg(feature = "bits")] pad_bits_before: Option, /// pad a number of bytes before pad_bytes_before: Option, /// pad a number of bits after + #[cfg(feature = "bits")] pad_bits_after: Option, /// pad a number of bytes after @@ -486,9 +502,11 @@ impl FieldData { ident: receiver.ident, ty: receiver.ty, endian: receiver.endian, + #[cfg(feature = "bits")] bits: receiver.bits, bytes: receiver.bytes, count: receiver.count?, + #[cfg(feature = "bits")] bits_read: receiver.bits_read?, bytes_read: receiver.bytes_read?, until: receiver.until?, @@ -499,8 +517,10 @@ impl FieldData { reader: receiver.reader?, writer: receiver.writer?, skip: receiver.skip, + #[cfg(feature = "bits")] pad_bits_before: receiver.pad_bits_before?, pad_bytes_before: receiver.pad_bytes_before?, + #[cfg(feature = "bits")] pad_bits_after: receiver.pad_bits_after?, pad_bytes_after: receiver.pad_bytes_after?, temp: receiver.temp, @@ -524,6 +544,7 @@ impl FieldData { fn validate(data: &FieldData) -> Result<(), TokenStream> { // Validate either `read_bytes` or `read_bits` is specified + #[cfg(feature = "bits")] if data.bits_read.is_some() && data.bytes_read.is_some() { return Err(cerror( data.bits_read.span(), @@ -532,6 +553,7 @@ impl FieldData { } // Validate either `count` or `bits_read`/`bytes_read` is specified + #[cfg(feature = "bits")] if data.count.is_some() && (data.bits_read.is_some() || data.bytes_read.is_some()) { if data.bits_read.is_some() { return Err(cerror( @@ -546,7 +568,16 @@ impl FieldData { } } + #[cfg(not(feature = "bits"))] + if data.count.is_some() && data.bytes_read.is_some() { + return Err(cerror( + data.count.span(), + "conflicting: both `count` and `bytes_read` specified on field", + )); + } + // Validate either `bits` or `bytes` is specified + #[cfg(feature = "bits")] if data.bits.is_some() && data.bytes.is_some() { // FIXME: Use `Span::join` once out of nightly return Err(cerror( @@ -565,6 +596,7 @@ impl FieldData { } // Validate usage of read_all + #[cfg(feature = "bits")] if data.read_all && (data.until.is_some() || data.count.is_some() @@ -572,7 +604,7 @@ impl FieldData { { return Err(cerror( data.bits.span(), - "conflicting: `read_all` cannot be used with `until`, count`, `bits_read`, or `bytes_read`", + "conflicting: `read_all` cannot be used with `until`, `count`, `bits_read`, or `bytes_read`", )); } @@ -707,6 +739,7 @@ struct DekuReceiver { id_type: Result, ReplacementError>, /// enum only: bit size of the enum `id` + #[cfg(feature = "bits")] #[darling(default)] bits: Option, @@ -816,6 +849,7 @@ struct DekuFieldReceiver { endian: Option, /// field bit size + #[cfg(feature = "bits")] #[darling(default)] bits: Option, @@ -828,6 +862,7 @@ struct DekuFieldReceiver { count: Result, ReplacementError>, /// tokens providing the number of bits for the length of the container + #[cfg(feature = "bits")] #[darling(default = "default_res_opt", map = "map_litstr_as_tokenstream")] bits_read: Result, ReplacementError>, @@ -871,6 +906,7 @@ struct DekuFieldReceiver { skip: bool, /// pad a number of bits before + #[cfg(feature = "bits")] #[darling(default = "default_res_opt", map = "map_litstr_as_tokenstream")] pad_bits_before: Result, ReplacementError>, @@ -879,6 +915,7 @@ struct DekuFieldReceiver { pad_bytes_before: Result, ReplacementError>, /// pad a number of bits after + #[cfg(feature = "bits")] #[darling(default = "default_res_opt", map = "map_litstr_as_tokenstream")] pad_bits_after: Result, ReplacementError>, diff --git a/deku-derive/src/macros/deku_read.rs b/deku-derive/src/macros/deku_read.rs index 287e03c3..1231fadf 100644 --- a/deku-derive/src/macros/deku_read.rs +++ b/deku-derive/src/macros/deku_read.rs @@ -7,7 +7,7 @@ use quote::quote; 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, + gen_type_from_ctx_id, token_contains_string, wrap_default_ctx, }; use crate::{DekuData, DekuDataEnum, DekuDataStruct, FieldData, Id}; @@ -557,6 +557,7 @@ fn emit_bit_byte_offsets( (bit_offset, byte_offset) } +#[cfg(feature = "bits")] fn emit_padding(bit_size: &TokenStream) -> TokenStream { let crate_ = super::get_crate_name(); quote! { @@ -584,6 +585,29 @@ fn emit_padding(bit_size: &TokenStream) -> TokenStream { } } +// TODO: if this is a simple calculation such as "8 + 2", this could be const +#[cfg(not(feature = "bits"))] +fn emit_padding_bytes(bit_size: &TokenStream) -> TokenStream { + let crate_ = super::get_crate_name(); + quote! { + { + use core::convert::TryFrom; + extern crate alloc; + use alloc::borrow::Cow; + let __deku_pad = usize::try_from(#bit_size).map_err(|e| + ::#crate_::DekuError::InvalidParam(Cow::from(format!( + "Invalid padding param \"({})\": cannot convert to usize", + stringify!(#bit_size) + ))) + )?; + + + let mut buf = vec![0; __deku_pad]; + let _ = __deku_reader.read_bytes(__deku_pad, &mut buf)?; + } + } +} + fn emit_field_read( input: &DekuData, i: usize, @@ -601,6 +625,7 @@ fn emit_field_read( // fields to check usage of bit/byte offset let field_check_vars = [ &f.count, + #[cfg(feature = "bits")] &f.bits_read, &f.bytes_read, &f.until, @@ -704,7 +729,10 @@ fn emit_field_read( } else { let read_args = gen_field_args( field_endian, + #[cfg(feature = "bits")] f.bits.as_ref(), + #[cfg(not(feature = "bits"))] + None, f.bytes.as_ref(), f.ctx.as_ref(), )?; @@ -741,17 +769,6 @@ fn emit_field_read( )? } } - } else if let Some(field_bits) = &f.bits_read { - quote! { - { - use core::borrow::Borrow; - #type_as_deku_read::from_reader_with_ctx - ( - __deku_reader, - (::#crate_::ctx::Limit::new_bit_size(::#crate_::ctx::BitSize(usize::try_from(*((#field_bits).borrow()))?)), (#read_args)) - )? - } - } } else if let Some(field_bytes) = &f.bytes_read { quote! { { @@ -785,27 +802,54 @@ fn emit_field_read( } } } else { - quote! { - #type_as_deku_read::from_reader_with_ctx - ( - __deku_reader, - (#read_args) - )? + let mut ret = quote! {}; + + #[cfg(feature = "bits")] + if let Some(field_bits) = &f.bits_read { + ret.extend(quote! { + { + use core::borrow::Borrow; + #type_as_deku_read::from_reader_with_ctx + ( + __deku_reader, + (::#crate_::ctx::Limit::new_bit_size(::#crate_::ctx::BitSize(usize::try_from(*((#field_bits).borrow()))?)), (#read_args)) + )? + } + }) + } + if ret.is_empty() { + ret.extend(quote! { + #type_as_deku_read::from_reader_with_ctx + ( + __deku_reader, + (#read_args) + )? + }) } + + ret } }; - let pad_bits_before = pad_bits( + #[cfg(feature = "bits")] + let pad_bits_before = crate::macros::pad_bits( f.pad_bits_before.as_ref(), f.pad_bytes_before.as_ref(), emit_padding, ); - let pad_bits_after = pad_bits( + #[cfg(feature = "bits")] + let pad_bits_after = crate::macros::pad_bits( f.pad_bits_after.as_ref(), f.pad_bytes_after.as_ref(), emit_padding, ); + #[cfg(not(feature = "bits"))] + let pad_bits_before = crate::macros::pad_bytes(f.pad_bytes_before.as_ref(), emit_padding_bytes); + + #[cfg(not(feature = "bits"))] + let pad_bits_after = crate::macros::pad_bytes(f.pad_bytes_after.as_ref(), emit_padding_bytes); + let field_read_normal = quote! { let __deku_value = #field_read_func; let __deku_value: #field_type = #field_map(__deku_value)?; diff --git a/deku-derive/src/macros/deku_write.rs b/deku-derive/src/macros/deku_write.rs index 7f7c6cf1..c0183eef 100644 --- a/deku-derive/src/macros/deku_write.rs +++ b/deku-derive/src/macros/deku_write.rs @@ -5,7 +5,7 @@ use proc_macro2::TokenStream; use quote::quote; use crate::macros::{ - assertion_failed, gen_ctx_types_and_arg, gen_field_args, gen_struct_destruction, pad_bits, + assertion_failed, gen_ctx_types_and_arg, gen_field_args, gen_struct_destruction, token_contains_string, wrap_default_ctx, }; use crate::{DekuData, DekuDataEnum, DekuDataStruct, FieldData, Id}; @@ -460,6 +460,7 @@ fn emit_bit_byte_offsets( (bit_offset, byte_offset) } +#[cfg(feature = "bits")] fn emit_padding(bit_size: &TokenStream) -> TokenStream { let crate_ = super::get_crate_name(); quote! { @@ -478,6 +479,26 @@ fn emit_padding(bit_size: &TokenStream) -> TokenStream { } } +// TODO: if this is a simple calculation such as "8 + 2", this could be const +#[cfg(not(feature = "bits"))] +fn emit_padding_bytes(bit_size: &TokenStream) -> TokenStream { + let crate_ = super::get_crate_name(); + quote! { + { + use core::convert::TryFrom; + extern crate alloc; + use alloc::borrow::Cow; + let __deku_pad = usize::try_from(#bit_size).map_err(|e| + ::#crate_::DekuError::InvalidParam(Cow::from(format!( + "Invalid padding param \"({})\": cannot convert to usize", + stringify!(#bit_size) + ))) + )?; + __deku_writer.write_bytes(&vec![0; __deku_pad])?; + } + } +} + fn emit_field_write( input: &DekuData, i: usize, @@ -582,7 +603,10 @@ fn emit_field_write( } else { let write_args = gen_field_args( field_endian, + #[cfg(feature = "bits")] f.bits.as_ref(), + #[cfg(not(feature = "bits"))] + None, f.bytes.as_ref(), f.ctx.as_ref(), )?; @@ -602,17 +626,25 @@ fn emit_field_write( } }; - let pad_bits_before = pad_bits( + #[cfg(feature = "bits")] + let pad_bits_before = crate::macros::pad_bits( f.pad_bits_before.as_ref(), f.pad_bytes_before.as_ref(), emit_padding, ); - let pad_bits_after = pad_bits( + #[cfg(feature = "bits")] + let pad_bits_after = crate::macros::pad_bits( f.pad_bits_after.as_ref(), f.pad_bytes_after.as_ref(), emit_padding, ); + #[cfg(not(feature = "bits"))] + let pad_bits_before = crate::macros::pad_bytes(f.pad_bytes_before.as_ref(), emit_padding_bytes); + + #[cfg(not(feature = "bits"))] + let pad_bits_after = crate::macros::pad_bytes(f.pad_bytes_after.as_ref(), emit_padding_bytes); + let field_write_normal = quote! { #field_write_func ?; }; diff --git a/deku-derive/src/macros/mod.rs b/deku-derive/src/macros/mod.rs index 847db153..19555dd0 100644 --- a/deku-derive/src/macros/mod.rs +++ b/deku-derive/src/macros/mod.rs @@ -340,6 +340,7 @@ fn token_contains_string(tok: &Option, s: &str) -> bool { .unwrap_or(false) } +#[cfg(feature = "bits")] fn pad_bits( bits: Option<&TokenStream>, bytes: Option<&TokenStream>, @@ -355,6 +356,17 @@ fn pad_bits( } } +#[cfg(not(feature = "bits"))] +fn pad_bytes( + bytes: Option<&TokenStream>, + emit_padding: fn(&TokenStream) -> TokenStream, +) -> TokenStream { + match bytes { + Some(pad_bytes) => emit_padding("e! {((#pad_bytes))}), + None => quote!(), + } +} + /// assertion is false, raise error fn assertion_failed( v: &TokenStream, diff --git a/src/impls/bool.rs b/src/impls/bool.rs index e8f27432..f0bda1f4 100644 --- a/src/impls/bool.rs +++ b/src/impls/bool.rs @@ -73,6 +73,7 @@ mod tests { assert_eq!(expected, res_read); } + #[cfg(feature = "bits")] #[test] fn test_bool_with_context() { let input = &[0b01_000000]; @@ -83,12 +84,16 @@ mod tests { assert!(res_read); } + #[cfg(feature = "bits")] #[test] - fn test_writer() { + fn test_writer_bits() { let mut writer = Writer::new(Cursor::new(vec![])); true.to_writer(&mut writer, BitSize(1)).unwrap(); assert_eq!(vec![true], writer.rest()); + } + #[test] + fn test_writer() { let mut writer = Writer::new(Cursor::new(vec![])); true.to_writer(&mut writer, ()).unwrap(); assert_eq!(vec![1], writer.inner.into_inner()); diff --git a/src/impls/boxed.rs b/src/impls/boxed.rs index 46011b0b..af3af822 100644 --- a/src/impls/boxed.rs +++ b/src/impls/boxed.rs @@ -81,6 +81,7 @@ mod tests { use crate::ctx::*; use crate::native_endian; use crate::reader::Reader; + #[cfg(feature = "bits")] use bitvec::prelude::*; #[rstest(input, expected, @@ -101,6 +102,7 @@ mod tests { } // Note: Copied tests from vec.rs impl + #[cfg(feature = "bits")] #[rstest(input, endian, bit_size, limit, expected, expected_rest_bits, expected_rest_bytes, expected_write, case::normal_le([0xAA, 0xBB, 0xCC, 0xDD].as_ref(), Endian::Little, Some(16), 2.into(), vec![0xBBAA, 0xDDCC].into_boxed_slice(), bits![u8, Msb0;], &[], vec![0xAA, 0xBB, 0xCC, 0xDD]), case::normal_be([0xAA, 0xBB, 0xCC, 0xDD].as_ref(), Endian::Big, Some(16), 2.into(), vec![0xAABB, 0xCCDD].into_boxed_slice(), bits![u8, Msb0;], &[], vec![0xAA, 0xBB, 0xCC, 0xDD]), diff --git a/src/impls/hashmap.rs b/src/impls/hashmap.rs index ea5cc3c3..642be7dc 100644 --- a/src/impls/hashmap.rs +++ b/src/impls/hashmap.rs @@ -231,6 +231,7 @@ mod tests { use crate::reader::Reader; use super::*; + #[cfg(feature = "bits")] use bitvec::prelude::*; // Macro to create a deterministic HashMap for tests @@ -250,6 +251,7 @@ mod tests { }; ); + #[cfg(feature = "bits")] #[rstest(input, endian, bit_size, limit, expected, expected_rest_bits, expected_rest_bytes, case::count_0([0xAA].as_ref(), Endian::Little, Some(8), 0.into(), FxHashMap::default(), bits![u8, Msb0;], &[0xaa]), case::count_1([0x01, 0xAA, 0x02, 0xBB].as_ref(), Endian::Little, Some(8), 1.into(), fxhashmap!{0x01 => 0xAA}, bits![u8, Msb0;], &[0x02, 0xbb]), diff --git a/src/impls/hashset.rs b/src/impls/hashset.rs index d061aed6..7f11e092 100644 --- a/src/impls/hashset.rs +++ b/src/impls/hashset.rs @@ -212,6 +212,7 @@ impl, S, Ctx: Copy> DekuWriter for HashSet { #[cfg(test)] mod tests { + #[cfg(feature = "bits")] use crate::bitvec::{bits, BitSlice, Msb0}; use no_std_io::io::Cursor; use rstest::rstest; @@ -221,6 +222,7 @@ mod tests { use super::*; + #[cfg(feature = "bits")] #[rstest(input, endian, bit_size, limit, expected, expected_rest_bits, expected_rest_bytes, case::count_0([0xAA].as_ref(), Endian::Little, Some(8), 0.into(), FxHashSet::default(), bits![u8, Msb0;], &[0xaa]), case::count_1([0xAA, 0xBB].as_ref(), Endian::Little, Some(8), 1.into(), vec![0xAA].into_iter().collect(), bits![u8, Msb0;], &[0xbb]), @@ -285,6 +287,7 @@ mod tests { } // Note: These tests also exist in boxed.rs + #[cfg(feature = "bits")] #[rstest(input, endian, bit_size, limit, expected, expected_rest_bits, expected_rest_bytes, expected_write, case::normal_le([0xAA, 0xBB, 0xCC, 0xDD].as_ref(), Endian::Little, Some(16), 2.into(), vec![0xBBAA, 0xDDCC].into_iter().collect(), bits![u8, Msb0;], &[], vec![0xCC, 0xDD, 0xAA, 0xBB]), case::normal_be([0xAA, 0xBB, 0xCC, 0xDD].as_ref(), Endian::Big, Some(16), 2.into(), vec![0xAABB, 0xCCDD].into_iter().collect(), bits![u8, Msb0;], &[], vec![0xCC, 0xDD, 0xAA, 0xBB]), diff --git a/src/impls/nonzero.rs b/src/impls/nonzero.rs index c42419d7..6000742b 100644 --- a/src/impls/nonzero.rs +++ b/src/impls/nonzero.rs @@ -65,13 +65,14 @@ ImplDekuTraits!(NonZeroIsize, isize); #[cfg(test)] mod tests { + use std::io::Cursor; + use hexlit::hex; use rstest::rstest; use crate::reader::Reader; use super::*; - use bitvec::prelude::*; #[rstest(input, expected, case(&hex!("FF"), NonZeroU8::new(0xFF).unwrap()), @@ -80,7 +81,7 @@ mod tests { case(&hex!("00"), NonZeroU8::new(0xFF).unwrap()), )] fn test_non_zero(input: &[u8], expected: NonZeroU8) { - let mut cursor = std::io::Cursor::new(input); + let mut cursor = Cursor::new(input); let mut reader = Reader::new(&mut cursor); let res_read = NonZeroU8::from_reader_with_ctx(&mut reader, ()).unwrap(); assert_eq!(expected, res_read); diff --git a/src/impls/primitive.rs b/src/impls/primitive.rs index d113fc18..a3aff12b 100644 --- a/src/impls/primitive.rs +++ b/src/impls/primitive.rs @@ -803,6 +803,7 @@ mod tests { native_endian!(-0.006_f64) ); + #[cfg(feature = "bits")] #[rstest(input, endian, bit_size, expected, expected_rest_bits, expected_rest_bytes, case::normal([0xDD, 0xCC, 0xBB, 0xAA].as_ref(), Endian::Little, Some(32), 0xAABB_CCDD, bits![u8, Msb0;], &[]), case::normal([0xDD, 0xCC, 0xBB, 0xAA].as_ref(), Endian::Big, Some(32), 0xDDCC_BBAA, bits![u8, Msb0;], &[]), @@ -880,6 +881,7 @@ mod tests { assert_eq!(expected_rest_bytes, buf); } + #[cfg(feature = "bits")] #[rstest(input, endian, bit_size, expected, expected_leftover, case::normal_le(0xDDCC_BBAA, Endian::Little, None, vec![0xAA, 0xBB, 0xCC, 0xDD], vec![]), case::normal_be(0xDDCC_BBAA, Endian::Big, None, vec![0xDD, 0xCC, 0xBB, 0xAA], vec![]), @@ -925,6 +927,7 @@ mod tests { assert_hex::assert_eq_hex!(expected, writer.inner.into_inner()); } + #[cfg(feature = "bits")] #[rstest(input, endian, bit_size, expected, expected_write, case::normal([0xDD, 0xCC, 0xBB, 0xAA].as_ref(), Endian::Little, Some(32), 0xAABB_CCDD, vec![0xDD, 0xCC, 0xBB, 0xAA]), )] @@ -970,11 +973,17 @@ mod tests { }; } + #[cfg(feature = "bits")] TestSignExtending!(test_sign_extend_i8, i8); + #[cfg(feature = "bits")] TestSignExtending!(test_sign_extend_i16, i16); + #[cfg(feature = "bits")] TestSignExtending!(test_sign_extend_i32, i32); + #[cfg(feature = "bits")] TestSignExtending!(test_sign_extend_i64, i64); + #[cfg(feature = "bits")] TestSignExtending!(test_sign_extend_i128, i128); + #[cfg(feature = "bits")] TestSignExtending!(test_sign_extend_isize, isize); macro_rules! TestSignExtendingPanic { @@ -998,9 +1007,14 @@ mod tests { }; } + #[cfg(feature = "bits")] TestSignExtendingPanic!(test_sign_extend_i8_panic, i8, 8); + #[cfg(feature = "bits")] TestSignExtendingPanic!(test_sign_extend_i16_panic, i16, 16); + #[cfg(feature = "bits")] TestSignExtendingPanic!(test_sign_extend_i32_panic, i32, 32); + #[cfg(feature = "bits")] TestSignExtendingPanic!(test_sign_extend_i64_panic, i64, 64); + #[cfg(feature = "bits")] TestSignExtendingPanic!(test_sign_extend_i128_panic, i128, 128); } diff --git a/src/impls/slice.rs b/src/impls/slice.rs index 40269062..15b3e18b 100644 --- a/src/impls/slice.rs +++ b/src/impls/slice.rs @@ -96,12 +96,14 @@ where #[cfg(test)] mod tests { use super::*; + #[cfg(feature = "bits")] use bitvec::prelude::*; use rstest::rstest; use std::io::Cursor; use crate::{ctx::Endian, reader::Reader, writer::Writer, DekuReader}; + #[cfg(feature = "bits")] #[rstest(input,endian,expected, case::normal_le([0xDD, 0xCC, 0xBB, 0xAA].as_ref(), Endian::Little, [0xCCDD, 0xAABB]), case::normal_be([0xDD, 0xCC, 0xBB, 0xAA].as_ref(), Endian::Big, [0xDDCC, 0xBBAA]), diff --git a/src/impls/vec.rs b/src/impls/vec.rs index da3bd471..33c89c99 100644 --- a/src/impls/vec.rs +++ b/src/impls/vec.rs @@ -176,6 +176,7 @@ impl, Ctx: Copy> DekuWriter for Vec { #[cfg(test)] mod tests { + #[cfg(feature = "bits")] use crate::bitvec::{bits, BitSlice, Msb0}; use rstest::rstest; use std::io::Cursor; @@ -184,6 +185,7 @@ mod tests { use super::*; + #[cfg(feature = "bits")] #[rstest(input, limit, expected, expected_rest_bits, expected_rest_bytes, case::count_0([0xAA].as_ref(), 0.into(), vec![], bits![u8, Msb0;], &[0xaa]), case::count_1([0xAA, 0xBB].as_ref(), 1.into(), vec![0xAA], bits![u8, Msb0;], &[0xbb]), @@ -211,6 +213,7 @@ mod tests { assert_eq!(expected_rest_bytes, buf); } + #[cfg(feature = "bits")] #[rstest(input, endian, bit_size, limit, expected, expected_rest_bits, expected_rest_bytes, case::count_0([0xAA].as_ref(), Endian::Little, Some(8), 0.into(), vec![], bits![u8, Msb0;], &[0xaa]), case::count_1([0xAA, 0xBB].as_ref(), Endian::Little, Some(8), 1.into(), vec![0xAA], bits![u8, Msb0;], &[0xbb]), @@ -271,6 +274,7 @@ mod tests { } // Note: These tests also exist in boxed.rs + #[cfg(feature = "bits")] #[rstest(input, endian, bit_size, limit, expected, expected_rest_bits, expected_rest_bytes, expected_write, case::normal_le([0xAA, 0xBB, 0xCC, 0xDD].as_ref(), Endian::Little, Some(16), 2.into(), vec![0xBBAA, 0xDDCC], bits![u8, Msb0;], &[], vec![0xAA, 0xBB, 0xCC, 0xDD]), case::normal_be([0xAA, 0xBB, 0xCC, 0xDD].as_ref(), Endian::Big, Some(16), 2.into(), vec![0xAABB, 0xCCDD], bits![u8, Msb0;], &[], vec![0xAA, 0xBB, 0xCC, 0xDD]), diff --git a/src/reader.rs b/src/reader.rs index ba55161b..715fa5ed 100644 --- a/src/reader.rs +++ b/src/reader.rs @@ -454,6 +454,7 @@ mod tests { use no_std_io::io::Cursor; #[test] + #[cfg(feature = "bits")] fn test_end() { let input = hex!("aabb"); let mut cursor = Cursor::new(input); @@ -474,6 +475,7 @@ mod tests { } #[test] + #[cfg(feature = "bits")] fn test_bits_less() { let input = hex!("aa"); let mut cursor = Cursor::new(input); diff --git a/src/writer.rs b/src/writer.rs index ce3f3910..bfe25769 100644 --- a/src/writer.rs +++ b/src/writer.rs @@ -206,7 +206,8 @@ mod tests { use hexlit::hex; #[test] - fn test_writer() { + #[cfg(feature = "bits")] + fn test_writer_bits() { let mut out_buf = Cursor::new(vec![]); let mut writer = Writer::new(&mut out_buf); @@ -243,4 +244,16 @@ mod tests { &mut vec![0xaa, 0xbb, 0xf1, 0xaa, 0x1f, 0x1a, 0xaf] ); } + + #[test] + #[cfg(feature = "bits")] + fn test_writer_bytes() { + let mut out_buf = Cursor::new(vec![]); + let mut writer = Writer::new(&mut out_buf); + + let mut input = hex!("aa"); + writer.write_bytes(&mut input).unwrap(); + + assert_eq!(&mut out_buf.into_inner(), &mut vec![0xaa]); + } } diff --git a/tests/mod.rs b/tests/mod.rs index a61389cf..eece9c90 100644 --- a/tests/mod.rs +++ b/tests/mod.rs @@ -2,3 +2,5 @@ mod test_attributes; mod test_compile; +#[cfg(feature = "bits")] +mod test_to_bits; diff --git a/tests/test_alloc.rs b/tests/test_alloc.rs index 5da05c81..a5348d6e 100644 --- a/tests/test_alloc.rs +++ b/tests/test_alloc.rs @@ -7,12 +7,14 @@ use deku::prelude::*; #[global_allocator] static A: AllocCounterSystem = AllocCounterSystem; +#[cfg(feature = "bits")] #[derive(Debug, PartialEq, DekuRead, DekuWrite)] #[deku(ctx = "_endian: Endian")] struct NestedStruct { field_a: u8, } +#[cfg(feature = "bits")] #[derive(Debug, PartialEq, DekuRead, DekuWrite)] #[deku(id_type = "u8", ctx = "_endian: Endian")] enum NestedEnum { @@ -20,6 +22,7 @@ enum NestedEnum { VarA(u8), } +#[cfg(feature = "bits")] #[derive(Debug, PartialEq, DekuRead, DekuWrite)] #[deku(id_type = "u32", bytes = 2, ctx = "_endian: Endian")] enum NestedEnum2 { @@ -27,6 +30,7 @@ enum NestedEnum2 { VarA(u8), } +#[cfg(feature = "bits")] #[derive(Debug, PartialEq, DekuRead, DekuWrite)] #[deku(endian = "big")] struct TestDeku { @@ -44,6 +48,7 @@ struct TestDeku { //field_i: NestedEnum2, } +#[cfg(feature = "bits")] mod tests { use alloc_counter::count_alloc; use hexlit::hex; diff --git a/tests/test_attributes/test_limits/mod.rs b/tests/test_attributes/test_limits/mod.rs index c7e74d0a..b4ce8478 100644 --- a/tests/test_attributes/test_limits/mod.rs +++ b/tests/test_attributes/test_limits/mod.rs @@ -1,3 +1,4 @@ +#[cfg(feature = "bits")] mod test_bits_read; mod test_bytes_read; mod test_count; diff --git a/tests/test_attributes/test_padding/mod.rs b/tests/test_attributes/test_padding/mod.rs index 5c1d5e7a..8ac0311d 100644 --- a/tests/test_attributes/test_padding/mod.rs +++ b/tests/test_attributes/test_padding/mod.rs @@ -2,11 +2,14 @@ use std::convert::{TryFrom, TryInto}; use deku::prelude::*; +#[cfg(feature = "bits")] mod test_pad_bits_after; +#[cfg(feature = "bits")] mod test_pad_bits_before; mod test_pad_bytes_after; mod test_pad_bytes_before; +#[cfg(feature = "bits")] #[test] #[allow(clippy::identity_op)] fn test_pad_bits_before_and_pad_bytes_before() { @@ -34,6 +37,7 @@ fn test_pad_bits_before_and_pad_bytes_before() { assert_eq!(vec![0b10_000000, 0x00, 0xbb], ret_write); } +#[cfg(feature = "bits")] #[test] fn test_pad_bits_after_and_pad_bytes_after() { #[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 846c61c7..d8baa16b 100644 --- a/tests/test_attributes/test_padding/test_pad_bytes_after.rs +++ b/tests/test_attributes/test_padding/test_pad_bytes_after.rs @@ -42,6 +42,8 @@ fn test_pad_bytes_after_not_enough() { let _ret_read = TestStruct::try_from(data.as_slice()).unwrap(); } +// TODO: add cfg test with updated msg for not(bits) +#[cfg(feature = "bits")] #[test] #[should_panic( expected = r#"InvalidParam("Invalid padding param \"(((- 2) * 8))\": cannot convert to usize")"# @@ -59,6 +61,8 @@ fn test_pad_bytes_after_read_err() { let _ret_read = TestStruct::try_from(data.as_slice()).unwrap(); } +// TODO: add cfg test with updated msg for not(bits) +#[cfg(feature = "bits")] #[test] #[should_panic( expected = r#"InvalidParam("Invalid padding param \"(((- 2) * 8))\": cannot convert to usize")"# 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 f9a92e39..6ebbb9cb 100644 --- a/tests/test_attributes/test_padding/test_pad_bytes_before.rs +++ b/tests/test_attributes/test_padding/test_pad_bytes_before.rs @@ -42,6 +42,8 @@ fn test_pad_bytes_before_not_enough() { let _ret_read = TestStruct::try_from(data.as_slice()).unwrap(); } +// TODO: add cfg test with updated msg for not(bits) +#[cfg(feature = "bits")] #[test] #[should_panic( expected = r#"InvalidParam("Invalid padding param \"(((- 2) * 8))\": cannot convert to usize")"# @@ -59,6 +61,8 @@ fn test_pad_bytes_before_read_err() { let _ret_read = TestStruct::try_from(data.as_slice()).unwrap(); } +// TODO: add cfg test with updated msg for not(bits) +#[cfg(feature = "bits")] #[test] #[should_panic( expected = r#"InvalidParam("Invalid padding param \"(((- 2) * 8))\": cannot convert to usize")"# diff --git a/tests/test_compile/mod.rs b/tests/test_compile/mod.rs index 92a37681..30a680e2 100644 --- a/tests/test_compile/mod.rs +++ b/tests/test_compile/mod.rs @@ -1,4 +1,5 @@ #[test] +#[cfg(feature = "bits")] #[cfg(not(tarpaulin))] #[cfg_attr(miri, ignore)] fn test_compile() { diff --git a/tests/test_enum.rs b/tests/test_enum.rs index 4459ff0e..f4329ca8 100644 --- a/tests/test_enum.rs +++ b/tests/test_enum.rs @@ -8,6 +8,7 @@ use rstest::*; /// General smoke tests for enums /// TODO: These should be divided into smaller tests +#[cfg(feature = "bits")] #[derive(PartialEq, Debug, DekuRead, DekuWrite)] #[deku(id_type = "u8")] enum TestEnum { @@ -32,6 +33,7 @@ enum TestEnum { VarDefault { id: u8, value: u8 }, } +#[cfg(feature = "bits")] #[rstest(input,expected, case(&hex!("01AB"), TestEnum::VarA(0xAB)), case(&hex!("0269"), TestEnum::VarB(0b0110, 0b1001)), diff --git a/tests/test_from_bytes.rs b/tests/test_from_bytes.rs index a992c5ba..aac1f4d7 100644 --- a/tests/test_from_bytes.rs +++ b/tests/test_from_bytes.rs @@ -1,5 +1,6 @@ use deku::prelude::*; +#[cfg(feature = "bits")] #[test] fn test_from_bytes_struct() { #[derive(Debug, PartialEq, DekuRead, DekuWrite)] @@ -28,6 +29,7 @@ fn test_from_bytes_struct() { assert_eq!(0, i); } +#[cfg(feature = "bits")] #[test] fn test_from_bytes_enum() { #[derive(Debug, PartialEq, DekuRead, DekuWrite)] diff --git a/tests/test_from_reader.rs b/tests/test_from_reader.rs index 02c927d3..1e7e87dc 100644 --- a/tests/test_from_reader.rs +++ b/tests/test_from_reader.rs @@ -1,6 +1,7 @@ use deku::prelude::*; use no_std_io::io::Seek; +#[cfg(feature = "bits")] #[test] fn test_from_reader_struct() { #[derive(Debug, PartialEq, DekuRead, DekuWrite)] @@ -21,7 +22,6 @@ fn test_from_reader_struct() { total_read = amt_read; assert_eq!(TestDeku(0b0110), ret_read); - env_logger::init(); c.rewind().unwrap(); let (amt_read, ret_read) = TestDeku::from_reader((&mut c, total_read)).unwrap(); assert_eq!(amt_read, 12); @@ -34,6 +34,7 @@ fn test_from_reader_struct() { assert_eq!(TestDeku(0b1010), ret_read); } +#[cfg(feature = "bits")] #[test] fn test_from_reader_enum() { #[derive(Debug, PartialEq, DekuRead, DekuWrite)] diff --git a/tests/test_regression.rs b/tests/test_regression.rs index 0bf30b85..e3a75890 100644 --- a/tests/test_regression.rs +++ b/tests/test_regression.rs @@ -5,6 +5,7 @@ use std::io::Cursor; // BitSlice to type // // https://github.com/sharksforarms/deku/issues/224 +#[cfg(feature = "bits")] #[test] fn issue_224() { #[derive(Debug, PartialEq, DekuRead, DekuWrite)] @@ -66,6 +67,7 @@ fn issue_224() { let _packet = Packet::from_reader((&mut c, 0)).unwrap(); } +#[cfg(feature = "bits")] // Extra zeroes added when reading fewer bytes than needed to fill a number // // https://github.com/sharksforarms/deku/issues/282 @@ -128,6 +130,7 @@ mod issue_282 { // Invalid alignment assumptions when converting doing Bits and Bytes optimizations // // https://github.com/sharksforarms/deku/issues/292 +#[cfg(feature = "bits")] #[test] fn test_regression_292() { let test_data = [0x0f, 0xf0]; diff --git a/tests/test_struct.rs b/tests/test_struct.rs index c5bb117b..92ed213e 100644 --- a/tests/test_struct.rs +++ b/tests/test_struct.rs @@ -10,11 +10,13 @@ mod test_common; /// TODO: These should be divided into smaller tests // Common struct to test nesting +#[cfg(feature = "bits")] #[derive(PartialEq, Debug, DekuRead, DekuWrite)] pub struct DoubleNestedDeku { pub data: u16, } +#[cfg(feature = "bits")] // Common struct to test nesting #[derive(PartialEq, Debug, DekuRead, DekuWrite)] pub struct NestedDeku { @@ -26,6 +28,7 @@ pub struct NestedDeku { pub inner: DoubleNestedDeku, } +#[cfg(feature = "bits")] #[test] #[should_panic(expected = r#"Parse("Too much data")"#)] fn test_read_too_much_data() { @@ -39,6 +42,7 @@ fn test_read_too_much_data() { TestStruct::try_from(test_data).unwrap(); } +#[cfg(feature = "bits")] #[test] fn test_unnamed_struct() { #[derive(PartialEq, Debug, DekuRead, DekuWrite)] @@ -96,6 +100,7 @@ fn test_unnamed_struct() { assert_eq!(test_data, ret_write); } +#[cfg(feature = "bits")] #[test] fn test_named_struct() { #[derive(PartialEq, Debug, DekuRead, DekuWrite)] diff --git a/tests/test_to_bits.rs b/tests/test_to_bits.rs index 1515a403..860aaa76 100644 --- a/tests/test_to_bits.rs +++ b/tests/test_to_bits.rs @@ -1,8 +1,10 @@ use std::convert::TryFrom; +#[cfg(feature = "bits")] use deku::bitvec::Lsb0; use deku::prelude::*; +#[cfg(feature = "bits")] #[derive(PartialEq, Debug, DekuRead, DekuWrite)] pub struct Test { #[deku(bits = "4")] @@ -11,6 +13,7 @@ pub struct Test { pub b: u8, } +#[cfg(feature = "bits")] #[test] fn test_to_bits_correct() { let test_data: &[u8] = &[0xf1]; @@ -19,6 +22,7 @@ fn test_to_bits_correct() { assert_eq!(deku::bitvec::bitvec![1, 1, 1, 1, 0, 0, 0, 1], bits); } +#[cfg(feature = "bits")] #[derive(PartialEq, Debug, DekuRead, DekuWrite)] pub struct TestOver { #[deku(bits = "4")] @@ -29,6 +33,7 @@ pub struct TestOver { pub c: u8, } +#[cfg(feature = "bits")] #[test] fn test_to_bits_correct_over() { let test_data: &[u8] = &[0xf1, 0x80]; @@ -37,6 +42,7 @@ fn test_to_bits_correct_over() { assert_eq!(deku::bitvec::bitvec![1, 1, 1, 1, 0, 0, 0, 1, 1], bits); } +#[cfg(feature = "bits")] #[derive(PartialEq, Debug, DekuRead, DekuWrite)] #[deku(id_type = "u8", bits = "4")] enum TestEnum { @@ -44,6 +50,7 @@ enum TestEnum { VarA, } +#[cfg(feature = "bits")] #[test] fn test_to_bits_enum() { let test_data: &[u8] = &[0b1010_0000];