Coverage Report

Created: 2026-05-30 06:25

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
15.3k
    pub fn new(inner: T) -> FramedWrite<T, B> {
86
15.3k
        let chain_threshold = if inner.is_write_vectored() {
87
0
            CHAIN_THRESHOLD
88
        } else {
89
15.3k
            CHAIN_THRESHOLD_WITHOUT_VECTORED_IO
90
        };
91
15.3k
        FramedWrite {
92
15.3k
            inner,
93
15.3k
            final_flush_done: false,
94
15.3k
            encoder: Encoder {
95
15.3k
                hpack: hpack::Encoder::default(),
96
15.3k
                buf: Cursor::new(BytesMut::with_capacity(DEFAULT_BUFFER_CAPACITY)),
97
15.3k
                next: None,
98
15.3k
                last_data_frame: None,
99
15.3k
                max_frame_size: frame::DEFAULT_MAX_FRAME_SIZE,
100
15.3k
                chain_threshold,
101
15.3k
                min_buffer_capacity: chain_threshold + frame::HEADER_LEN,
102
15.3k
            },
103
15.3k
        }
104
15.3k
    }
<h2::codec::framed_write::FramedWrite<h2_support::mock::Mock, h2::proto::streams::prioritize::Prioritized<bytes::bytes::Bytes>>>::new
Line
Count
Source
85
807
    pub fn new(inner: T) -> FramedWrite<T, B> {
86
807
        let chain_threshold = if inner.is_write_vectored() {
87
0
            CHAIN_THRESHOLD
88
        } else {
89
807
            CHAIN_THRESHOLD_WITHOUT_VECTORED_IO
90
        };
91
807
        FramedWrite {
92
807
            inner,
93
807
            final_flush_done: false,
94
807
            encoder: Encoder {
95
807
                hpack: hpack::Encoder::default(),
96
807
                buf: Cursor::new(BytesMut::with_capacity(DEFAULT_BUFFER_CAPACITY)),
97
807
                next: None,
98
807
                last_data_frame: None,
99
807
                max_frame_size: frame::DEFAULT_MAX_FRAME_SIZE,
100
807
                chain_threshold,
101
807
                min_buffer_capacity: chain_threshold + frame::HEADER_LEN,
102
807
            },
103
807
        }
104
807
    }
<h2::codec::framed_write::FramedWrite<h2_support::mock::Pipe, bytes::bytes::Bytes>>::new
Line
Count
Source
85
807
    pub fn new(inner: T) -> FramedWrite<T, B> {
86
807
        let chain_threshold = if inner.is_write_vectored() {
87
0
            CHAIN_THRESHOLD
88
        } else {
89
807
            CHAIN_THRESHOLD_WITHOUT_VECTORED_IO
90
        };
91
807
        FramedWrite {
92
807
            inner,
93
807
            final_flush_done: false,
94
807
            encoder: Encoder {
95
807
                hpack: hpack::Encoder::default(),
96
807
                buf: Cursor::new(BytesMut::with_capacity(DEFAULT_BUFFER_CAPACITY)),
97
807
                next: None,
98
807
                last_data_frame: None,
99
807
                max_frame_size: frame::DEFAULT_MAX_FRAME_SIZE,
100
807
                chain_threshold,
101
807
                min_buffer_capacity: chain_threshold + frame::HEADER_LEN,
102
807
            },
103
807
        }
104
807
    }
<h2::codec::framed_write::FramedWrite<fuzz_e2e::MockIo, h2::proto::streams::prioritize::Prioritized<bytes::bytes::Bytes>>>::new
Line
Count
Source
85
13.7k
    pub fn new(inner: T) -> FramedWrite<T, B> {
86
13.7k
        let chain_threshold = if inner.is_write_vectored() {
87
0
            CHAIN_THRESHOLD
88
        } else {
89
13.7k
            CHAIN_THRESHOLD_WITHOUT_VECTORED_IO
90
        };
91
13.7k
        FramedWrite {
92
13.7k
            inner,
93
13.7k
            final_flush_done: false,
94
13.7k
            encoder: Encoder {
95
13.7k
                hpack: hpack::Encoder::default(),
96
13.7k
                buf: Cursor::new(BytesMut::with_capacity(DEFAULT_BUFFER_CAPACITY)),
97
13.7k
                next: None,
98
13.7k
                last_data_frame: None,
99
13.7k
                max_frame_size: frame::DEFAULT_MAX_FRAME_SIZE,
100
13.7k
                chain_threshold,
101
13.7k
                min_buffer_capacity: chain_threshold + frame::HEADER_LEN,
102
13.7k
            },
103
13.7k
        }
104
13.7k
    }
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
801k
    pub fn poll_ready(&mut self, cx: &mut Context) -> Poll<io::Result<()>> {
111
801k
        if !self.encoder.has_capacity() {
112
            // Try flushing
113
308k
            ready!(self.flush(cx))?;
114
115
2.69k
            if !self.encoder.has_capacity() {
116
0
                return Poll::Pending;
117
2.69k
            }
118
493k
        }
119
120
496k
        Poll::Ready(Ok(()))
121
801k
    }
