1use core::fmt;
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
10#[repr(u32)]
11pub enum ErrorCode {
12 NoError = 0x0,
14 ProtocolError = 0x1,
16 InternalError = 0x2,
18 FlowControlError = 0x3,
20 SettingsTimeout = 0x4,
22 StreamClosed = 0x5,
24 FrameSizeError = 0x6,
26 RefusedStream = 0x7,
28 Cancel = 0x8,
30 CompressionError = 0x9,
32 ConnectError = 0xa,
34 EnhanceYourCalm = 0xb,
36 InadequateSecurity = 0xc,
38 Http11Required = 0xd,
40}
41
42impl ErrorCode {
43 #[must_use]
47 pub fn from_u32(v: u32) -> Self {
48 match v {
49 0x0 => Self::NoError,
50 0x1 => Self::ProtocolError,
51 0x2 => Self::InternalError,
52 0x3 => Self::FlowControlError,
53 0x4 => Self::SettingsTimeout,
54 0x5 => Self::StreamClosed,
55 0x6 => Self::FrameSizeError,
56 0x7 => Self::RefusedStream,
57 0x8 => Self::Cancel,
58 0x9 => Self::CompressionError,
59 0xa => Self::ConnectError,
60 0xb => Self::EnhanceYourCalm,
61 0xc => Self::InadequateSecurity,
62 0xd => Self::Http11Required,
63 _ => Self::InternalError,
64 }
65 }
66}
67
68#[derive(Debug, Clone, PartialEq, Eq)]
70pub enum Http2Error {
71 ShortFrameHeader,
73 ShortPayload,
75 FrameTooLarge {
77 got: u32,
79 max: u32,
81 },
82 UnknownFrameType(u8),
84 BadPreface,
86 InvalidState,
88 StreamIdZero,
90 StreamIdNonZero,
92 FlowControlExceeded,
94 Protocol(ErrorCode),
96}
97
98impl fmt::Display for Http2Error {
99 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
100 match self {
101 Self::ShortFrameHeader => f.write_str("short frame header (< 9 bytes)"),
102 Self::ShortPayload => f.write_str("short frame payload"),
103 Self::FrameTooLarge { got, max } => write!(f, "frame too large: {got} > {max}"),
104 Self::UnknownFrameType(t) => write!(f, "unknown frame type 0x{t:x}"),
105 Self::BadPreface => f.write_str("bad connection preface"),
106 Self::InvalidState => f.write_str("invalid stream state for frame"),
107 Self::StreamIdZero => f.write_str("stream id 0 not allowed"),
108 Self::StreamIdNonZero => f.write_str("stream id must be 0"),
109 Self::FlowControlExceeded => f.write_str("flow control window exceeded"),
110 Self::Protocol(e) => write!(f, "protocol error: {e:?}"),
111 }
112 }
113}
114
115#[cfg(feature = "std")]
116impl std::error::Error for Http2Error {}
117
118#[cfg(test)]
119#[allow(clippy::expect_used, clippy::unwrap_used, clippy::panic)]
120mod tests {
121 use super::*;
122
123 #[test]
124 fn from_u32_round_trip() {
125 for code in [
126 ErrorCode::NoError,
127 ErrorCode::ProtocolError,
128 ErrorCode::InternalError,
129 ErrorCode::FlowControlError,
130 ErrorCode::SettingsTimeout,
131 ErrorCode::StreamClosed,
132 ErrorCode::FrameSizeError,
133 ErrorCode::RefusedStream,
134 ErrorCode::Cancel,
135 ErrorCode::CompressionError,
136 ErrorCode::ConnectError,
137 ErrorCode::EnhanceYourCalm,
138 ErrorCode::InadequateSecurity,
139 ErrorCode::Http11Required,
140 ] {
141 assert_eq!(ErrorCode::from_u32(code as u32), code);
142 }
143 }
144
145 #[test]
146 fn unknown_code_maps_to_internal_error() {
147 assert_eq!(ErrorCode::from_u32(0xffff), ErrorCode::InternalError);
148 }
149
150 #[test]
151 fn error_display_does_not_panic() {
152 let _ = alloc::format!("{}", Http2Error::ShortFrameHeader);
153 let _ = alloc::format!("{}", Http2Error::FrameTooLarge { got: 1, max: 0 });
154 }
155}