| #[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)) |
| } |
| } |
| |
| bitfield! { |
| #[derive(Copy, Clone)] |
| /// documentation comments also work! |
| struct FooBar(u32); |
| impl Debug; |
| 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; |
| getter_only, _: 3, 1; |
| _, 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; |
| single_bit, set_single_bit: 3; |
| #[allow(dead_code)] |
| u8, into Foo, into_foo1, set_into_foo1: 31, 31; |
| #[allow(dead_code)] |
| pub u8, into Foo, into_foo2, set_into_foo2: 31, 31; |
| u8; |
| #[allow(dead_code)] |
| into Foo, into_foo3, set_into_foo3: 31, 31; |
| #[allow(dead_code)] |
| pub into Foo, into_foo4, set_into_foo4: 31, 31; |
| #[allow(dead_code)] |
| into Foo, _, set_into_foo5: 31, 31; |
| into Foo, into_foo6, _: 29, 29, 3; |
| 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, u128_getter, set_u128: 8, 1; |
| 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_eq!(false, 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_eq!(false, 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_eq!(false, 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_eq!(true, 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_eq!(true, 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()); |
| } |
| |
| #[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(unknown_lints)] |
| #[allow(identity_op)] |
| #[allow(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 _: 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_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, getter_only_array: [2, 3, 1]\ |
| , all_bits: 1234567890, single_bit: false, into_foo1: Foo(0), into_foo2: Foo(0)\ |
| , into_foo3: Foo(0), into_foo4: Foo(0), into_foo6: [Foo(0), Foo(1), 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! { |
| struct ArrayBitfield([u8]); |
| 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! { |
| 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); |
| } |
| |
| mod some_module { |
| bitfield! { |
| pub 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; |
| use std; |
| 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) |
| } |
| 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)] |
| } |
| 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 { |
| "" |
| } |
| 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; |
| use std::fmt::Debug; |
| use std::fmt::Error; |
| use std::fmt::Formatter; |
| 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 |
| } |
| fn set_bit_range(&mut self, msb: usize, lsb: usize, value: u8) { |
| self.0 = msb as u16 + lsb as u16 + u16::from(value) |
| } |
| } |
| |
| #[allow(unknown_lints)] |
| #[allow(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_eq!(bf.field3(), true); |
| bf.set_field1(42); |
| assert_eq!(bf, BitField1(10 + 0 + 42)); |
| } |
| |
| bitfield!{ |
| pub 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 |
| } |
| 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 |
| } |
| 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 |
| } |
| 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 |
| } |
| 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 |
| } |
| 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 |
| } |
| 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 |
| } |
| 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 |
| } |
| 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])); |
| } |
| } |