1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
//! `#[bin]` foundation (ROADMAP Phase 2, P2.0): one attribute macro folds the
//! codec and the required-by-default builder, lowering to
//! `#[derive(BitDecode, BitEncode, BitsBuilder)]` + `#[bit_stream(...)]`. Field
//! directives (`#[br]`/`#[bw]`) arrive in later chunks.
mod macro_ {
use bnb::{BuilderError, bin, u4, u12};
#[bin]
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
struct Frame {
version: u4,
#[builder(default)]
flags: u4,
payload_len: u12,
}
#[test]
fn folds_codec_and_builder() {
let f = Frame::builder()
.version(u4::new(4))
.payload_len(u12::new(100))
.build()
.unwrap();
assert_eq!(f.flags, u4::new(0), "builder default");
let bytes = f.to_bytes().unwrap();
assert_eq!(Frame::decode_exact(&bytes).unwrap(), f);
}
#[test]
fn enforces_required_fields() {
let err = Frame::builder().version(u4::new(4)).build().unwrap_err();
assert_eq!(err, BuilderError::MissingField("payload_len"));
}
#[bin(bits = lsb)]
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
struct LsbWord {
a: u4,
b: u12,
}
#[test]
fn bit_order_option_lowers() {
let v = LsbWord {
a: u4::new(0xA),
b: u12::new(0),
};
// LSB-first packs the first field into the low bits.
assert_eq!(v.to_bytes().unwrap()[0] & 0x0F, 0xA);
}
#[bin(read_only)]
#[derive(Debug, PartialEq, Eq)]
struct ReadOnly {
a: u4,
b: u12,
}
#[test]
fn read_only_decodes_only() {
let r = ReadOnly::peek(&[0xAB, 0xCD]).unwrap();
assert_eq!(
r,
ReadOnly {
a: u4::new(0xA),
b: u12::new(0xBCD)
}
);
// No `to_bytes`/builder is generated for a read_only type (enforced at compile
// time — only Decode is derived).
}
// Fields named `r`/`w` once collided with the codec's generated source/sink and were
// a hard error. The params are now `__bnb_r`/`__bnb_w`, so `r`/`w` are ordinary field
// names — even usable as a sibling local in a directive like `count`.
#[bin(big)]
#[derive(Debug, PartialEq, Eq)]
struct Rw {
r: u8,
w: u8,
#[br(count = r as usize)]
tail: Vec<u8>,
}
#[test]
fn fields_named_r_and_w_roundtrip() {
let v = Rw::builder().r(3).w(7).tail(vec![1, 2, 3]).build().unwrap();
let bytes = v.to_bytes().unwrap();
assert_eq!(bytes, vec![3, 7, 1, 2, 3]);
assert_eq!(Rw::decode_exact(&bytes).unwrap(), v);
}
}