Coverage Report

Created: 2026-09-14 06:40

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/h2/src/codec/framed_write.rs
Line
Count
Source
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.5k
    pub fn new(inner: T) -> FramedWrite<T, B> {
86
13.5k
        let chain_threshold = if inner.is_write_vectored() {
87
0
            CHAIN_THRESHOLD
88
        } else {
89
13.5k
            CHAIN_THRESHOLD_WITHOUT_VECTORED_IO
90
        };
91
13.5k
        FramedWrite {
92
13.5k
            inner,
93
13.5k
            final_flush_done: false,
94
13.5k
            encoder: Encoder {
95
13.5k
                hpack: hpack::Encoder::default(),
96
13.5k
                buf: Cursor::new(BytesMut::with_capacity(DEFAULT_BUFFER_CAPACITY)),
97
13.5k
                next: None,
98
13.5k
                last_data_frame: None,
99
13.5k
                max_frame_size: frame::DEFAULT_MAX_FRAME_SIZE,
100
13.5k
                chain_threshold,
101
13.5k
                min_buffer_capacity: chain_threshold + frame::HEADER_LEN,
102
13.5k
            },
103
13.5k
        }
104
13.5k
    }
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
816
    pub fn new(inner: T) -> FramedWrite<T, B> {
86
816
        let chain_threshold = if inner.is_write_vectored() {
87
0
            CHAIN_THRESHOLD
88
        } else {
89
816
            CHAIN_THRESHOLD_WITHOUT_VECTORED_IO
90
        };
91
816
        FramedWrite {
92
816
            inner,
93
816
            final_flush_done: false,
94
816
            encoder: Encoder {
95
816
                hpack: hpack::Encoder::default(),
96
816
                buf: Cursor::new(BytesMut::with_capacity(DEFAULT_BUFFER_CAPACITY)),
97
816
                next: None,
98
816
                last_data_frame: None,
99
816
                max_frame_size: frame::DEFAULT_MAX_FRAME_SIZE,
100
816
                chain_threshold,
101
816
                min_buffer_capacity: chain_threshold + frame::HEADER_LEN,
102
816
            },
103
816
        }
104
816
    }
<h2::codec::framed_write::FramedWrite<h2_support::mock::Pipe, bytes::bytes::Bytes>>::new
Line
Count
Source
85
816
    pub fn new(inner: T) -> FramedWrite<T, B> {
86
816
        let chain_threshold = if inner.is_write_vectored() {
87
0
            CHAIN_THRESHOLD
88
        } else {
89
816
            CHAIN_THRESHOLD_WITHOUT_VECTORED_IO
90
        };
91
816
        FramedWrite {
92
816
            inner,
93
816
            final_flush_done: false,
94
816
            encoder: Encoder {
95
816
                hpack: hpack::Encoder::default(),
96
816
                buf: Cursor::new(BytesMut::with_capacity(DEFAULT_BUFFER_CAPACITY)),
97
816
                next: None,
98
816
                last_data_frame: None,
99
816
                max_frame_size: frame::DEFAULT_MAX_FRAME_SIZE,
100
816
                chain_threshold,
101
816
                min_buffer_capacity: chain_threshold + frame::HEADER_LEN,
102
816
            },
103
816
        }
104
816
    }
<h2::codec::framed_write::FramedWrite<fuzz_e2e::MockIo, h2::proto::streams::prioritize::Prioritized<bytes::bytes::Bytes>>>::new
Line
Count
Source
85
11.9k
    pub fn new(inner: T) -> FramedWrite<T, B> {
86
11.9k
        let chain_threshold = if inner.is_write_vectored() {
87
0
            CHAIN_THRESHOLD
88
        } else {
89
11.9k
            CHAIN_THRESHOLD_WITHOUT_VECTORED_IO
90
        };
91
11.9k
        FramedWrite {
92
11.9k
            inner,
93
11.9k
            final_flush_done: false,
94
11.9k
            encoder: Encoder {
95
11.9k
                hpack: hpack::Encoder::default(),
96
11.9k
                buf: Cursor::new(BytesMut::with_capacity(DEFAULT_BUFFER_CAPACITY)),
97
11.9k
                next: None,
98
11.9k
                last_data_frame: None,
99
11.9k
                max_frame_size: frame::DEFAULT_MAX_FRAME_SIZE,
100
11.9k
                chain_threshold,
101
11.9k
                min_buffer_capacity: chain_threshold + frame::HEADER_LEN,
102
11.9k
            },
103
11.9k
        }
104
11.9k
    }
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
1.21M
    pub fn poll_ready(&mut self, cx: &mut Context) -> Poll<io::Result<()>> {
111
1.21M
        if !self.encoder.has_capacity() {
112
            // Try flushing
113
740k
            ready!(self.flush(cx))?;
114
115
2.08k
            if !self.encoder.has_capacity() {
116
0
                return Poll::Pending;
117
2.08k
            }
118
470k
        }
119
120
472k
        Poll::Ready(Ok(()))
121
1.21M
    }
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
1.21M
    pub fn poll_ready(&mut self, cx: &mut Context) -> Poll<io::Result<()>> {
111
1.21M
        if !self.encoder.has_capacity() {
112
            // Try flushing
113
740k
            ready!(self.flush(cx))?;
114
115
2.08k
            if !self.encoder.has_capacity() {
116
0
                return Poll::Pending;
117
2.08k
            }
118
470k
        }
119
120
472k
        Poll::Ready(Ok(()))
121
1.21M
    }
