mod integration {
use bnb::{BitDecode, BitEncode, BitEnum, u4, u48, u108};
use proptest::prelude::*;
#[derive(BitEnum, Copy, Clone, Eq, PartialEq, Debug)]
#[bit_enum(u48)]
#[repr(u64)]
enum Sync {
BaseStationVoice = 0x755F_D7DF_75F7,
BaseStationData = 0xDFF5_7D75_DF5D,
MobileStationVoice = 0x7F7D_5DD5_7DFD,
#[catch_all]
Unknown(u48),
}
#[derive(BitDecode, BitEncode, Copy, Clone, Eq, PartialEq, Debug)]
struct Burst {
payload_1: u108,
sync: Sync,
payload_2: u108,
}
#[derive(BitDecode, BitEncode, Copy, Clone, Eq, PartialEq, Debug)]
struct Frame {
color_code: u4,
data_type: u4,
#[nested]
burst: Burst,
crc: [u8; 2],
}
fn frame_with(sync: Sync) -> Frame {
Frame {
color_code: u4::new(0x5),
data_type: u4::new(0xA),
burst: Burst {
payload_1: u108::from_raw(0x0123_4567_89AB_CDEF_0123_4567),
sync,
payload_2: u108::from_raw(0x0FED_CBA9_8765_4321_0FED_CBA9),
},
crc: [0xBE, 0xEF],
}
}
#[test]
fn frame_round_trips_with_no_binrw() {
let frame = frame_with(Sync::BaseStationData);
let bytes = frame.to_bytes().unwrap();
assert_eq!(bytes.len(), 36, "288 bits");
assert_eq!(Frame::decode_exact(&bytes).unwrap(), frame);
}
#[test]
fn recognizes_a_known_sync_and_preserves_unknown() {
let known = frame_with(Sync::MobileStationVoice);
assert_eq!(
Frame::decode_exact(&known.to_bytes().unwrap())
.unwrap()
.burst
.sync,
Sync::MobileStationVoice
);
let bogus = frame_with(Sync::Unknown(u48::from_raw(0x0000_0000_0001)));
let decoded = Frame::decode_exact(&bogus.to_bytes().unwrap()).unwrap();
assert_eq!(
decoded.burst.sync,
Sync::Unknown(u48::from_raw(0x0000_0000_0001))
);
}
#[test]
fn golden_bytes() {
let frame = frame_with(Sync::BaseStationVoice);
let bytes = frame.to_bytes().unwrap();
let golden: [u8; 36] = [
0x5a, 0x00, 0x00, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56,
0x77, 0x55, 0xfd, 0x7d, 0xf7, 0x5f, 0x70, 0x00, 0x0f, 0xed, 0xcb, 0xa9, 0x87, 0x65,
0x43, 0x21, 0x0f, 0xed, 0xcb, 0xa9, 0xbe, 0xef,
];
assert_eq!(bytes, golden, "got {bytes:02x?}");
assert_eq!(Frame::decode_exact(&golden).unwrap(), frame);
}
proptest! {
#[test]
fn frame_round_trips_prop(
cc in any::<u8>(),
dt in any::<u8>(),
p1 in any::<u128>(),
p2 in any::<u128>(),
sync_raw in any::<u64>(),
crc in any::<[u8; 2]>(),
) {
let frame = Frame {
color_code: u4::from_raw(cc),
data_type: u4::from_raw(dt),
burst: Burst {
payload_1: u108::from_raw(p1),
sync: <Sync as bnb::Bits>::from_bits(u128::from(sync_raw)),
payload_2: u108::from_raw(p2),
},
crc,
};
let bytes = frame.to_bytes().unwrap();
prop_assert_eq!(bytes.len(), 36);
prop_assert_eq!(Frame::decode_exact(&bytes).unwrap(), frame);
}
}
}