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
//! Where the mux core gets memory, and the one way it is allowed to fail.
//!
//! The core does not allocate for itself and does not name
//! [`crate::pool::Pool`]. Every buffer it needs — a connection's stream-0
//! landing zone, a stream's request/response pair, the HPACK scratch — comes
//! from a caller-supplied [`BufferSource`], which the caller implements and
//! which **may refuse**. That is the whole contract, and both halves matter:
//!
//! - *Caller-supplied* is what lets something other than the real pool stand
//! behind it. A deterministic simulator that wants to drive the core into
//! memory pressure has somewhere to stand, instead of having to arrange the
//! pressure through a global allocator it does not control.
//! - *May refuse* is what keeps the existing behaviour expressible. Refusal
//! is **not** an error condition here. A source that answers `None`
//! mid-request is reporting a transient shortage, and the caller's
//! obligation is to degrade the smallest unit it can: one stream is refused
//! with `RST_STREAM(REFUSED_STREAM)` and the connection carries on, because
//! the streams already running will hand their buffers back. Escalating a
//! shortage to a connection error would convert it into the loss of every
//! in-flight request that would have survived it.
//!
//! Neither half is new behaviour. Both checkout sites were already
//! `Option`-fallible with a `REFUSED_STREAM`-shaped fallback; what was missing
//! was a name for the thing being called, so the core reached for a concrete
//! `Weak<RefCell<Pool>>` instead. This module supplies the name and
//! [`PoolBufferSource`] supplies the one implementation the proxy itself uses,
//! which does exactly what the direct reach did.
//!
//! ## What is under the contract, and what is not
//!
//! Under it: the connection's own `zero` buffer, a stream's request/response
//! buffer pair, and the HPACK codec pair together with the three reusable
//! scratch buffers beside them (see `HpackState`, `hpack_state.rs`).
//!
//! Not under it, deliberately:
//!
//! - **Growth of the HPACK codec's own buffers.** The dynamic tables of the
//! `crate::protocol::mux::hpack` pair and the decoder's Huffman scratch
//! buffer start empty and grow to a high-water mark bounded by the RFC 7541
//! §4.2 table-size settings and the longest decoded string. They are brought
//! under the contract at *acquisition* — the pair is built inside a fallible
//! `HpackState::new` — and their growth after acquisition reaches the global
//! allocator, like a scratch buffer's below.
//! - **Growth of an already-acquired scratch buffer.** `scratch` hands over an
//! empty `Vec` that the core then grows and reclaims on its own schedule.
//! Pre-sizing one and refusing to grow it is a behaviour change — it needs
//! an answer for what a header block larger than the reservation does — and
//! is not made here.
//! - **`H2Scheduler`'s pass-order buffer (`h2_scheduler.rs`).** It holds
//! stream ids rather than octets, and it is already bounded by the
//! concurrent-stream admission gate that decides how many ids can exist.
use ;
use crate;
/// The caller-supplied origin of every buffer the mux core uses.
///
/// Implementors may refuse either request at any time, including in the
/// middle of a request. See the module documentation for what a refusal
/// obliges the caller to do — in short, degrade one stream, never the
/// connection.
/// The [`BufferSource`] the proxy itself runs on: the worker's shared
/// [`Pool`], reached through the same weak handle the core used to hold
/// directly.
///
/// Every method is the expression that used to sit at the call site, moved
/// here unchanged — an upgrade-then-checkout for [`BufferSource::checkout`],
/// and a plain empty `Vec` for [`BufferSource::scratch`]. The pool has no
/// scratch arena to draw the latter from, and inventing one would be a
/// behaviour change rather than the relocation this is.