122
123
    /// Returns whether a frame can be buffered without first flushing the
124
    /// underlying I/O object.
125
1.13M
    pub(crate) fn has_capacity(&self) -> bool {
126
1.13M
        self.encoder.has_capacity()
127
1.13M
    }
Unexecuted instantiation: <h2::codec::framed_write::FramedWrite<_, _>>::has_capacity
<h2::codec::framed_write::FramedWrite<fuzz_e2e::MockIo, h2::proto::streams::prioritize::Prioritized<bytes::bytes::Bytes>>>::has_capacity
Line
Count
Source
125
1.13M
    pub(crate) fn has_capacity(&self) -> bool {
126
1.13M
        self.encoder.has_capacity()
127
1.13M
    }
128
129
    /// Buffer a frame.
130
    ///
131
    /// `poll_ready` must be called first to ensure that a frame may be
132
    /// accepted.
133
242k
    pub fn buffer(&mut self, item: Frame<B>) -> Result<(), UserError> {
134
242k
        self.encoder.buffer(item)
135
242k
    }
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
133
816
    pub fn buffer(&mut self, item: Frame<B>) -> Result<(), UserError> {
134
816
        self.encoder.buffer(item)
135
816
    }
<h2::codec::framed_write::FramedWrite<fuzz_e2e::MockIo, h2::proto::streams::prioritize::Prioritized<bytes::bytes::Bytes>>>::buffer
Line
Count
Source
133
241k
    pub fn buffer(&mut self, item: Frame<B>) -> Result<(), UserError> {
134
241k
        self.encoder.buffer(item)
135
241k
    }
136
137
    /// Flush buffered data to the wire
138
1.20M
    pub fn flush(&mut self, cx: &mut Context) -> Poll<io::Result<()>> {
139
1.20M
        let span = tracing::trace_span!("FramedWrite::flush");
140
1.20M
        let _e = span.enter();
141
142
        loop {
143
1.21M
            while !self.encoder.is_empty() {
144
743k
                let n = match self.encoder.next {
145
743k
                    Some(Next::Data(ref mut frame)) => {
146
743k
                        tracing::trace!(queued_data_frame = true);
147
743k
                        let mut buf = (&mut self.encoder.buf).chain(frame.payload_mut());
148
743k
                        ready!(poll_write_buf(Pin::new(&mut self.inner), cx, &mut buf))?
149
                    }
150
                    _ => {
151
220k
                        tracing::trace!(queued_data_frame = false);
152
220k
                        ready!(poll_write_buf(
153
220k
                            Pin::new(&mut self.inner),
154
220k
                            cx,
155
220k
                            &mut self.encoder.buf
156
220k
                        ))?
157
                    }
158
                };
159
9.66k
                if n == 0 {
160
                    // No progress is possible; retrying would busy-loop.
161
0
                    tracing::trace!("write returned zero, but non-zero bytes remaining");
162
0
                    return Poll::Ready(Err(io::ErrorKind::WriteZero.into()));
163
9.66k
                }
164
            }
165
166
253k
            match self.encoder.unset_frame() {
167
0
                ControlFlow::Continue => (),
168
253k
                ControlFlow::Break => break,
169
            }
170
        }
171
172
253k
        tracing::trace!("flushing buffer");
173
        // Flush the upstream
174
253k
        ready!(Pin::new(&mut self.inner).poll_flush(cx))?;
175
176
253k
        Poll::Ready(Ok(()))
177
1.20M
    }
