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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
//! Streaming KLV decoder
//!
//! [`Decoder<P>`] owns a growing byte buffer and an optional in-flight
//! [`crate::traits::Partial`] state. It yields fully-decoded values of the
//! Partial's `Final` type as enough bytes arrive. It is the user-facing API
//! for parsing KLV from fragmented transports (short TCP reads, ring
//! buffers, UDP re-assembly) where a single logical packet may straddle
//! multiple reads, AND for resuming a packet whose body was cut mid-decode
//! (delivered through [`crate::decoder::Packet::NeedMore`])
//!
//! # Two modes of operation
//!
//! * **Fresh mode** (`partial = None`): [`Decoder::next`] uses
//! [`crate::traits::SeekSentinel`] to locate each packet boundary and
//! then runs [`crate::traits::DecodePartial::decode_partial`] on the
//! framed body. This is the original sentinel-framed streaming flow
//!
//! * **Resume mode** (`partial = Some(p)`): the decoder was constructed
//! from a [`Packet::NeedMore`] return inside `decode_partial` and
//! already carries a half-built packet. [`Decoder::next`] resumes
//! directly into the existing partial without re-seeking the sentinel,
//! so previously-decoded fields are not lost
//!
//! # Framing requirement (fresh mode only)
//!
//! In fresh mode, the final type `T` (`P::Final`) must implement
//! [`crate::traits::SeekSentinel`]. Without a sentinel there is no way to
//! tell one packet's bytes from the next inside a continuous byte stream.
//! Resume mode bypasses the sentinel entirely - the partial is already
//! past the framing
//!
//! See [`crate::traits::DecodePartial`] for the underlying trait,
//! [`crate::decoder::Packet`] for the two-state signal (`Ready` / `NeedMore`), and
//! [`crate::traits::Partial`] for the partial-to-final conversion contract.
// --------------------------------------------------
// mods
// --------------------------------------------------
// --------------------------------------------------
// re-exports
// --------------------------------------------------
pub use *;
pub use *;
// --------------------------------------------------
// local
// --------------------------------------------------
use crate;
// --------------------------------------------------
// external
// --------------------------------------------------
use PhantomData;
// --------------------------------------------------
// constants
// --------------------------------------------------
const EMPTY: & = &;
/// Owned-buffer streaming decoder, parameterised on the [`Partial`] type.
///
/// Accepts bytes via [`feed`](Self::feed) and yields decoded values via
/// [`next`](Self::next). A `None` from `next` means "need more bytes,
/// call `feed` again" - malformed packets are silently skipped (the
/// framed bytes are drained to guarantee forward progress).
///
/// # Example
///
/// ```ignore
/// // fresh mode (no in-flight partial): seek sentinel + decode framed body
/// let mut dec = Decoder::<<MyPacket as DecodePartial<&[u8]>>::Partial>::new();
/// let mut scratch = [0u8; 2048];
/// loop {
/// let n = socket.recv(&mut scratch)?;
/// dec.feed(&scratch[..n]);
/// while let Some(pkt) = dec.next() {
/// handle(pkt);
/// }
/// }
///
/// // resume mode: handed back from `Packet::NeedMore`
/// match MyPacket::decode_partial(&mut input) {
/// Ok(Packet::Ready(t)) => use_packet(t),
/// Ok(Packet::NeedMore(partial)) => {
/// let mut dec = Decoder::new();
/// dec.feed(more_bytes);
/// while let Some(pkt) = dec.next() {
/// use_packet(pkt);
/// break;
/// }
/// }
/// Err(label) => report(label),
/// }
/// ```
/// [`Decoder`] implementation of [`Default`]
/// [`Decoder`] implementation
/// [`Decoder`] decoding implementation - resume mode
///
/// This is just the &[u8] specialization of [`Decoder`]
///
/// When the decoder carries an in-flight partial, [`next`](Self::next)
/// resumes [`DecodePartial::decode_partial`] without re-seeking the
/// sentinel: the partial state already lives past the framing.