Coverage Report

Created: 2025-08-29 06:13

/src/h2/src/codec/framed_write.rs
Line
Count
Source (jump to first uncovered line)
1
use crate::codec::UserError;
2
use crate::codec::UserError::*;
3
use crate::frame::{self, Frame, FrameSize};
4
use crate::hpack;
5
6
use bytes::{Buf, BufMut, BytesMut};
7
use std::pin::Pin;
8
use std::task::{Context, Poll};
9
use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
10
use tokio_util::io::poll_write_buf;
11
12
use std::io::{self, Cursor};
13
14
// A macro to get around a method needing to borrow &mut self
15
macro_rules! limited_write_buf {
16
    ($self:expr) => {{
17
        let limit = $self.max_frame_size() + frame::HEADER_LEN;
18
        $self.buf.get_mut().limit(limit)
19
    }};
20
}
21
22
#[derive(Debug)]
23
pub struct FramedWrite<T, B> {
24
    /// Upstream `AsyncWrite`
25
    inner: T,
26
    final_flush_done: bool,
27
28
    encoder: Encoder<B>,
29
}
30
31
#[derive(Debug)]
32
struct Encoder<B> {
33
    /// HPACK encoder
34
    hpack: hpack::Encoder,
35
36
    /// Write buffer
37
    ///
38
    /// TODO: Should this be a ring buffer?
39
    buf: Cursor<BytesMut>,
40
41
    /// Next frame to encode
42
    next: Option<Next<B>>,
43
44
    /// Last data frame
45
    last_data_frame: Option<frame::Data<B>>,
46
47
    /// Max frame size, this is specified by the peer
48
    max_frame_size: FrameSize,
49
50
    /// Chain payloads bigger than this.
51
    chain_threshold: usize,
52
53
    /// Min buffer required to attempt to write a frame
54
    min_buffer_capacity: usize,
55
}
56
57
#[derive(Debug)]
58
enum Next<B> {
59
    Data(frame::Data<B>),
60
    Continuation(frame::Continuation),
61
}
62
63
/// Initialize the connection with this amount of write buffer.
64
///
65
/// The minimum MAX_FRAME_SIZE is 16kb, so always be able to send a HEADERS
66
/// frame that big.
67
const DEFAULT_BUFFER_CAPACITY: usize = 16 * 1_024;
68
69
/// Chain payloads bigger than this when vectored I/O is enabled. The remote
70
/// will never advertise a max frame size less than this (well, the spec says
71
/// the max frame size can't be less than 16kb, so not even close).
72
const CHAIN_THRESHOLD: usize = 256;
73
74
/// Chain payloads bigger than this when vectored I/O is **not** enabled.
75
/// A larger value in this scenario will reduce the number of small and
76
/// fragmented data being sent, and hereby improve the throughput.
77
const CHAIN_THRESHOLD_WITHOUT_VECTORED_IO: usize = 1024;
78
79
// TODO: Make generic
80
impl<T, B> FramedWrite<T, B>
81
where
82
    T: AsyncWrite + Unpin,
83
    B: Buf,
