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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
//! A decoded control message as a tree of named fields.
//!
//! [`AnyControlMessage::fields`](crate::dispatch::AnyControlMessage::fields)
//! turns any draft's `ControlMessage` into a [`FieldMap`] whose keys are the
//! field names that draft gives them. The names are the drafts' own, in
//! snake_case, and the field order is the order the draft defines — so a
//! reader that has never heard of a message can still show it, and two drafts
//! that spell the same concept differently keep their own spelling. The
//! per-draft `fields` modules are what it dispatches to.
//!
//! # Why a tree of the crate's own making
//!
//! The obvious return types are `serde_json::Value` and `ciborium::Value`, and
//! this crate depends on neither. A codec that gained a serialization format's
//! value type would make everything downstream carry it, to describe messages
//! that have nothing to do with that format. [`FieldValue`] is `std` and a
//! `Vec`, and each caller renders it into whatever it already writes: the
//! vector tests into JSON, where a varint becomes a decimal string and a byte
//! string becomes hex, and a trace writer into CBOR, where both have a type of
//! their own.
//!
//! That split is also why [`FieldValue::Uint`] and [`FieldValue::Bytes`] are
//! distinct from [`FieldValue::Text`] rather than pre-rendered into it. A
//! converter that flattened them would force every consumer to guess which
//! strings were numbers.
/// Parameter tables more than one draft shares.
///
/// A draft whose parameter handling is its own keeps it in its own `fields.rs`,
/// which is where all but four of them are. Only drafts 07 through 10 share:
/// one message table across all four, and one setup table across the three that
/// dropped ROLE. Anything reachable from a single draft belongs to that draft,
/// or a build of that draft alone compiles code nothing can call.
pub
/// One field's value inside a decoded control message.
///
/// Absent optional fields are omitted from their [`FieldMap`] rather than
/// given a zero: a field the wire never carried and a field carrying zero are
/// different, and only omission can say so.
/// A decoded message's fields, in the order the draft defines them.
///
/// Ordered rather than sorted because the order is information: it is the
/// order the fields appear on the wire, which is what makes a rendering of
/// one message comparable to a rendering of the same message from another
/// implementation.