Unexecuted instantiation: <h2::codec::framed_write::FramedWrite<_, _>>::flush
<h2::codec::framed_write::FramedWrite<h2_support::mock::Pipe, bytes::bytes::Bytes>>::flush
Line
Count
Source
138
816
    pub fn flush(&mut self, cx: &mut Context) -> Poll<io::Result<()>> {
139
816
        let span = tracing::trace_span!("FramedWrite::flush");
140
816
        let _e = span.enter();
141
142
        loop {
143
816
            while !self.encoder.is_empty() {
144
0
                let n = match self.encoder.next {
145
0
                    Some(Next::Data(ref mut frame)) => {
146
0
                        tracing::trace!(queued_data_frame = true);
147
0
                        let mut buf = (&mut self.encoder.buf).chain(frame.payload_mut());
148
0
                        ready!(poll_write_buf(Pin::new(&mut self.inner), cx, &mut buf))?
149
                    }
150
                    _ => {
151
0
                        tracing::trace!(queued_data_frame = false);
152
0
                        ready!(poll_write_buf(
153
0
                            Pin::new(&mut self.inner),
154
0
                            cx,
155
0
                            &mut self.encoder.buf
156
0
                        ))?
157
                    }
158
                };
159
0
                if n == 0 {
160
                    // No progress is possible; retrying would busy-loop.
161
0
                    tracing::trace!("write returned zero, but non-zero bytes remaining");
162
0
                    return Poll::Ready(Err(io::ErrorKind::WriteZero.into()));
163
0
                }
164
            }
165
166
816
            match self.encoder.unset_frame() {
167
0
                ControlFlow::Continue => (),
168
816
                ControlFlow::Break => break,
169
            }
170
        }
171
172
816
        tracing::trace!("flushing buffer");
173
        // Flush the upstream
174
816
        ready!(Pin::new(&mut self.inner).poll_flush(cx))?;
175
176
816
        Poll::Ready(Ok(()))
177
816
    }
<h2::codec::framed_write::FramedWrite<fuzz_e2e::MockIo, h2::proto::streams::prioritize::Prioritized<bytes::bytes::Bytes>>>::flush
Line
Count
Source
138
1.20M
    pub fn flush(&mut self, cx: &mut Context) -> Poll<io::Result<()>> {
139
1.20M
        let span = tracing::trace_span!("FramedWrite::flush");
140
1.20M
        let _e = span.enter();
141
142
        loop {
143
1.21M
            while !self.encoder.is_empty() {
144
743k
                let n = match self.encoder.next {
145
743k
                    Some(Next::Data(ref mut frame)) => {
146
743k
                        tracing::trace!(queued_data_frame = true);
147
743k
                        let mut buf = (&mut self.encoder.buf).chain(frame.payload_mut());
148
743k
                        ready!(poll_write_buf(Pin::new(&mut self.inner), cx, &mut buf))?
149
                    }
150
                    _ => {
151
220k
                        tracing::trace!(queued_data_frame = false);
152
220k
                        ready!(poll_write_buf(
153
220k
                            Pin::new(&mut self.inner),
154
220k
                            cx,
155
220k
                            &mut self.encoder.buf
156
220k
                        ))?
157
                    }
158
                };
159
9.66k
                if n == 0 {
160
                    // No progress is possible; retrying would busy-loop.
161
0
                    tracing::trace!("write returned zero, but non-zero bytes remaining");
162
0
                    return Poll::Ready(Err(io::ErrorKind::WriteZero.into()));
163
9.66k
                }
164
            }
165
166
252k
            match self.encoder.unset_frame() {
167
0
                ControlFlow::Continue => (),
168
252k
                ControlFlow::Break => break,
169
            }
170
        }
171
172
252k
        tracing::trace!("flushing buffer");
173
        // Flush the upstream
174
252k
        ready!(Pin::new(&mut self.inner).poll_flush(cx))?;
175
176
252k
        Poll::Ready(Ok(()))
177
1.20M
    }
178
179
    /// Close the codec
