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
//! Phase 3 SESSION-lane codec (soldr#2365, slice 3a): bridge the proxy pump's
//! `SessionFrame`s onto the v1 `Frame` envelope and back.
//!
//! The pump ([`crate::broker::session_pump`]) speaks in-memory `SessionFrame`
//! channels; this module is the byte-boundary twin that lets those frames cross
//! a real transport. Each `SessionFrame` rides exactly one `Frame` on the
//! [`SESSION_PAYLOAD_PROTOCOL`] lane, encoded with the same
//! `[u8 framing_version=1][u32 LE len][prost Frame]` wire shape every other
//! lane uses (via [`encode_framed`] / [`try_decode_framed`]).
//!
//! **Direction.** The frame kind is derived from the `SessionFrame` variant:
//! client→daemon frames (`Stdin`, `StdinEof`) are `REQUEST`, daemon→client
//! frames (`Stdout`, `Stderr`, `Exit`) are `RESPONSE`. This is a provisional
//! hint, not request/response correlation — a compile session is one long-lived
//! bidirectional exchange, so `request_id` carries a session-local **sequence
//! number** for observability, not a request/response pairing. A later slice
//! (3b) that multiplexes many sessions over one endpoint will introduce a real
//! session id; until then one transport carries one session and direction is
//! implied by which half of the duplex a frame arrives on.
//!
//! This module deliberately does **not** touch the broker socket, `FrameClient`,
//! or any OS handle: it is a pure `SessionFrame <-> bytes` codec so the fidelity
//! it guarantees (byte-transparency across partial-frame boundaries) can be
//! proven in isolation and reused by whatever transport slice 3b lands.
use Message;
use crate;
use crate;
/// The `Frame` kind a `SessionFrame` rides under, derived from its direction.
///
/// Inbound (client→daemon) stdin frames are `REQUEST`; outbound
/// (daemon→client) stdout/stderr/exit frames are `RESPONSE`. See the module
/// docs for why this is a hint rather than request/response correlation.
/// Wrap one `SessionFrame` in a SESSION-lane `Frame`.
///
/// The envelope carries the v1 defaults (`envelope_version`,
/// `payload_encoding = NONE`, no deadline, empty trace context) from
/// [`Frame::request`], with `payload_protocol` pinned to
/// [`SESSION_PAYLOAD_PROTOCOL`], `request_id` set to the session-local `seq`,
/// and `kind` derived from the frame's direction. A `SessionFrame` with no
/// `kind` set (an empty oneof — never produced by the pump) defaults to
/// `REQUEST`; it still round-trips, carrying an empty payload.
/// Encode one `SessionFrame` to complete wire bytes
/// (`[1][u32 len][prost Frame]`), ready to write to a transport.
///
/// # Errors
///
/// [`FramingError::FrameTooLarge`] when the encoded envelope exceeds the frame
/// cap — propagated from [`encode_framed`].
/// One `SessionFrame` decoded from the front of a byte buffer, plus how many
/// wire bytes it occupied.
///
/// `PartialEq` only, not `Eq`: prost stops auto-deriving `Eq` for `SessionFrame`
/// once its oneof includes `SessionStart` (which carries a repeated message
/// field), and equality here is only ever used through `assert_eq!` (which needs
/// `PartialEq`).
/// Incrementally decode one SESSION-lane `SessionFrame` from the front of `buf`.
///
/// Returns `Ok(None)` when `buf` does not yet hold a complete frame — the
/// caller reads more bytes and retries. On `Ok(Some(decoded))` the caller
/// consumes `decoded.consumed` bytes. This mirrors [`try_decode_framed`] and
/// adds the SESSION-lane payload decode on top.
///
/// # Errors
///
/// - [`SessionCodecError::Framing`] for a malformed outer frame (bad framing
/// version, oversize, or undecodable envelope).
/// - [`SessionCodecError::WrongProtocol`] when the envelope is well-formed but
/// is not on the SESSION lane — a caller multiplexing lanes must route by
/// `payload_protocol` before calling this.
/// - [`SessionCodecError::Decode`] when the envelope payload is not a valid
/// `SessionFrame`.
/// Errors from [`try_decode_session_frame`].