1use core::fmt;
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
8#[repr(u32)]
9pub enum ErrorCode {
10 NoError = 0x0,
11 ProtocolError = 0x1,
12 InternalError = 0x2,
13 FlowControlError = 0x3,
14 SettingsTimeout = 0x4,
15 StreamClosed = 0x5,
16 FrameSizeError = 0x6,
17 RefusedStream = 0x7,
18 Cancel = 0x8,
19 CompressionError = 0x9,
20 ConnectError = 0xa,
21 EnhanceYourCalm = 0xb,
22 InadequateSecurity = 0xc,
23 Http11Required = 0xd,
24}
25
26impl ErrorCode {
27 pub fn value(self) -> u32 {
29 self as u32
30 }
31
32 pub fn from_value(v: u32) -> Option<Self> {
34 use ErrorCode::*;
35 Some(match v {
36 0x0 => NoError,
37 0x1 => ProtocolError,
38 0x2 => InternalError,
39 0x3 => FlowControlError,
40 0x4 => SettingsTimeout,
41 0x5 => StreamClosed,
42 0x6 => FrameSizeError,
43 0x7 => RefusedStream,
44 0x8 => Cancel,
45 0x9 => CompressionError,
46 0xa => ConnectError,
47 0xb => EnhanceYourCalm,
48 0xc => InadequateSecurity,
49 0xd => Http11Required,
50 _ => return None,
51 })
52 }
53
54 pub fn name(self) -> &'static str {
56 use ErrorCode::*;
57 match self {
58 NoError => "NO_ERROR",
59 ProtocolError => "PROTOCOL_ERROR",
60 InternalError => "INTERNAL_ERROR",
61 FlowControlError => "FLOW_CONTROL_ERROR",
62 SettingsTimeout => "SETTINGS_TIMEOUT",
63 StreamClosed => "STREAM_CLOSED",
64 FrameSizeError => "FRAME_SIZE_ERROR",
65 RefusedStream => "REFUSED_STREAM",
66 Cancel => "CANCEL",
67 CompressionError => "COMPRESSION_ERROR",
68 ConnectError => "CONNECT_ERROR",
69 EnhanceYourCalm => "ENHANCE_YOUR_CALM",
70 InadequateSecurity => "INADEQUATE_SECURITY",
71 Http11Required => "HTTP_1_1_REQUIRED",
72 }
73 }
74}
75
76#[derive(Debug, Clone, PartialEq, Eq)]
79pub struct H2Error {
80 pub code: ErrorCode,
81 pub message: Option<String>,
82 pub stream_id: Option<u32>,
83}
84
85impl H2Error {
86 pub fn new(code: ErrorCode, message: impl Into<String>) -> Self {
88 Self {
89 code,
90 message: Some(message.into()),
91 stream_id: None,
92 }
93 }
94
95 pub fn code(code: ErrorCode) -> Self {
97 Self {
98 code,
99 message: None,
100 stream_id: None,
101 }
102 }
103
104 pub fn stream(code: ErrorCode, message: impl Into<String>, stream_id: u32) -> Self {
106 Self {
107 code,
108 message: Some(message.into()),
109 stream_id: Some(stream_id),
110 }
111 }
112}
113
114impl fmt::Display for H2Error {
115 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
116 match &self.message {
117 Some(m) => write!(f, "{}: {m}", self.code.name()),
118 None => f.write_str(self.code.name()),
119 }
120 }
121}
122
123impl std::error::Error for H2Error {}