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
//! `ctx` (ROADMAP Phase 2, P2.3, "Layer 1"): thread context from a parent into a
//! child's parse/serialize. A `#[bin(ctx(...))]` type gets inherent
//! `decode_with`/`encode_with` + a generated `…Ctx` struct, and does **not**
//! implement `BitDecode`/`BitEncode` (the core traits take no context). A
//! `#[br(ctx { … })]` field passes the context in.
mod macro_ {
use bnb::{bin, u4};
// --- A child whose length depends on context passed by the parent (a TLV-ish
// shape: the parent reads a length/tag, the child is parsed accordingly). ---
#[bin(ctx(n: u8))]
#[derive(Debug, PartialEq, Eq, Clone)]
struct Value {
flag: u4,
#[br(count = n)] // uses the ctx param
data: Vec<u8>,
}
#[bin]
#[derive(Debug, PartialEq, Eq, Clone)]
struct Tlv {
n: u8,
#[br(ctx { n })] // `n` is a parent FIELD -> resolves to self.n on encode
value: Value,
}
#[test]
fn ctx_threads_a_field_into_a_child() {
let t = Tlv {
n: 3,
value: Value {
flag: u4::new(0x5),
data: vec![0x11, 0x22, 0x33],
},
};
let bytes = t.to_bytes().unwrap();
assert_eq!(Tlv::decode_exact(&bytes).unwrap(), t);
}
// --- A SEQUENCE-OF whose elements each need the parent's own context. ---
#[bin(ctx(version: u8))]
#[derive(Debug, PartialEq, Eq, Clone)]
struct Item {
kind: u4,
#[br(count = version)]
data: Vec<u8>,
}
#[bin(ctx(version: u8))]
#[derive(Debug, PartialEq, Eq, Clone)]
struct Container {
flags: u4,
n: u16,
#[br(count = n, ctx { version })] // `version` is a parent CTX PARAM -> stays a local
items: Vec<Item>,
}
#[test]
fn ctx_threads_into_a_count_loop() {
let c = Container {
flags: u4::new(0xF),
n: 2,
items: vec![
Item {
kind: u4::new(1),
data: vec![0xA, 0xB],
},
Item {
kind: u4::new(2),
data: vec![0xC, 0xD],
},
],
};
let ctx = ContainerCtx { version: 2 };
let bytes = c.to_bytes_with(ctx.clone()).unwrap();
assert_eq!(Container::decode_with_exact(&bytes, ctx).unwrap(), c);
}
}