Coverage Report

Created: 2026-09-14 06:40

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/h2/src/codec/mod.rs
Line
Count
Source
1
mod error;
2
mod framed_read;
3
mod framed_write;
4
5
pub use self::error::{SendError, UserError};
6
7
use self::framed_read::FramedRead;
8
use self::framed_write::FramedWrite;
9
10
use crate::frame::{self, Data, Frame};
11
use crate::proto::Error;
12
13
use bytes::Buf;
14
use futures_core::Stream;
15
use futures_sink::Sink;
16
use std::pin::Pin;
17
use std::task::{Context, Poll};
18
use tokio::io::{AsyncRead, AsyncWrite};
19
use tokio_util::codec::length_delimited;
20
21
use std::io;
22
23
#[derive(Debug)]
24
pub struct Codec<T, B> {
25
    inner: FramedRead<FramedWrite<T, B>>,
26
}
27
28
impl<T, B> Codec<T, B>
29
where
30
    T: AsyncRead + AsyncWrite + Unpin,
31
    B: Buf,
32
{
33
    /// Returns a new `Codec` with the default max frame size
34
    #[inline]
35
13.5k
    pub fn new(io: T) -> Self {
36
13.5k
        Self::with_max_recv_frame_size(io, frame::DEFAULT_MAX_FRAME_SIZE as usize)
37
13.5k
    }
Unexecuted instantiation: <h2::codec::Codec<_, _>>::new
<h2::codec::Codec<h2_support::mock::Mock, h2::proto::streams::prioritize::Prioritized<bytes::bytes::Bytes>>>::new
Line
Count
Source
35
816
    pub fn new(io: T) -> Self {
36
816
        Self::with_max_recv_frame_size(io, frame::DEFAULT_MAX_FRAME_SIZE as usize)
37
816
    }
<h2::codec::Codec<h2_support::mock::Pipe, bytes::bytes::Bytes>>::new
Line
Count
Source
35
816
    pub fn new(io: T) -> Self {
36
816
        Self::with_max_recv_frame_size(io, frame::DEFAULT_MAX_FRAME_SIZE as usize)
37
816
    }
<h2::codec::Codec<fuzz_e2e::MockIo, h2::proto::streams::prioritize::Prioritized<bytes::bytes::Bytes>>>::new
Line
Count
Source
35
11.9k
    pub fn new(io: T) -> Self {
36
11.9k
        Self::with_max_recv_frame_size(io, frame::DEFAULT_MAX_FRAME_SIZE as usize)
37
11.9k
    }
38
39
    /// Returns a new `Codec` with the given maximum frame size
40
13.5k
    pub fn with_max_recv_frame_size(io: T, max_frame_size: usize) -> Self {
41
        // Wrap with writer
42
13.5k
        let framed_write = FramedWrite::new(io);
43
44
        // Delimit the frames
45
13.5k
        let delimited = length_delimited::Builder::new()
46
13.5k
            .big_endian()
47
13.5k
            .length_field_length(3)
48
13.5k
            .length_adjustment(9)
49
13.5k
            .num_skip(0) // Don't skip the header
50
13.5k
            .new_read(framed_write);
51
52
13.5k
        let mut inner = FramedRead::new(delimited);
53
54
        // Use FramedRead's method since it checks the value is within range.
55
13.5k
        inner.set_max_frame_size(max_frame_size);
56
57
13.5k
        Codec { inner }
58
13.5k
    }
Unexecuted instantiation: <h2::codec::Codec<_, _>>::with_max_recv_frame_size
<h2::codec::Codec<h2_support::mock::Mock, h2::proto::streams::prioritize::Prioritized<bytes::bytes::Bytes>>>::with_max_recv_frame_size
Line
Count
Source
40
816
    pub fn with_max_recv_frame_size(io: T, max_frame_size: usize) -> Self {
41
        // Wrap with writer
42
816
        let framed_write = FramedWrite::new(io);
43
44
        // Delimit the frames
45
816
        let delimited = length_delimited::Builder::new()
46
816
            .big_endian()
47
816
            .length_field_length(3)
48
816
            .length_adjustment(9)
49
816
            .num_skip(0) // Don't skip the header
50
816
            .new_read(framed_write);
51
52
816
        let mut inner = FramedRead::new(delimited);
53
54
        // Use FramedRead's method since it checks the value is within range.
55
816
        inner.set_max_frame_size(max_frame_size);
56
57
816
        Codec { inner }
58
816
    }
<h2::codec::Codec<h2_support::mock::Pipe, bytes::bytes::Bytes>>::with_max_recv_frame_size
Line
Count
Source
40
816
    pub fn with_max_recv_frame_size(io: T, max_frame_size: usize) -> Self {
41
        // Wrap with writer
42
816
        let framed_write = FramedWrite::new(io);
43
44
        // Delimit the frames
45
816
        let delimited = length_delimited::Builder::new()
46
816
            .big_endian()
47
816
            .length_field_length(3)
48
816
            .length_adjustment(9)
49
816
            .num_skip(0) // Don't skip the header
50
816
            .new_read(framed_write);
51
52
816
        let mut inner = FramedRead::new(delimited);
53
54
        // Use FramedRead's method since it checks the value is within range.
55
816
        inner.set_max_frame_size(max_frame_size);
56
57
816
        Codec { inner }
58
816
    }
<h2::codec::Codec<fuzz_e2e::MockIo, h2::proto::streams::prioritize::Prioritized<bytes::bytes::Bytes>>>::with_max_recv_frame_size
Line
Count
Source
40
11.9k
    pub fn with_max_recv_frame_size(io: T, max_frame_size: usize) -> Self {
41
        // Wrap with writer
42
11.9k
        let framed_write = FramedWrite::new(io);
43
44
        // Delimit the frames
45
11.9k
        let delimited = length_delimited::Builder::new()
46
11.9k
            .big_endian()
47
11.9k
            .length_field_length(3)
48
11.9k
            .length_adjustment(9)
49
11.9k
            .num_skip(0) // Don't skip the header
50
11.9k
            .new_read(framed_write);
51
52
11.9k
        let mut inner = FramedRead::new(delimited);
53
54
        // Use FramedRead's method since it checks the value is within range.
55
11.9k
        inner.set_max_frame_size(max_frame_size);
56
57
11.9k
        Codec { inner }
58
11.9k
    }
59
}
60
61
impl<T, B> Codec<T, B> {
62
    /// Updates the max received frame size.
63
    ///
64
    /// The change takes effect the next time a frame is decoded. In other
65
    /// words, if a frame is currently in process of being decoded with a frame
66
    /// size greater than `val` but less than the max frame size in effect
67
    /// before calling this function, then the frame will be allowed.
68
    #[inline]
69
0
    pub fn set_max_recv_frame_size(&mut self, val: usize) {
70
0
        self.inner.set_max_frame_size(val)
71
0
    }
Unexecuted instantiation: <h2::codec::Codec<_, _>>::set_max_recv_frame_size
Unexecuted instantiation: <h2::codec::Codec<h2_support::mock::Mock, h2::proto::streams::prioritize::Prioritized<bytes::bytes::Bytes>>>::set_max_recv_frame_size
Unexecuted instantiation: <h2::codec::Codec<fuzz_e2e::MockIo, h2::proto::streams::prioritize::Prioritized<bytes::bytes::Bytes>>>::set_max_recv_frame_size
72
73
    /// Returns the current max received frame size setting.
74
    ///
75
    /// This is the largest size this codec will accept from the wire. Larger
76
    /// frames will be rejected.
77
    #[cfg(feature = "unstable")]
78
    #[inline]
79
0
    pub fn max_recv_frame_size(&self) -> usize {
80
0
        self.inner.max_frame_size()
81
0
    }
82
83
    /// Returns the max frame size that can be sent to the peer.
84
459k
    pub fn max_send_frame_size(&self) -> usize {
85
459k
        self.inner.get_ref().max_frame_size()
86
459k
    }
Unexecuted instantiation: <h2::codec::Codec<_, _>>::max_send_frame_size
<h2::codec::Codec<fuzz_e2e::MockIo, h2::proto::streams::prioritize::Prioritized<bytes::bytes::Bytes>>>::max_send_frame_size
Line
Count
Source
84
459k
    pub fn max_send_frame_size(&self) -> usize {
85
459k
        self.inner.get_ref().max_frame_size()
86
459k
    }
87
88
    /// Set the peer's max frame size.
89
171
    pub fn set_max_send_frame_size(&mut self, val: usize) {
90
171
        self.framed_write().set_max_frame_size(val)
91
171
    }
Unexecuted instantiation: <h2::codec::Codec<_, _>>::set_max_send_frame_size
<h2::codec::Codec<fuzz_e2e::MockIo, h2::proto::streams::prioritize::Prioritized<bytes::bytes::Bytes>>>::set_max_send_frame_size
Line
Count
Source
89
171
    pub fn set_max_send_frame_size(&mut self, val: usize) {
90
171
        self.framed_write().set_max_frame_size(val)
91
171
    }
92
93
    /// Set the peer's header table size size.
94
978
    pub fn set_send_header_table_size(&mut self, val: usize) {
95
978
        self.framed_write().set_header_table_size(val)
96
978
    }
Unexecuted instantiation: <h2::codec::Codec<_, _>>::set_send_header_table_size
<h2::codec::Codec<fuzz_e2e::MockIo, h2::proto::streams::prioritize::Prioritized<bytes::bytes::Bytes>>>::set_send_header_table_size
Line
Count
Source
94
978
    pub fn set_send_header_table_size(&mut self, val: usize) {
95
978
        self.framed_write().set_header_table_size(val)
96
978
    }
97
98
    /// Set the decoder header table size size.
99
0
    pub fn set_recv_header_table_size(&mut self, val: usize) {
100
0
        self.inner.set_header_table_size(val)
101
0
    }
Unexecuted instantiation: <h2::codec::Codec<_, _>>::set_recv_header_table_size
Unexecuted instantiation: <h2::codec::Codec<fuzz_e2e::MockIo, h2::proto::streams::prioritize::Prioritized<bytes::bytes::Bytes>>>::set_recv_header_table_size
102
103
    /// Set the max header list size that can be received.
104
0
    pub fn set_max_recv_header_list_size(&mut self, val: usize) {
105
0
        self.inner.set_max_header_list_size(val);
106
0
    }
Unexecuted instantiation: <h2::codec::Codec<_, _>>::set_max_recv_header_list_size
Unexecuted instantiation: <h2::codec::Codec<h2_support::mock::Mock, h2::proto::streams::prioritize::Prioritized<bytes::bytes::Bytes>>>::set_max_recv_header_list_size
Unexecuted instantiation: <h2::codec::Codec<fuzz_e2e::MockIo, h2::proto::streams::prioritize::Prioritized<bytes::bytes::Bytes>>>::set_max_recv_header_list_size
107
108
    /// Get a reference to the inner stream.
109
    #[cfg(feature = "unstable")]
110
0
    pub fn get_ref(&self) -> &T {
111
0
        self.inner.get_ref().get_ref()
112
0
    }
113
114
    /// Get a mutable reference to the inner stream.
115
816
    pub fn get_mut(&mut self) -> &mut T {
116
816
        self.inner.get_mut().get_mut()
117
816
    }
Unexecuted instantiation: <h2::codec::Codec<_, _>>::get_mut
<h2::codec::Codec<h2_support::mock::Pipe, bytes::bytes::Bytes>>::get_mut
Line
Count
Source
115
816
    pub fn get_mut(&mut self) -> &mut T {
116
816
        self.inner.get_mut().get_mut()
117
816
    }
118
119
    /// Takes the data payload value that was fully written to the socket
120
927k
    pub(crate) fn take_last_data_frame(&mut self) -> Option<Data<B>> {
121
927k
        self.framed_write().take_last_data_frame()
122
927k
    }
Unexecuted instantiation: <h2::codec::Codec<_, _>>::take_last_data_frame
<h2::codec::Codec<fuzz_e2e::MockIo, h2::proto::streams::prioritize::Prioritized<bytes::bytes::Bytes>>>::take_last_data_frame
Line
Count
Source
120
927k
    pub(crate) fn take_last_data_frame(&mut self) -> Option<Data<B>> {
121
927k
        self.framed_write().take_last_data_frame()
122
927k
    }
123
124
3.98M
    fn framed_write(&mut self) -> &mut FramedWrite<T, B> {
125
3.98M
        self.inner.get_mut()
126
3.98M
    }
Unexecuted instantiation: <h2::codec::Codec<_, _>>::framed_write
<h2::codec::Codec<h2_support::mock::Mock, h2::proto::streams::prioritize::Prioritized<bytes::bytes::Bytes>>>::framed_write
Line
Count
Source
124
816
    fn framed_write(&mut self) -> &mut FramedWrite<T, B> {
125
816
        self.inner.get_mut()
126
816
    }
<h2::codec::Codec<h2_support::mock::Pipe, bytes::bytes::Bytes>>::framed_write
Line
Count
Source
124
816
    fn framed_write(&mut self) -> &mut FramedWrite<T, B> {
125
816
        self.inner.get_mut()
126
816
    }
<h2::codec::Codec<fuzz_e2e::MockIo, h2::proto::streams::prioritize::Prioritized<bytes::bytes::Bytes>>>::framed_write
Line
Count
Source
124
3.98M
    fn framed_write(&mut self) -> &mut FramedWrite<T, B> {
125
3.98M
        self.inner.get_mut()
126
3.98M
    }
127
}
128
129
impl<T, B> Codec<T, B>
130
where
131
    T: AsyncWrite + Unpin,