122
123
    /// Buffer a frame.
124
    ///
125
    /// `poll_ready` must be called first to ensure that a frame may be
126
    /// accepted.
127
208k
    pub fn buffer(&mut self, item: Frame<B>) -> Result<(), UserError> {
128
208k
        self.encoder.buffer(item)
129
208k
    }
<h2::codec::framed_write::FramedWrite<h2_support::mock::Mock, h2::proto::streams::prioritize::Prioritized<bytes::bytes::Bytes>>>::buffer
Line
Count
Source
127
807
    pub fn buffer(&mut self, item: Frame<B>) -> Result<(), UserError> {
128
807
        self.encoder.buffer(item)
129
807
    }
<h2::codec::framed_write::FramedWrite<fuzz_e2e::MockIo, h2::proto::streams::prioritize::Prioritized<bytes::bytes::Bytes>>>::buffer
Line
Count
Source
127
207k
    pub fn buffer(&mut self, item: Frame<B>) -> Result<(), UserError> {
128
207k
        self.encoder.buffer(item)
129
207k
    }
130
131
    /// Flush buffered data to the wire
132
472k
    pub fn flush(&mut self, cx: &mut Context) -> Poll<io::Result<()>> {
133
472k
        let span = tracing::trace_span!("FramedWrite::flush");
134
472k
        let _e = span.enter();
135
136
        loop {
137
484k
            while !self.encoder.is_empty() {
138
311k
                match self.encoder.next {
139
311k
                    Some(Next::Data(ref mut frame)) => {
140
311k
                        tracing::trace!(queued_data_frame = true);
141
311k
                        let mut buf = (&mut self.encoder.buf).chain(frame.payload_mut());
142
311k
                        ready!(poll_write_buf(Pin::new(&mut self.inner), cx, &mut buf))?
143
                    }
144
                    _ => {
145
25.9k
                        tracing::trace!(queued_data_frame = false);
146
25.9k
                        ready!(poll_write_buf(
147
25.9k
                            Pin::new(&mut self.inner),
148
25.9k
                            cx,
149
25.9k
                            &mut self.encoder.buf
150
25.9k
                        ))?
151
                    }
152
                };
153
            }
154
155
147k
            match self.encoder.unset_frame() {
156
0
                ControlFlow::Continue => (),
157
147k
                ControlFlow::Break => break,
158
            }
159
        }
160
161
147k
        tracing::trace!("flushing buffer");
162
        // Flush the upstream
163
147k
        ready!(Pin::new(&mut self.inner).poll_flush(cx))?;
164
165
147k
        Poll::Ready(Ok(()))
166
472k
    }
<h2::codec::framed_write::FramedWrite<h2_support::mock::Pipe, bytes::bytes::Bytes>>::flush
Line
Count
Source
132
807
    pub fn flush(&mut self, cx: &mut Context) -> Poll<io::Result<()>> {
133
807
        let span = tracing::trace_span!("FramedWrite::flush");
134
807
        let _e = span.enter();
135
136
        loop {
137
807
            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
807
            match self.encoder.unset_frame() {
156
0
                ControlFlow::Continue => (),
157
807
                ControlFlow::Break => break,
158
            }
159
        }
160
161
807
        tracing::trace!("flushing buffer");
162
        // Flush the upstream
163
807
        ready!(Pin::new(&mut self.inner).poll_flush(cx))?;
164
165
807
        Poll::Ready(Ok(()))
166
807
    }
