Skip to content
Merged
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
53 changes: 52 additions & 1 deletion .github/workflows/no-std.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,55 @@ jobs:
- run: |
cd nostd-app
cargo add bitfields --path ../bitfields --package nostd-app
- run: cargo build --target thumbv7em-none-eabihf
cargo add buddy_system_allocator --package nostd-app
- run: |
cat > nostd-app/src/main.rs << 'EOF'
#![no_std]
#![no_main]

use bitfields::{bitfield, bitflag};

// pick a panicking behavior
use panic_halt as _; // you can put a breakpoint on `rust_begin_unwind` to catch panics
// use panic_abort as _; // requires nightly
// use panic_itm as _; // logs messages over ITM; requires ITM support
// use panic_semihosting as _; // logs messages to the host stderr; requires a debugger

use cortex_m_rt::entry;
use buddy_system_allocator::LockedHeap;
extern crate alloc;

#[global_allocator]
static HEAP_ALLOCATOR: LockedHeap<32> = LockedHeap::empty();

#[entry]
fn main() -> ! {
loop {
#[bitfield(u32)]
pub struct Bitfield {
a: u8,
b: u8,
c: u8,
d: u8,
}

#[bitfield([u8; 4], array_heap_no_std = true)]
pub struct ArrayHeapBitfield {
a: u8,
b: u8,
c: u8,
d: u8,
}

#[bitflag(u8)]
#[derive(Debug, PartialEq)]
enum Flags {
#[base]
Unknown = 0,
A = 1,
B = 2,
}
}
}
EOF
- run: cargo build --target thumbv7em-none-eabihf
7 changes: 7 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

124 changes: 73 additions & 51 deletions README.md

Large diffs are not rendered by default.

11 changes: 8 additions & 3 deletions bitfields/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ bitfields-impl = { path = "../bitfields_impl", version = "2.0.8" }

[dev-dependencies]
trybuild = "1.0.116"
dummy-alloc = "1.0.0"

# Represents the bitfield arguments the user can enable or disable by default for
# all bitfields instead of specifying them for each bitfield.
Expand Down Expand Up @@ -44,7 +45,8 @@ default = [
"bitflag_from_endian_big",
"bitflag_into_endian_big",
"bitflag_derive_copy",
"disable_array_heap",
"disable_array_heap_no_std",
"disable_array_heap_std",
]

order_lsb = []
Expand Down Expand Up @@ -98,8 +100,11 @@ disable_toggle_bit_ops = []
generate_builder = []
disable_builder = []

enable_array_heap = []
disable_array_heap = []
enable_array_heap_std = []
disable_array_heap_std = []

enable_array_heap_no_std = []
disable_array_heap_no_std = []

bitflag_from_endian_big = []
bitflag_from_endian_little = []
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#![no_std]

use bitfields::bitfield;
use core::panic::PanicInfo;
extern crate alloc;
use dummy_alloc::DummyAllocator;

#[panic_handler]
fn panic(_info: &PanicInfo) -> ! {
loop {}
}

#[global_allocator]
static ALLOCATOR: DummyAllocator = DummyAllocator;

#[bitfield([u8; 4], array_heap_no_std = true)]
struct ArrayHeapBitfield {
a: u8,
b: u8,
c: u8,
d: u8,
}

