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
//! The sans-IO byte-stream parser contract — core-tier, no `std`, no
//! `alloc` dependency of its own (implementors own whatever buffer they
//! need; this module only names the shape).
//!
//! # Where this came from
//!
//! Three format parsers landed in this workspace independently
//! (`proxima-gguf::GgufParser`, `proxima-onnx::OnnxParser`,
//! `proxima-safetensors::SafetensorsParser`), each briefed on its own and
//! each inventing its own FSM shape. Two of the three already matched:
//! `GgufParser`/`OnnxParser` both imitated
//! `proxima-protocols::http1_codec::h1_connection::Connection`
//! (`feed_bytes`/`poll`, `&mut self`, one owned growing buffer) by name in
//! their own module docs — that type predates both and is the actual
//! prior art, not a fresh design. `SafetensorsParser` instead imitated
//! `proxima_codec::DelimiterFraming` (`push(self, chunk) -> Self`,
//! self-consuming, cursor folded into the enum variant) — a real,
//! independently-motivated shape in this workspace, but a different one.
//!
//! [`ByteStreamParser`] names the `&mut self` `feed`/`poll` shape as the
//! one contract, because it was *already* established twice
//! (`h1_connection::Connection`, and `GgufParser`/`OnnxParser` copying it)
//! before any of these three parsers existed, and because it is strictly
//! more capable than the self-consuming shape: it lets a caller feed and
//! drain in independent, arbitrarily-interleaved calls (`feed` any number
//! of times, then `poll` any number of times to drain a backlog of
//! events), which a self-consuming `push` cannot do without threading the
//! returned `Self` back through every call site by hand.
//!
//! `DelimiterFraming`'s self-consuming shape is not wrong where it lives —
//! its own doc explains the invariant it buys (the scan cursor can never
//! drift from the buffer it scans, because both live in the same enum
//! variant, moved together). That invariant is about `next_frame`'s
//! *internal* bookkeeping, not about the `&mut self` vs. self-consuming
//! choice at the public boundary: nothing stops a `&mut self` method from
//! reconstructing the same enum internally via `core::mem::replace` with a
//! cheap placeholder, which is exactly how `SafetensorsParser` now
//! implements this trait (`proxima-safetensors/src/parser.rs`) — same
//! variant-folded-cursor invariant, `&mut self` boundary.
//!
//! # Not a [`Pipe`](crate::pipe::Pipe)
//!
//! A parser here is fed bytes and polled for events an unbounded,
//! caller-controlled number of times per `feed` call (see `GgufParser`'s
//! `poll_kv`, which recurses into itself via `self.poll()` after
//! committing each KV pair with no new bytes in between). `Pipe::call` is
//! one `In -> Result<Out, Err>` step; there is no `In` shape that
//! expresses "attempt progress again against what's already buffered,
//! with no new input." This is the same non-`Pipe` argument
//! `proxima-safetensors::header_codec` and `proxima_codec::DelimiterFraming`
//! already made for their own stateful loops — restated here because it
//! applies to the whole trait, not just one impl.
/// One [`ByteStreamParser::poll`] outcome: either not enough buffered
/// bytes to make progress (call [`ByteStreamParser::feed`]), or one unit
/// of progress in the form of `Event`.
/// The sans-IO byte-stream parser contract. Owns its own buffering
/// strategy entirely; this trait only fixes the shape callers drive it
/// through.
///
/// `feed` never inspects or parses the bytes it is given — appending is
/// infallible and cannot fail on malformed input, because malformed input
/// is only discoverable once `poll` actually looks at the buffered bytes.
/// `poll` attempts exactly one unit of progress against whatever is
/// currently buffered and never blocks: [`Outcome::NeedMore`] means "call
/// `feed` again," not "wait." `finish` is a read-only check — `Ok(())`
/// only if the parser has reached a valid terminal state; otherwise the
/// byte stream ended mid-item. It never hands back an owned final value:
/// an impl that has one (e.g. `SafetensorsParser::into_manifest`) surfaces
/// it as a `poll` event or a separate accessor, keeping `finish`'s
/// signature uniform across every impl regardless of what "done" produces.
/// Drives any [`ByteStreamParser`] to completion from a chunked byte
/// stream — feeds each chunk, drains every event it produces (looping
/// `poll` until [`Outcome::NeedMore`]) before asking for the next chunk,
/// then calls [`ByteStreamParser::finish`]. `on_event` runs once per
/// emitted event, in order.
///
/// This is the proof the shared contract is load-bearing rather than a
/// relocation: one generic loop drives `GgufParser`, `OnnxParser`, and
/// `SafetensorsParser` alike (see each crate's `sans_io` test module) —
/// before this trait existed, a caller wanting that had to hand-write the
/// same feed/poll loop three times, once per concrete type.
///
/// # Errors
///
/// The first [`ByteStreamParser::Error`] any `feed`d chunk's `poll` or the
/// final `finish` call surfaces.