84
{
85
13.1k
    pub fn new(inner: T) -> FramedWrite<T, B> {
86
13.1k
        let chain_threshold = if inner.is_write_vectored() {
87
0
            CHAIN_THRESHOLD
88
        } else {
89
13.1k
            CHAIN_THRESHOLD_WITHOUT_VECTORED_IO
90
        };
91
13.1k
        FramedWrite {
92
13.1k
            inner,
93
13.1k
            final_flush_done: false,
94
13.1k
            encoder: Encoder {
95
13.1k
                hpack: hpack::Encoder::default(),
96
13.1k
                buf: Cursor::new(BytesMut::with_capacity(DEFAULT_BUFFER_CAPACITY)),
97
13.1k
                next: None,
98
13.1k
                last_data_frame: None,
99
13.1k
                max_frame_size: frame::DEFAULT_MAX_FRAME_SIZE,
100
13.1k
                chain_threshold,
101
13.1k
                min_buffer_capacity: chain_threshold + frame::HEADER_LEN,
102
13.1k
            },
103
13.1k
        }
104
13.1k
    }
Unexecuted instantiation: <h2::codec::framed_write::FramedWrite<_, _>>::new
<h2::codec::framed_write::FramedWrite<h2_support::mock::Mock, h2::proto::streams::prioritize::Prioritized<bytes::bytes::Bytes>>>::new
Line
Count
Source
85
411
    pub fn new(inner: T) -> FramedWrite<T, B> {
86
411
        let chain_threshold = if inner.is_write_vectored() {
87
0
            CHAIN_THRESHOLD
88
        } else {
89
411
            CHAIN_THRESHOLD_WITHOUT_VECTORED_IO
90
        };
91
411
        FramedWrite {
92
411
            inner,
93
411
            final_flush_done: false,
94
411
            encoder: Encoder {
95
411
                hpack: hpack::Encoder::default(),
96
411
                buf: Cursor::new(BytesMut::with_capacity(DEFAULT_BUFFER_CAPACITY)),
97
411
                next: None,
98
411
                last_data_frame: None,
99
411
                max_frame_size: frame::DEFAULT_MAX_FRAME_SIZE,
100
411
                chain_threshold,
101
411
                min_buffer_capacity: chain_threshold + frame::HEADER_LEN,
102
411
            },
103
411
        }
104
411
    }
<h2::codec::framed_write::FramedWrite<h2_support::mock::Pipe, bytes::bytes::Bytes>>::new
Line
Count
Source
85
411
    pub fn new(inner: T) -> FramedWrite<T, B> {
86
411
        let chain_threshold = if inner.is_write_vectored() {
87
0
            CHAIN_THRESHOLD
88
        } else {
89
411
            CHAIN_THRESHOLD_WITHOUT_VECTORED_IO
90
        };
91
411
        FramedWrite {
92
411
            inner,
93
411
            final_flush_done: false,
94
411
            encoder: Encoder {
95
411
                hpack: hpack::Encoder::default(),
96
411
                buf: Cursor::new(BytesMut::with_capacity(DEFAULT_BUFFER_CAPACITY)),
97
411
                next: None,
98
411
                last_data_frame: None,
99
411
                max_frame_size: frame::DEFAULT_MAX_FRAME_SIZE,
100
411
                chain_threshold,
101
411
                min_buffer_capacity: chain_threshold + frame::HEADER_LEN,
102
411
            },
103
411
        }
104
411
    }
<h2::codec::framed_write::FramedWrite<fuzz_e2e::MockIo, h2::proto::streams::prioritize::Prioritized<bytes::bytes::Bytes>>>::new
Line
Count
Source
85
12.2k
    pub fn new(inner: T) -> FramedWrite<T, B> {
86
12.2k
        let chain_threshold = if inner.is_write_vectored() {
87
0
            CHAIN_THRESHOLD
88
        } else {
89
12.2k
            CHAIN_THRESHOLD_WITHOUT_VECTORED_IO
90
        };
91
12.2k
        FramedWrite {
92
12.2k
            inner,
93
12.2k
            final_flush_done: false,
94
12.2k
            encoder: Encoder {
95
12.2k
                hpack: hpack::Encoder::default(),
96
12.2k
                buf: Cursor::new(BytesMut::with_capacity(DEFAULT_BUFFER_CAPACITY)),
97
12.2k
                next: None,
98
12.2k
                last_data_frame: None,
99
12.2k
                max_frame_size: frame::DEFAULT_MAX_FRAME_SIZE,
100
12.2k
                chain_threshold,
101
12.2k
                min_buffer_capacity: chain_threshold + frame::HEADER_LEN,
102
12.2k
            },
103
12.2k
        }
104
12.2k
    }
105
106
    /// Returns `Ready` when `send` is able to accept a frame
107
    ///
108
    /// Calling this function may result in the current contents of the buffer
109
    /// to be flushed to `T`.
110
2.59M
    pub fn poll_ready(&mut self, cx: &mut Context) -> Poll<io::Result<()>> {
111
2.59M
        if !self.encoder.has_capacity() {
112
            // Try flushing
113
849k
            ready!(self.flush(cx))?;
114
115
3.31k
            if !self.encoder.has_capacity() {
116
0
                return Poll::Pending;
117
3.31k
            }
118
1.74M
        }
119
120
1.75M
        Poll::Ready(Ok(()))
121
2.59M
    }
Unexecuted instantiation: <h2::codec::framed_write::FramedWrite<_, _>>::poll_ready
<h2::codec::framed_write::FramedWrite<fuzz_e2e::MockIo, h2::proto::streams::prioritize::Prioritized<bytes::bytes::Bytes>>>::poll_ready
Line
Count
Source
110
2.59M
    pub fn poll_ready(&mut self, cx: &mut Context) -> Poll<io::Result<()>> {
111
2.59M
        if !self.encoder.has_capacity() {
112
            // Try flushing
113
849k
            ready!(self.flush(cx))?;
114
115
3.31k
            if !self.encoder.has_capacity() {
116
0
                return Poll::Pending;
117
3.31k
            }
118
1.74M
        }
119
120
1.75M
        Poll::Ready(Ok(()))
121
2.59M
    }
122
123
    /// Buffer a frame.
124
    ///
125
    /// `poll_ready` must be called first to ensure that a frame may be
126
    /// accepted.
127
234k
    pub fn buffer(&mut self, item: Frame<B>) -> Result<(), UserError> {
128
234k
        self.encoder.buffer(item)
129
234k
    }
Unexecuted instantiation: <h2::codec::framed_write::FramedWrite<_, _>>::buffer
<h2::codec::framed_write::FramedWrite<h2_support::mock::Mock, h2::proto::streams::prioritize::Prioritized<bytes::bytes::Bytes>>>::buffer
Line
Count
Source
127
411
    pub fn buffer(&mut self, item: Frame<B>) -> Result<(), UserError> {
128
411
        self.encoder.buffer(item)
129
411
    }
<h2::codec::framed_write::FramedWrite<fuzz_e2e::MockIo, h2::proto::streams::prioritize::Prioritized<bytes::bytes::Bytes>>>::buffer
Line
Count
Source
127
234k
    pub fn buffer(&mut self, item: Frame<B>) -> Result<(), UserError> {
128
234k
        self.encoder.buffer(item)
129
234k
    }
130
131
    /// Flush buffered data to the wire
132
1.62M
    pub fn flush(&mut self, cx: &mut Context) -> Poll<io::Result<()>> {
133
1.62M
        let span = tracing::trace_span!("FramedWrite::flush");
134
1.62M
        let _e = span.enter();
135
136
        loop {
137
1.63M
            while !self.encoder.is_empty() {
138
837k
                match self.encoder.next {
139
837k
                    Some(Next::Data(ref mut frame)) => {
140
837k
                        tracing::trace!(queued_data_frame = true);
141
837k
                        let mut buf = (&mut self.encoder.buf).chain(frame.payload_mut());
142
837k
                        ready!(poll_write_buf(Pin::new(&mut self.inner), cx, &mut buf))?
143
                    }
144
                    _ => {
145
63.0k
                        tracing::trace!(queued_data_frame = false);
146
63.0k
                        ready!(poll_write_buf(
147
63.0k
                            Pin::new(&mut self.inner),
148
63.0k
                            cx,
149
63.0k
                            &mut self.encoder.buf
150
63.0k
                        ))?
151
                    }
152
                };
153
            }
154
155
735k
            match self.encoder.unset_frame() {
156
0
                ControlFlow::Continue => (),
157
735k
                ControlFlow::Break => break,
158
735k
            }
159
735k
        }
160
735k
161
735k
        tracing::trace!("flushing buffer");
162
        // Flush the upstream
163
735k
        ready!(Pin::new(&mut self.inner).poll_flush(cx))?;
164
165
735k
        Poll::Ready(Ok(()))
166
1.62M
    }
Unexecuted instantiation: <h2::codec::framed_write::FramedWrite<_, _>>::flush
<h2::codec::framed_write::FramedWrite<h2_support::mock::Pipe, bytes::bytes::Bytes>>::flush
Line
Count
Source
132
411
    pub fn flush(&mut self, cx: &mut Context) -> Poll<io::Result<()>> {
133
411
        let span = tracing::trace_span!("FramedWrite::flush");
134
411
        let _e = span.enter();
135
136
        loop {
137
411
            while !self.encoder.is_empty() {
138
0
                match self.encoder.next {
139
0
                    Some(Next::Data(ref mut frame)) => {
140
0
                        tracing::trace!(queued_data_frame = true);
141
0
                        let mut buf = (&mut self.encoder.buf).chain(frame.payload_mut());
142
0
                        ready!(poll_write_buf(Pin::new(&mut self.inner), cx, &mut buf))?
143
                    }
144
                    _ => {
145
0
                        tracing::trace!(queued_data_frame = false);
146
0
                        ready!(poll_write_buf(
147
0
                            Pin::new(&mut self.inner),
148
0
                            cx,
149
0
                            &mut self.encoder.buf
150
0
                        ))?
151
                    }
152
                };
153
            }
154
155
411
            match self.encoder.unset_frame() {
156
0
                ControlFlow::Continue => (),
157
411
                ControlFlow::Break => break,
158
411
            }
159
411
        }
160
411
161
411
        tracing::trace!("flushing buffer");
162
        // Flush the upstream
163
411
        ready!(Pin::new(&mut self.inner).poll_flush(cx))?;
164
165
411
        Poll::Ready(Ok(()))
166
411
    }
<h2::codec::framed_write::FramedWrite<fuzz_e2e::MockIo, h2::proto::streams::prioritize::Prioritized<bytes::bytes::Bytes>>>::flush
Line
Count
Source
132
1.62M
    pub fn flush(&mut self, cx: &mut Context) -> Poll<io::Result<()>> {
133
1.62M
        let span = tracing::trace_span!("FramedWrite::flush");
134
1.62M
        let _e = span.enter();
135
136
        loop {
137
1.63M
            while !self.encoder.is_empty() {
138
837k
                match self.encoder.next {
139
837k
                    Some(Next::Data(ref mut frame)) => {
140
837k
                        tracing::trace!(queued_data_frame = true);
141
837k
                        let mut buf = (&mut self.encoder.buf).chain(frame.payload_mut());
142
837k
                        ready!(poll_write_buf(Pin::new(&mut self.inner), cx, &mut buf))?
143
                    }
144
                    _ => {
145
63.0k
                        tracing::trace!(queued_data_frame = false);
146
63.0k
                        ready!(poll_write_buf(
147
63.0k
                            Pin::new(&mut self.inner),
148
63.0k
                            cx,
149
63.0k
                            &mut self.encoder.buf
150
63.0k
                        ))?
151
                    }
152
                };
153
            }
154
155
735k
            match self.encoder.unset_frame() {
156
0
                ControlFlow::Continue => (),
157
735k
                ControlFlow::Break => break,
158
735k
            }
159
735k
        }
160
735k
161
735k
        tracing::trace!("flushing buffer");
162
        // Flush the upstream
163
735k
        ready!(Pin::new(&mut self.inner).poll_flush(cx))?;
164
165
735k
        Poll::Ready(Ok(()))
166
1.62M
    }
167
168
    /// Close the codec
169
11.3k
    pub fn shutdown(&mut self, cx: &mut Context) -> Poll<io::Result<()>> {
170
11.3k
        if !self.final_flush_done {
171
11.3k
            ready!(self.flush(cx))?;
172
1.45k
            self.final_flush_done = true;
173
0
        }
174
1.45k
        Pin::new(&mut self.inner).poll_shutdown(cx)
175
11.3k
    }
Unexecuted instantiation: <h2::codec::framed_write::FramedWrite<_, _>>::shutdown
<h2::codec::framed_write::FramedWrite<h2_support::mock::Pipe, bytes::bytes::Bytes>>::shutdown
Line
Count
Source
169
411
    pub fn shutdown(&mut self, cx: &mut Context) -> Poll<io::Result<()>> {
170
411
        if !self.final_flush_done {
171
411
            ready!(self.flush(cx))?;
172
411
            self.final_flush_done = true;
173
0
        }
174
411
        Pin::new(&mut self.inner).poll_shutdown(cx)
175
411
    }
<h2::codec::framed_write::FramedWrite<fuzz_e2e::MockIo, h2::proto::streams::prioritize::Prioritized<bytes::bytes::Bytes>>>::shutdown
Line
Count
Source
169
10.9k
    pub fn shutdown(&mut self, cx: &mut Context) -> Poll<io::Result<()>> {
170
10.9k
        if !self.final_flush_done {
171
10.9k
            ready!(self.flush(cx))?;
172
1.04k
            self.final_flush_done = true;
173
0
        }
174
1.04k
        Pin::new(&mut self.inner).poll_shutdown(cx)
175
10.9k
    }
176
}
177
178
#[must_use]
179
enum ControlFlow {
180
    Continue,
181
    Break,
182
}
183
184
impl<B> Encoder<B>
185
where
186
    B: Buf,
