diff --git a/Cargo.toml b/Cargo.toml index 7dd1cef..56d96ab 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,11 +16,16 @@ members = ["bilge-impl"] [workspace.package] version = "0.3.0" -categories = ["data-structures", "no-std::no-alloc", "embedded", "rust-patterns"] +categories = [ + "data-structures", + "no-std::no-alloc", + "embedded", + "rust-patterns", +] description = "Use bitsized types as if they were a feature of rust." documentation = "https://docs.rs/bilge" edition = "2021" -keywords = ["bilge", "bitfield", "bits", "register"] +keywords = ["bilge", "bitfield", "bits", "register"] license = "MIT OR Apache-2.0" readme = "README.md" repository = "https://github.com/hecatia-elegua/bilge" @@ -55,6 +60,7 @@ custom_bits = { path = "tests/custom_bits" } assert_matches = "1.5.0" serde = "1.0" serde_test = "1.0" +defmt = "1.0.1" # examples # volatile = { git = "https://github.com/theseus-os/volatile" } diff --git a/bilge-impl/src/bitsize.rs b/bilge-impl/src/bitsize.rs index 68704ea..2766fb6 100644 --- a/bilge-impl/src/bitsize.rs +++ b/bilge-impl/src/bitsize.rs @@ -147,7 +147,7 @@ fn generate_struct(item: &ItemStruct, declared_bitsize: u8) -> TokenStream { #vis struct #ident #fields_def // constness: when we get const blocks evaluated at compile time, add a const computed_bitsize - const _: () = assert!( + const _: () = ::core::assert!( (#computed_bitsize) == (#declared_bitsize), concat!("struct size and declared bit size differ: ", // stringify!(#computed_bitsize), diff --git a/bilge-impl/src/bitsize_internal/struct_gen.rs b/bilge-impl/src/bitsize_internal/struct_gen.rs index 0808edf..e7ee107 100644 --- a/bilge-impl/src/bitsize_internal/struct_gen.rs +++ b/bilge-impl/src/bitsize_internal/struct_gen.rs @@ -163,7 +163,7 @@ pub(crate) fn generate_getter_inner(ty: &Type, is_getter: bool) -> TokenStream { #elem_value match <#ty>::try_from(elem_value) { Ok(v) => v, - Err(_) => panic!("unreachable"), + Err(_) => ::core::panic!("unreachable"), } } } else { diff --git a/bilge-impl/src/debug_bits.rs b/bilge-impl/src/debug_bits.rs index e425656..65f0e3e 100644 --- a/bilge-impl/src/debug_bits.rs +++ b/bilge-impl/src/debug_bits.rs @@ -40,7 +40,7 @@ pub(super) fn debug_bits(item: TokenStream) -> TokenStream { #(#calls)*.finish() } } - Fields::Unit => todo!("this is a unit struct, which is not supported right now"), + Fields::Unit => ::core::todo!("this is a unit struct, which is not supported right now"), }; quote! { diff --git a/bilge-impl/src/fmt_bits.rs b/bilge-impl/src/fmt_bits.rs index 6d71da7..e2c1632 100644 --- a/bilge-impl/src/fmt_bits.rs +++ b/bilge-impl/src/fmt_bits.rs @@ -16,7 +16,7 @@ pub(crate) fn binary(item: TokenStream) -> TokenStream { } fn generate_struct_binary_impl(struct_name: &Ident, fields: &Fields) -> TokenStream { - let write_underscore = quote! { write!(f, "_")?; }; + let write_underscore = quote! { ::core::write!(f, "_")?; }; // fields are printed from most significant to least significant, separated by an underscore let writes = fields @@ -32,7 +32,7 @@ fn generate_struct_binary_impl(struct_name: &Ident, fields: &Fields) -> TokenStr let first_bit_pos = last_bit_pos - field_size; last_bit_pos -= field_size; let extracted = field_mask & (self.value >> first_bit_pos); - write!(f, "{:0width$b}", extracted, width = field_size)?; + ::core::write!(f, "{:0width$b}", extracted, width = field_size)?; } }) .reduce(|acc, next| quote!(#acc #write_underscore #next)); @@ -62,7 +62,7 @@ fn generate_enum_binary_impl( let value = match self { #( #to_int_match_arms )* }; - write!(f, "{:0width$b}", value, width = <#enum_name as Bitsized>::BITS) + ::core::write!(f, "{:0width$b}", value, width = <#enum_name as Bitsized>::BITS) } }; diff --git a/bilge-impl/src/serde_bits.rs b/bilge-impl/src/serde_bits.rs index 66fc3f2..a5bb917 100644 --- a/bilge-impl/src/serde_bits.rs +++ b/bilge-impl/src/serde_bits.rs @@ -52,7 +52,7 @@ pub(super) fn serialize_bits(item: TokenStream) -> TokenStream { state.end() } } - Fields::Unit => todo!("this is a unit struct, which is not supported right now"), + Fields::Unit => ::core::todo!("this is a unit struct, which is not supported right now"), }; quote! { @@ -133,7 +133,7 @@ pub(super) fn deserialize_bits(item: TokenStream) -> TokenStream { .enumerate() .map(|(i, _)| deserialize_field_parts(i, &syn::parse_str(&format!("val_{}", i)).unwrap_or_else(unreachable))) .multiunzip(), - Fields::Unit => todo!("this is a unit struct, which is not supported right now"), + Fields::Unit => ::core::todo!("this is a unit struct, which is not supported right now"), }; if field_expecting.len() > 1 { diff --git a/bilge-impl/src/shared.rs b/bilge-impl/src/shared.rs index 40ed376..9521d79 100644 --- a/bilge-impl/src/shared.rs +++ b/bilge-impl/src/shared.rs @@ -142,7 +142,7 @@ pub fn enum_fills_bitsize(bitsize: u8, variants_count: usize) -> bool { #[inline] pub fn unreachable(_: T) -> U { - unreachable!("should have already been validated") + ::core::unreachable!("should have already been validated") } pub fn is_attribute(attr: &Attribute, name: &str) -> bool { diff --git a/examples/zz_experimental_problems.rs b/examples/zz_experimental_problems.rs index c0f488b..ceecbd8 100644 --- a/examples/zz_experimental_problems.rs +++ b/examples/zz_experimental_problems.rs @@ -14,6 +14,7 @@ enum Unfilled { C, } +#[allow(unused)] fn main() { // This file mostly shows one flaw to still be solved or at least to be made configurable: // The inner value of a bitfield, which holds invariants, can currently still be changed. @@ -50,7 +51,7 @@ mod somebits { // mean all the private items would not be accessible.. // // If we find any other way to make `value` inaccessible, update this. - #[allow(dead_code)] + #[allow(dead_code, unused)] fn modify_inner() { let a = 0b10101010; let mut b = SomeBits::new(true, true, true); diff --git a/tests/defmt_compatibility.rs b/tests/defmt_compatibility.rs new file mode 100644 index 0000000..2e64f41 --- /dev/null +++ b/tests/defmt_compatibility.rs @@ -0,0 +1,85 @@ +#![cfg(feature = "serde")] +use bilge::prelude::*; + +// defmt is intended to be used with macro_use to fully override all core formatting. +// We're checking that our macros don't use any unqualified macros shadowed by defmt (e.g. write!()) +// in proc macros where we don't intend to interact with the target's stdout. +#[allow(unused)] +#[macro_use] +extern crate defmt; + +#[bitsize(39)] +#[derive(FromBits, DebugBits, PartialEq)] +struct NestedMess { + tu_tuple_ple: (u1, (u2, u8), u1), + // this has special handling, transmuting [[]] to [] internally to generate less + arr_arr_ay_ay: [[InnerTupleStruct; 2]; 2], + bit: u1, + arr_arr_tu_arr_arr_tuple_ay_ay_ple_ay_ay: [[([[(InnerTupleStruct, u2); 2]; 1], u1); 2]; 1], +} + +#[bitsize(2)] +#[derive(Clone, Copy, FromBits, DebugBits, PartialEq)] +struct InnerTupleStruct(u1, bool); + +#[bitsize(18)] +#[derive(TryFromBits, DebugBits, PartialEq)] +struct UnfilledEnumMess { + big_fumble: [[([[(HaveFun, u2); 2]; 1], u1); 2]; 1], +} + +#[bitsize(2)] +#[derive(TryFromBits, Debug, PartialEq, Clone, Copy)] +enum HaveFun { + Yes, + No, + Maybe, +} + +/// Passes if it compiles, i.e. none of the derive macros are accidentally shadowed. +#[test] +fn nested_mess_compiles() { + let tu_tuple_ple = (u1::new(0), (u2::new(0b00), 0b1111_1111), u1::new(1)); + let arr_arr_ay_ay = [ + [InnerTupleStruct::from(u2::new(3)), InnerTupleStruct::from(u2::new(0b10))], + [InnerTupleStruct::from(u2::new(3)), InnerTupleStruct::from(u2::new(0))], + ]; + let bit = u1::new(1); + let arr_arr_tu_arr_arr_tuple_ay_ay_ple_ay_ay = [[ + ( + [[ + (InnerTupleStruct::from(u2::new(3)), u2::new(3)), + (InnerTupleStruct::from(u2::new(3)), u2::new(3)), + ]], + u1::new(0), + ), + ( + [[ + (InnerTupleStruct::from(u2::new(0b10)), u2::new(3)), + (InnerTupleStruct::from(u2::new(3)), u2::new(3)), + ]], + u1::new(0), + ), + ]]; + let _mess = NestedMess::new(tu_tuple_ple, arr_arr_ay_ay, bit, arr_arr_tu_arr_arr_tuple_ay_ay_ple_ay_ay); +} + +#[bitsize(31)] +#[derive(FromBits, PartialEq, SerializeBits, DeserializeBits, DebugBits)] +struct BitsStruct { + padding: u1, + reserved: u1, + field1: u8, + padding: u1, + field2: u5, + reserved: u1, + field3: i8, + padding: u1, + field4: i5, +} + +/// Passes if it compiles. Checks serde-related macros. +#[test] +fn serde_struct_compiles() { + let _serde_struct = BitsStruct::from(u31::new(0b01110_0_10110001_0_01001_0_00100011_0_0)); +} diff --git a/tests/ui/default-should-be-used.stderr b/tests/ui/default-should-be-used.stderr index 6385609..89a7d9c 100644 --- a/tests/ui/default-should-be-used.stderr +++ b/tests/ui/default-should-be-used.stderr @@ -22,4 +22,11 @@ error[E0277]: the trait bound `Inner: Default` is not satisfied --> tests/ui/default-should-be-used.rs:14:8 | 14 | b: Inner, - | ^^^^^ the trait `Default` is not implemented for `Inner` + | ^^^^^ unsatisfied trait bound + | +help: the trait `Default` is not implemented for `Inner` + --> tests/ui/default-should-be-used.rs:17:1 + | +17 | #[bitsize(2)] + | ^^^^^^^^^^^^^ + = note: this error originates in the attribute macro `::bilge::bitsize_internal` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/fallback/more.stderr b/tests/ui/fallback/more.stderr index 1615002..399f52c 100644 --- a/tests/ui/fallback/more.stderr +++ b/tests/ui/fallback/more.stderr @@ -4,7 +4,7 @@ error: `#[fallback]` does not support variants with named fields --> tests/ui/fallback/more.rs:9:5 | -9 | / #[fallback] + 9 | / #[fallback] 10 | | Dee { fallback: u15 }, | |_________________________^ diff --git a/tests/ui/vis-privacy-is-respected.stderr b/tests/ui/vis-privacy-is-respected.stderr index ea52bce..8d2020a 100644 --- a/tests/ui/vis-privacy-is-respected.stderr +++ b/tests/ui/vis-privacy-is-respected.stderr @@ -1,7 +1,7 @@ error[E0624]: method `val_0` is private --> tests/ui/vis-privacy-is-respected.rs:29:11 | -5 | #[bitsize(96)] + 5 | #[bitsize(96)] | -------------- private method defined here ... 29 | diary.val_0(); @@ -10,7 +10,7 @@ error[E0624]: method `val_0` is private error[E0624]: method `set_val_0` is private --> tests/ui/vis-privacy-is-respected.rs:31:11 | -5 | #[bitsize(96)] + 5 | #[bitsize(96)] | -------------- private method defined here ... 31 | diary.set_val_0(rusti); @@ -19,7 +19,7 @@ error[E0624]: method `set_val_0` is private error[E0624]: method `val_1_at` is private --> tests/ui/vis-privacy-is-respected.rs:37:7 | -9 | #[bitsize(8)] + 9 | #[bitsize(8)] | ------------- private method defined here ... 37 | a.val_1_at(1); @@ -28,7 +28,7 @@ error[E0624]: method `val_1_at` is private error[E0624]: method `set_val_1_at` is private --> tests/ui/vis-privacy-is-respected.rs:38:7 | -9 | #[bitsize(8)] + 9 | #[bitsize(8)] | ------------- private method defined here ... 38 | a.set_val_1_at(1, u2::new(0));