use super::*;
macro_rules! test_bitfield {
($ty:ident, $field:ident: $bit:expr) => {
let bits = $ty.bits();
let exp_val = ((bits & (0x1 << $bit)) >> $bit) != 0;
assert_eq!($ty.$field(), exp_val);
paste::paste! { $ty.[<set_ $field>](false); }
assert!(!$ty.$field())
};
($ty:ident, $field:ident: $lsb:expr, $msb:expr) => {
let bits = $ty.bits();
let width = $msb - $lsb + 1;
let mask = (0x1 << width) - 1;
let exp_val = (bits & (mask << $lsb)) >> $lsb;
assert_eq!($ty.$field(), exp_val);
paste::paste! { $ty.[<set_ $field>](0); }
assert_eq!($ty.$field(), 0)
};
}
macro_rules! test_bitfield_arr {
($ty:ident, $field:ident: $bit:expr, $val:expr) => {
assert_eq!($ty.$field(), $val);
paste::paste! { $ty.[<set_ $field>](false); }
assert!(!$ty.$field());
};
($ty:ident, $field:ident: $lsb:expr, $msb:expr, $val:expr) => {
assert_eq!($ty.$field(), $val);
paste::paste! { $ty.[<set_ $field>](0); }
assert_eq!($ty.$field(), 0);
};
}
#[test]
fn test_bitfield_u8() {
bitfield! {
pub TestU8(u8): u8,
mask: 0xff,
default: 0,
{
pub range2: 7, 5;
pub range1: 4, 3;
pub bit2: 2;
pub bit1: 1;
pub bit0: 0;
}
}
(0..=u8::MAX).for_each(|bits| {
let mut test = TestU8::from(bits);
test_bitfield!(test, range2: 5, 7);
test_bitfield!(test, range1: 3, 4);
test_bitfield!(test, bit2: 2);
test_bitfield!(test, bit1: 1);
test_bitfield!(test, bit0: 0);
});
}
#[test]
fn test_bitfield_u16() {
bitfield! {
pub TestU16(u16): u16,
mask: 0xffff,
default: 0,
{
pub range2: 15, 8;
pub range1: 7, 5;
pub range0: 4, 2;
pub bit1: 1;
pub bit0: 0;
}
}
(0..=u16::BITS)
.map(|r| ((1u32 << r) - 1) as u16)
.for_each(|bits| {
let mut test = TestU16::from(bits);
test_bitfield!(test, range2: 8, 15);
test_bitfield!(test, range1: 5, 7);
test_bitfield!(test, range0: 2, 4);
test_bitfield!(test, bit1: 1);
test_bitfield!(test, bit0: 0);
});
}
#[test]
fn test_bitfield_u32() {
bitfield! {
pub TestU32(u32): u32,
mask: 0xffff,
default: 0,
{
pub range3: 31, 16;
pub range2: 15, 8;
pub range1: 7, 5;
pub range0: 4, 2;
pub bit1: 1;
pub bit0: 0;
}
}
(0..=u32::BITS)
.map(|r| ((1u64 << r) - 1) as u32)
.for_each(|bits| {
let mut test = TestU32::from(bits);
test_bitfield!(test, range3: 16, 31);
test_bitfield!(test, range2: 8, 15);
test_bitfield!(test, range1: 5, 7);
test_bitfield!(test, range0: 2, 4);
test_bitfield!(test, bit1: 1);
test_bitfield!(test, bit0: 0);
});
}
#[test]
fn test_bitfield_u64() {
bitfield! {
pub TestU64(u64): u64,
mask: 0xffff,
default: 0,
{
pub range4: 63, 32;
pub range3: 31, 16;
pub range2: 15, 8;
pub range1: 7, 5;
pub range0: 4, 2;
pub bit1: 1;
pub bit0: 0;
}
}
(0..=u64::BITS)
.map(|r| ((1u128 << r) - 1) as u64)
.for_each(|bits| {
let mut test = TestU64::from(bits);
test_bitfield!(test, range4: 32, 63);
test_bitfield!(test, range3: 16, 31);
test_bitfield!(test, range2: 8, 15);
test_bitfield!(test, range1: 5, 7);
test_bitfield!(test, range0: 2, 4);
test_bitfield!(test, bit1: 1);
test_bitfield!(test, bit0: 0);
});
}
#[test]
fn test_bitfield_array_lsb() {
bitfield! {
pub TestU8x3(LSB0 [u8; 3]): u8 {
pub range3: 23, 16;
pub range2: 15, 8;
pub range1: 7, 5;
pub range0: 4, 2;
pub bit1: 1;
pub bit0: 0;
}
}
(0..=24).map(|r| (1u32 << r) - 1).for_each(|bits| {
let [b0, b1, b2, _] = bits.to_le_bytes();
let mut test = TestU8x3([b0, b1, b2]);
let [b0, b1, b2] = test.bytes();
let exp_range1 = (b0 & (0x7 << 5)) >> 5;
let exp_range0 = (b0 & (0x7 << 2)) >> 2;
let exp_bit1 = ((b0 & 0x1 << 1) >> 1) != 0;
let exp_bit0 = b0 & 0x1 != 0;
test_bitfield_arr!(test, range3: 16, 23, b2);
test_bitfield_arr!(test, range2: 8, 15, b1);
test_bitfield_arr!(test, range1: 5, 7, exp_range1);
test_bitfield_arr!(test, range0: 2, 4, exp_range0);
test_bitfield_arr!(test, bit1: 1, exp_bit1);
test_bitfield_arr!(test, bit0: 0, exp_bit0);
});
}
#[test]
fn test_bitfield_array_msb() {
bitfield! {
pub TestU8x3(MSB0 [u8; 3]): u8 {
pub range3: 23, 16;
pub range2: 15, 8;
pub range1: 7, 5;
pub range0: 4, 2;
pub bit1: 1;
pub bit0: 0;
}
}
(0..=24).map(|r| (1u32 << r) - 1).for_each(|bits| {
let [_, b0, b1, b2] = bits.to_be_bytes();
let mut test = TestU8x3([b0, b1, b2]);
let [b0, b1, b2] = test.bytes();
let exp_range1 = (b2 & (0x7 << 5)) >> 5;
let exp_range0 = (b2 & (0x7 << 2)) >> 2;
let exp_bit1 = ((b2 & 0x1 << 1) >> 1) != 0;
let exp_bit0 = b2 & 0x1 != 0;
test_bitfield_arr!(test, range3: 16, 23, b0);
test_bitfield_arr!(test, range2: 8, 15, b1);
test_bitfield_arr!(test, range1: 5, 7, exp_range1);
test_bitfield_arr!(test, range0: 2, 4, exp_range0);
test_bitfield_arr!(test, bit1: 1, exp_bit1);
test_bitfield_arr!(test, bit0: 0, exp_bit0);
});
}
#[test]
fn test_bitfield_user_ty() {
bitfield! {
A: u8,
mask: 0xf,
default: 0,
{
a: 3, 0;
}
}
bitfield! {
B: u8,
mask: 0xf,
default: 0,
{
b: 3, 0;
}
}
bitfield! {
TestUser: u8,
mask: 0xff,
default: 0,
{
b: B, 7, 4;
a: A, 3, 0;
}
}
(0..=u8::MAX).for_each(|bits| {
let mut test = TestUser::try_from_inner(bits).unwrap();
let exp_a = A::try_from_inner(bits & 0xf).unwrap();
let exp_b = B::try_from_inner(bits >> 4).unwrap();
assert_eq!(test.a(), Ok(exp_a));
let a = A::try_from_inner(bits & A::MASK).unwrap();
test.set_a(a);
assert_eq!(test.a(), Ok(a));
assert_eq!(test.b(), Ok(exp_b));
let b = B::try_from_inner(bits & B::MASK).unwrap();
test.set_b(b);
assert_eq!(test.b(), Ok(b));
});
}