132
    B: Buf,
133
{
134
    /// Returns `Ready` when the codec can buffer a frame
135
1.21M
    pub fn poll_ready(&mut self, cx: &mut Context) -> Poll<io::Result<()>> {
136
1.21M
        self.framed_write().poll_ready(cx)
137
1.21M
    }
Unexecuted instantiation: <h2::codec::Codec<_, _>>::poll_ready
<h2::codec::Codec<fuzz_e2e::MockIo, h2::proto::streams::prioritize::Prioritized<bytes::bytes::Bytes>>>::poll_ready
Line
Count
Source
135
1.21M
    pub fn poll_ready(&mut self, cx: &mut Context) -> Poll<io::Result<()>> {
136
1.21M
        self.framed_write().poll_ready(cx)
137
1.21M
    }
138
139
    /// Returns whether the codec can buffer a frame without flushing the
140
    /// underlying I/O object.
141
1.13M
    pub(crate) fn has_send_capacity(&mut self) -> bool {
142
1.13M
        self.framed_write().has_capacity()
143
1.13M
    }
Unexecuted instantiation: <h2::codec::Codec<_, _>>::has_send_capacity
<h2::codec::Codec<fuzz_e2e::MockIo, h2::proto::streams::prioritize::Prioritized<bytes::bytes::Bytes>>>::has_send_capacity
Line
Count
Source
141
1.13M
    pub(crate) fn has_send_capacity(&mut self) -> bool {
142
1.13M
        self.framed_write().has_capacity()
143
1.13M
    }
144
145
    /// Buffer a frame.
146
    ///
147
    /// `poll_ready` must be called first to ensure that a frame may be
148
    /// accepted.
149
    ///
150
    /// TODO: Rename this to avoid conflicts with Sink::buffer
151
242k
    pub fn buffer(&mut self, item: Frame<B>) -> Result<(), UserError> {
152
242k
        self.framed_write().buffer(item)
153
242k
    }
Unexecuted instantiation: <h2::codec::Codec<_, _>>::buffer
<h2::codec::Codec<h2_support::mock::Mock, h2::proto::streams::prioritize::Prioritized<bytes::bytes::Bytes>>>::buffer
Line
Count
Source
151
816
    pub fn buffer(&mut self, item: Frame<B>) -> Result<(), UserError> {
152
816
        self.framed_write().buffer(item)
153
816
    }
<h2::codec::Codec<fuzz_e2e::MockIo, h2::proto::streams::prioritize::Prioritized<bytes::bytes::Bytes>>>::buffer
Line
Count
Source
151
241k
    pub fn buffer(&mut self, item: Frame<B>) -> Result<(), UserError> {
152
241k
        self.framed_write().buffer(item)
153
241k
    }
154
155
    /// Flush buffered data to the wire
156
456k
    pub fn flush(&mut self, cx: &mut Context) -> Poll<io::Result<()>> {
157
456k
        self.framed_write().flush(cx)
158
456k
    }
Unexecuted instantiation: <h2::codec::Codec<_, _>>::flush
<h2::codec::Codec<fuzz_e2e::MockIo, h2::proto::streams::prioritize::Prioritized<bytes::bytes::Bytes>>>::flush
Line
Count
Source
156
456k
    pub fn flush(&mut self, cx: &mut Context) -> Poll<io::Result<()>> {
157
456k
        self.framed_write().flush(cx)
158
456k
    }
159
160
    /// Shutdown the send half
161
10.9k
    pub fn shutdown(&mut self, cx: &mut Context) -> Poll<io::Result<()>> {
162
10.9k
        self.framed_write().shutdown(cx)
163
10.9k
    }
Unexecuted instantiation: <h2::codec::Codec<_, _>>::shutdown
<h2::codec::Codec<h2_support::mock::Pipe, bytes::bytes::Bytes>>::shutdown
Line
Count
Source
161
816
    pub fn shutdown(&mut self, cx: &mut Context) -> Poll<io::Result<()>> {
162
816
        self.framed_write().shutdown(cx)
163
816
    }
<h2::codec::Codec<fuzz_e2e::MockIo, h2::proto::streams::prioritize::Prioritized<bytes::bytes::Bytes>>>::shutdown
Line
Count
Source
161
10.1k
    pub fn shutdown(&mut self, cx: &mut Context) -> Poll<io::Result<()>> {
162
10.1k
        self.framed_write().shutdown(cx)
163
10.1k
    }
164
}
165
166
impl<T, B> Stream for Codec<T, B>
167
where
168
    T: AsyncRead + Unpin,
