bitfielder 0.1.1

Yet another bitfield library
Documentation
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! {
        /// Test U8.
        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! {
        /// Test U16.
        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! {
        /// Test U32.
        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! {
        /// Test U64.
        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! {
        /// Test 24-bit array.
        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! {
        /// Test 24-bit array.
        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! {
        /// Test A.
        A: u8,
        mask: 0xf,
        default: 0,
        {
            a: 3, 0;
        }
    }

    bitfield! {
        /// Test B.
        B: u8,
        mask: 0xf,
        default: 0,
        {
            b: 3, 0;
        }
    }

    bitfield! {
        /// Test User defined fields.
        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));
    });
}