Coverage Report

Created: 2025-08-26 07:09

/src/h2/src/frame/mod.rs
Line
Count
Source (jump to first uncovered line)
1
use crate::hpack;
2
3
use bytes::Bytes;
4
5
use std::fmt;
6
7
/// A helper macro that unpacks a sequence of 4 bytes found in the buffer with
8
/// the given identifier, starting at the given offset, into the given integer
9
/// type. Obviously, the integer type should be able to support at least 4
10
/// bytes.
11
///
12
/// # Examples
13
///
14
/// ```ignore
15
/// # // We ignore this doctest because the macro is not exported.
16
/// let buf: [u8; 4] = [0, 0, 0, 1];
17
/// assert_eq!(1u32, unpack_octets_4!(buf, 0, u32));
18
/// ```
19
macro_rules! unpack_octets_4 {
20
    // TODO: Get rid of this macro
21
    ($buf:expr, $offset:expr, $tip:ty) => {
22
        (($buf[$offset + 0] as $tip) << 24)
23
            | (($buf[$offset + 1] as $tip) << 16)
24
            | (($buf[$offset + 2] as $tip) << 8)
25
            | (($buf[$offset + 3] as $tip) << 0)
26
    };
27
}
28
29
#[cfg(test)]
30
mod tests {
31
    #[test]
32
    fn test_unpack_octets_4() {
33
        let buf: [u8; 4] = [0, 0, 0, 1];
34
        assert_eq!(1u32, unpack_octets_4!(buf, 0, u32));
35
    }
36
}
37
38
mod data;
39
mod go_away;
40
mod head;
41
mod headers;
42
mod ping;
43
mod priority;
44
mod reason;
45
mod reset;
46
mod settings;
47
mod stream_id;
48
mod util;
49
mod window_update;
50
51
pub use self::data::Data;
52
pub use self::go_away::GoAway;
53
pub use self::head::{Head, Kind};
54
pub use self::headers::{
55
    parse_u64, Continuation, Headers, Pseudo, PushPromise, PushPromiseHeaderError,
56
};
57
pub use self::ping::Ping;
58
pub use self::priority::{Priority, StreamDependency};
59
pub use self::reason::Reason;
60
pub use self::reset::Reset;
61
pub use self::settings::Settings;
62
pub use self::stream_id::{StreamId, StreamIdOverflow};
63
pub use self::window_update::WindowUpdate;
64
65
#[cfg(feature = "unstable")]
66
pub use crate::hpack::BytesStr;
67
68
// Re-export some constants
69
70
pub use self::settings::{
71
    DEFAULT_INITIAL_WINDOW_SIZE, DEFAULT_MAX_FRAME_SIZE, DEFAULT_SETTINGS_HEADER_TABLE_SIZE,
72
    MAX_MAX_FRAME_SIZE,
73
};
74
75
pub type FrameSize = u32;
76
77
pub const HEADER_LEN: usize = 9;
78
79
#[derive(Eq, PartialEq)]
80
pub enum Frame<T = Bytes> {
81
    Data(Data<T>),
82
    Headers(Headers),
83
    Priority(Priority),
84
    PushPromise(PushPromise),
85
    Settings(Settings),
86
    Ping(Ping),
87
    GoAway(GoAway),
88
    WindowUpdate(WindowUpdate),
89
    Reset(Reset),
90
}
91
92
impl<T> Frame<T> {
93
185k
    pub fn map<F, U>(self, f: F) -> Frame<U>
94
185k
    where
95
185k
        F: FnOnce(T) -> U,
96
185k
    {
97
        use self::Frame::*;
98
99
185k
        match self {
100
0
            Data(frame) => frame.map(f).into(),
101
184k
            Headers(frame) => frame.into(),
102
0
            Priority(frame) => frame.into(),
103
0
            PushPromise(frame) => frame.into(),
104
0
            Settings(frame) => frame.into(),
105
0
            Ping(frame) => frame.into(),
106
0
            GoAway(frame) => frame.into(),
107
0
            WindowUpdate(frame) => frame.into(),
108
1.45k
            Reset(frame) => frame.into(),
109
        }
110
185k
    }
Unexecuted instantiation: <h2::frame::Frame<_>>::map::<_, _>
<h2::frame::Frame>::map::<<h2::proto::streams::prioritize::Prioritize>::pop_frame<bytes::bytes::Bytes>::{closure#3}, h2::proto::streams::prioritize::Prioritized<bytes::bytes::Bytes>>
Line
Count
Source
93
185k
    pub fn map<F, U>(self, f: F) -> Frame<U>
94
185k
    where
95
185k
        F: FnOnce(T) -> U,
96
185k
    {
97
        use self::Frame::*;
98
99
185k
        match self {
100
0
            Data(frame) => frame.map(f).into(),
101
184k
            Headers(frame) => frame.into(),
102
0
            Priority(frame) => frame.into(),
103
0
            PushPromise(frame) => frame.into(),
104
0
            Settings(frame) => frame.into(),
105
0
            Ping(frame) => frame.into(),
106
0
            GoAway(frame) => frame.into(),
107
0
            WindowUpdate(frame) => frame.into(),
108
1.45k
            Reset(frame) => frame.into(),
109
        }
110
185k
    }
111
}
112
113
impl<T> fmt::Debug for Frame<T> {
114
0
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
115
        use self::Frame::*;
116
117
0
        match *self {
118
0
            Data(ref frame) => fmt::Debug::fmt(frame, fmt),
119
0
            Headers(ref frame) => fmt::Debug::fmt(frame, fmt),
120
0
            Priority(ref frame) => fmt::Debug::fmt(frame, fmt),
121
0
            PushPromise(ref frame) => fmt::Debug::fmt(frame, fmt),
122
0
            Settings(ref frame) => fmt::Debug::fmt(frame, fmt),
123
0
            Ping(ref frame) => fmt::Debug::fmt(frame, fmt),
124
0
            GoAway(ref frame) => fmt::Debug::fmt(frame, fmt),
125
0
            WindowUpdate(ref frame) => fmt::Debug::fmt(frame, fmt),
126
0
            Reset(ref frame) => fmt::Debug::fmt(frame, fmt),
127
        }
128
0
    }
Unexecuted instantiation: <h2::frame::Frame<_> as core::fmt::Debug>::fmt
Unexecuted instantiation: <h2::frame::Frame<h2::proto::streams::prioritize::Prioritized<bytes::bytes::Bytes>> as core::fmt::Debug>::fmt
Unexecuted instantiation: <h2::frame::Frame as core::fmt::Debug>::fmt
Unexecuted instantiation: <h2::frame::Frame<h2::proto::streams::prioritize::Prioritized<bytes::bytes::Bytes>> as core::fmt::Debug>::fmt
Unexecuted instantiation: <h2::frame::Frame as core::fmt::Debug>::fmt
129
}
130
131
/// Errors that can occur during parsing an HTTP/2 frame.
132
#[derive(Debug, Clone, PartialEq, Eq)]
133
pub enum Error {
134
    /// A length value other than 8 was set on a PING message.
135
    BadFrameSize,
136
137
    /// The padding length was larger than the frame-header-specified
138
    /// length of the payload.
139
    TooMuchPadding,
140
141
    /// An invalid setting value was provided
142
    InvalidSettingValue,
143
144
    /// An invalid window update value
145
    InvalidWindowUpdateValue,
146
147
    /// The payload length specified by the frame header was not the
148
    /// value necessary for the specific frame type.
149
    InvalidPayloadLength,
150
151
    /// Received a payload with an ACK settings frame
152
    InvalidPayloadAckSettings,
153
154
    /// An invalid stream identifier was provided.
155
    ///
156
    /// This is returned if a SETTINGS or PING frame is received with a stream
157
    /// identifier other than zero.
158
    InvalidStreamId,
159
160
    /// A request or response is malformed.
161
    MalformedMessage,
162
163
    /// An invalid stream dependency ID was provided
164
    ///
165
    /// This is returned if a HEADERS or PRIORITY frame is received with an
166
    /// invalid stream identifier.
167
    InvalidDependencyId,
168
169
    /// Failed to perform HPACK decoding
170
    Hpack(hpack::DecoderError),
171
}