187
{
188
735k
    fn unset_frame(&mut self) -> ControlFlow {
189
735k
        // Clear internal buffer
190
735k
        self.buf.set_position(0);
191
735k
        self.buf.get_mut().clear();
192
735k
193
735k
        // The data frame has been written, so unset it
194
735k
        match self.next.take() {
195
3.18k
            Some(Next::Data(frame)) => {
196
3.18k
                self.last_data_frame = Some(frame);
197
3.18k
                debug_assert!(self.is_empty());
198
3.18k
                ControlFlow::Break
199
            }
200
0
            Some(Next::Continuation(frame)) => {
201
0
                // Buffer the continuation frame, then try to write again
202
0
                let mut buf = limited_write_buf!(self);
203
0
                if let Some(continuation) = frame.encode(&mut buf) {
204
0
                    self.next = Some(Next::Continuation(continuation));
205
0
                }
206
0
                ControlFlow::Continue
207
            }
208
732k
            None => ControlFlow::Break,
209
        }
210
735k
    }
Unexecuted instantiation: <h2::codec::framed_write::Encoder<_>>::unset_frame
<h2::codec::framed_write::Encoder<bytes::bytes::Bytes>>::unset_frame
Line
Count
Source
188
411
    fn unset_frame(&mut self) -> ControlFlow {
189
411
        // Clear internal buffer
190
411
        self.buf.set_position(0);
191
411
        self.buf.get_mut().clear();
192
411
193
411
        // The data frame has been written, so unset it
194
411
        match self.next.take() {
195
0
            Some(Next::Data(frame)) => {
196
0
                self.last_data_frame = Some(frame);
197
0
                debug_assert!(self.is_empty());
198
0
                ControlFlow::Break
199
            }
200
0
            Some(Next::Continuation(frame)) => {
201
0
                // Buffer the continuation frame, then try to write again
202
0
                let mut buf = limited_write_buf!(self);
203
0
                if let Some(continuation) = frame.encode(&mut buf) {
204
0
                    self.next = Some(Next::Continuation(continuation));
205
0
                }
206
0
                ControlFlow::Continue
207
            }
208
411
            None => ControlFlow::Break,
209
        }
210
411
    }
<h2::codec::framed_write::Encoder<h2::proto::streams::prioritize::Prioritized<bytes::bytes::Bytes>>>::unset_frame
Line
Count
Source
188
735k
    fn unset_frame(&mut self) -> ControlFlow {
189
735k
        // Clear internal buffer
190
735k
        self.buf.set_position(0);
191
735k
        self.buf.get_mut().clear();
192
735k
193
735k
        // The data frame has been written, so unset it
194
735k
        match self.next.take() {
195
3.18k
            Some(Next::Data(frame)) => {
196
3.18k
                self.last_data_frame = Some(frame);
197
3.18k
                debug_assert!(self.is_empty());
198
3.18k
                ControlFlow::Break
199
            }
200
0
            Some(Next::Continuation(frame)) => {
201
0
                // Buffer the continuation frame, then try to write again
202
0
                let mut buf = limited_write_buf!(self);
203
0
                if let Some(continuation) = frame.encode(&mut buf) {
204
0
                    self.next = Some(Next::Continuation(continuation));
205
0
                }
206
0
                ControlFlow::Continue
207
            }
208
732k
            None => ControlFlow::Break,
209
        }
210
735k
    }
211
212
234k
    fn buffer(&mut self, item: Frame<B>) -> Result<(), UserError> {
213
234k
        // Ensure that we have enough capacity to accept the write.
214
234k
        assert!(self.has_capacity());
215
234k
        let span = tracing::trace_span!("FramedWrite::buffer", frame = ?item);
216
234k
        let _e = span.enter();
217
234k
218
234k
        tracing::debug!(frame = ?item, "send");
219
220
234k
        match item {
221
19.1k
            Frame::Data(mut v) => {
222
19.1k
                // Ensure that the payload is not greater than the max frame.
223
19.1k
                let len = v.payload().remaining();
224
19.1k
225
19.1k
                if len > self.max_frame_size() {
226
0
                    return Err(PayloadTooBig);
227
19.1k
                }
228
19.1k
229
19.1k
                if len >= self.chain_threshold {
230
4.36k
                    let head = v.head();
231
4.36k
232
4.36k
                    // Encode the frame head to the buffer
233
4.36k
                    head.encode(len, self.buf.get_mut());
234
4.36k
235
4.36k
                    if self.buf.get_ref().remaining() < self.chain_threshold {
236
3.03k
                        let extra_bytes = self.chain_threshold - self.buf.remaining();
237
3.03k
                        self.buf.get_mut().put(v.payload_mut().take(extra_bytes));
238
3.03k
                    }
239
240
                    // Save the data frame
241
4.36k
                    self.next = Some(Next::Data(v));
242
                } else {
243
14.7k
                    v.encode_chunk(self.buf.get_mut());
244
14.7k
245
14.7k
                    // The chunk has been fully encoded, so there is no need to
246
14.7k
                    // keep it around
247
14.7k
                    assert_eq!(v.payload().remaining(), 0, "chunk not fully encoded");
248
249
                    // Save off the last frame...
250
14.7k
                    self.last_data_frame = Some(v);
251
                }
252
            }
253
188k
            Frame::Headers(v) => {
254
188k
                let mut buf = limited_write_buf!(self);
255
188k
                if let Some(continuation) = v.encode(&mut self.hpack, &mut buf) {
256
0
                    self.next = Some(Next::Continuation(continuation));
257
188k
                }
258
            }
259
0
            Frame::PushPromise(v) => {
260
0
                let mut buf = limited_write_buf!(self);
261
0
                if let Some(continuation) = v.encode(&mut self.hpack, &mut buf) {
262
0
                    self.next = Some(Next::Continuation(continuation));
263
0
                }
264
            }
265
20.0k
            Frame::Settings(v) => {
266
20.0k
                v.encode(self.buf.get_mut());
267
20.0k
                tracing::trace!(rem = self.buf.remaining(), "encoded settings");
268
            }
269
5.77k
            Frame::GoAway(v) => {
270
5.77k
                v.encode(self.buf.get_mut());
271
5.77k
                tracing::trace!(rem = self.buf.remaining(), "encoded go_away");
272
            }
273
219
            Frame::Ping(v) => {
274
219
                v.encode(self.buf.get_mut());
275
219
                tracing::trace!(rem = self.buf.remaining(), "encoded ping");
276
            }
277
38
            Frame::WindowUpdate(v) => {
278
38
                v.encode(self.buf.get_mut());
279
38
                tracing::trace!(rem = self.buf.remaining(), "encoded window_update");
280
            }
281
282
            Frame::Priority(_) => {
283
                /*
284
                v.encode(self.buf.get_mut());
285
                tracing::trace!("encoded priority; rem={:?}", self.buf.remaining());
286
                */
287
0
                unimplemented!();
288
            }
289
1.59k
            Frame::Reset(v) => {
290
1.59k
                v.encode(self.buf.get_mut());
291
1.59k
                tracing::trace!(rem = self.buf.remaining(), "encoded reset");
292
            }
293
        }
294
295
234k
        Ok(())
296
234k
    }
Unexecuted instantiation: <h2::codec::framed_write::Encoder<_>>::buffer
<h2::codec::framed_write::Encoder<h2::proto::streams::prioritize::Prioritized<bytes::bytes::Bytes>>>::buffer
Line
Count
Source
212
411
    fn buffer(&mut self, item: Frame<B>) -> Result<(), UserError> {
213
411
        // Ensure that we have enough capacity to accept the write.
214
411
        assert!(self.has_capacity());
215
411
        let span = tracing::trace_span!("FramedWrite::buffer", frame = ?item);
216
411
        let _e = span.enter();
217
411
218
411
        tracing::debug!(frame = ?item, "send");
219
220
411
        match item {
221
0
            Frame::Data(mut v) => {
222
0
                // Ensure that the payload is not greater than the max frame.
223
0
                let len = v.payload().remaining();
224
0
225
0
                if len > self.max_frame_size() {
226
0
                    return Err(PayloadTooBig);
227
0
                }
228
0
229
0
                if len >= self.chain_threshold {
230
0
                    let head = v.head();
231
0
232
0
                    // Encode the frame head to the buffer
233
0
                    head.encode(len, self.buf.get_mut());
234
0
235
0
                    if self.buf.get_ref().remaining() < self.chain_threshold {
236
0
                        let extra_bytes = self.chain_threshold - self.buf.remaining();
237
0
                        self.buf.get_mut().put(v.payload_mut().take(extra_bytes));
238
0
                    }
239
240
                    // Save the data frame
241
0
                    self.next = Some(Next::Data(v));
242
                } else {
243
0
                    v.encode_chunk(self.buf.get_mut());
244
0
245
0
                    // The chunk has been fully encoded, so there is no need to
246
0
                    // keep it around
247
0
                    assert_eq!(v.payload().remaining(), 0, "chunk not fully encoded");
248
249
                    // Save off the last frame...
250
0
                    self.last_data_frame = Some(v);
251
                }
252
            }
253
0
            Frame::Headers(v) => {
254
0
                let mut buf = limited_write_buf!(self);
255
0
                if let Some(continuation) = v.encode(&mut self.hpack, &mut buf) {
256
0
                    self.next = Some(Next::Continuation(continuation));
257
0
                }
258
            }
259
0
            Frame::PushPromise(v) => {
260
0
                let mut buf = limited_write_buf!(self);
261
0
                if let Some(continuation) = v.encode(&mut self.hpack, &mut buf) {
262
0
                    self.next = Some(Next::Continuation(continuation));
263
0
                }
264
            }
265
411
            Frame::Settings(v) => {
266
411
                v.encode(self.buf.get_mut());
267
411
                tracing::trace!(rem = self.buf.remaining(), "encoded settings");
268
            }
269
0
            Frame::GoAway(v) => {
270
0
                v.encode(self.buf.get_mut());
271
0
                tracing::trace!(rem = self.buf.remaining(), "encoded go_away");
272
            }
273
0
            Frame::Ping(v) => {
274
0
                v.encode(self.buf.get_mut());
275
0
                tracing::trace!(rem = self.buf.remaining(), "encoded ping");
276
            }
277
0
            Frame::WindowUpdate(v) => {
278
0
                v.encode(self.buf.get_mut());
279
0
                tracing::trace!(rem = self.buf.remaining(), "encoded window_update");
280
            }
281
282
            Frame::Priority(_) => {
283
                /*
284
                v.encode(self.buf.get_mut());
285
                tracing::trace!("encoded priority; rem={:?}", self.buf.remaining());
286
                */
287
0
                unimplemented!();
288
            }
289
0
            Frame::Reset(v) => {
290
0
                v.encode(self.buf.get_mut());
291
0
                tracing::trace!(rem = self.buf.remaining(), "encoded reset");
292
            }
293
        }
294
295
411
        Ok(())
296
411
    }
<h2::codec::framed_write::Encoder<h2::proto::streams::prioritize::Prioritized<bytes::bytes::Bytes>>>::buffer
Line
Count
Source
212
234k
    fn buffer(&mut self, item: Frame<B>) -> Result<(), UserError> {
213
234k
        // Ensure that we have enough capacity to accept the write.
214
234k
        assert!(self.has_capacity());
215
234k
        let span = tracing::trace_span!("FramedWrite::buffer", frame = ?item);
216
234k
        let _e = span.enter();
217
234k
218
234k
        tracing::debug!(frame = ?item, "send");
219
220
234k
        match item {
221
19.1k
            Frame::Data(mut v) => {
222
19.1k
                // Ensure that the payload is not greater than the max frame.
223
19.1k
                let len = v.payload().remaining();
224
19.1k
225
19.1k
                if len > self.max_frame_size() {
226
0
                    return Err(PayloadTooBig);
227
19.1k
                }
228
19.1k
229
19.1k
                if len >= self.chain_threshold {
230
4.36k
                    let head = v.head();
231
4.36k
232
4.36k
                    // Encode the frame head to the buffer
233
4.36k
                    head.encode(len, self.buf.get_mut());
234
4.36k
235
4.36k
                    if self.buf.get_ref().remaining() < self.chain_threshold {
236
3.03k
                        let extra_bytes = self.chain_threshold - self.buf.remaining();
237
3.03k
                        self.buf.get_mut().put(v.payload_mut().take(extra_bytes));
238
3.03k
                    }
239
240
                    // Save the data frame
241
4.36k
                    self.next = Some(Next::Data(v));
242
                } else {
243
14.7k
                    v.encode_chunk(self.buf.get_mut());
244
14.7k
245
14.7k
                    // The chunk has been fully encoded, so there is no need to
246
14.7k
                    // keep it around
247
14.7k
                    assert_eq!(v.payload().remaining(), 0, "chunk not fully encoded");
248
249
                    // Save off the last frame...
250
14.7k
                    self.last_data_frame = Some(v);
251
                }
252
            }
253
188k
            Frame::Headers(v) => {
254
188k
                let mut buf = limited_write_buf!(self);
255
188k
                if let Some(continuation) = v.encode(&mut self.hpack, &mut buf) {
256
0
                    self.next = Some(Next::Continuation(continuation));
257
188k
                }
258
            }
259
0
            Frame::PushPromise(v) => {
260
0
                let mut buf = limited_write_buf!(self);
261
0
                if let Some(continuation) = v.encode(&mut self.hpack, &mut buf) {
262
0
                    self.next = Some(Next::Continuation(continuation));
263
0
                }
264
            }
265
19.6k
            Frame::Settings(v) => {
266
19.6k
                v.encode(self.buf.get_mut());
267
19.6k
                tracing::trace!(rem = self.buf.remaining(), "encoded settings");
268
            }
269
5.77k
            Frame::GoAway(v) => {
270
5.77k
                v.encode(self.buf.get_mut());
271
5.77k
                tracing::trace!(rem = self.buf.remaining(), "encoded go_away");
272
            }
273
219
            Frame::Ping(v) => {
274
219
                v.encode(self.buf.get_mut());
275
219
                tracing::trace!(rem = self.buf.remaining(), "encoded ping");
276
            }
277
38
            Frame::WindowUpdate(v) => {
278
38
                v.encode(self.buf.get_mut());
279
38
                tracing::trace!(rem = self.buf.remaining(), "encoded window_update");
280
            }
281
282
            Frame::Priority(_) => {
283
                /*
284
                v.encode(self.buf.get_mut());
285
                tracing::trace!("encoded priority; rem={:?}", self.buf.remaining());
286
                */
287
0
                unimplemented!();
288
            }
289
1.59k
            Frame::Reset(v) => {
290
1.59k
                v.encode(self.buf.get_mut());
291
1.59k
                tracing::trace!(rem = self.buf.remaining(), "encoded reset");
292
            }
293
        }
294
295
234k
        Ok(())
296
234k
    }
297
298
2.83M
    fn has_capacity(&self) -> bool {
299
2.83M
        self.next.is_none()
300
2.00M
            && (self.buf.get_ref().capacity() - self.buf.get_ref().len()
301
2.00M
                >= self.min_buffer_capacity)
302
2.83M
    }
Unexecuted instantiation: <h2::codec::framed_write::Encoder<_>>::has_capacity
<h2::codec::framed_write::Encoder<h2::proto::streams::prioritize::Prioritized<bytes::bytes::Bytes>>>::has_capacity
Line
Count
Source
298
411
    fn has_capacity(&self) -> bool {
299
411
        self.next.is_none()
300
411
            && (self.buf.get_ref().capacity() - self.buf.get_ref().len()
301
411
                >= self.min_buffer_capacity)
302
411
    }
<h2::codec::framed_write::Encoder<h2::proto::streams::prioritize::Prioritized<bytes::bytes::Bytes>>>::has_capacity
Line
Count
Source
298
2.83M
    fn has_capacity(&self) -> bool {
299
2.83M
        self.next.is_none()
300
2.00M
            && (self.buf.get_ref().capacity() - self.buf.get_ref().len()
301
2.00M
                >= self.min_buffer_capacity)
302
2.83M
    }
303
304
1.63M
    fn is_empty(&self) -> bool {
305
840k
        match self.next {
306
840k
            Some(Next::Data(ref frame)) => !frame.payload().has_remaining(),
307
795k
            _ => !self.buf.has_remaining(),
308
        }
309
1.63M
    }
Unexecuted instantiation: <h2::codec::framed_write::Encoder<_>>::is_empty
<h2::codec::framed_write::Encoder<bytes::bytes::Bytes>>::is_empty
Line
Count
Source
304
411
    fn is_empty(&self) -> bool {
305
0
        match self.next {
306
0
            Some(Next::Data(ref frame)) => !frame.payload().has_remaining(),
307
411
            _ => !self.buf.has_remaining(),
308
        }
309
411
    }
<h2::codec::framed_write::Encoder<h2::proto::streams::prioritize::Prioritized<bytes::bytes::Bytes>>>::is_empty
Line
Count
Source
304
1.63M
    fn is_empty(&self) -> bool {
305
840k
        match self.next {
306
840k
            Some(Next::Data(ref frame)) => !frame.payload().has_remaining(),
307
795k
            _ => !self.buf.has_remaining(),
308
        }
309
1.63M
    }
310
}
311
312
impl<B> Encoder<B> {
313
972k
    fn max_frame_size(&self) -> usize {
314
972k
        self.max_frame_size as usize
315
972k
    }
Unexecuted instantiation: <h2::codec::framed_write::Encoder<_>>::max_frame_size
Unexecuted instantiation: <h2::codec::framed_write::Encoder<h2::proto::streams::prioritize::Prioritized<bytes::bytes::Bytes>>>::max_frame_size
Unexecuted instantiation: <h2::codec::framed_write::Encoder<bytes::bytes::Bytes>>::max_frame_size
<h2::codec::framed_write::Encoder<h2::proto::streams::prioritize::Prioritized<bytes::bytes::Bytes>>>::max_frame_size
Line
Count
Source
313
972k
    fn max_frame_size(&self) -> usize {
314
972k
        self.max_frame_size as usize
315
972k
    }
316
}
317
318
impl<T, B> FramedWrite<T, B> {
319
    /// Returns the max frame size that can be sent
320
764k
    pub fn max_frame_size(&self) -> usize {
321
764k
        self.encoder.max_frame_size()
322
764k
    }
Unexecuted instantiation: <h2::codec::framed_write::FramedWrite<_, _>>::max_frame_size
<h2::codec::framed_write::FramedWrite<fuzz_e2e::MockIo, h2::proto::streams::prioritize::Prioritized<bytes::bytes::Bytes>>>::max_frame_size
Line
Count
Source
320
764k
    pub fn max_frame_size(&self) -> usize {
321
764k
        self.encoder.max_frame_size()
322
764k
    }
323
324
    /// Set the peer's max frame size.
325
320
    pub fn set_max_frame_size(&mut self, val: usize) {
326
320
        assert!(val <= frame::MAX_MAX_FRAME_SIZE as usize);
327
320
        self.encoder.max_frame_size = val as FrameSize;
328
320
    }
Unexecuted instantiation: <h2::codec::framed_write::FramedWrite<_, _>>::set_max_frame_size
<h2::codec::framed_write::FramedWrite<fuzz_e2e::MockIo, h2::proto::streams::prioritize::Prioritized<bytes::bytes::Bytes>>>::set_max_frame_size
Line
Count
Source
325
320
    pub fn set_max_frame_size(&mut self, val: usize) {
326
320
        assert!(val <= frame::MAX_MAX_FRAME_SIZE as usize);
327
320
        self.encoder.max_frame_size = val as FrameSize;
328
320
    }
329
330
    /// Set the peer's header table size.
331
1.67k
    pub fn set_header_table_size(&mut self, val: usize) {
332
1.67k
        self.encoder.hpack.update_max_size(val);
333
1.67k
    }
Unexecuted instantiation: <h2::codec::framed_write::FramedWrite<_, _>>::set_header_table_size
<h2::codec::framed_write::FramedWrite<fuzz_e2e::MockIo, h2::proto::streams::prioritize::Prioritized<bytes::bytes::Bytes>>>::set_header_table_size
Line
Count
Source
331
1.67k
    pub fn set_header_table_size(&mut self, val: usize) {
332
1.67k
        self.encoder.hpack.update_max_size(val);
333
1.67k
    }
334
335
    /// Retrieve the last data frame that has been sent
336
1.70M
    pub fn take_last_data_frame(&mut self) -> Option<frame::Data<B>> {
337
1.70M
        self.encoder.last_data_frame.take()
338
1.70M
    }
Unexecuted instantiation: <h2::codec::framed_write::FramedWrite<_, _>>::take_last_data_frame
<h2::codec::framed_write::FramedWrite<fuzz_e2e::MockIo, h2::proto::streams::prioritize::Prioritized<bytes::bytes::Bytes>>>::take_last_data_frame
Line
Count
Source
336
1.70M
    pub fn take_last_data_frame(&mut self) -> Option<frame::Data<B>> {
337
1.70M
        self.encoder.last_data_frame.take()
338
1.70M
    }
339
340
411
    pub fn get_mut(&mut self) -> &mut T {
341
411
        &mut self.inner
342
411
    }
Unexecuted instantiation: <h2::codec::framed_write::FramedWrite<_, _>>::get_mut
<h2::codec::framed_write::FramedWrite<h2_support::mock::Pipe, bytes::bytes::Bytes>>::get_mut
Line
Count
Source
340
411
    pub fn get_mut(&mut self) -> &mut T {
341
411
        &mut self.inner
342
411
    }
343
}
344
345
impl<T: AsyncRead + Unpin, B> AsyncRead for FramedWrite<T, B> {
346
1.62M
    fn poll_read(
347
1.62M
        mut self: Pin<&mut Self>,
348
1.62M
        cx: &mut Context<'_>,
349
1.62M
        buf: &mut ReadBuf,
350
1.62M
    ) -> Poll<io::Result<()>> {
351
1.62M
        Pin::new(&mut self.inner).poll_read(cx, buf)
352
1.62M
    }
Unexecuted instantiation: <h2::codec::framed_write::FramedWrite<_, _> as tokio::io::async_read::AsyncRead>::poll_read
Unexecuted instantiation: <h2::codec::framed_write::FramedWrite<h2_support::mock::Pipe, bytes::bytes::Bytes> as tokio::io::async_read::AsyncRead>::poll_read
<h2::codec::framed_write::FramedWrite<fuzz_e2e::MockIo, h2::proto::streams::prioritize::Prioritized<bytes::bytes::Bytes>> as tokio::io::async_read::AsyncRead>::poll_read
Line
Count
Source
346
1.62M
    fn poll_read(
347
1.62M
        mut self: Pin<&mut Self>,
348
1.62M
        cx: &mut Context<'_>,
349
1.62M
        buf: &mut ReadBuf,
350
1.62M
    ) -> Poll<io::Result<()>> {
351
1.62M
        Pin::new(&mut self.inner).poll_read(cx, buf)
352
1.62M
    }
353
}
354
355
// We never project the Pin to `B`.
356
impl<T: Unpin, B> Unpin for FramedWrite<T, B> {}
357
358
#[cfg(feature = "unstable")]
359
mod unstable {
360
    use super::*;
361
362
    impl<T, B> FramedWrite<T, B> {
363
0
        pub fn get_ref(&self) -> &T {
364
0
            &self.inner
365
0
        }
366
    }
367
}