<h2::codec::framed_write::FramedWrite<fuzz_e2e::MockIo, h2::proto::streams::prioritize::Prioritized<bytes::bytes::Bytes>>>::flush
Line
Count
Source
132
471k
    pub fn flush(&mut self, cx: &mut Context) -> Poll<io::Result<()>> {
133
471k
        let span = tracing::trace_span!("FramedWrite::flush");
134
471k
        let _e = span.enter();
135
136
        loop {
137
483k
            while !self.encoder.is_empty() {
138
311k
                match self.encoder.next {
139
311k
                    Some(Next::Data(ref mut frame)) => {
140
311k
                        tracing::trace!(queued_data_frame = true);
141
311k
                        let mut buf = (&mut self.encoder.buf).chain(frame.payload_mut());
142
311k
                        ready!(poll_write_buf(Pin::new(&mut self.inner), cx, &mut buf))?
143
                    }
144
                    _ => {
145
25.9k
                        tracing::trace!(queued_data_frame = false);
146
25.9k
                        ready!(poll_write_buf(
147
25.9k
                            Pin::new(&mut self.inner),
148
25.9k
                            cx,
149
25.9k
                            &mut self.encoder.buf
150
25.9k
                        ))?
151
                    }
152
                };
153
            }
154
155
146k
            match self.encoder.unset_frame() {
156
0
                ControlFlow::Continue => (),
157
146k
                ControlFlow::Break => break,
158
            }
159
        }
160
161
146k
        tracing::trace!("flushing buffer");
162
        // Flush the upstream
163
146k
        ready!(Pin::new(&mut self.inner).poll_flush(cx))?;
164
165
146k
        Poll::Ready(Ok(()))
166
471k
    }
167
168
    /// Close the codec
169
13.6k
    pub fn shutdown(&mut self, cx: &mut Context) -> Poll<io::Result<()>> {
170
13.6k
        if !self.final_flush_done {
171
13.6k
            ready!(self.flush(cx))?;
172
2.02k
            self.final_flush_done = true;
173
0
        }
174
2.02k
        Pin::new(&mut self.inner).poll_shutdown(cx)
175
13.6k
    }
<h2::codec::framed_write::FramedWrite<h2_support::mock::Pipe, bytes::bytes::Bytes>>::shutdown
Line
Count
Source
169
807
    pub fn shutdown(&mut self, cx: &mut Context) -> Poll<io::Result<()>> {
170
807
        if !self.final_flush_done {
171
807
            ready!(self.flush(cx))?;
172
807
            self.final_flush_done = true;
173
0
        }
174
807
        Pin::new(&mut self.inner).poll_shutdown(cx)
175
807
    }
<h2::codec::framed_write::FramedWrite<fuzz_e2e::MockIo, h2::proto::streams::prioritize::Prioritized<bytes::bytes::Bytes>>>::shutdown
Line
Count
Source
169
12.8k
    pub fn shutdown(&mut self, cx: &mut Context) -> Poll<io::Result<()>> {
170
12.8k
        if !self.final_flush_done {
171
12.8k
            ready!(self.flush(cx))?;
172
1.21k
            self.final_flush_done = true;
173
0
        }
174
1.21k
        Pin::new(&mut self.inner).poll_shutdown(cx)
175
12.8k
    }
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
147k
    fn unset_frame(&mut self) -> ControlFlow {
189
        // Clear internal buffer
190
147k
        self.buf.set_position(0);
191
147k
        self.buf.get_mut().clear();
192
193
        // The data frame has been written, so unset it
194
147k
        match self.next.take() {
195
2.59k
            Some(Next::Data(frame)) => {
196
2.59k
                self.last_data_frame = Some(frame);
197
2.59k
                debug_assert!(self.is_empty());
198
2.59k
                ControlFlow::Break
199
            }
200
0
            Some(Next::Continuation(frame)) => {
201
                // 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
144k
            None => ControlFlow::Break,
209
        }
210
147k
    }
<h2::codec::framed_write::Encoder<bytes::bytes::Bytes>>::unset_frame
Line
Count
Source
188
807
    fn unset_frame(&mut self) -> ControlFlow {
189
        // Clear internal buffer
190
807
        self.buf.set_position(0);
191
807
        self.buf.get_mut().clear();
192
193
        // The data frame has been written, so unset it
194
807
        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
                // 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
807
            None => ControlFlow::Break,
209
        }
210
807
    }
