Implement full SSD1306 OLED display support: - Splash screen on boot (1.5s) with project name, version, board - Dashboard showing radio state, config, counters, RSSI/SNR - RSSI history sparkline (64-sample ring buffer, 2px-wide bars) - DisplayOn/DisplayOff host commands routed via dedicated channel - Pure render functions against generic DrawTarget (no hardware coupling) - Display on/off control bypasses radio task entirely Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1268 lines
34 KiB
Rust
1268 lines
34 KiB
Rust
#![recursion_limit = "128"]
|
|
#![allow(clippy::cognitive_complexity)]
|
|
|
|
#[macro_use]
|
|
extern crate bitfield;
|
|
|
|
// We use a constant to make sure bits positions don't need to be literals but
|
|
// can also be constants or expressions.
|
|
const THREE: usize = 3;
|
|
|
|
#[derive(Copy, Clone, Debug)]
|
|
pub struct Foo(u16);
|
|
impl From<u8> for Foo {
|
|
fn from(value: u8) -> Foo {
|
|
Foo(u16::from(value))
|
|
}
|
|
}
|
|
|
|
impl From<Foo> for u8 {
|
|
fn from(value: Foo) -> u8 {
|
|
value.0 as u8
|
|
}
|
|
}
|
|
|
|
bitfield! {
|
|
#[derive(Copy, Clone)]
|
|
/// documentation comments also work!
|
|
struct FooBar(u32);
|
|
impl Debug;
|
|
impl BitOr;
|
|
foo1, set_foo1: 0, 0;
|
|
u8;
|
|
foo2, set_foo2: 31, 31;
|
|
foo3, set_foo3: THREE, 0;
|
|
// We make sure attributes are applied to fields. If attributes were not
|
|
// applied, the compilation would fail with a `duplicate definition`
|
|
// error.
|
|
#[cfg(not(test))]
|
|
foo3, set_foo3: 3, 0;
|
|
u16, foo4, set_foo4: 31, 28;
|
|
foo5, set_foo5: 0, 0, 32;
|
|
u32;
|
|
foo6, set_foo6: 5, THREE, THREE;
|
|
mask GETTER_MASK(u32), getter_only, _: 3, 1;
|
|
mask SETTER_MASK(u32), _, setter_only: 2*2, 2;
|
|
pub mask PUB_GETTER_MASK(u32), pub_getter_only, _: 3, 1;
|
|
pub mask PUB_SETTER_MASK(u32), _, pub_setter_only: 2*2, 2;
|
|
getter_only_array, _: 5, 3, 3;
|
|
_, setter_only_array: 2*THREE, 4, 3;
|
|
all_bits, set_all_bits: 31, 0;
|
|
mask SINGLE_BIT_MASK(u32), single_bit, set_single_bit: 3;
|
|
u8, into Foo, into_foo1, set_into_foo1: 31, 31;
|
|
pub u8, mask PUB_MASK(u32), into Foo, into_foo2, set_into_foo2: 31, 31;
|
|
u8, from into Foo, from_foo1, set_from_foo1: 31, 31;
|
|
u8, from into Foo, _, set_from_foo2: 31, 31;
|
|
u8;
|
|
into Foo, into_foo3, set_into_foo3: 31, 31;
|
|
pub into Foo, into_foo4, set_into_foo4: 31, 31;
|
|
into Foo, _, set_into_foo5: 31, 31;
|
|
into Foo, into_foo6, _: 29, 29, 3;
|
|
from into Foo, from_foo3, set_from_foo3: 31, 31;
|
|
from into Foo, _, set_from_foo4: 31, 31;
|
|
from into Foo, from_foo5, set_from_foo5: 29, 29, 3;
|
|
from into Foo, from_foo6, _: 31, 31;
|
|
i8;
|
|
signed_single_bit, set_signed_single_bit: 0, 0;
|
|
signed_two_bits, set_signed_two_bits: 1, 0;
|
|
signed_eight_bits, set_signed_eight_bits: 7, 0;
|
|
signed_eight_bits_unaligned, set_signed_eight_bits_unaligned: 8, 1;
|
|
u128, mask U128_MASK(u128), u128_getter, set_u128: 8, 1;
|
|
i128, mask I128_MASK(i128), i128_getter, set_i128: 8, 1;
|
|
}
|
|
|
|
impl FooBar {
|
|
bitfield_fields! {
|
|
// Boolean field don't need a type
|
|
foo7, _: 1;
|
|
}
|
|
|
|
bitfield_fields! {
|
|
// If all fields have a type, we don't need to specify a default type
|
|
u8, foo8,_: 1, 0;
|
|
u32, foo9, _: 2, 0;
|
|
}
|
|
|
|
bitfield_fields! {
|
|
// We can still set a default type
|
|
u16;
|
|
foo10, _: 2, 0;
|
|
u32, foo11, _: 2, 0;
|
|
foo12, _: 2, 0;
|
|
}
|
|
|
|
// Check if an empty bitfield_fields compiles without errors.
|
|
bitfield_fields! {}
|
|
}
|
|
|
|
#[test]
|
|
fn test_single_bit() {
|
|
let mut fb = FooBar(0);
|
|
|
|
fb.set_foo1(1);
|
|
assert_eq!(0x1, fb.0);
|
|
assert_eq!(0x1, fb.foo1());
|
|
assert_eq!(0x0, fb.foo2());
|
|
assert!(!fb.single_bit());
|
|
assert_eq!(-1, fb.signed_single_bit());
|
|
|
|
fb.set_foo2(1);
|
|
assert_eq!(0x8000_0001, fb.0);
|
|
assert_eq!(0x1, fb.foo1());
|
|
assert_eq!(0x1, fb.foo2());
|
|
assert!(!fb.single_bit());
|
|
assert_eq!(-1, fb.signed_single_bit());
|
|
|
|
fb.set_foo1(0);
|
|
assert_eq!(0x8000_0000, fb.0);
|
|
assert_eq!(0x0, fb.foo1());
|
|
assert_eq!(0x1, fb.foo2());
|
|
assert!(!fb.single_bit());
|
|
assert_eq!(0, fb.signed_single_bit());
|
|
|
|
fb.set_single_bit(true);
|
|
assert_eq!(0x8000_0008, fb.0);
|
|
assert_eq!(0x0, fb.foo1());
|
|
assert_eq!(0x1, fb.foo2());
|
|
assert!(fb.single_bit());
|
|
assert_eq!(0, fb.signed_single_bit());
|
|
|
|
fb.set_signed_single_bit(-1);
|
|
assert_eq!(0x8000_0009, fb.0);
|
|
assert_eq!(0x1, fb.foo1());
|
|
assert_eq!(0x1, fb.foo2());
|
|
assert!(fb.single_bit());
|
|
assert_eq!(-1, fb.signed_single_bit());
|
|
}
|
|
|
|
#[test]
|
|
fn test_single_bit_plus_garbage() {
|
|
let mut fb = FooBar(0);
|
|
|
|
fb.set_foo1(0b10);
|
|
assert_eq!(0x0, fb.0);
|
|
assert_eq!(0x0, fb.foo1());
|
|
assert_eq!(0x0, fb.foo2());
|
|
|
|
fb.set_foo1(0b11);
|
|
assert_eq!(0x1, fb.0);
|
|
assert_eq!(0x1, fb.foo1());
|
|
assert_eq!(0x0, fb.foo2());
|
|
}
|
|
|
|
#[test]
|
|
fn test_multiple_bit() {
|
|
let mut fb = FooBar(0);
|
|
|
|
fb.set_foo3(0x0F);
|
|
assert_eq!(0xF, fb.0);
|
|
assert_eq!(0xF, fb.foo3());
|
|
assert_eq!(0x0, fb.foo4());
|
|
|
|
fb.set_foo4(0x0F);
|
|
assert_eq!(0xF000_000F, fb.0);
|
|
assert_eq!(0xF, fb.foo3());
|
|
assert_eq!(0xF, fb.foo4());
|
|
|
|
fb.set_foo3(0);
|
|
assert_eq!(0xF000_0000, fb.0);
|
|
assert_eq!(0x0, fb.foo3());
|
|
assert_eq!(0xF, fb.foo4());
|
|
|
|
fb.set_foo3(0xA);
|
|
assert_eq!(0xF000_000A, fb.0);
|
|
assert_eq!(0xA, fb.foo3());
|
|
assert_eq!(0xF, fb.foo4());
|
|
}
|
|
|
|
bitfield! {
|
|
#[derive(Clone, Copy)]
|
|
struct FourFields(u8);
|
|
impl BitOr;
|
|
impl BitAnd;
|
|
impl BitXor;
|
|
impl new;
|
|
a, set_a: 0;
|
|
b, set_b: 1;
|
|
c, set_c: 2;
|
|
d, set_d: 3;
|
|
}
|
|
|
|
#[test]
|
|
fn test_bitwise_ops() {
|
|
let mut ff1 = FourFields(0);
|
|
ff1.set_a(true);
|
|
ff1.set_b(true);
|
|
let mut ff2 = FourFields(0);
|
|
ff2.set_a(true);
|
|
ff2.set_c(true);
|
|
|
|
let ffand = ff1 & ff2;
|
|
assert!(ffand.a());
|
|
assert!(!ffand.b());
|
|
assert!(!ffand.c());
|
|
assert!(!ffand.d());
|
|
|
|
let ffor = ff1 | ff2;
|
|
assert!(ffor.a());
|
|
assert!(ffor.b());
|
|
assert!(ffor.c());
|
|
assert!(!ffor.d());
|
|
|
|
let ffxor = ff1 ^ ff2;
|
|
assert!(!ffxor.a());
|
|
assert!(ffxor.b());
|
|
assert!(ffxor.c());
|
|
assert!(!ffxor.d());
|
|
|
|
ff1 ^= ff2;
|
|
assert!(!ff1.a());
|
|
assert!(ff1.b());
|
|
assert!(ff1.c());
|
|
assert!(!ff1.d());
|
|
}
|
|
|
|
#[test]
|
|
fn test_constructor() {
|
|
let ff1 = FourFields::new(true, false, true, false);
|
|
assert!(ff1.a());
|
|
assert!(!ff1.b());
|
|
assert!(ff1.c());
|
|
assert!(!ff1.d());
|
|
}
|
|
|
|
#[test]
|
|
fn test_getter_setter_only() {
|
|
let mut fb = FooBar(0);
|
|
fb.setter_only(0x7);
|
|
assert_eq!(0x1C, fb.0);
|
|
assert_eq!(0x6, fb.getter_only());
|
|
}
|
|
|
|
#[test]
|
|
fn test_array_field1() {
|
|
let mut fb = FooBar(0);
|
|
|
|
fb.set_foo5(0, 1);
|
|
assert_eq!(0x1, fb.0);
|
|
assert_eq!(1, fb.foo5(0));
|
|
|
|
fb.set_foo5(0, 0);
|
|
assert_eq!(0x0, fb.0);
|
|
assert_eq!(0, fb.foo5(0));
|
|
|
|
fb.set_foo5(0, 1);
|
|
fb.set_foo5(6, 1);
|
|
fb.set_foo5(31, 1);
|
|
assert_eq!(0x8000_0041, fb.0);
|
|
assert_eq!(1, fb.foo5(0));
|
|
assert_eq!(1, fb.foo5(6));
|
|
assert_eq!(1, fb.foo5(31));
|
|
assert_eq!(0, fb.foo5(1));
|
|
assert_eq!(0, fb.foo5(5));
|
|
assert_eq!(0, fb.foo5(7));
|
|
assert_eq!(0, fb.foo5(30));
|
|
}
|
|
|
|
#[test]
|
|
fn test_array_field2() {
|
|
let mut fb = FooBar(0);
|
|
|
|
fb.set_foo6(0, 1);
|
|
assert_eq!(0x8, fb.0);
|
|
assert_eq!(1, fb.foo6(0));
|
|
assert_eq!(0, fb.foo6(1));
|
|
assert_eq!(0, fb.foo6(2));
|
|
|
|
fb.set_foo6(0, 7);
|
|
assert_eq!(0x38, fb.0);
|
|
assert_eq!(7, fb.foo6(0));
|
|
assert_eq!(0, fb.foo6(1));
|
|
assert_eq!(0, fb.foo6(2));
|
|
|
|
fb.set_foo6(2, 7);
|
|
assert_eq!(0xE38, fb.0);
|
|
assert_eq!(7, fb.foo6(0));
|
|
assert_eq!(0, fb.foo6(1));
|
|
assert_eq!(7, fb.foo6(2));
|
|
|
|
fb.set_foo6(0, 0);
|
|
assert_eq!(0xE00, fb.0);
|
|
assert_eq!(0, fb.foo6(0));
|
|
assert_eq!(0, fb.foo6(1));
|
|
assert_eq!(7, fb.foo6(2));
|
|
}
|
|
|
|
#[allow(clippy::identity_op)]
|
|
#[allow(clippy::erasing_op)]
|
|
#[test]
|
|
fn test_setter_only_array() {
|
|
let mut fb = FooBar(0);
|
|
|
|
fb.setter_only_array(0, 0);
|
|
assert_eq!(0x0, fb.0);
|
|
|
|
fb.setter_only_array(0, 0b111);
|
|
assert_eq!(0b111 << (4 + 0 * 2), fb.0);
|
|
|
|
fb.setter_only_array(0, 0);
|
|
fb.setter_only_array(1, 0b111);
|
|
assert_eq!(0b111 << (4 + 1 * 3), fb.0);
|
|
|
|
fb.setter_only_array(1, 0);
|
|
fb.setter_only_array(2, 0b111);
|
|
assert_eq!(0b111 << (4 + 2 * 3), fb.0);
|
|
}
|
|
|
|
#[test]
|
|
fn test_getter_only_array() {
|
|
let mut fb = FooBar(0);
|
|
|
|
assert_eq!(0, fb.getter_only_array(0));
|
|
assert_eq!(0, fb.getter_only_array(1));
|
|
assert_eq!(0, fb.getter_only_array(2));
|
|
|
|
fb.0 = !(0x1FF << 3);
|
|
assert_eq!(0, fb.getter_only_array(0));
|
|
assert_eq!(0, fb.getter_only_array(1));
|
|
assert_eq!(0, fb.getter_only_array(2));
|
|
|
|
fb.0 = 0xF << 3;
|
|
assert_eq!(0b111, fb.getter_only_array(0));
|
|
assert_eq!(0b001, fb.getter_only_array(1));
|
|
assert_eq!(0, fb.getter_only_array(2));
|
|
|
|
fb.0 = 0xF << 6;
|
|
assert_eq!(0, fb.getter_only_array(0));
|
|
assert_eq!(0b111, fb.getter_only_array(1));
|
|
assert_eq!(0b001, fb.getter_only_array(2));
|
|
|
|
fb.0 = 0xF << 8;
|
|
assert_eq!(0, fb.getter_only_array(0));
|
|
assert_eq!(0b100, fb.getter_only_array(1));
|
|
assert_eq!(0b111, fb.getter_only_array(2));
|
|
|
|
fb.0 = 0b101_010_110 << 3;
|
|
assert_eq!(0b110, fb.getter_only_array(0));
|
|
assert_eq!(0b010, fb.getter_only_array(1));
|
|
assert_eq!(0b101, fb.getter_only_array(2));
|
|
}
|
|
|
|
#[test]
|
|
fn test_signed() {
|
|
let mut fb = FooBar(0);
|
|
|
|
assert_eq!(0, fb.signed_two_bits());
|
|
assert_eq!(0, fb.signed_eight_bits());
|
|
assert_eq!(0, fb.signed_eight_bits_unaligned());
|
|
|
|
fb.set_signed_two_bits(-2);
|
|
assert_eq!(0b10, fb.0);
|
|
assert_eq!(-2, fb.signed_two_bits());
|
|
assert_eq!(2, fb.signed_eight_bits());
|
|
assert_eq!(1, fb.signed_eight_bits_unaligned());
|
|
|
|
fb.set_signed_two_bits(-1);
|
|
assert_eq!(0b11, fb.0);
|
|
assert_eq!(-1, fb.signed_two_bits());
|
|
assert_eq!(3, fb.signed_eight_bits());
|
|
assert_eq!(1, fb.signed_eight_bits_unaligned());
|
|
|
|
fb.set_signed_two_bits(0);
|
|
assert_eq!(0, fb.0);
|
|
assert_eq!(0, fb.signed_two_bits());
|
|
assert_eq!(0, fb.signed_eight_bits());
|
|
assert_eq!(0, fb.signed_eight_bits_unaligned());
|
|
|
|
fb.set_signed_two_bits(1);
|
|
assert_eq!(1, fb.0);
|
|
assert_eq!(1, fb.signed_two_bits());
|
|
assert_eq!(1, fb.signed_eight_bits());
|
|
assert_eq!(0, fb.signed_eight_bits_unaligned());
|
|
|
|
fb.set_signed_eight_bits(0);
|
|
assert_eq!(0, fb.0);
|
|
assert_eq!(0, fb.signed_two_bits());
|
|
assert_eq!(0, fb.signed_eight_bits());
|
|
assert_eq!(0, fb.signed_eight_bits_unaligned());
|
|
|
|
fb.set_signed_eight_bits(-1);
|
|
assert_eq!(0xFF, fb.0);
|
|
assert_eq!(-1, fb.signed_two_bits());
|
|
assert_eq!(-1, fb.signed_eight_bits());
|
|
assert_eq!(127, fb.signed_eight_bits_unaligned());
|
|
|
|
fb.set_signed_eight_bits(-128);
|
|
assert_eq!(0x80, fb.0);
|
|
assert_eq!(0, fb.signed_two_bits());
|
|
assert_eq!(-128, fb.signed_eight_bits());
|
|
assert_eq!(64, fb.signed_eight_bits_unaligned());
|
|
|
|
fb.set_signed_eight_bits(127);
|
|
assert_eq!(0x7F, fb.0);
|
|
assert_eq!(-1, fb.signed_two_bits());
|
|
assert_eq!(127, fb.signed_eight_bits());
|
|
assert_eq!(63, fb.signed_eight_bits_unaligned());
|
|
|
|
fb.set_signed_eight_bits_unaligned(0);
|
|
assert_eq!(1, fb.0);
|
|
assert_eq!(1, fb.signed_two_bits());
|
|
assert_eq!(1, fb.signed_eight_bits());
|
|
assert_eq!(0, fb.signed_eight_bits_unaligned());
|
|
|
|
fb.set_signed_eight_bits(0);
|
|
fb.set_signed_eight_bits_unaligned(-1);
|
|
assert_eq!(0x1FE, fb.0);
|
|
assert_eq!(-2, fb.signed_two_bits());
|
|
assert_eq!(-2, fb.signed_eight_bits());
|
|
assert_eq!(-1, fb.signed_eight_bits_unaligned());
|
|
|
|
fb.set_signed_eight_bits_unaligned(-128);
|
|
assert_eq!(0x100, fb.0);
|
|
assert_eq!(0, fb.signed_two_bits());
|
|
assert_eq!(0, fb.signed_eight_bits());
|
|
assert_eq!(-128, fb.signed_eight_bits_unaligned());
|
|
fb.set_signed_eight_bits_unaligned(127);
|
|
assert_eq!(0xFE, fb.0);
|
|
assert_eq!(-2, fb.signed_two_bits());
|
|
assert_eq!(-2, fb.signed_eight_bits());
|
|
assert_eq!(127, fb.signed_eight_bits_unaligned());
|
|
}
|
|
|
|
#[test]
|
|
fn test_field_type() {
|
|
let fb = FooBar(0);
|
|
let _: u32 = fb.foo1();
|
|
let _: u8 = fb.foo2();
|
|
let _: u8 = fb.foo3();
|
|
let _: u16 = fb.foo4();
|
|
let _: u8 = fb.foo5(0);
|
|
let _: u32 = fb.foo6(0);
|
|
|
|
let _: bool = fb.foo7();
|
|
let _: u8 = fb.foo8();
|
|
let _: u32 = fb.foo9();
|
|
let _: u16 = fb.foo10();
|
|
let _: u32 = fb.foo11();
|
|
let _: u16 = fb.foo12();
|
|
|
|
let _: Foo = fb.into_foo1();
|
|
let _: Foo = fb.into_foo2();
|
|
let _: Foo = fb.into_foo3();
|
|
let _: Foo = fb.into_foo4();
|
|
let _: Foo = fb.into_foo6(0);
|
|
|
|
let _: Foo = fb.from_foo1();
|
|
let _: Foo = fb.from_foo3();
|
|
let _: Foo = fb.from_foo5(0);
|
|
|
|
let _: i8 = fb.signed_single_bit();
|
|
let _: i8 = fb.signed_two_bits();
|
|
let _: i8 = fb.signed_eight_bits();
|
|
let _: i8 = fb.signed_eight_bits_unaligned();
|
|
|
|
let _: u128 = fb.u128_getter();
|
|
let _: i128 = fb.i128_getter();
|
|
}
|
|
|
|
#[test]
|
|
fn test_into_setter() {
|
|
let mut fb = FooBar(0);
|
|
|
|
// We just check that the parameter type is correct
|
|
fb.set_into_foo1(0u8);
|
|
fb.set_into_foo2(0u8);
|
|
fb.set_into_foo3(0u8);
|
|
fb.set_into_foo4(0u8);
|
|
}
|
|
|
|
#[test]
|
|
fn test_from_setter() {
|
|
let mut fb = FooBar(0);
|
|
assert_eq!(0, fb.0);
|
|
|
|
fb.set_from_foo1(Foo(1));
|
|
assert_eq!(1 << 31, fb.0);
|
|
fb.set_from_foo1(Foo(0));
|
|
assert_eq!(0, fb.0);
|
|
|
|
fb.set_from_foo2(Foo(1));
|
|
assert_eq!(1 << 31, fb.0);
|
|
fb.set_from_foo2(Foo(0));
|
|
assert_eq!(0, fb.0);
|
|
|
|
fb.set_from_foo3(Foo(1));
|
|
assert_eq!(1 << 31, fb.0);
|
|
fb.set_from_foo3(Foo(0));
|
|
assert_eq!(0, fb.0);
|
|
|
|
fb.set_from_foo4(Foo(1));
|
|
assert_eq!(1 << 31, fb.0);
|
|
fb.set_from_foo4(Foo(0));
|
|
assert_eq!(0, fb.0);
|
|
|
|
fb.set_from_foo5(1, Foo(1));
|
|
assert_eq!(1 << 30, fb.0);
|
|
}
|
|
|
|
#[test]
|
|
fn test_all_bits() {
|
|
let mut fb = FooBar(0);
|
|
|
|
assert_eq!(0, fb.all_bits());
|
|
|
|
fb.set_all_bits(!0u32);
|
|
assert_eq!(!0u32, fb.0);
|
|
assert_eq!(!0u32, fb.all_bits());
|
|
|
|
fb.0 = 0x8000_0001;
|
|
assert_eq!(0x8000_0001, fb.all_bits());
|
|
}
|
|
|
|
#[test]
|
|
fn test_is_copy() {
|
|
let a = FooBar(0);
|
|
let _b = a;
|
|
let _c = a;
|
|
}
|
|
|
|
#[test]
|
|
fn test_debug() {
|
|
let fb = FooBar(1_234_567_890);
|
|
let expected = "FooBar { .0: 1234567890, foo1: 0, foo2: 0, foo3: 2, foo3: 2, foo4: 4, foo5: [0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0], foo6: [2, 3, 1], getter_only: 1, pub_getter_only: 1, getter_only_array: [2, 3, 1], all_bits: 1234567890, single_bit: false, into_foo1: Foo(0), into_foo2: Foo(0), from_foo1: Foo(0), into_foo3: Foo(0), into_foo4: Foo(0), into_foo6: [Foo(0), Foo(1), Foo(0)], from_foo3: Foo(0), from_foo5: [Foo(0), Foo(1), Foo(0)], from_foo6: Foo(0), signed_single_bit: 0, signed_two_bits: -2, signed_eight_bits: -46, signed_eight_bits_unaligned: 105, u128_getter: 105, i128_getter: 105 }";
|
|
assert_eq!(expected, format!("{:?}", fb))
|
|
}
|
|
|
|
bitfield! {
|
|
#[derive(Clone, Copy)]
|
|
struct ArrayBitfield([u8]);
|
|
impl BitAnd;
|
|
impl BitOr;
|
|
impl BitXor;
|
|
impl new;
|
|
impl new{foo_unsigned (set_foo1: u32, set_foo2: u32, set_foo3: u32, set_foo4: u32)};
|
|
impl new{foo_signed (set_signed_foo1: i32, set_signed_foo2: i32, set_signed_foo3: i32, set_signed_foo4: i32)};
|
|
u32;
|
|
foo1, set_foo1: 0, 0;
|
|
foo2, set_foo2: 7, 0;
|
|
foo3, set_foo3: 8, 1;
|
|
foo4, set_foo4: 19, 4;
|
|
i32;
|
|
signed_foo1, set_signed_foo1: 0, 0;
|
|
signed_foo2, set_signed_foo2: 7, 0;
|
|
signed_foo3, set_signed_foo3: 8, 1;
|
|
signed_foo4, set_signed_foo4: 19, 4;
|
|
u128, u128_getter, set_u128: 19, 4;
|
|
}
|
|
|
|
#[test]
|
|
fn test_arraybitfield() {
|
|
let mut ab = ArrayBitfield([0; 3]);
|
|
|
|
assert_eq!(0u32, ab.foo1());
|
|
assert_eq!(0u32, ab.foo2());
|
|
assert_eq!(0u32, ab.foo3());
|
|
assert_eq!(0u32, ab.foo4());
|
|
assert_eq!(0i32, ab.signed_foo1());
|
|
assert_eq!(0i32, ab.signed_foo2());
|
|
assert_eq!(0i32, ab.signed_foo3());
|
|
assert_eq!(0i32, ab.signed_foo4());
|
|
assert_eq!(0u128, ab.u128_getter());
|
|
|
|
ab.set_foo1(1);
|
|
assert_eq!([1, 0, 0], ab.0);
|
|
assert_eq!(1, ab.foo1());
|
|
assert_eq!(1, ab.foo2());
|
|
assert_eq!(0, ab.foo3());
|
|
assert_eq!(0, ab.foo4());
|
|
assert_eq!(-1, ab.signed_foo1());
|
|
assert_eq!(1, ab.signed_foo2());
|
|
assert_eq!(0, ab.signed_foo3());
|
|
assert_eq!(0, ab.signed_foo4());
|
|
assert_eq!(0, ab.u128_getter());
|
|
|
|
ab.set_foo1(0);
|
|
ab.set_foo2(0xFF);
|
|
assert_eq!([0xFF, 0, 0], ab.0);
|
|
assert_eq!(1, ab.foo1());
|
|
assert_eq!(0xFF, ab.foo2());
|
|
assert_eq!(0x7F, ab.foo3());
|
|
assert_eq!(0x0F, ab.foo4());
|
|
assert_eq!(-1, ab.signed_foo1());
|
|
assert_eq!(-1, ab.signed_foo2());
|
|
assert_eq!(127, ab.signed_foo3());
|
|
assert_eq!(0x0F, ab.signed_foo4());
|
|
assert_eq!(0x0F, ab.u128_getter());
|
|
|
|
ab.set_foo2(0);
|
|
ab.set_foo3(0xFF);
|
|
assert_eq!([0xFE, 0x01, 0], ab.0);
|
|
assert_eq!(0, ab.foo1());
|
|
assert_eq!(0xFE, ab.foo2());
|
|
assert_eq!(0xFF, ab.foo3());
|
|
assert_eq!(0x1F, ab.foo4());
|
|
assert_eq!(0, ab.signed_foo1());
|
|
assert_eq!(-2, ab.signed_foo2());
|
|
assert_eq!(-1, ab.signed_foo3());
|
|
assert_eq!(0x1F, ab.signed_foo4());
|
|
assert_eq!(0x1F, ab.u128_getter());
|
|
|
|
ab.set_foo3(0);
|
|
ab.set_foo4(0xFFFF);
|
|
assert_eq!([0xF0, 0xFF, 0x0F], ab.0);
|
|
assert_eq!(0, ab.foo1());
|
|
assert_eq!(0xF0, ab.foo2());
|
|
assert_eq!(0xF8, ab.foo3());
|
|
assert_eq!(0xFFFF, ab.foo4());
|
|
assert_eq!(0, ab.signed_foo1());
|
|
assert_eq!(-16, ab.signed_foo2());
|
|
assert_eq!(-8, ab.signed_foo3());
|
|
assert_eq!(-1, ab.signed_foo4());
|
|
assert_eq!(0xFFFF, ab.u128_getter());
|
|
|
|
ab.set_foo4(0x0);
|
|
ab.set_signed_foo1(0);
|
|
assert_eq!([0x00, 0x00, 0x00], ab.0);
|
|
|
|
ab.set_signed_foo1(-1);
|
|
assert_eq!([0x01, 0x00, 0x00], ab.0);
|
|
|
|
ab.set_signed_foo1(0);
|
|
ab.set_signed_foo2(127);
|
|
assert_eq!([0x7F, 0x00, 0x00], ab.0);
|
|
|
|
ab.set_signed_foo2(-128);
|
|
assert_eq!([0x80, 0x00, 0x00], ab.0);
|
|
|
|
ab.set_signed_foo2(1);
|
|
assert_eq!([0x01, 0x00, 0x00], ab.0);
|
|
|
|
ab.set_signed_foo2(-1);
|
|
assert_eq!([0xFF, 0x00, 0x00], ab.0);
|
|
|
|
ab.set_signed_foo2(0);
|
|
ab.set_signed_foo3(127);
|
|
assert_eq!([0xFE, 0x00, 0x00], ab.0);
|
|
|
|
ab.set_signed_foo3(-1);
|
|
assert_eq!([0xFE, 0x01, 0x00], ab.0);
|
|
|
|
ab.set_signed_foo3(0);
|
|
ab.set_signed_foo4(-1);
|
|
assert_eq!([0xF0, 0xFF, 0x0F], ab.0);
|
|
|
|
ab.set_signed_foo4(0);
|
|
ab.set_u128(0xFFFF);
|
|
assert_eq!([0xF0, 0xFF, 0x0F], ab.0);
|
|
}
|
|
|
|
#[test]
|
|
fn test_arraybitfield2() {
|
|
// Check that the macro can be called from a function.
|
|
bitfield! {
|
|
struct ArrayBitfield2([u16]);
|
|
impl Debug;
|
|
u32;
|
|
foo1, set_foo1: 0, 0;
|
|
foo2, set_foo2: 7, 0;
|
|
foo3, set_foo3: 8, 1;
|
|
foo4, set_foo4: 20, 4;
|
|
}
|
|
let mut ab = ArrayBitfield2([0; 2]);
|
|
|
|
assert_eq!(0, ab.foo1());
|
|
assert_eq!(0, ab.foo2());
|
|
assert_eq!(0, ab.foo3());
|
|
assert_eq!(0, ab.foo4());
|
|
|
|
ab.set_foo1(1);
|
|
assert_eq!([1, 0], ab.0);
|
|
assert_eq!(1, ab.foo1());
|
|
assert_eq!(1, ab.foo2());
|
|
assert_eq!(0, ab.foo3());
|
|
assert_eq!(0, ab.foo4());
|
|
|
|
ab.set_foo1(0);
|
|
ab.set_foo2(0xFF);
|
|
assert_eq!([0xFF, 0], ab.0);
|
|
assert_eq!(1, ab.foo1());
|
|
assert_eq!(0xFF, ab.foo2());
|
|
assert_eq!(0x7F, ab.foo3());
|
|
assert_eq!(0x0F, ab.foo4());
|
|
|
|
ab.set_foo2(0);
|
|
ab.set_foo3(0xFF);
|
|
assert_eq!([0x1FE, 0x0], ab.0);
|
|
assert_eq!(0, ab.foo1());
|
|
assert_eq!(0xFE, ab.foo2());
|
|
assert_eq!(0xFF, ab.foo3());
|
|
assert_eq!(0x1F, ab.foo4());
|
|
|
|
ab.set_foo3(0);
|
|
ab.set_foo4(0xFFFF);
|
|
assert_eq!([0xFFF0, 0xF], ab.0);
|
|
assert_eq!(0, ab.foo1());
|
|
assert_eq!(0xF0, ab.foo2());
|
|
assert_eq!(0xF8, ab.foo3());
|
|
assert_eq!(0xFFFF, ab.foo4());
|
|
}
|
|
|
|
bitfield! {
|
|
pub(self) struct ArrayBitfieldMsb0(MSB0 [u8]);
|
|
impl Debug;
|
|
u32;
|
|
foo1, set_foo1: 0, 0;
|
|
foo2, set_foo2: 7, 0;
|
|
foo3, set_foo3: 8, 1;
|
|
foo4, set_foo4: 19, 4;
|
|
i32;
|
|
signed_foo1, set_signed_foo1: 0, 0;
|
|
signed_foo2, set_signed_foo2: 7, 0;
|
|
signed_foo3, set_signed_foo3: 8, 1;
|
|
signed_foo4, set_signed_foo4: 19, 4;
|
|
}
|
|
|
|
#[test]
|
|
fn test_arraybitfield_msb0() {
|
|
let mut ab = ArrayBitfieldMsb0([0; 3]);
|
|
|
|
assert_eq!(0, ab.foo1());
|
|
assert_eq!(0, ab.foo2());
|
|
assert_eq!(0, ab.foo3());
|
|
assert_eq!(0, ab.foo4());
|
|
assert_eq!(0, ab.signed_foo1());
|
|
assert_eq!(0, ab.signed_foo2());
|
|
assert_eq!(0, ab.signed_foo3());
|
|
assert_eq!(0, ab.signed_foo4());
|
|
|
|
ab.set_foo1(1);
|
|
assert_eq!([0b1000_0000, 0, 0], ab.0);
|
|
assert_eq!(1, ab.foo1());
|
|
assert_eq!(0b1000_0000, ab.foo2());
|
|
assert_eq!(0, ab.foo3());
|
|
assert_eq!(0, ab.foo4());
|
|
assert_eq!(-1, ab.signed_foo1());
|
|
assert_eq!(-128, ab.signed_foo2());
|
|
assert_eq!(0, ab.signed_foo3());
|
|
assert_eq!(0, ab.signed_foo4());
|
|
|
|
ab.set_foo1(0);
|
|
ab.set_foo2(0xFF);
|
|
assert_eq!([0b1111_1111, 0, 0], ab.0);
|
|
assert_eq!(1, ab.foo1());
|
|
assert_eq!(0b1111_1111, ab.foo2());
|
|
assert_eq!(0b1111_1110, ab.foo3());
|
|
assert_eq!(0b1111_0000_0000_0000, ab.foo4());
|
|
assert_eq!(-1, ab.signed_foo1());
|
|
assert_eq!(-1, ab.signed_foo2());
|
|
assert_eq!(-2, ab.signed_foo3());
|
|
assert_eq!(-4096, ab.signed_foo4());
|
|
|
|
ab.set_foo2(0);
|
|
ab.set_foo3(0xFF);
|
|
assert_eq!([0b0111_1111, 0b1000_0000, 0], ab.0);
|
|
assert_eq!(0, ab.foo1());
|
|
assert_eq!(0b0111_1111, ab.foo2());
|
|
assert_eq!(0xFF, ab.foo3());
|
|
assert_eq!(0b1111_1000_0000_0000, ab.foo4());
|
|
assert_eq!(0, ab.signed_foo1());
|
|
assert_eq!(127, ab.signed_foo2());
|
|
assert_eq!(-1, ab.signed_foo3());
|
|
assert_eq!(-2048, ab.signed_foo4());
|
|
|
|
ab.set_foo3(0);
|
|
ab.set_foo4(0xFFFF);
|
|
assert_eq!([0x0F, 0xFF, 0xF0], ab.0);
|
|
assert_eq!(0, ab.foo1());
|
|
assert_eq!(0x0F, ab.foo2());
|
|
assert_eq!(0b0001_1111, ab.foo3());
|
|
assert_eq!(0xFFFF, ab.foo4());
|
|
assert_eq!(0, ab.signed_foo1());
|
|
assert_eq!(0x0F, ab.signed_foo2());
|
|
assert_eq!(0b0001_1111, ab.signed_foo3());
|
|
assert_eq!(-1, ab.signed_foo4());
|
|
|
|
ab.set_foo4(0x0);
|
|
ab.set_signed_foo1(0);
|
|
assert_eq!([0x00, 0x00, 0x00], ab.0);
|
|
|
|
ab.set_signed_foo1(-1);
|
|
assert_eq!([0b1000_0000, 0x00, 0x00], ab.0);
|
|
|
|
ab.set_signed_foo1(0);
|
|
ab.set_signed_foo2(127);
|
|
assert_eq!([0x7F, 0x00, 0x00], ab.0);
|
|
|
|
ab.set_signed_foo2(-128);
|
|
assert_eq!([0x80, 0x00, 0x00], ab.0);
|
|
|
|
ab.set_signed_foo2(1);
|
|
assert_eq!([0x01, 0x00, 0x00], ab.0);
|
|
|
|
ab.set_signed_foo2(-1);
|
|
assert_eq!([0xFF, 0x00, 0x00], ab.0);
|
|
|
|
ab.set_signed_foo2(0);
|
|
ab.set_signed_foo3(127);
|
|
assert_eq!([0b0011_1111, 0b1000_0000, 0], ab.0);
|
|
|
|
ab.set_signed_foo3(-1);
|
|
assert_eq!([0b0111_1111, 0b1000_0000, 0], ab.0);
|
|
|
|
ab.set_signed_foo3(0);
|
|
ab.set_signed_foo4(-1);
|
|
assert_eq!([0x0F, 0xFF, 0xF0], ab.0);
|
|
}
|
|
|
|
#[test]
|
|
fn test_arraybitfield_bitops() {
|
|
let mut a = ArrayBitfield([1u8; 3]);
|
|
let b = ArrayBitfield([1u8, 2u8, 4u8]);
|
|
|
|
let c = a | b;
|
|
assert_eq!(c.0, [1, 3, 5]);
|
|
|
|
let d = a & b;
|
|
assert_eq!(d.0, [1, 0, 0]);
|
|
|
|
let e = a ^ b;
|
|
assert_eq!(e.0, [0, 3, 5]);
|
|
|
|
a ^= b;
|
|
assert_eq!(a.0, [0, 3, 5]);
|
|
|
|
let mut vec_a = ArrayBitfield(vec![1u8; 3]);
|
|
let vec_b = ArrayBitfield(vec![1u8, 2u8, 4u8]);
|
|
|
|
let vec_c = vec_a.clone() | vec_b.clone();
|
|
assert_eq!(vec_c.0, [1, 3, 5]);
|
|
|
|
let vec_d = vec_a.clone() & vec_b.clone();
|
|
assert_eq!(vec_d.0, [1, 0, 0]);
|
|
|
|
let vec_e = vec_a.clone() ^ vec_b.clone();
|
|
assert_eq!(vec_e.0, [0, 3, 5]);
|
|
|
|
vec_a ^= vec_b;
|
|
assert_eq!(vec_a.0, [0, 3, 5]);
|
|
}
|
|
|
|
#[test]
|
|
fn test_arraybitfield_constructor() {
|
|
let a: ArrayBitfield<[u8; 3]> = ArrayBitfield::new(1, 2, 3, 4, -1, -2, -3, -4, 0b0001_0000);
|
|
println!("{:b}", a.0[0]);
|
|
assert_eq!(a.foo1(), 0);
|
|
assert_eq!(a.foo2(), 10);
|
|
assert_eq!(a.foo3(), 133);
|
|
assert_eq!(a.foo4(), 16);
|
|
|
|
let b: ArrayBitfield<[u8; 3]> = ArrayBitfield::foo_unsigned(1, 4, 6, u32::MAX);
|
|
assert_eq!(b.signed_foo1(), 0);
|
|
assert_eq!(b.signed_foo2(), -4);
|
|
assert_eq!(b.signed_foo3(), -2);
|
|
assert_eq!(b.signed_foo4(), -1);
|
|
}
|
|
|
|
mod some_module {
|
|
bitfield! {
|
|
pub(super) struct PubBitFieldInAModule(u32);
|
|
impl Debug;
|
|
/// Attribute works on pub fields
|
|
pub field1, set_field1: 1;
|
|
pub field2, _: 1;
|
|
pub _, set_field3: 1;
|
|
pub u16, field4, set_field4: 1;
|
|
/// Check if multiple attributes are applied
|
|
#[cfg(not(test))]
|
|
pub u16, field4, set_field4: 1;
|
|
pub u16, _, set_field5: 1;
|
|
pub u16, field6, _: 1;
|
|
pub field7, set_field7: 1;
|
|
pub field8, set_field8: 1, 1;
|
|
#[cfg(not(test))]
|
|
/// And make sure not only the last attributes is applied
|
|
pub field8, set_field8: 1, 1;
|
|
pub field9, set_field9: 1, 1, 1;
|
|
pub u32, field10, set_field10: 1;
|
|
pub u32, field11, set_field11: 1, 1;
|
|
pub u32, field12, set_field12: 1, 1, 1;
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn struct_can_be_public() {
|
|
let _ = some_module::PubBitFieldInAModule(0);
|
|
}
|
|
#[test]
|
|
fn field_can_be_public() {
|
|
let mut a = some_module::PubBitFieldInAModule(0);
|
|
let _ = a.field1();
|
|
a.set_field1(true);
|
|
let _ = a.field2();
|
|
a.set_field3(true);
|
|
let _ = a.field4();
|
|
a.set_field4(true);
|
|
a.set_field5(true);
|
|
let _ = a.field6();
|
|
let _ = a.field7();
|
|
a.set_field7(true);
|
|
let _ = a.field8();
|
|
a.set_field8(0);
|
|
let _ = a.field9(0);
|
|
a.set_field9(0, 0);
|
|
let _ = a.field10();
|
|
a.set_field10(true);
|
|
let _ = a.field11();
|
|
a.set_field11(0);
|
|
let _ = a.field12(0);
|
|
a.set_field12(0, 0);
|
|
}
|
|
|
|
// Everything in this module is to make sure that its possible to specify types
|
|
// in most of the possible ways.
|
|
#[allow(dead_code)]
|
|
mod test_types {
|
|
use bitfield::{BitRange, BitRangeMut};
|
|
use std::sync::atomic::{self, AtomicUsize};
|
|
|
|
struct Foo;
|
|
|
|
impl Foo {
|
|
bitfield_fields! {
|
|
std::sync::atomic::AtomicUsize, field1, set_field1: 0, 0;
|
|
std::sync::atomic::AtomicUsize;
|
|
field2, set_field2: 0, 0;
|
|
::std::sync::atomic::AtomicUsize, field3, set_field3: 0, 0;
|
|
::std::sync::atomic::AtomicUsize;
|
|
field4, set_field4: 0, 0;
|
|
atomic::AtomicUsize, field5, set_field5: 0, 0;
|
|
atomic::AtomicUsize;
|
|
field6, set_field6: 0, 0;
|
|
AtomicUsize, field7, set_field7: 0, 0;
|
|
AtomicUsize;
|
|
field8, set_field8: 0, 0;
|
|
Vec<std::sync::atomic::AtomicUsize>, field9, set_field9: 0, 0;
|
|
Vec<std::sync::atomic::AtomicUsize>;
|
|
field10, set_field10: 0, 0;
|
|
Vec<::std::sync::atomic::AtomicUsize>, field11, set_field11: 0, 0;
|
|
Vec<::std::sync::atomic::AtomicUsize>;
|
|
field12, set_field12: 0, 0;
|
|
Vec<atomic::AtomicUsize>, field13, set_field13: 0, 0;
|
|
Vec<atomic::AtomicUsize>;
|
|
field14, set_field14: 0, 0;
|
|
Vec<AtomicUsize>, field15, set_field15: 0, 0;
|
|
Vec<AtomicUsize>;
|
|
field16, set_field16: 0, 0;
|
|
&str, field17, set_field17: 0, 0;
|
|
&str;
|
|
field18, set_field18: 0, 0;
|
|
&'static str, field19, set_field19: 0, 0;
|
|
&'static str;
|
|
field20, set_field20: 0, 0;
|
|
}
|
|
}
|
|
|
|
impl BitRange<AtomicUsize> for Foo {
|
|
fn bit_range(&self, _msb: usize, _lsb: usize) -> AtomicUsize {
|
|
AtomicUsize::new(0)
|
|
}
|
|
}
|
|
|
|
impl BitRangeMut<AtomicUsize> for Foo {
|
|
fn set_bit_range(&mut self, _msb: usize, _lsb: usize, _value: AtomicUsize) {}
|
|
}
|
|
|
|
impl BitRange<Vec<AtomicUsize>> for Foo {
|
|
fn bit_range(&self, _msb: usize, _lsb: usize) -> Vec<AtomicUsize> {
|
|
vec![AtomicUsize::new(0)]
|
|
}
|
|
}
|
|
|
|
impl BitRangeMut<Vec<AtomicUsize>> for Foo {
|
|
fn set_bit_range(&mut self, _msb: usize, _lsb: usize, _value: Vec<AtomicUsize>) {}
|
|
}
|
|
|
|
impl<'a> BitRange<&'a str> for Foo {
|
|
fn bit_range(&self, _msb: usize, _lsb: usize) -> &'a str {
|
|
""
|
|
}
|
|
}
|
|
|
|
impl<'a> BitRangeMut<&'a str> for Foo {
|
|
fn set_bit_range(&mut self, _msb: usize, _lsb: usize, _value: &'a str) {}
|
|
}
|
|
|
|
#[test]
|
|
fn test_field_type() {
|
|
let test = Foo;
|
|
let _: AtomicUsize = test.field1();
|
|
let _: AtomicUsize = test.field2();
|
|
let _: AtomicUsize = test.field3();
|
|
let _: AtomicUsize = test.field4();
|
|
let _: AtomicUsize = test.field5();
|
|
let _: AtomicUsize = test.field6();
|
|
let _: AtomicUsize = test.field7();
|
|
let _: AtomicUsize = test.field8();
|
|
let _: Vec<AtomicUsize> = test.field9();
|
|
let _: Vec<AtomicUsize> = test.field10();
|
|
let _: Vec<AtomicUsize> = test.field11();
|
|
let _: Vec<AtomicUsize> = test.field12();
|
|
let _: Vec<AtomicUsize> = test.field13();
|
|
let _: Vec<AtomicUsize> = test.field14();
|
|
let _: Vec<AtomicUsize> = test.field15();
|
|
let _: Vec<AtomicUsize> = test.field16();
|
|
let _: &str = test.field17();
|
|
let _: &str = test.field18();
|
|
let _: &'static str = test.field19();
|
|
let _: &'static str = test.field20();
|
|
}
|
|
}
|
|
|
|
#[allow(dead_code)]
|
|
mod test_no_default_bitrange {
|
|
use bitfield::{BitRange, BitRangeMut};
|
|
use std::fmt::Debug;
|
|
use std::fmt::Error;
|
|
use std::fmt::Formatter;
|
|
|
|
use crate::FooBar;
|
|
bitfield! {
|
|
#[derive(Eq, PartialEq)]
|
|
pub struct BitField1(u16);
|
|
no default BitRange;
|
|
impl Debug;
|
|
u8;
|
|
field1, set_field1: 10, 0;
|
|
pub field2, _ : 12, 3;
|
|
field3, set_field3: 2;
|
|
}
|
|
|
|
impl BitRange<u8> for BitField1 {
|
|
fn bit_range(&self, msb: usize, lsb: usize) -> u8 {
|
|
(msb + lsb) as u8
|
|
}
|
|
}
|
|
|
|
impl BitRangeMut<u8> for BitField1 {
|
|
fn set_bit_range(&mut self, msb: usize, lsb: usize, value: u8) {
|
|
self.0 = msb as u16 + lsb as u16 + u16::from(value)
|
|
}
|
|
}
|
|
|
|
#[allow(clippy::identity_op)]
|
|
#[test]
|
|
fn custom_bitrange_implementation_is_used() {
|
|
let mut bf = BitField1(0);
|
|
assert_eq!(bf.field1(), 10 + 0);
|
|
assert_eq!(bf.field2(), 12 + 3);
|
|
assert!(bf.field3());
|
|
bf.set_field1(42);
|
|
assert_eq!(bf, BitField1(10 + 0 + 42));
|
|
}
|
|
|
|
bitfield! {
|
|
pub(crate) struct BitField2(u16);
|
|
no default BitRange;
|
|
u8;
|
|
field1, set_field1: 10, 0;
|
|
pub field2, _ : 12, 3;
|
|
field3, set_field3: 0;
|
|
}
|
|
|
|
impl BitRange<u8> for BitField2 {
|
|
fn bit_range(&self, _msb: usize, _lsb: usize) -> u8 {
|
|
0
|
|
}
|
|
}
|
|
|
|
impl BitRangeMut<u8> for BitField2 {
|
|
fn set_bit_range(&mut self, _msb: usize, _lsb: usize, _value: u8) {}
|
|
}
|
|
|
|
// Make sure Debug wasn't implemented by implementing it.
|
|
impl Debug for BitField2 {
|
|
fn fmt(&self, _: &mut Formatter) -> Result<(), Error> {
|
|
unimplemented!()
|
|
}
|
|
}
|
|
|
|
// Check that we can put `impl Debug` before `no default BitRange`
|
|
bitfield! {
|
|
pub struct BitField3(u16);
|
|
impl Debug;
|
|
no default BitRange;
|
|
u8;
|
|
field1, set_field1: 10, 0;
|
|
pub field2, _ : 12, 3;
|
|
field3, set_field3: 0;
|
|
}
|
|
|
|
impl BitRange<u8> for BitField3 {
|
|
fn bit_range(&self, _msb: usize, _lsb: usize) -> u8 {
|
|
0
|
|
}
|
|
}
|
|
|
|
impl BitRangeMut<u8> for BitField3 {
|
|
fn set_bit_range(&mut self, _msb: usize, _lsb: usize, _value: u8) {}
|
|
}
|
|
|
|
bitfield! {
|
|
#[derive(Eq, PartialEq)]
|
|
pub struct BitField4([u16]);
|
|
no default BitRange;
|
|
impl Debug;
|
|
u8;
|
|
field1, set_field1: 10, 0;
|
|
pub field2, _ : 12, 3;
|
|
field3, set_field3: 2;
|
|
}
|
|
|
|
impl<T> BitRange<u8> for BitField4<T> {
|
|
fn bit_range(&self, _msb: usize, _lsb: usize) -> u8 {
|
|
0
|
|
}
|
|
}
|
|
|
|
impl<T> BitRangeMut<u8> for BitField4<T> {
|
|
fn set_bit_range(&mut self, _msb: usize, _lsb: usize, _value: u8) {}
|
|
}
|
|
|
|
bitfield! {
|
|
pub struct BitField5([u16]);
|
|
no default BitRange;
|
|
u8;
|
|
field1, set_field1: 10, 0;
|
|
pub field2, _ : 12, 3;
|
|
field3, set_field3: 0;
|
|
}
|
|
|
|
impl<T> BitRange<u8> for BitField5<T> {
|
|
fn bit_range(&self, _msb: usize, _lsb: usize) -> u8 {
|
|
0
|
|
}
|
|
}
|
|
|
|
impl<T> BitRangeMut<u8> for BitField5<T> {
|
|
fn set_bit_range(&mut self, _msb: usize, _lsb: usize, _value: u8) {}
|
|
}
|
|
|
|
// Make sure Debug wasn't implemented by implementing it.
|
|
impl<T> Debug for BitField5<T> {
|
|
fn fmt(&self, _: &mut Formatter) -> Result<(), Error> {
|
|
unimplemented!()
|
|
}
|
|
}
|
|
|
|
// Check that we can put `impl Debug` before `no default BitRange`
|
|
bitfield! {
|
|
pub struct BitField6([u16]);
|
|
impl Debug;
|
|
no default BitRange;
|
|
u8;
|
|
field1, set_field1: 10, 0;
|
|
pub field2, _ : 12, 3;
|
|
field3, set_field3: 0;
|
|
}
|
|
|
|
impl<T> BitRange<u8> for BitField6<T> {
|
|
fn bit_range(&self, _msb: usize, _lsb: usize) -> u8 {
|
|
0
|
|
}
|
|
}
|
|
|
|
impl<T> BitRangeMut<u8> for BitField6<T> {
|
|
fn set_bit_range(&mut self, _msb: usize, _lsb: usize, _value: u8) {}
|
|
}
|
|
|
|
bitfield! {
|
|
#[derive(Eq, PartialEq)]
|
|
pub struct BitField7(MSB0 [u16]);
|
|
no default BitRange;
|
|
impl Debug;
|
|
u8;
|
|
field1, set_field1: 10, 0;
|
|
pub field2, _ : 12, 3;
|
|
field3, set_field3: 2;
|
|
}
|
|
|
|
impl<T> BitRange<u8> for BitField7<T> {
|
|
fn bit_range(&self, _msb: usize, _lsb: usize) -> u8 {
|
|
0
|
|
}
|
|
}
|
|
|
|
impl<T> BitRangeMut<u8> for BitField7<T> {
|
|
fn set_bit_range(&mut self, _msb: usize, _lsb: usize, _value: u8) {}
|
|
}
|
|
|
|
bitfield! {
|
|
pub struct BitField8(MSB0 [u16]);
|
|
no default BitRange;
|
|
u8;
|
|
field1, set_field1: 10, 0;
|
|
pub field2, _ : 12, 3;
|
|
field3, set_field3: 0;
|
|
}
|
|
|
|
impl<T> BitRange<u8> for BitField8<T> {
|
|
fn bit_range(&self, _msb: usize, _lsb: usize) -> u8 {
|
|
0
|
|
}
|
|
}
|
|
|
|
impl<T> BitRangeMut<u8> for BitField8<T> {
|
|
fn set_bit_range(&mut self, _msb: usize, _lsb: usize, _value: u8) {}
|
|
}
|
|
|
|
// Make sure Debug wasn't implemented by implementing it.
|
|
impl<T> Debug for BitField8<T> {
|
|
fn fmt(&self, _: &mut Formatter) -> Result<(), Error> {
|
|
unimplemented!()
|
|
}
|
|
}
|
|
|
|
// Check that we can put `impl Debug` before `no default BitRange`
|
|
bitfield! {
|
|
pub struct BitField9([u16]);
|
|
impl Debug;
|
|
no default BitRange;
|
|
u8;
|
|
field1, set_field1: 10, 0;
|
|
pub field2, _ : 12, 3;
|
|
field3, set_field3: 0;
|
|
}
|
|
|
|
impl<T> BitRange<u8> for BitField9<T> {
|
|
fn bit_range(&self, _msb: usize, _lsb: usize) -> u8 {
|
|
0
|
|
}
|
|
}
|
|
|
|
impl<T> BitRangeMut<u8> for BitField9<T> {
|
|
fn set_bit_range(&mut self, _msb: usize, _lsb: usize, _value: u8) {}
|
|
}
|
|
|
|
#[test]
|
|
fn test_debug_is_implemented_with_no_default_bitrange() {
|
|
format!("{:?}", BitField1(0));
|
|
format!("{:?}", BitField3(0));
|
|
format!("{:?}", BitField4([0; 1]));
|
|
format!("{:?}", BitField6([0; 1]));
|
|
format!("{:?}", BitField7([0; 1]));
|
|
format!("{:?}", BitField9([0; 1]));
|
|
}
|
|
|
|
#[test]
|
|
fn masks() {
|
|
assert_eq!(FooBar::I128_MASK, 0b111111110i128);
|
|
assert_eq!(FooBar::U128_MASK, 0b111111110u128);
|
|
assert_eq!(FooBar::SETTER_MASK, 0b11100u32);
|
|
assert_eq!(FooBar::GETTER_MASK, 0b1110u32);
|
|
assert_eq!(FooBar::PUB_SETTER_MASK, 0b11100u32);
|
|
assert_eq!(FooBar::PUB_GETTER_MASK, 0b1110u32);
|
|
assert_eq!(FooBar::SINGLE_BIT_MASK, 1 << 3);
|
|
assert_eq!(FooBar::PUB_MASK, 1 << 31);
|
|
}
|
|
}
|