Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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" }
Expand Down
2 changes: 1 addition & 1 deletion bilge-impl/src/bitsize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
2 changes: 1 addition & 1 deletion bilge-impl/src/bitsize_internal/struct_gen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
2 changes: 1 addition & 1 deletion bilge-impl/src/debug_bits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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! {
Expand Down
6 changes: 3 additions & 3 deletions bilge-impl/src/fmt_bits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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));
Expand Down Expand Up @@ -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)
}
};

Expand Down
4 changes: 2 additions & 2 deletions bilge-impl/src/serde_bits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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! {
Expand Down Expand Up @@ -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 {
Expand Down
2 changes: 1 addition & 1 deletion bilge-impl/src/shared.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ pub fn enum_fills_bitsize(bitsize: u8, variants_count: usize) -> bool {

#[inline]
pub fn unreachable<T, U>(_: T) -> U {
unreachable!("should have already been validated")
::core::unreachable!("should have already been validated")
}

pub fn is_attribute(attr: &Attribute, name: &str) -> bool {
Expand Down
3 changes: 2 additions & 1 deletion examples/zz_experimental_problems.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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);
Expand Down
85 changes: 85 additions & 0 deletions tests/defmt_compatibility.rs
Original file line number Diff line number Diff line change
@@ -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));
}
9 changes: 8 additions & 1 deletion tests/ui/default-should-be-used.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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)
2 changes: 1 addition & 1 deletion tests/ui/fallback/more.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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 },
| |_________________________^

Expand Down
8 changes: 4 additions & 4 deletions tests/ui/vis-privacy-is-respected.stderr
Original file line number Diff line number Diff line change
@@ -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();
Expand All @@ -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);
Expand All @@ -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);
Expand All @@ -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));
Expand Down