<h2::codec::framed_write::Encoder<h2::proto::streams::prioritize::Prioritized<bytes::bytes::Bytes>>>::unset_frame
Line
Count
Source
188
146k
    fn unset_frame(&mut self) -> ControlFlow {
189
        // Clear internal buffer
190
146k
        self.buf.set_position(0);
191
146k
        self.buf.get_mut().clear();
192
193
        // The data frame has been written, so unset it
194
146k
        match self.next.take() {
195
2.59k
            Some(Next::Data(frame)) => {
196
2.59k
                self.last_data_frame = Some(frame);
197
2.59k
                debug_assert!(self.is_empty());
198
2.59k
                ControlFlow::Break
199
            }
200
0
            Some(Next::Continuation(frame)) => {
201
                // 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
143k
            None => ControlFlow::Break,
209
        }
210
146k
    }
211
212
208k
    fn buffer(&mut self, item: Frame<B>) -> Result<(), UserError> {
213
        // Ensure that we have enough capacity to accept the write.
214
208k
        assert!(self.has_capacity());
215
208k
        let span = tracing::trace_span!("FramedWrite::buffer", frame = ?item);
216
208k
        let _e = span.enter();
217
218
208k
        tracing::debug!(frame = ?item, "send");
219
220
208k
        match item {
221
15.9k
            Frame::Data(mut v) => {
222
                // Ensure that the payload is not greater than the max frame.
223
15.9k
                let len = v.payload().remaining();
224
225
15.9k
                if len > self.max_frame_size() {
226
0
                    return Err(PayloadTooBig);
227
15.9k
                }
228
229
15.9k
                if len >= self.chain_threshold {
230
3.58k
                    let head = v.head();
231
232
                    // Encode the frame head to the buffer
233
3.58k
                    head.encode(len, self.buf.get_mut());
234
235
3.58k
                    if self.buf.get_ref().remaining() < self.chain_threshold {
236
2.47k
                        let extra_bytes = self.chain_threshold - self.buf.remaining();
237
2.47k
                        self.buf.get_mut().put(v.payload_mut().take(extra_bytes));
238
2.47k
                    }
239
240
                    // Save the data frame
241
3.58k
                    self.next = Some(Next::Data(v));
242
                } else {
243
12.3k
                    v.encode_chunk(self.buf.get_mut());
244
245
                    // The chunk has been fully encoded, so there is no need to
246
                    // keep it around
247
12.3k
                    assert_eq!(v.payload().remaining(), 0, "chunk not fully encoded");
248
249
                    // Save off the last frame...
250
12.3k
                    self.last_data_frame = Some(v);
251
                }
252
            }
253
160k
            Frame::Headers(v) => {
254
160k
                let mut buf = limited_write_buf!(self);
255
160k
                if let Some(continuation) = v.encode(&mut self.hpack, &mut buf) {
256
0
                    self.next = Some(Next::Continuation(continuation));
257
160k
                }
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.9k
            Frame::Settings(v) => {
266
20.9k
                v.encode(self.buf.get_mut());
267
20.9k
                tracing::trace!(rem = self.buf.remaining(), "encoded settings");
268
            }
269
7.34k
            Frame::GoAway(v) => {
270
7.34k
                v.encode(self.buf.get_mut());
271
7.34k
                tracing::trace!(rem = self.buf.remaining(), "encoded go_away");
272
            }
273
343
            Frame::Ping(v) => {
274
343
                v.encode(self.buf.get_mut());
275
343
                tracing::trace!(rem = self.buf.remaining(), "encoded ping");
276
            }
277
17
            Frame::WindowUpdate(v) => {
278
17
                v.encode(self.buf.get_mut());
279
17
                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
3.70k
            Frame::Reset(v) => {
290
3.70k
                v.encode(self.buf.get_mut());
291
3.70k
                tracing::trace!(rem = self.buf.remaining(), "encoded reset");
292
            }
293
        }
294
295
208k
        Ok(())
296
208k
    }
<h2::codec::framed_write::Encoder<h2::proto::streams::prioritize::Prioritized<bytes::bytes::Bytes>>>::buffer
Line
Count
Source
212
807
    fn buffer(&mut self, item: Frame<B>) -> Result<(), UserError> {
213
        // Ensure that we have enough capacity to accept the write.
214
807
        assert!(self.has_capacity());
215
807
        let span = tracing::trace_span!("FramedWrite::buffer", frame = ?item);
216
807
        let _e = span.enter();
217
218
807
        tracing::debug!(frame = ?item, "send");
219
220
807
        match item {
221
0
            Frame::Data(mut v) => {
222
                // Ensure that the payload is not greater than the max frame.
223
0
                let len = v.payload().remaining();
224
225
0
                if len > self.max_frame_size() {
226
0
                    return Err(PayloadTooBig);
227
0
                }
228
229
0
                if len >= self.chain_threshold {
230
0
                    let head = v.head();
231
232
                    // Encode the frame head to the buffer
233
0
                    head.encode(len, self.buf.get_mut());
234
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
245
                    // The chunk has been fully encoded, so there is no need to
246
                    // 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
807
            Frame::Settings(v) => {
266
807
                v.encode(self.buf.get_mut());
267
807
                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
807
        Ok(())
296
807
    }
<h2::codec::framed_write::Encoder<h2::proto::streams::prioritize::Prioritized<bytes::bytes::Bytes>>>::buffer
Line
Count
Source
212
207k
    fn buffer(&mut self, item: Frame<B>) -> Result<(), UserError> {
213
        // Ensure that we have enough capacity to accept the write.
214
207k
        assert!(self.has_capacity());
215
207k
        let span = tracing::trace_span!("FramedWrite::buffer", frame = ?item);
216
207k
        let _e = span.enter();
217
218
207k
        tracing::debug!(frame = ?item, "send");
219
220
207k
        match item {
221
15.9k
            Frame::Data(mut v) => {
222
                // Ensure that the payload is not greater than the max frame.
223
15.9k
                let len = v.payload().remaining();
224
225
15.9k
                if len > self.max_frame_size() {
226
0
                    return Err(PayloadTooBig);
227
15.9k
                }
228
229
15.9k
                if len >= self.chain_threshold {
230
3.58k
                    let head = v.head();
231
232
                    // Encode the frame head to the buffer
233
3.58k
                    head.encode(len, self.buf.get_mut());
234
235
3.58k
                    if self.buf.get_ref().remaining() < self.chain_threshold {
236
2.47k
                        let extra_bytes = self.chain_threshold - self.buf.remaining();
237
2.47k
                        self.buf.get_mut().put(v.payload_mut().take(extra_bytes));
238
2.47k
                    }
239
240
                    // Save the data frame
241
3.58k
                    self.next = Some(Next::Data(v));
242
                } else {
243
12.3k
                    v.encode_chunk(self.buf.get_mut());
244
245
                    // The chunk has been fully encoded, so there is no need to
246
                    // keep it around
247
12.3k
                    assert_eq!(v.payload().remaining(), 0, "chunk not fully encoded");
248
249
                    // Save off the last frame...
250
12.3k
                    self.last_data_frame = Some(v);
251
                }
252
            }
253
160k
            Frame::Headers(v) => {
254
160k
                let mut buf = limited_write_buf!(self);
255
160k
                if let Some(continuation) = v.encode(&mut self.hpack, &mut buf) {
256
0
                    self.next = Some(Next::Continuation(continuation));
257
160k
                }
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.1k
            Frame::Settings(v) => {
266
20.1k
                v.encode(self.buf.get_mut());
267
20.1k
                tracing::trace!(rem = self.buf.remaining(), "encoded settings");
268
            }
269
7.34k
            Frame::GoAway(v) => {
270
7.34k
                v.encode(self.buf.get_mut());
271
7.34k
                tracing::trace!(rem = self.buf.remaining(), "encoded go_away");
272
            }
273
343
            Frame::Ping(v) => {
274
343
                v.encode(self.buf.get_mut());
275
343
                tracing::trace!(rem = self.buf.remaining(), "encoded ping");
276
            }
277
17
            Frame::WindowUpdate(v) => {
278
17
                v.encode(self.buf.get_mut());
279
17
                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
3.70k
            Frame::Reset(v) => {
290
3.70k
                v.encode(self.buf.get_mut());
291
3.70k
                tracing::trace!(rem = self.buf.remaining(), "encoded reset");
292
            }
293
        }
294
295
207k
        Ok(())
296
207k
    }
297
298
1.01M
    fn has_capacity(&self) -> bool {
299
1.01M
        self.next.is_none()
300
706k
            && (self.buf.get_ref().capacity() - self.buf.get_ref().len()
301
706k
                >= self.min_buffer_capacity)
302
1.01M
    }
<h2::codec::framed_write::Encoder<h2::proto::streams::prioritize::Prioritized<bytes::bytes::Bytes>>>::has_capacity
Line
Count
Source
298
807
    fn has_capacity(&self) -> bool {
299
807
        self.next.is_none()
300
807
            && (self.buf.get_ref().capacity() - self.buf.get_ref().len()
301
807
                >= self.min_buffer_capacity)
302
807
    }
<h2::codec::framed_write::Encoder<h2::proto::streams::prioritize::Prioritized<bytes::bytes::Bytes>>>::has_capacity
Line
Count
Source
298
1.01M
    fn has_capacity(&self) -> bool {
299
1.01M
        self.next.is_none()
300
705k
            && (self.buf.get_ref().capacity() - self.buf.get_ref().len()
301
705k
                >= self.min_buffer_capacity)
302
1.01M
    }
303
304
484k
    fn is_empty(&self) -> bool {
305
313k
        match self.next {
306
313k
            Some(Next::Data(ref frame)) => !frame.payload().has_remaining(),
307
170k
            _ => !self.buf.has_remaining(),
308
        }
309
484k
    }
<h2::codec::framed_write::Encoder<bytes::bytes::Bytes>>::is_empty
Line
Count
Source
304
807
    fn is_empty(&self) -> bool {
305
0
        match self.next {
306
0
            Some(Next::Data(ref frame)) => !frame.payload().has_remaining(),
307
807
            _ => !self.buf.has_remaining(),
308
        }
309
807
    }
<h2::codec::framed_write::Encoder<h2::proto::streams::prioritize::Prioritized<bytes::bytes::Bytes>>>::is_empty
Line
Count
Source
304
483k
    fn is_empty(&self) -> bool {
305
313k
        match self.next {
306
313k
            Some(Next::Data(ref frame)) => !frame.payload().has_remaining(),
307
169k
            _ => !self.buf.has_remaining(),
308
        }
309
483k
    }
310
}
311
312
impl<B> Encoder<B> {
313
328k
    fn max_frame_size(&self) -> usize {
314
328k
        self.max_frame_size as usize
315
328k
    }
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
328k
    fn max_frame_size(&self) -> usize {
314
328k
        self.max_frame_size as usize
315
328k
    }
316
}
317
318
impl<T, B> FramedWrite<T, B> {
319
    /// Returns the max frame size that can be sent
320
151k
    pub fn max_frame_size(&self) -> usize {
321
151k
        self.encoder.max_frame_size()
322
151k
    }
323
324
    /// Set the peer's max frame size.
325
336
    pub fn set_max_frame_size(&mut self, val: usize) {
326
336
        assert!(val <= frame::MAX_MAX_FRAME_SIZE as usize);
327
336
        self.encoder.max_frame_size = val as FrameSize;
328
336
    }
329
330
    /// Set the peer's header table size.
331
1.52k
    pub fn set_header_table_size(&mut self, val: usize) {
332
1.52k
        self.encoder.hpack.update_max_size(val);
333
1.52k
    }
334
335
    /// Retrieve the last data frame that has been sent
336
472k
    pub fn take_last_data_frame(&mut self) -> Option<frame::Data<B>> {
337
472k
        self.encoder.last_data_frame.take()
338
472k
    }
339
340
807
    pub fn get_mut(&mut self) -> &mut T {
341
807
        &mut self.inner
342
807
    }
343
}
344
345
impl<T: AsyncRead + Unpin, B> AsyncRead for FramedWrite<T, B> {
346
471k
    fn poll_read(
347
471k
        mut self: Pin<&mut Self>,
348
471k
        cx: &mut Context<'_>,
349
471k
        buf: &mut ReadBuf,
350
471k
    ) -> Poll<io::Result<()>> {
351
471k
        Pin::new(&mut self.inner).poll_read(cx, buf)
352
471k
    }
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
471k
    fn poll_read(
347
471k
        mut self: Pin<&mut Self>,
348
471k
        cx: &mut Context<'_>,
349
471k
        buf: &mut ReadBuf,
350
471k
    ) -> Poll<io::Result<()>> {
351
471k
        Pin::new(&mut self.inner).poll_read(cx, buf)
352
471k
    }
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
        pub fn get_ref(&self) -> &T {
364
            &self.inner
365
        }
366
    }
367
}