fn main() {
let bitfield = ArrayHeapBitfield::from_slice(&[0x11, 0x22, 0x33, 0x44]);
assert_eq!(bitfield.a(), 0x44);
assert_eq!(bitfield.b(), 0x33);
assert_eq!(bitfield.c(), 0x22);
assert_eq!(bitfield.d(), 0x11);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
error: unwinding panics are not supported without std
|
= help: using nightly cargo, use -Zbuild-std with panic="abort" to avoid unwinding
= note: since the core library is usually precompiled with panic="unwind", rebuilding your crate with panic="abort" may not be enough to fix the problem
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
error: Unknown argument 'enable_disable_bit_ops'. Valid arguments are: 'array_heap', 'bit_ops', 'builder', 'clear_bit_ops', 'copy', 'debug', 'default', 'from_endian', 'from_into_bits', 'from_traits', 'into_endian', 'invert_bit_ops', 'new', 'order', 'set_get_bit_ops', 'toggle_bit_ops', 'write_bit_ops', 'write_endian'.
error: Unknown argument 'enable_disable_bit_ops'. Valid arguments are: 'array_heap_no_std', 'array_heap_std', 'bit_ops', 'builder', 'clear_bit_ops', 'copy', 'debug', 'default', 'from_endian', 'from_into_bits', 'from_traits', 'into_endian', 'invert_bit_ops', 'new', 'order', 'set_get_bit_ops', 'toggle_bit_ops', 'write_bit_ops', 'write_endian'.
--> tests/compile_error_cases/errors/bitfield_invalid_bitfield_enable_disable_bit_ops_value.rs:3:17
|
3 | #[bitfield(u32, enable_disable_bit_ops = 123)]
| ^^^^^^^^^^^^^^^^^^^^^^

error: Unknown argument 'enable_disable_bit_ops'. Valid arguments are: 'array_heap', 'bit_ops', 'builder', 'clear_bit_ops', 'copy', 'debug', 'default', 'from_endian', 'from_into_bits', 'from_traits', 'into_endian', 'invert_bit_ops', 'new', 'order', 'set_get_bit_ops', 'toggle_bit_ops', 'write_bit_ops', 'write_endian'.
error: Unknown argument 'enable_disable_bit_ops'. Valid arguments are: 'array_heap_no_std', 'array_heap_std', 'bit_ops', 'builder', 'clear_bit_ops', 'copy', 'debug', 'default', 'from_endian', 'from_into_bits', 'from_traits', 'into_endian', 'invert_bit_ops', 'new', 'order', 'set_get_bit_ops', 'toggle_bit_ops', 'write_bit_ops', 'write_endian'.
--> tests/compile_error_cases/errors/bitfield_invalid_bitfield_enable_disable_bit_ops_value.rs:9:17
|
9 | #[bitfield(u32, enable_disable_bit_ops = invalid)]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error: Unknown argument 'deez'. Valid arguments are: 'array_heap', 'bit_ops', 'builder', 'clear_bit_ops', 'copy', 'debug', 'default', 'from_endian', 'from_into_bits', 'from_traits', 'into_endian', 'invert_bit_ops', 'new', 'order', 'set_get_bit_ops', 'toggle_bit_ops', 'write_bit_ops', 'write_endian'.
error: Unknown argument 'deez'. Valid arguments are: 'array_heap_no_std', 'array_heap_std', 'bit_ops', 'builder', 'clear_bit_ops', 'copy', 'debug', 'default', 'from_endian', 'from_into_bits', 'from_traits', 'into_endian', 'invert_bit_ops', 'new', 'order', 'set_get_bit_ops', 'toggle_bit_ops', 'write_bit_ops', 'write_endian'.
--> tests/compile_error_cases/errors/bitfield_unknown_arg.rs:3:17
|
3 | #[bitfield(u32, deez = what)]
Expand Down
34 changes: 34 additions & 0 deletions bitfields/tests/lib_array_backed_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4977,4 +4977,38 @@ mod tests {
"clear_bytes: _reserved must retain its default 0x78"
);
}

#[test]
fn bitfield_array_heap_std_true() {
#[bitfield([u8; 4], array_heap_std = true)]
struct Bitfield {
a: u8,
b: u8,
c: u8,
d: u8,
}

let bitfield = Bitfield::from_slice(&[0x11, 0x22, 0x33, 0x44]);
assert_eq!(bitfield.a(), 0x44);
assert_eq!(bitfield.b(), 0x33);
assert_eq!(bitfield.c(), 0x22);
assert_eq!(bitfield.d(), 0x11);
}

#[test]
fn bitfield_array_heap_std_false() {
#[bitfield([u8; 4], array_heap_std = false)]
struct Bitfield {
a: u8,
b: u8,
c: u8,
d: u8,
}

let bitfield = Bitfield::from_slice(&[0x11, 0x22, 0x33, 0x44]);
assert_eq!(bitfield.a(), 0x44);
assert_eq!(bitfield.b(), 0x33);
assert_eq!(bitfield.c(), 0x22);
assert_eq!(bitfield.d(), 0x11);
}
}
10 changes: 7 additions & 3 deletions bitfields_impl/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ default = [
"bitflag_from_endian_big",
"bitflag_into_endian_big",
"bitflag_derive_copy",
"disable_array_heap",
"disable_array_heap_no_std",
"disable_array_heap_std",
]

order_lsb = []
Expand Down Expand Up @@ -103,8 +104,11 @@ disable_toggle_bit_ops = []
generate_builder = []
disable_builder = []

enable_array_heap = []
disable_array_heap = []
enable_array_heap_std = []
disable_array_heap_std = []