180
10.9k
    pub fn shutdown(&mut self, cx: &mut Context) -> Poll<io::Result<()>> {
181
10.9k
        if !self.final_flush_done {
182
10.9k
            ready!(self.flush(cx))?;
183
1.49k
            self.final_flush_done = true;
184
0
        }
185
1.49k
        Pin::new(&mut self.inner).poll_shutdown(cx)
186
10.9k
    }
Unexecuted instantiation: <h2::codec::framed_write::FramedWrite<_, _>>::shutdown
<h2::codec::framed_write::FramedWrite<h2_support::mock::Pipe, bytes::bytes::Bytes>>::shutdown
Line
Count
Source
180
816
    pub fn shutdown(&mut self, cx: &mut Context) -> Poll<io::Result<()>> {
181
816
        if !self.final_flush_done {
182
816
            ready!(self.flush(cx))?;
183
816
            self.final_flush_done = true;
184
0
        }
185
816
        Pin::new(&mut self.inner).poll_shutdown(cx)
186
816
    }
<h2::codec::framed_write::FramedWrite<fuzz_e2e::MockIo, h2::proto::streams::prioritize::Prioritized<bytes::bytes::Bytes>>>::shutdown
Line
Count
Source
180
10.1k
    pub fn shutdown(&mut self, cx: &mut Context) -> Poll<io::Result<()>> {
181
10.1k
        if !self.final_flush_done {
182
10.1k
            ready!(self.flush(cx))?;
183
681
            self.final_flush_done = true;
184
0
        }
185
681
        Pin::new(&mut self.inner).poll_shutdown(cx)
186
10.1k
    }
187
}
188
189
#[must_use]
190
enum ControlFlow {
191
    Continue,
192
    Break,
193
}
194
195
impl<B> Encoder<B>
196
where
197
    B: Buf,
