1use crate::coding;
2
3#[derive(thiserror::Error, Debug, Clone)]
5#[non_exhaustive]
6pub enum Error {
7 #[error("transport error")]
8 Transport,
9
10 #[error("decode error")]
11 Decode,
12
13 #[error("unsupported versions")]
15 Version,
16
17 #[error("extension required")]
19 RequiredExtension,
20
21 #[error("unexpected stream type")]
23 UnexpectedStream,
24
25 #[error("varint bounds exceeded")]
27 BoundsExceeded,
28
29 #[error("duplicate")]
32 Duplicate,
33
34 #[error("cancelled")]
36 Cancel,
37
38 #[error("timeout")]
40 Timeout,
41
42 #[error("old")]
44 Old,
45
46 #[error("app code={0}")]
48 App(u16),
49
50 #[error("not found")]
51 NotFound,
52
53 #[error("wrong frame size")]
54 WrongSize,
55
56 #[error("protocol violation")]
57 ProtocolViolation,
58
59 #[error("unauthorized")]
60 Unauthorized,
61
62 #[error("unexpected message")]
63 UnexpectedMessage,
64
65 #[error("unsupported")]
66 Unsupported,
67
68 #[error("encode error")]
69 Encode,
70
71 #[error("too many parameters")]
72 TooManyParameters,
73
74 #[error("invalid role")]
75 InvalidRole,
76
77 #[error("unknown ALPN: {0}")]
78 UnknownAlpn(String),
79
80 #[error("dropped")]
81 Dropped,
82
83 #[error("closed")]
84 Closed,
85}
86
87impl Error {
88 pub fn to_code(&self) -> u32 {
90 match self {
91 Self::Cancel => 0,
92 Self::RequiredExtension => 1,
93 Self::Old => 2,
94 Self::Timeout => 3,
95 Self::Transport => 4,
96 Self::Decode => 5,
97 Self::Unauthorized => 6,
98 Self::Version => 9,
99 Self::UnexpectedStream => 10,
100 Self::BoundsExceeded => 11,
101 Self::Duplicate => 12,
102 Self::NotFound => 13,
103 Self::WrongSize => 14,
104 Self::ProtocolViolation => 15,
105 Self::UnexpectedMessage => 16,
106 Self::Unsupported => 17,
107 Self::Encode => 18,
108 Self::TooManyParameters => 19,
109 Self::InvalidRole => 20,
110 Self::UnknownAlpn(_) => 21,
111 Self::Dropped => 24,
112 Self::Closed => 25,
113 Self::App(app) => *app as u32 + 64,
114 }
115 }
116
117 pub fn from_code(code: u32) -> Self {
119 match code {
120 0 => Self::Cancel,
121 1 => Self::RequiredExtension,
122 2 => Self::Old,
123 3 => Self::Timeout,
124 4 => Self::Transport,
125 5 => Self::Decode,
126 6 => Self::Unauthorized,
127 9 => Self::Version,
128 10 => Self::UnexpectedStream,
129 11 => Self::BoundsExceeded,
130 12 => Self::Duplicate,
131 13 => Self::NotFound,
132 14 => Self::WrongSize,
133 15 => Self::ProtocolViolation,
134 16 => Self::UnexpectedMessage,
135 17 => Self::Unsupported,
136 18 => Self::Encode,
137 19 => Self::TooManyParameters,
138 20 => Self::InvalidRole,
139 24 => Self::Dropped,
140 25 => Self::Closed,
141 code if code >= 64 => match u16::try_from(code - 64) {
142 Ok(app) => Self::App(app),
143 Err(_) => Self::ProtocolViolation,
144 },
145 _ => Self::ProtocolViolation,
146 }
147 }
148
149 pub fn from_transport(err: impl web_transport_trait::Error) -> Self {
151 if let Some(code) = err.stream_error() {
152 return Self::from_code(code);
153 }
154
155 tracing::warn!(%err, "transport error");
156 Self::Transport
157 }
158}
159
160impl From<coding::DecodeError> for Error {
161 fn from(err: coding::DecodeError) -> Self {
162 tracing::warn!(%err, "decode error");
163 Error::Decode
164 }
165}
166
167impl From<coding::BoundsExceeded> for Error {
168 fn from(err: coding::BoundsExceeded) -> Self {
169 tracing::warn!(%err, "bounds exceeded");
170 Error::BoundsExceeded
171 }
172}
173
174impl From<coding::EncodeError> for Error {
175 fn from(err: coding::EncodeError) -> Self {
176 tracing::warn!(%err, "encode error");
177 Error::Encode
178 }
179}
180
181pub type Result<T> = std::result::Result<T, Error>;