use bnb::{Bitfield, Bits, bin, bitfield, u4, u11, u17};
#[bitfield(u32, bits = msb, bytes = be)]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
struct AutoWord {
hi: u17, lo: u11, }
#[test]
fn auto_width_is_field_sum() {
assert_eq!(<AutoWord as Bitfield>::WIDTH, 28);
assert_eq!(<AutoWord as Bits>::BITS, 28);
let w = AutoWord::new()
.with_hi(u17::new(0x1FFFF))
.with_lo(u11::new(0));
assert_eq!(w.raw(), 0x1FFFF << 11);
let w = AutoWord::new()
.with_hi(u17::new(0))
.with_lo(u11::new(0x7FF));
assert_eq!(w.raw(), 0x7FF);
let w = AutoWord::new()
.with_hi(u17::new(0x15555))
.with_lo(u11::new(0x2AA));
assert_eq!(AutoWord::from_be_bytes(w.to_be_bytes()), w);
}
#[bitfield(u32, bytes = be)]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
struct PlacedWord {
#[bits(15..=31)] hi: u17,
#[bits(0..=10)] lo: u11,
}
#[test]
fn manual_ranges_place_bits_with_a_gap() {
assert_eq!(<PlacedWord as Bitfield>::WIDTH, 32);
let w = PlacedWord::new().with_hi(u17::new(1)).with_lo(u11::new(1));
assert_eq!(w.raw(), (1u32 << 15) | 1);
let full = PlacedWord::new()
.with_hi(u17::new(0x1FFFF))
.with_lo(u11::new(0x7FF));
assert_eq!(full.raw(), 0xFFFF_87FF);
assert_eq!(full.raw() & (0xF << 11), 0, "the reserved gap is untouched");
assert_eq!(full.hi(), u17::new(0x1FFFF));
assert_eq!(full.lo(), u11::new(0x7FF));
}
#[bin]
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
struct Msg {
tag: u4,
word: AutoWord, }
#[test]
fn bitfield_nests_in_bin_stream() {
let word = AutoWord::new()
.with_hi(u17::new(0x1FFFF))
.with_lo(u11::new(0x000));
let m = Msg {
tag: u4::new(0xF),
word,
};
let bytes = m.to_bytes().unwrap();
assert_eq!(bytes.len(), 4, "4 + 28 = 32 bits, no padding");
assert_eq!(bytes, [0xFF, 0xFF, 0xF8, 0x00]);
assert_eq!(Msg::decode_exact(&bytes).unwrap(), m);
}