198
{
199
253k
    fn unset_frame(&mut self) -> ControlFlow {
200
        // Clear internal buffer
201
253k
        self.buf.set_position(0);
202
253k
        self.buf.get_mut().clear();
203
204
        // The data frame has been written, so unset it
205
253k
        match self.next.take() {
206
1.98k
            Some(Next::Data(frame)) => {
207
1.98k
                self.last_data_frame = Some(frame);
208
1.98k
                debug_assert!(self.is_empty());
209
1.98k
                ControlFlow::Break
210
            }
211
0
            Some(Next::Continuation(frame)) => {
212
                // Buffer the continuation frame, then try to write again
213
0
                let mut buf = limited_write_buf!(self);
214
0
                if let Some(continuation) = frame.encode(&mut buf) {
215
0
                    self.next = Some(Next::Continuation(continuation));
216
0
                }
217
0
                ControlFlow::Continue
218
            }
219
251k
            None => ControlFlow::Break,
220
        }
221
253k
    }
Unexecuted instantiation: <h2::codec::framed_write::Encoder<_>>::unset_frame
<h2::codec::framed_write::Encoder<bytes::bytes::Bytes>>::unset_frame
Line
Count
Source
199
816
    fn unset_frame(&mut self) -> ControlFlow {
200
        // Clear internal buffer
201
816
        self.buf.set_position(0);
202
816
        self.buf.get_mut().clear();
203
204
        // The data frame has been written, so unset it
205
816
        match self.next.take() {
206
0
            Some(Next::Data(frame)) => {
207
0
                self.last_data_frame = Some(frame);
208
0
                debug_assert!(self.is_empty());
209
0
                ControlFlow::Break
210
            }
211
0
            Some(Next::Continuation(frame)) => {
212
                // Buffer the continuation frame, then try to write again
213
0
                let mut buf = limited_write_buf!(self);
214
0
                if let Some(continuation) = frame.encode(&mut buf) {
215
0
                    self.next = Some(Next::Continuation(continuation));
216
0
                }
217
0
                ControlFlow::Continue
218
            }
219
816
            None => ControlFlow::Break,
220
        }
221
816
    }
<h2::codec::framed_write::Encoder<h2::proto::streams::prioritize::Prioritized<bytes::bytes::Bytes>>>::unset_frame
Line
Count
Source
199
252k
    fn unset_frame(&mut self) -> ControlFlow {
200
        // Clear internal buffer
201
252k
        self.buf.set_position(0);
202
252k
        self.buf.get_mut().clear();
203
204
        // The data frame has been written, so unset it
205
252k
        match self.next.take() {
206
1.98k
            Some(Next::Data(frame)) => {
207
1.98k
                self.last_data_frame = Some(frame);
208
1.98k
                debug_assert!(self.is_empty());
209
1.98k
                ControlFlow::Break
210
            }
211
0
            Some(Next::Continuation(frame)) => {
212
                // Buffer the continuation frame, then try to write again
213
0
                let mut buf = limited_write_buf!(self);
214
0
                if let Some(continuation) = frame.encode(&mut buf) {
215
0
                    self.next = Some(Next::Continuation(continuation));
216
0
                }
217
0
                ControlFlow::Continue
218
            }
219
250k
            None => ControlFlow::Break,
220
        }
221
252k
    }
222
223
242k
    fn buffer(&mut self, item: Frame<B>) -> Result<(), UserError> {
224
        // Ensure that we have enough capacity to accept the write.
225
242k
        assert!(self.has_capacity());
226
242k
        let span = tracing::trace_span!("FramedWrite::buffer", frame = ?item);
227
242k
        let _e = span.enter();
228
229
242k
        tracing::debug!(frame = ?item, "send");
230
231
242k
        match item {
232
15.3k
            Frame::Data(mut v) => {
233
                // Ensure that the payload is not greater than the max frame.
234
15.3k
                let len = v.payload().remaining();
235
236
15.3k
                if len > self.max_frame_size() {
237
0
                    return Err(PayloadTooBig);
238
15.3k
                }
239
240
15.3k
                if len >= self.chain_threshold {
241
3.17k
                    let head = v.head();
242
243
                    // Encode the frame head to the buffer
244
3.17k
                    head.encode(len, self.buf.get_mut());
245
246
3.17k
                    if self.buf.get_ref().remaining() < self.chain_threshold {
247
1.72k
                        let extra_bytes = self.chain_threshold - self.buf.remaining();
248
1.72k
                        self.buf.get_mut().put(v.payload_mut().take(extra_bytes));
249
1.72k
                    }
250
251
                    // Save the data frame
252
3.17k
                    self.next = Some(Next::Data(v));
253
                } else {
254
12.2k
                    v.encode_chunk(self.buf.get_mut());
255
256
                    // The chunk has been fully encoded, so there is no need to
257
                    // keep it around
258
12.2k
                    assert_eq!(v.payload().remaining(), 0, "chunk not fully encoded");
259
260
                    // Save off the last frame...
261
12.2k
                    self.last_data_frame = Some(v);
262
                }
263
            }
264
201k
            Frame::Headers(v) => {
265
201k
                let mut buf = limited_write_buf!(self);
266
201k
                if let Some(continuation) = v.encode(&mut self.hpack, &mut buf) {
267
0
                    self.next = Some(Next::Continuation(continuation));
268
201k
                }
269
            }
270
0
            Frame::PushPromise(v) => {
271
0
                let mut buf = limited_write_buf!(self);
272
0
                if let Some(continuation) = v.encode(&mut self.hpack, &mut buf) {
273
0
                    self.next = Some(Next::Continuation(continuation));
274
0
                }
275
            }
276
18.0k
            Frame::Settings(v) => {
277
18.0k
                v.encode(self.buf.get_mut());
278
18.0k
                tracing::trace!(rem = self.buf.remaining(), "encoded settings");
279
            }
280
6.60k
            Frame::GoAway(v) => {
281
6.60k
                v.encode(self.buf.get_mut());
282
6.60k
                tracing::trace!(rem = self.buf.remaining(), "encoded go_away");
283
            }
284
219
            Frame::Ping(v) => {
285
219
                v.encode(self.buf.get_mut());
286
219
                tracing::trace!(rem = self.buf.remaining(), "encoded ping");
287
            }
288
6
            Frame::WindowUpdate(v) => {
289
6
                v.encode(self.buf.get_mut());
290
6
                tracing::trace!(rem = self.buf.remaining(), "encoded window_update");
291
            }
292
293
            Frame::Priority(_) => {
294
                /*
295
                v.encode(self.buf.get_mut());
296
                tracing::trace!("encoded priority; rem={:?}", self.buf.remaining());
297
                */
298
0
                unimplemented!();
299
            }
300
671
            Frame::Reset(v) => {
301
671
                v.encode(self.buf.get_mut());
302
671
                tracing::trace!(rem = self.buf.remaining(), "encoded reset");
303
            }
304
        }
305
306
242k
        Ok(())
307
242k
    }
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
223
816
    fn buffer(&mut self, item: Frame<B>) -> Result<(), UserError> {
224
        // Ensure that we have enough capacity to accept the write.
225
816
        assert!(self.has_capacity());
226
816
        let span = tracing::trace_span!("FramedWrite::buffer", frame = ?item);
227
816
        let _e = span.enter();
228
229
816
        tracing::debug!(frame = ?item, "send");
230
231
816
        match item {
232
0
            Frame::Data(mut v) => {
233
                // Ensure that the payload is not greater than the max frame.
234
0
                let len = v.payload().remaining();
235
236
0
                if len > self.max_frame_size() {
237
0
                    return Err(PayloadTooBig);
238
0
                }
239
240
0
                if len >= self.chain_threshold {
241
0
                    let head = v.head();
242
243
                    // Encode the frame head to the buffer
244
0
                    head.encode(len, self.buf.get_mut());
245
246
0
                    if self.buf.get_ref().remaining() < self.chain_threshold {
247
0
                        let extra_bytes = self.chain_threshold - self.buf.remaining();
248
0
                        self.buf.get_mut().put(v.payload_mut().take(extra_bytes));
249
0
                    }
250
251
                    // Save the data frame
252
0
                    self.next = Some(Next::Data(v));
253
                } else {
254
0
                    v.encode_chunk(self.buf.get_mut());
255
256
                    // The chunk has been fully encoded, so there is no need to
257
                    // keep it around
258
0
                    assert_eq!(v.payload().remaining(), 0, "chunk not fully encoded");
259
260
                    // Save off the last frame...
261
0
                    self.last_data_frame = Some(v);
262
                }
263
            }
264
0
            Frame::Headers(v) => {
265
0
                let mut buf = limited_write_buf!(self);
266
0
                if let Some(continuation) = v.encode(&mut self.hpack, &mut buf) {
267
0
                    self.next = Some(Next::Continuation(continuation));
268
0
                }
269
            }
270
0
            Frame::PushPromise(v) => {
271
0
                let mut buf = limited_write_buf!(self);
272
0
                if let Some(continuation) = v.encode(&mut self.hpack, &mut buf) {
273
0
                    self.next = Some(Next::Continuation(continuation));
274
0
                }
275
            }
276
816
            Frame::Settings(v) => {
277
816
                v.encode(self.buf.get_mut());
278
816
                tracing::trace!(rem = self.buf.remaining(), "encoded settings");
279
            }
280
0
            Frame::GoAway(v) => {
281
0
                v.encode(self.buf.get_mut());
282
0
                tracing::trace!(rem = self.buf.remaining(), "encoded go_away");
283
            }
284
0
            Frame::Ping(v) => {
285
0
                v.encode(self.buf.get_mut());
286
0
                tracing::trace!(rem = self.buf.remaining(), "encoded ping");
287
            }
288
0
            Frame::WindowUpdate(v) => {
289
0
                v.encode(self.buf.get_mut());
290
0
                tracing::trace!(rem = self.buf.remaining(), "encoded window_update");
291
            }
292
293
            Frame::Priority(_) => {
294
                /*
295
                v.encode(self.buf.get_mut());
296
                tracing::trace!("encoded priority; rem={:?}", self.buf.remaining());
297
                */
298
0
                unimplemented!();
299
            }
300
0
            Frame::Reset(v) => {
301
0
                v.encode(self.buf.get_mut());
302
0
                tracing::trace!(rem = self.buf.remaining(), "encoded reset");
303
            }
304
        }
305
306
816
        Ok(())
307
816
    }
<h2::codec::framed_write::Encoder<h2::proto::streams::prioritize::Prioritized<bytes::bytes::Bytes>>>::buffer
Line
Count
Source
223
241k
    fn buffer(&mut self, item: Frame<B>) -> Result<(), UserError> {
224
        // Ensure that we have enough capacity to accept the write.
225
241k
        assert!(self.has_capacity());
226
241k
        let span = tracing::trace_span!("FramedWrite::buffer", frame = ?item);
227
241k
        let _e = span.enter();
228
229
241k
        tracing::debug!(frame = ?item, "send");
230
231
241k
        match item {
232
15.3k
            Frame::Data(mut v) => {
233
                // Ensure that the payload is not greater than the max frame.
234
15.3k
                let len = v.payload().remaining();
235
236
15.3k
                if len > self.max_frame_size() {
237
0
                    return Err(PayloadTooBig);
238
15.3k
                }
239
240
15.3k
                if len >= self.chain_threshold {
241
3.17k
                    let head = v.head();
242
243
                    // Encode the frame head to the buffer
244
3.17k
                    head.encode(len, self.buf.get_mut());
245
246
3.17k
                    if self.buf.get_ref().remaining() < self.chain_threshold {
247
1.72k
                        let extra_bytes = self.chain_threshold - self.buf.remaining();
248
1.72k
                        self.buf.get_mut().put(v.payload_mut().take(extra_bytes));
249
1.72k
                    }
250
251
                    // Save the data frame
252
3.17k
                    self.next = Some(Next::Data(v));
253
                } else {
254
12.2k
                    v.encode_chunk(self.buf.get_mut());
255
256
                    // The chunk has been fully encoded, so there is no need to
257
                    // keep it around
258
12.2k
                    assert_eq!(v.payload().remaining(), 0, "chunk not fully encoded");
259
260
                    // Save off the last frame...
261
12.2k
                    self.last_data_frame = Some(v);
262
                }
263
            }
264
201k
            Frame::Headers(v) => {
265
201k
                let mut buf = limited_write_buf!(self);
266
201k
                if let Some(continuation) = v.encode(&mut self.hpack, &mut buf) {
267
0
                    self.next = Some(Next::Continuation(continuation));
268
201k
                }
269
            }
270
0
            Frame::PushPromise(v) => {
271
0
                let mut buf = limited_write_buf!(self);
272
0
                if let Some(continuation) = v.encode(&mut self.hpack, &mut buf) {
273
0
                    self.next = Some(Next::Continuation(continuation));
274
0
                }
275
            }
276
17.2k
            Frame::Settings(v) => {
277
17.2k
                v.encode(self.buf.get_mut());
278
17.2k
                tracing::trace!(rem = self.buf.remaining(), "encoded settings");
279
            }
280
6.60k
            Frame::GoAway(v) => {
281
6.60k
                v.encode(self.buf.get_mut());
282
6.60k
                tracing::trace!(rem = self.buf.remaining(), "encoded go_away");
283
            }
284
219
            Frame::Ping(v) => {
285
219
                v.encode(self.buf.get_mut());
286
219
                tracing::trace!(rem = self.buf.remaining(), "encoded ping");
287
            }
288
6
            Frame::WindowUpdate(v) => {
289
6
                v.encode(self.buf.get_mut());
290
6
                tracing::trace!(rem = self.buf.remaining(), "encoded window_update");
291
            }
292
293
            Frame::Priority(_) => {
294
                /*
295
                v.encode(self.buf.get_mut());
296
                tracing::trace!("encoded priority; rem={:?}", self.buf.remaining());
297
                */
298
0
                unimplemented!();
299
            }
300
671
            Frame::Reset(v) => {
301
671
                v.encode(self.buf.get_mut());
302
671
                tracing::trace!(rem = self.buf.remaining(), "encoded reset");
303
            }
304
        }
305
306
241k
        Ok(())
307
241k
    }
308
309
2.59M
    fn has_capacity(&self) -> bool {
310
2.59M
        self.next.is_none()
311
1.84M
            && (self.buf.get_ref().capacity() - self.buf.get_ref().len()
312
1.84M
                >= self.min_buffer_capacity)
313
2.59M
    }
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
309
816
    fn has_capacity(&self) -> bool {
310
816
        self.next.is_none()
311
816
            && (self.buf.get_ref().capacity() - self.buf.get_ref().len()
312
816
                >= self.min_buffer_capacity)
313
816
    }
<h2::codec::framed_write::Encoder<h2::proto::streams::prioritize::Prioritized<bytes::bytes::Bytes>>>::has_capacity
Line
Count
Source
309
2.59M
    fn has_capacity(&self) -> bool {
310
2.59M
        self.next.is_none()
311
1.84M
            && (self.buf.get_ref().capacity() - self.buf.get_ref().len()
312
1.84M
                >= self.min_buffer_capacity)
313
2.59M
    }
314
315
1.21M
    fn is_empty(&self) -> bool {
316
745k
        match self.next {
317
745k
            Some(Next::Data(ref frame)) => !frame.payload().has_remaining(),
318
472k
            _ => !self.buf.has_remaining(),
319
        }
320
1.21M
    }
Unexecuted instantiation: <h2::codec::framed_write::Encoder<_>>::is_empty
<h2::codec::framed_write::Encoder<bytes::bytes::Bytes>>::is_empty
Line
Count
Source
315
816
    fn is_empty(&self) -> bool {
316
0
        match self.next {
317
0
            Some(Next::Data(ref frame)) => !frame.payload().has_remaining(),
318
816
            _ => !self.buf.has_remaining(),
319
        }
320
816
    }
<h2::codec::framed_write::Encoder<h2::proto::streams::prioritize::Prioritized<bytes::bytes::Bytes>>>::is_empty
Line
Count
Source
315
1.21M
    fn is_empty(&self) -> bool {
316
745k
        match self.next {
317
745k
            Some(Next::Data(ref frame)) => !frame.payload().has_remaining(),
318
471k
            _ => !self.buf.has_remaining(),
319
        }
320
1.21M
    }
321
}
322
323
impl<B> Encoder<B> {
324
676k
    fn max_frame_size(&self) -> usize {
325
676k
        self.max_frame_size as usize
326
676k
    }
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
324
676k
    fn max_frame_size(&self) -> usize {
325
676k
        self.max_frame_size as usize
326
676k
    }
327
}
328
329
impl<T, B> FramedWrite<T, B> {
330
    /// Returns the max frame size that can be sent
331
459k
    pub fn max_frame_size(&self) -> usize {
332
459k
        self.encoder.max_frame_size()
333
459k
    }
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
331
459k
    pub fn max_frame_size(&self) -> usize {
332
459k
        self.encoder.max_frame_size()
333
459k
    }
334
335
    /// Set the peer's max frame size.
336
171
    pub fn set_max_frame_size(&mut self, val: usize) {
337
171
        assert!(val <= frame::MAX_MAX_FRAME_SIZE as usize);
338
171
        self.encoder.max_frame_size = val as FrameSize;
339
171
    }
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
336
171
    pub fn set_max_frame_size(&mut self, val: usize) {
337
171
        assert!(val <= frame::MAX_MAX_FRAME_SIZE as usize);
338
171
        self.encoder.max_frame_size = val as FrameSize;
339
171
    }
340
341
    /// Set the peer's header table size.
342
978
    pub fn set_header_table_size(&mut self, val: usize) {
343
978
        self.encoder.hpack.update_max_size(val);
344
978
    }
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
342
978
    pub fn set_header_table_size(&mut self, val: usize) {
343
978
        self.encoder.hpack.update_max_size(val);
344
978
    }
345
346
    /// Retrieve the last data frame that has been sent
347
927k
    pub fn take_last_data_frame(&mut self) -> Option<frame::Data<B>> {
348
927k
        self.encoder.last_data_frame.take()
349
927k
    }
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
347
927k
    pub fn take_last_data_frame(&mut self) -> Option<frame::Data<B>> {
348
927k
        self.encoder.last_data_frame.take()
349
927k
    }
350
351
816
    pub fn get_mut(&mut self) -> &mut T {
352
816
        &mut self.inner
353
816
    }
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
351
816
    pub fn get_mut(&mut self) -> &mut T {
352
816
        &mut self.inner
353
816
    }
354
}
355
356
impl<T: AsyncRead + Unpin, B> AsyncRead for FramedWrite<T, B> {
357
1.20M
    fn poll_read(
358
1.20M
        mut self: Pin<&mut Self>,
359
1.20M
        cx: &mut Context<'_>,
360
1.20M
        buf: &mut ReadBuf,
361
1.20M
    ) -> Poll<io::Result<()>> {
362
1.20M
        Pin::new(&mut self.inner).poll_read(cx, buf)
363
1.20M
    }
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
357
1.20M
    fn poll_read(
358
1.20M
        mut self: Pin<&mut Self>,
359
1.20M
        cx: &mut Context<'_>,
360
1.20M
        buf: &mut ReadBuf,
361
1.20M
    ) -> Poll<io::Result<()>> {
362
1.20M
        Pin::new(&mut self.inner).poll_read(cx, buf)
363
1.20M
    }
364
}
365
366
// We never project the Pin to `B`.
367
impl<T: Unpin, B> Unpin for FramedWrite<T, B> {}
368
369
#[cfg(feature = "unstable")]
370
mod unstable {
371
    use super::*;
372
373
    impl<T, B> FramedWrite<T, B> {
374
0
        pub fn get_ref(&self) -> &T {
375
0
            &self.inner
376
0
        }
377
    }
378
}