1use std::fmt;
13use std::io;
14
15#[derive(Debug, Clone, Copy, PartialEq, Eq)]
21#[non_exhaustive]
22pub enum ParseErrorKind {
23 HeadersTooLarge,
25 ConnectionClosed,
27 NoRequestLine,
29 IncompleteHeaders,
31 MalformedRequestLine,
33 MalformedRequestTarget,
35 MalformedHeader,
37 UnsupportedMethod,
39 UnsupportedHttpVersion,
41 TooManyHeaders,
43 MissingHostHeader,
45 DuplicateHeader,
47 ConflictingHeaders,
49 InvalidContentLength,
51 UnsupportedTransferEncoding,
53}
54
55impl fmt::Display for ParseErrorKind {
56 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
57 match self {
58 Self::HeadersTooLarge => f.write_str("headers too large"),
59 Self::ConnectionClosed => f.write_str("connection closed before headers complete"),
60 Self::NoRequestLine => f.write_str("no request line"),
61 Self::IncompleteHeaders => f.write_str("headers not terminated by \\r\\n\\r\\n"),
62 Self::MalformedRequestLine => f.write_str("malformed request line"),
63 Self::MalformedRequestTarget => f.write_str("request target contains invalid byte"),
64 Self::MalformedHeader => f.write_str("malformed header line"),
65 Self::UnsupportedMethod => f.write_str("unsupported method"),
66 Self::UnsupportedHttpVersion => f.write_str("unsupported HTTP version"),
67 Self::TooManyHeaders => f.write_str("too many headers"),
68 Self::MissingHostHeader => f.write_str("missing required Host header"),
69 Self::DuplicateHeader => f.write_str("duplicate header not allowed"),
70 Self::ConflictingHeaders => {
71 f.write_str("conflicting Transfer-Encoding and Content-Length")
72 }
73 Self::InvalidContentLength => f.write_str("invalid Content-Length value"),
74 Self::UnsupportedTransferEncoding => {
75 f.write_str("unsupported Transfer-Encoding (only chunked is supported)")
76 }
77 }
78 }
79}
80
81#[derive(Debug, Clone, Copy, PartialEq, Eq)]
87#[non_exhaustive]
88pub enum BodyErrorKind {
89 BodyTooLarge,
91 UnexpectedEof,
93 InvalidChunkSize,
95 MalformedChunkedEncoding,
97}
98
99impl fmt::Display for BodyErrorKind {
100 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
101 match self {
102 Self::BodyTooLarge => f.write_str("body exceeds buffer size"),
103 Self::UnexpectedEof => f.write_str("connection closed before body complete"),
104 Self::InvalidChunkSize => f.write_str("invalid chunk size"),
105 Self::MalformedChunkedEncoding => f.write_str("malformed chunked encoding"),
106 }
107 }
108}
109
110#[derive(Debug, Clone, Copy, PartialEq, Eq)]
116#[non_exhaustive]
117pub enum PctErrorKind {
118 InvalidEscape,
120 BufferTooSmall,
122}
123
124impl fmt::Display for PctErrorKind {
125 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
126 match self {
127 Self::InvalidEscape => f.write_str("invalid percent-encoded escape"),
128 Self::BufferTooSmall => f.write_str("decode buffer too small"),
129 }
130 }
131}
132
133#[derive(Debug, Clone, Copy, PartialEq, Eq)]
139#[non_exhaustive]
140pub enum MediaErrorKind {
141 Empty,
143 MissingSlash,
145 InvalidToken,
147}
148
149impl fmt::Display for MediaErrorKind {
150 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
151 match self {
152 Self::Empty => f.write_str("empty media type"),
153 Self::MissingSlash => f.write_str("media type missing '/'"),
154 Self::InvalidToken => f.write_str("media type has empty token"),
155 }
156 }
157}
158
159#[derive(Debug, Clone, Copy, PartialEq, Eq)]
165#[non_exhaustive]
166pub enum ResponseErrorKind {
167 HeaderCapacityExceeded,
169 InvalidHeaderName,
171 InvalidHeaderValue,
173 DuplicateContentLength,
175}
176
177impl fmt::Display for ResponseErrorKind {
178 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
179 match self {
180 Self::HeaderCapacityExceeded => f.write_str("response header capacity exceeded"),
181 Self::InvalidHeaderName => f.write_str("response header name contains invalid byte"),
182 Self::InvalidHeaderValue => {
183 f.write_str("response header value contains forbidden byte (NUL, CR, or LF)")
184 }
185 Self::DuplicateContentLength => f.write_str("duplicate Content-Length header"),
186 }
187 }
188}
189
190#[derive(Debug)]
217pub enum Error {
218 Io(io::Error),
220 Parse(ParseErrorKind),
222 Body(BodyErrorKind),
224 Response(ResponseErrorKind),
226 Pct(PctErrorKind),
228 Media(MediaErrorKind),
230}
231
232impl fmt::Display for Error {
233 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
234 match self {
235 Self::Io(e) => fmt::Display::fmt(e, f),
236 Self::Parse(k) => fmt::Display::fmt(k, f),
237 Self::Body(k) => fmt::Display::fmt(k, f),
238 Self::Response(k) => fmt::Display::fmt(k, f),
239 Self::Pct(k) => fmt::Display::fmt(k, f),
240 Self::Media(k) => fmt::Display::fmt(k, f),
241 }
242 }
243}
244
245impl std::error::Error for Error {
246 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
247 match self {
248 Self::Io(e) => Some(e),
249 _ => None,
250 }
251 }
252}
253
254impl From<io::Error> for Error {
255 fn from(e: io::Error) -> Self {
256 Self::Io(e)
257 }
258}
259
260impl From<ParseErrorKind> for Error {
261 fn from(k: ParseErrorKind) -> Self {
262 Self::Parse(k)
263 }
264}
265
266impl From<BodyErrorKind> for Error {
267 fn from(k: BodyErrorKind) -> Self {
268 Self::Body(k)
269 }
270}
271
272impl From<ResponseErrorKind> for Error {
273 fn from(k: ResponseErrorKind) -> Self {
274 Self::Response(k)
275 }
276}
277
278impl From<PctErrorKind> for Error {
279 fn from(k: PctErrorKind) -> Self {
280 Self::Pct(k)
281 }
282}
283
284impl From<MediaErrorKind> for Error {
285 fn from(k: MediaErrorKind) -> Self {
286 Self::Media(k)
287 }
288}
289
290impl From<Error> for io::Error {
291 fn from(e: Error) -> Self {
292 match e {
293 Error::Io(e) => e,
294 Error::Response(_) | Error::Pct(_) | Error::Media(_) => {
295 Self::new(io::ErrorKind::InvalidInput, e)
296 }
297 other => Self::new(io::ErrorKind::InvalidData, other),
298 }
299 }
300}
301
302#[derive(Debug)]
312pub struct ReadError {
313 pub error: Error,
315 pub bytes_read: usize,
319}
320
321impl fmt::Display for ReadError {
322 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
323 self.error.fmt(f)
324 }
325}
326
327impl std::error::Error for ReadError {
328 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
329 self.error.source()
330 }
331}
332
333impl From<ReadError> for io::Error {
334 fn from(e: ReadError) -> Self {
335 e.error.into()
336 }
337}