1use std::io;
4
5use thiserror::Error;
6
7pub type Result<T> = std::result::Result<T, Error>;
9
10#[derive(Debug, Error)]
12#[non_exhaustive]
13pub enum Error {
14 #[error("session is closed")]
16 SessionClosed,
17
18 #[error("remote sent GoAway: {0}")]
21 GoAway(ErrorCode),
22
23 #[error("stream {0} was reset by peer")]
25 StreamReset(u32),
26
27 #[error("too many concurrent streams (limit {0})")]
29 TooManyStreams(usize),
30
31 #[error("operation timed out")]
33 Timeout,
34
35 #[error("protocol error: {0}")]
37 Protocol(&'static str),
38
39 #[error("I/O error: {0}")]
41 Io(#[from] io::Error),
42}
43
44impl From<Error> for io::Error {
45 fn from(err: Error) -> io::Error {
46 match err {
47 Error::Io(e) => e,
48 Error::SessionClosed | Error::GoAway(_) => {
49 io::Error::new(io::ErrorKind::NotConnected, err)
50 }
51 Error::StreamReset(_) => io::Error::new(io::ErrorKind::ConnectionReset, err),
52 Error::Timeout => io::Error::new(io::ErrorKind::TimedOut, err),
53 Error::Protocol(_) => io::Error::new(io::ErrorKind::InvalidData, err),
54 Error::TooManyStreams(_) => io::Error::other(err),
55 }
56 }
57}
58
59#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
64#[non_exhaustive]
65pub enum ErrorCode {
66 Normal,
68 ProtocolError,
70 InternalError,
72 FlowControlError,
74 StreamLimit,
76 InvalidVersion,
78 Timeout,
80 Unknown(u32),
82}
83
84impl ErrorCode {
85 pub const fn as_u32(self) -> u32 {
87 match self {
88 ErrorCode::Normal => 0,
89 ErrorCode::ProtocolError => 1,
90 ErrorCode::InternalError => 2,
91 ErrorCode::FlowControlError => 3,
92 ErrorCode::StreamLimit => 4,
93 ErrorCode::InvalidVersion => 5,
94 ErrorCode::Timeout => 6,
95 ErrorCode::Unknown(v) => v,
96 }
97 }
98}
99
100impl From<u32> for ErrorCode {
101 fn from(v: u32) -> Self {
102 match v {
103 0 => ErrorCode::Normal,
104 1 => ErrorCode::ProtocolError,
105 2 => ErrorCode::InternalError,
106 3 => ErrorCode::FlowControlError,
107 4 => ErrorCode::StreamLimit,
108 5 => ErrorCode::InvalidVersion,
109 6 => ErrorCode::Timeout,
110 other => ErrorCode::Unknown(other),
111 }
112 }
113}
114
115impl std::fmt::Display for ErrorCode {
116 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
117 match self {
118 ErrorCode::Normal => f.write_str("normal"),
119 ErrorCode::ProtocolError => f.write_str("protocol error"),
120 ErrorCode::InternalError => f.write_str("internal error"),
121 ErrorCode::FlowControlError => f.write_str("flow control error"),
122 ErrorCode::StreamLimit => f.write_str("stream limit"),
123 ErrorCode::InvalidVersion => f.write_str("invalid version"),
124 ErrorCode::Timeout => f.write_str("timeout"),
125 ErrorCode::Unknown(v) => write!(f, "unknown error code {v}"),
126 }
127 }
128}