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
//! ctx Layer 2 (ROADMAP Phase 2): the polymorphic `DecodeWith<A>`/`EncodeWith<A>`
//! companion traits. Every `BitDecode` type is `DecodeWith<()>` (blanket); a
//! `#[bin(ctx(...))]` type is `DecodeWith<…Ctx>`. So one generic bound `T:
//! DecodeWith<A>` spans both context-free and context-taking messages — what a
//! hand-written combinator needs (the inherent `decode_with` call sites are
//! unchanged).
mod macro_ {
use bnb::{BitError, BitReader, DecodeWith, Source, bin, u4, u12};
#[bin]
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
struct Plain {
a: u4,
b: u12,
}
#[bin(ctx(n: u8))]
#[derive(Debug, PartialEq, Eq, Clone)]
struct WithCtx {
flag: u4,
#[br(count = n)]
data: Vec<u8>,
}
// A generic combinator over *any* decodable-with-context message.
fn decode_one<T: DecodeWith<A>, A, S: Source>(r: &mut S, args: A) -> Result<T, BitError> {
T::decode_with(r, args)
}
#[test]
fn one_bound_spans_context_free_and_context_taking() {
// Context-free: A = ().
let plain = Plain {
a: u4::new(1),
b: u12::new(0x234),
};
let bytes = plain.to_bytes().unwrap();
let mut r = BitReader::new(&bytes);
let got: Plain = decode_one(&mut r, ()).unwrap();
assert_eq!(got, plain);
// Context-taking: A = WithCtxCtx.
let ctx = WithCtxCtx { n: 2 };
let wc = WithCtx {
flag: u4::new(0xF),
data: vec![0xAA, 0xBB],
};
let bytes = wc.to_bytes().unwrap();
let mut r = BitReader::new(&bytes);
let got: WithCtx = decode_one(&mut r, ctx).unwrap();
assert_eq!(got, wc);
}
}