enable_array_heap_no_std = []
disable_array_heap_no_std = []

bitflag_from_endian_big = []
bitflag_from_endian_little = []
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,7 @@ impl BitfieldStructFeatureGenerator {
}

if bitfield.arguments().derive_copy() {
let is_heap_array = bitfield.arguments().array_heap() && !bitfield.is_integer_backed();
if is_heap_array {
if bitfield.is_array_heap() {
attributes_tokens.push(quote! {
#[derive(core::clone::Clone)]
});
Expand All @@ -105,10 +104,14 @@ impl BitfieldStructFeatureGenerator {
/// Returns the backing storage type tokens for the bitfield struct field.
fn get_backing_field_type_tokens(bitfield: &Bitfield) -> TokenStream {
let inner = bitfield.spanned_data_type_token().to_tokens();
if bitfield.arguments().array_heap() && !bitfield.is_integer_backed() {
if !bitfield.is_array_heap() {
inner
} else if bitfield.arguments().array_heap_std() {
quote! { ::std::boxed::Box<#inner> }
} else if bitfield.arguments().array_heap_no_std() {
quote! { ::alloc::boxed::Box<#inner> }
} else {
inner
unreachable!()
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@ pub enum BitsSource {

/// Returns the function modifiers for generated functions (e.g., `const`).
pub fn get_function_modifier_tokens(bitfield: &Bitfield) -> Option<TokenStream> {
let is_heap_array = bitfield.arguments().array_heap() && !bitfield.is_integer_backed();
(!bitfield.has_ignored_fields() && !is_heap_array && supports_const_mut_refs())
(!bitfield.has_ignored_fields() && !bitfield.is_array_heap() && supports_const_mut_refs())
.then(|| quote::quote! { const })
}

Expand Down Expand Up @@ -55,14 +54,20 @@ pub fn generate_bitfield_struct_initialization_tokens(
length,
} => {
let length = length as usize;
if bitfield.arguments().array_heap() {
if !bitfield.is_array_heap() {
quote! {
[0u8; #length]
}
} else if bitfield.arguments().array_heap_std() {
quote! {
::std::boxed::Box::new([0u8; #length])
}
} else {
} else if bitfield.arguments().array_heap_no_std() {
quote! {
[0u8; #length]
::alloc::boxed::Box::new([0u8; #length])
}
} else {
unreachable!()
}
},
DataType::Custom => {
Expand Down Expand Up @@ -1004,6 +1009,6 @@ pub fn generate_backing_data_param_ident(bitfield: &Bitfield) -> TokenStream {
}

/// Returns the term used for the backing data of a bitfield.
pub const fn get_bits_or_bytes_term(bitfield: &Bitfield) -> &'static str {
pub fn get_bits_or_bytes_term(bitfield: &Bitfield) -> &'static str {
if bitfield.is_integer_backed() { "bits" } else { "bytes" }
}
Original file line number Diff line number Diff line change
Expand Up @@ -517,7 +517,7 @@ impl FromIntoBitsFeature {
let half_len = array_len / 2;
let last_idx = array_len - 1;

let is_heap = bitfield.arguments().array_heap();
let is_heap = bitfield.is_array_heap();

let into_bits_convert_tokens = |endian| match endian {
ConversionEndian::Little => {
Expand Down Expand Up @@ -601,7 +601,7 @@ impl FromIntoBitsFeature {
let half_len = array_len / 2;
let last_idx = array_len - 1;

let bits_access_tokens = if bitfield.arguments().array_heap() {
let bits_access_tokens = if bitfield.is_array_heap() {
quote! { *#bitfield_internal_value_ident_tokens }
} else {
quote! { #bitfield_internal_value_ident_tokens }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,7 @@ impl FromTraitsFeature {
bitfield.arguments().from_endian()
};

let is_heap_array =
into_bits && bitfield.arguments().array_heap() && !bitfield.is_integer_backed();
let is_heap_array = into_bits && bitfield.is_array_heap() && !bitfield.is_integer_backed();

match conversion_endian {
ConversionEndian::Little => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ impl InvertBitOpsFeature {
.array_length()
.expect("array-backed bitfield must have a known length");

let bits_init_tokens = if bitfield.arguments().array_heap() {
let bits_init_tokens = if bitfield.is_array_heap() {
quote! { let mut bits = *#bitfield_internal_value_ident_tokens; }
} else {
quote! { let mut bits = #bitfield_internal_value_ident_tokens; }
Expand Down
Loading