169
{
170
    type Item = Result<Frame, Error>;
171
172
1.24M
    fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
173
1.24M
        Pin::new(&mut self.inner).poll_next(cx)
174
1.24M
    }
Unexecuted instantiation: <h2::codec::Codec<_, _> as futures_core::stream::Stream>::poll_next
Unexecuted instantiation: <h2::codec::Codec<h2_support::mock::Pipe, bytes::bytes::Bytes> as futures_core::stream::Stream>::poll_next
<h2::codec::Codec<fuzz_e2e::MockIo, h2::proto::streams::prioritize::Prioritized<bytes::bytes::Bytes>> as futures_core::stream::Stream>::poll_next
Line
Count
Source
172
1.24M
    fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
173
1.24M
        Pin::new(&mut self.inner).poll_next(cx)
174
1.24M
    }
175
}
176
177
impl<T, B> Sink<Frame<B>> for Codec<T, B>
178
where
179
    T: AsyncWrite + Unpin,
180
    B: Buf,
181
{
182
    type Error = SendError;
183
184
0
    fn start_send(mut self: Pin<&mut Self>, item: Frame<B>) -> Result<(), Self::Error> {
185
0
        Codec::buffer(&mut self, item)?;
186
0
        Ok(())
187
0
    }
188
    /// Returns `Ready` when the codec can buffer a frame
189
0
    fn poll_ready(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
190
0
        self.framed_write().poll_ready(cx).map_err(Into::into)
191
0
    }
192
193
    /// Flush buffered data to the wire
194
0
    fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
195
0
        self.framed_write().flush(cx).map_err(Into::into)
196
0
    }
197
198
0
    fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
199
0
        ready!(self.shutdown(cx))?;
200
0
        Poll::Ready(Ok(()))
201
0
    }
202
}
203
204
// TODO: remove (or improve) this
205
impl<T> From<T> for Codec<T, bytes::Bytes>
206
where
207
    T: AsyncRead + AsyncWrite + Unpin,
208
{
209
0
    fn from(src: T) -> Self {
210
0
        Self::new(src)
211
0
    }
212
}