Coverage Report

Created: 2025-11-28 06:44

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/hyper-1.6.0/src/error.rs
Line
Count
Source
1
//! Error and Result module.
2
use std::error::Error as StdError;
3
use std::fmt;
4
5
/// Result type often returned from methods that can have hyper `Error`s.
6
pub type Result<T> = std::result::Result<T, Error>;
7
8
type Cause = Box<dyn StdError + Send + Sync>;
9
10
/// Represents errors that can occur handling HTTP streams.
11
///
12
/// # Formatting
13
///
14
/// The `Display` implementation of this type will only print the details of
15
/// this level of error, even though it may have been caused by another error
16
/// and contain that error in its source. To print all the relevant
17
/// information, including the source chain, using something like
18
/// `std::error::Report`, or equivalent 3rd party types.
19
///
20
/// The contents of the formatted error message of this specific `Error` type
21
/// is unspecified. **You must not depend on it.** The wording and details may
22
/// change in any version, with the goal of improving error messages.
23
///
24
/// # Source
25
///
26
/// A `hyper::Error` may be caused by another error. To aid in debugging,
27
/// those are exposed in `Error::source()` as erased types. While it is
28
/// possible to check the exact type of the sources, they **can not be depended
29
/// on**. They may come from private internal dependencies, and are subject to
30
/// change at any moment.
31
pub struct Error {
32
    inner: Box<ErrorImpl>,
33
}
34
35
struct ErrorImpl {
36
    kind: Kind,
37
    cause: Option<Cause>,
38
}
39
40
#[derive(Debug)]
41
pub(super) enum Kind {
42
    Parse(Parse),
43
    User(User),
44
    /// A message reached EOF, but is not complete.
45
    #[cfg(all(any(feature = "client", feature = "server"), feature = "http1"))]
46
    IncompleteMessage,
47
    /// A connection received a message (or bytes) when not waiting for one.
48
    #[cfg(all(any(feature = "client", feature = "server"), feature = "http1"))]
49
    UnexpectedMessage,
50
    /// A pending item was dropped before ever being processed.
51
    Canceled,
52
    /// Indicates a channel (client or body sender) is closed.
53
    #[cfg(any(
54
        all(feature = "http1", any(feature = "client", feature = "server")),
55
        all(feature = "http2", feature = "client")
56
    ))]
57
    ChannelClosed,
58
    /// An `io::Error` that occurred while trying to read or write to a network stream.
59
    #[cfg(all(
60
        any(feature = "client", feature = "server"),
61
        any(feature = "http1", feature = "http2")
62
    ))]
63
    Io,
64
    /// User took too long to send headers
65
    #[cfg(all(feature = "http1", feature = "server"))]
66
    HeaderTimeout,
67
    /// Error while reading a body from connection.
68
    #[cfg(all(
69
        any(feature = "client", feature = "server"),
70
        any(feature = "http1", feature = "http2")
71
    ))]
72
    Body,
73
    /// Error while writing a body to connection.
74
    #[cfg(all(
75
        any(feature = "client", feature = "server"),
76
        any(feature = "http1", feature = "http2")
77
    ))]
78
    BodyWrite,
79
    /// Error calling AsyncWrite::shutdown()
80
    #[cfg(all(any(feature = "client", feature = "server"), feature = "http1"))]
81
    Shutdown,
82
83
    /// A general error from h2.
84
    #[cfg(all(any(feature = "client", feature = "server"), feature = "http2"))]
85
    Http2,
86
}
87
88
#[derive(Debug)]
89
pub(super) enum Parse {
90
    Method,
91
    #[cfg(feature = "http1")]
92
    Version,
93
    #[cfg(all(any(feature = "client", feature = "server"), feature = "http1"))]
94
    VersionH2,
95
    Uri,
96
    #[cfg(all(feature = "http1", feature = "server"))]
97
    UriTooLong,
98
    #[cfg(feature = "http1")]
99
    Header(Header),
100
    #[cfg(any(feature = "http1", feature = "http2"))]
101
    #[cfg_attr(feature = "http2", allow(unused))]
102
    TooLarge,
103
    Status,
104
    #[cfg(all(any(feature = "client", feature = "server"), feature = "http1"))]
105
    Internal,
106
}
107
108
#[derive(Debug)]
109
#[cfg(feature = "http1")]
110
pub(super) enum Header {
111
    Token,
112
    #[cfg(any(feature = "client", feature = "server"))]
113
    ContentLengthInvalid,
114
    #[cfg(feature = "server")]
115
    TransferEncodingInvalid,
116
    #[cfg(any(feature = "client", feature = "server"))]
117
    TransferEncodingUnexpected,
118
}
119
120
#[derive(Debug)]
121
pub(super) enum User {
122
    /// Error calling user's Body::poll_data().
123
    #[cfg(all(
124
        any(feature = "client", feature = "server"),
125
        any(feature = "http1", feature = "http2")
126
    ))]
127
    Body,
128
    /// The user aborted writing of the outgoing body.
129
    #[cfg(any(
130
        all(feature = "http1", any(feature = "client", feature = "server")),
131
        feature = "ffi"
132
    ))]
133
    BodyWriteAborted,
134
    /// Error from future of user's Service.
135
    #[cfg(any(
136
        all(any(feature = "client", feature = "server"), feature = "http1"),
137
        all(feature = "server", feature = "http2")
138
    ))]
139
    Service,
140
    /// User tried to send a certain header in an unexpected context.
141
    ///
142
    /// For example, sending both `content-length` and `transfer-encoding`.
143
    #[cfg(any(feature = "http1", feature = "http2"))]
144
    #[cfg(feature = "server")]
145
    UnexpectedHeader,
146
    /// User tried to respond with a 1xx (not 101) response code.
147
    #[cfg(feature = "http1")]
148
    #[cfg(feature = "server")]
149
    UnsupportedStatusCode,
150
151
    /// User tried polling for an upgrade that doesn't exist.
152
    NoUpgrade,
153
154
    /// User polled for an upgrade, but low-level API is not using upgrades.
155
    #[cfg(all(any(feature = "client", feature = "server"), feature = "http1"))]
156
    ManualUpgrade,
157
158
    /// The dispatch task is gone.
159
    #[cfg(all(feature = "client", any(feature = "http1", feature = "http2")))]
160
    DispatchGone,
161
162
    /// User aborted in an FFI callback.
163
    #[cfg(feature = "ffi")]
164
    AbortedByCallback,
165
}
166
167
// Sentinel type to indicate the error was caused by a timeout.
168
#[derive(Debug)]
169
pub(super) struct TimedOut;
170
171
impl Error {
172
    /// Returns true if this was an HTTP parse error.
173
0
    pub fn is_parse(&self) -> bool {
174
0
        matches!(self.inner.kind, Kind::Parse(_))
175
0
    }
176
177
    /// Returns true if this was an HTTP parse error caused by a message that was too large.
178
    #[cfg(all(feature = "http1", feature = "server"))]
179
0
    pub fn is_parse_too_large(&self) -> bool {
180
0
        matches!(
181
0
            self.inner.kind,
182
            Kind::Parse(Parse::TooLarge) | Kind::Parse(Parse::UriTooLong)
183
        )
184
0
    }
185
186
    /// Returns true if this was an HTTP parse error caused by an invalid response status code or
187
    /// reason phrase.
188
0
    pub fn is_parse_status(&self) -> bool {
189
0
        matches!(self.inner.kind, Kind::Parse(Parse::Status))
190
0
    }
191
192
    /// Returns true if this error was caused by user code.
193
0
    pub fn is_user(&self) -> bool {
194
0
        matches!(self.inner.kind, Kind::User(_))
195
0
    }
196
197
    /// Returns true if this was about a `Request` that was canceled.
198
0
    pub fn is_canceled(&self) -> bool {
199
0
        matches!(self.inner.kind, Kind::Canceled)
200
0
    }
201
202
    /// Returns true if a sender's channel is closed.
203
0
    pub fn is_closed(&self) -> bool {
204
        #[cfg(not(any(
205
            all(feature = "http1", any(feature = "client", feature = "server")),
206
            all(feature = "http2", feature = "client")
207
        )))]
208
        return false;
209
210
        #[cfg(any(
211
            all(feature = "http1", any(feature = "client", feature = "server")),
212
            all(feature = "http2", feature = "client")
213
        ))]
214
0
        matches!(self.inner.kind, Kind::ChannelClosed)
215
0
    }
216
217
    /// Returns true if the connection closed before a message could complete.
218
0
    pub fn is_incomplete_message(&self) -> bool {
219
        #[cfg(not(all(any(feature = "client", feature = "server"), feature = "http1")))]
220
        return false;
221
222
        #[cfg(all(any(feature = "client", feature = "server"), feature = "http1"))]
223
0
        matches!(self.inner.kind, Kind::IncompleteMessage)
224
0
    }
225
226
    /// Returns true if the body write was aborted.
227
0
    pub fn is_body_write_aborted(&self) -> bool {
228
        #[cfg(not(any(
229
            all(feature = "http1", any(feature = "client", feature = "server")),
230
            feature = "ffi"
231
        )))]
232
        return false;
233
234
        #[cfg(any(
235
            all(feature = "http1", any(feature = "client", feature = "server")),
236
            feature = "ffi"
237
        ))]
238
0
        matches!(self.inner.kind, Kind::User(User::BodyWriteAborted))
239
0
    }
240
241
    /// Returns true if the error was caused by a timeout.
242
0
    pub fn is_timeout(&self) -> bool {
243
        #[cfg(all(feature = "http1", feature = "server"))]
244
0
        if matches!(self.inner.kind, Kind::HeaderTimeout) {
245
0
            return true;
246
0
        }
247
0
        self.find_source::<TimedOut>().is_some()
248
0
    }
249
250
0
    pub(super) fn new(kind: Kind) -> Error {
251
0
        Error {
252
0
            inner: Box::new(ErrorImpl { kind, cause: None }),
253
0
        }
254
0
    }
255
256
0
    pub(super) fn with<C: Into<Cause>>(mut self, cause: C) -> Error {
257
0
        self.inner.cause = Some(cause.into());
258
0
        self
259
0
    }
Unexecuted instantiation: <hyper::error::Error>::with::<tonic::status::Status>
Unexecuted instantiation: <hyper::error::Error>::with::<hyper::upgrade::UpgradeExpected>
Unexecuted instantiation: <hyper::error::Error>::with::<h2::error::Error>
Unexecuted instantiation: <hyper::error::Error>::with::<std::io::error::Error>
Unexecuted instantiation: <hyper::error::Error>::with::<hyper::proto::h2::ping::KeepAliveTimedOut>
Unexecuted instantiation: <hyper::error::Error>::with::<&str>
260
261
    #[cfg(any(all(feature = "http1", feature = "server"), feature = "ffi"))]
262
0
    pub(super) fn kind(&self) -> &Kind {
263
0
        &self.inner.kind
264
0
    }
265
266
0
    pub(crate) fn find_source<E: StdError + 'static>(&self) -> Option<&E> {
267
0
        let mut cause = self.source();
268
0
        while let Some(err) = cause {
269
0
            if let Some(typed) = err.downcast_ref() {
270
0
                return Some(typed);
271
0
            }
272
0
            cause = err.source();
273
        }
274
275
        // else
276
0
        None
277
0
    }
Unexecuted instantiation: <hyper::error::Error>::find_source::<hyper::error::TimedOut>
Unexecuted instantiation: <hyper::error::Error>::find_source::<h2::error::Error>
278
279
    #[cfg(all(any(feature = "client", feature = "server"), feature = "http2"))]
280
0
    pub(super) fn h2_reason(&self) -> h2::Reason {
281
        // Find an h2::Reason somewhere in the cause stack, if it exists,
282
        // otherwise assume an INTERNAL_ERROR.
283
0
        self.find_source::<h2::Error>()
284
0
            .and_then(|h2_err| h2_err.reason())
285
0
            .unwrap_or(h2::Reason::INTERNAL_ERROR)
286
0
    }
287
288
0
    pub(super) fn new_canceled() -> Error {
289
0
        Error::new(Kind::Canceled)
290
0
    }
291
292
    #[cfg(all(any(feature = "client", feature = "server"), feature = "http1"))]
293
0
    pub(super) fn new_incomplete() -> Error {
294
0
        Error::new(Kind::IncompleteMessage)
295
0
    }
296
297
    #[cfg(all(any(feature = "client", feature = "server"), feature = "http1"))]
298
0
    pub(super) fn new_too_large() -> Error {
299
0
        Error::new(Kind::Parse(Parse::TooLarge))
300
0
    }
301
302
    #[cfg(all(any(feature = "client", feature = "server"), feature = "http1"))]
303
0
    pub(super) fn new_version_h2() -> Error {
304
0
        Error::new(Kind::Parse(Parse::VersionH2))
305
0
    }
306
307
    #[cfg(all(any(feature = "client", feature = "server"), feature = "http1"))]
308
0
    pub(super) fn new_unexpected_message() -> Error {
309
0
        Error::new(Kind::UnexpectedMessage)
310
0
    }
311
312
    #[cfg(all(
313
        any(feature = "client", feature = "server"),
314
        any(feature = "http1", feature = "http2")
315
    ))]
316
0
    pub(super) fn new_io(cause: std::io::Error) -> Error {
317
0
        Error::new(Kind::Io).with(cause)
318
0
    }
319
320
    #[cfg(any(
321
        all(feature = "http1", any(feature = "client", feature = "server")),
322
        all(feature = "http2", feature = "client")
323
    ))]
324
0
    pub(super) fn new_closed() -> Error {
325
0
        Error::new(Kind::ChannelClosed)
326
0
    }
327
328
    #[cfg(all(
329
        any(feature = "client", feature = "server"),
330
        any(feature = "http1", feature = "http2")
331
    ))]
332
0
    pub(super) fn new_body<E: Into<Cause>>(cause: E) -> Error {
333
0
        Error::new(Kind::Body).with(cause)
334
0
    }
335
336
    #[cfg(all(
337
        any(feature = "client", feature = "server"),
338
        any(feature = "http1", feature = "http2")
339
    ))]
340
0
    pub(super) fn new_body_write<E: Into<Cause>>(cause: E) -> Error {
341
0
        Error::new(Kind::BodyWrite).with(cause)
342
0
    }
Unexecuted instantiation: <hyper::error::Error>::new_body_write::<h2::error::Error>
Unexecuted instantiation: <hyper::error::Error>::new_body_write::<&str>
Unexecuted instantiation: <hyper::error::Error>::new_body_write::<_>
343
344
    #[cfg(any(
345
        all(feature = "http1", any(feature = "client", feature = "server")),
346
        feature = "ffi"
347
    ))]
348
0
    pub(super) fn new_body_write_aborted() -> Error {
349
0
        Error::new(Kind::User(User::BodyWriteAborted))
350
0
    }
351
352
0
    fn new_user(user: User) -> Error {
353
0
        Error::new(Kind::User(user))
354
0
    }
355
356
    #[cfg(any(feature = "http1", feature = "http2"))]
357
    #[cfg(feature = "server")]
358
0
    pub(super) fn new_user_header() -> Error {
359
0
        Error::new_user(User::UnexpectedHeader)
360
0
    }
361
362
    #[cfg(all(feature = "http1", feature = "server"))]
363
0
    pub(super) fn new_header_timeout() -> Error {
364
0
        Error::new(Kind::HeaderTimeout)
365
0
    }
366
367
    #[cfg(feature = "http1")]
368
    #[cfg(feature = "server")]
369
0
    pub(super) fn new_user_unsupported_status_code() -> Error {
370
0
        Error::new_user(User::UnsupportedStatusCode)
371
0
    }
372
373
0
    pub(super) fn new_user_no_upgrade() -> Error {
374
0
        Error::new_user(User::NoUpgrade)
375
0
    }
376
377
    #[cfg(all(any(feature = "client", feature = "server"), feature = "http1"))]
378
0
    pub(super) fn new_user_manual_upgrade() -> Error {
379
0
        Error::new_user(User::ManualUpgrade)
380
0
    }
381
382
    #[cfg(any(
383
        all(any(feature = "client", feature = "server"), feature = "http1"),
384
        all(feature = "server", feature = "http2")
385
    ))]
386
0
    pub(super) fn new_user_service<E: Into<Cause>>(cause: E) -> Error {
387
0
        Error::new_user(User::Service).with(cause)
388
0
    }
389
390
    #[cfg(all(
391
        any(feature = "client", feature = "server"),
392
        any(feature = "http1", feature = "http2")
393
    ))]
394
0
    pub(super) fn new_user_body<E: Into<Cause>>(cause: E) -> Error {
395
0
        Error::new_user(User::Body).with(cause)
396
0
    }
Unexecuted instantiation: <hyper::error::Error>::new_user_body::<tonic::status::Status>
Unexecuted instantiation: <hyper::error::Error>::new_user_body::<_>
397
398
    #[cfg(all(any(feature = "client", feature = "server"), feature = "http1"))]
399
0
    pub(super) fn new_shutdown(cause: std::io::Error) -> Error {
400
0
        Error::new(Kind::Shutdown).with(cause)
401
0
    }
402
403
    #[cfg(feature = "ffi")]
404
    pub(super) fn new_user_aborted_by_callback() -> Error {
405
        Error::new_user(User::AbortedByCallback)
406
    }
407
408
    #[cfg(all(feature = "client", any(feature = "http1", feature = "http2")))]
409
0
    pub(super) fn new_user_dispatch_gone() -> Error {
410
0
        Error::new(Kind::User(User::DispatchGone))
411
0
    }
412
413
    #[cfg(all(any(feature = "client", feature = "server"), feature = "http2"))]
414
0
    pub(super) fn new_h2(cause: ::h2::Error) -> Error {
415
0
        if cause.is_io() {
416
0
            Error::new_io(cause.into_io().expect("h2::Error::is_io"))
417
        } else {
418
0
            Error::new(Kind::Http2).with(cause)
419
        }
420
0
    }
421
422
0
    fn description(&self) -> &str {
423
0
        match self.inner.kind {
424
0
            Kind::Parse(Parse::Method) => "invalid HTTP method parsed",
425
            #[cfg(feature = "http1")]
426
0
            Kind::Parse(Parse::Version) => "invalid HTTP version parsed",
427
            #[cfg(all(any(feature = "client", feature = "server"), feature = "http1"))]
428
0
            Kind::Parse(Parse::VersionH2) => "invalid HTTP version parsed (found HTTP2 preface)",
429
0
            Kind::Parse(Parse::Uri) => "invalid URI",
430
            #[cfg(all(feature = "http1", feature = "server"))]
431
0
            Kind::Parse(Parse::UriTooLong) => "URI too long",
432
            #[cfg(feature = "http1")]
433
0
            Kind::Parse(Parse::Header(Header::Token)) => "invalid HTTP header parsed",
434
            #[cfg(all(any(feature = "client", feature = "server"), feature = "http1"))]
435
            Kind::Parse(Parse::Header(Header::ContentLengthInvalid)) => {
436
0
                "invalid content-length parsed"
437
            }
438
            #[cfg(all(feature = "http1", feature = "server"))]
439
            Kind::Parse(Parse::Header(Header::TransferEncodingInvalid)) => {
440
0
                "invalid transfer-encoding parsed"
441
            }
442
            #[cfg(all(feature = "http1", any(feature = "client", feature = "server")))]
443
            Kind::Parse(Parse::Header(Header::TransferEncodingUnexpected)) => {
444
0
                "unexpected transfer-encoding parsed"
445
            }
446
            #[cfg(any(feature = "http1", feature = "http2"))]
447
0
            Kind::Parse(Parse::TooLarge) => "message head is too large",
448
0
            Kind::Parse(Parse::Status) => "invalid HTTP status-code parsed",
449
            #[cfg(all(any(feature = "client", feature = "server"), feature = "http1"))]
450
            Kind::Parse(Parse::Internal) => {
451
0
                "internal error inside Hyper and/or its dependencies, please report"
452
            }
453
            #[cfg(all(any(feature = "client", feature = "server"), feature = "http1"))]
454
0
            Kind::IncompleteMessage => "connection closed before message completed",
455
            #[cfg(all(any(feature = "client", feature = "server"), feature = "http1"))]
456
0
            Kind::UnexpectedMessage => "received unexpected message from connection",
457
            #[cfg(any(
458
                all(feature = "http1", any(feature = "client", feature = "server")),
459
                all(feature = "http2", feature = "client")
460
            ))]
461
0
            Kind::ChannelClosed => "channel closed",
462
0
            Kind::Canceled => "operation was canceled",
463
            #[cfg(all(feature = "http1", feature = "server"))]
464
0
            Kind::HeaderTimeout => "read header from client timeout",
465
            #[cfg(all(
466
                any(feature = "client", feature = "server"),
467
                any(feature = "http1", feature = "http2")
468
            ))]
469
0
            Kind::Body => "error reading a body from connection",
470
            #[cfg(all(
471
                any(feature = "client", feature = "server"),
472
                any(feature = "http1", feature = "http2")
473
            ))]
474
0
            Kind::BodyWrite => "error writing a body to connection",
475
            #[cfg(all(any(feature = "client", feature = "server"), feature = "http1"))]
476
0
            Kind::Shutdown => "error shutting down connection",
477
            #[cfg(all(any(feature = "client", feature = "server"), feature = "http2"))]
478
0
            Kind::Http2 => "http2 error",
479
            #[cfg(all(
480
                any(feature = "client", feature = "server"),
481
                any(feature = "http1", feature = "http2")
482
            ))]
483
0
            Kind::Io => "connection error",
484
485
            #[cfg(all(
486
                any(feature = "client", feature = "server"),
487
                any(feature = "http1", feature = "http2")
488
            ))]
489
0
            Kind::User(User::Body) => "error from user's Body stream",
490
            #[cfg(any(
491
                all(feature = "http1", any(feature = "client", feature = "server")),
492
                feature = "ffi"
493
            ))]
494
0
            Kind::User(User::BodyWriteAborted) => "user body write aborted",
495
            #[cfg(any(
496
                all(any(feature = "client", feature = "server"), feature = "http1"),
497
                all(feature = "server", feature = "http2")
498
            ))]
499
0
            Kind::User(User::Service) => "error from user's Service",
500
            #[cfg(any(feature = "http1", feature = "http2"))]
501
            #[cfg(feature = "server")]
502
0
            Kind::User(User::UnexpectedHeader) => "user sent unexpected header",
503
            #[cfg(feature = "http1")]
504
            #[cfg(feature = "server")]
505
            Kind::User(User::UnsupportedStatusCode) => {
506
0
                "response has 1xx status code, not supported by server"
507
            }
508
0
            Kind::User(User::NoUpgrade) => "no upgrade available",
509
            #[cfg(all(any(feature = "client", feature = "server"), feature = "http1"))]
510
0
            Kind::User(User::ManualUpgrade) => "upgrade expected but low level API in use",
511
            #[cfg(all(feature = "client", any(feature = "http1", feature = "http2")))]
512
0
            Kind::User(User::DispatchGone) => "dispatch task is gone",
513
            #[cfg(feature = "ffi")]
514
            Kind::User(User::AbortedByCallback) => "operation aborted by an application callback",
515
        }
516
0
    }
517
}
518
519
impl fmt::Debug for Error {
520
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
521
0
        let mut f = f.debug_tuple("hyper::Error");
522
0
        f.field(&self.inner.kind);
523
0
        if let Some(ref cause) = self.inner.cause {
524
0
            f.field(cause);
525
0
        }
526
0
        f.finish()
527
0
    }
528
}
529
530
impl fmt::Display for Error {
531
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
532
0
        f.write_str(self.description())
533
0
    }
534
}
535
536
impl StdError for Error {
537
0
    fn source(&self) -> Option<&(dyn StdError + 'static)> {
538
0
        self.inner
539
0
            .cause
540
0
            .as_ref()
541
0
            .map(|cause| &**cause as &(dyn StdError + 'static))
542
0
    }
543
}
544
545
#[doc(hidden)]
546
impl From<Parse> for Error {
547
0
    fn from(err: Parse) -> Error {
548
0
        Error::new(Kind::Parse(err))
549
0
    }
550
}
551
552
#[cfg(feature = "http1")]
553
impl Parse {
554
    #[cfg(any(feature = "client", feature = "server"))]
555
0
    pub(crate) fn content_length_invalid() -> Self {
556
0
        Parse::Header(Header::ContentLengthInvalid)
557
0
    }
558
559
    #[cfg(feature = "server")]
560
0
    pub(crate) fn transfer_encoding_invalid() -> Self {
561
0
        Parse::Header(Header::TransferEncodingInvalid)
562
0
    }
563
564
    #[cfg(any(feature = "client", feature = "server"))]
565
0
    pub(crate) fn transfer_encoding_unexpected() -> Self {
566
0
        Parse::Header(Header::TransferEncodingUnexpected)
567
0
    }
568
}
569
570
#[cfg(feature = "http1")]
571
impl From<httparse::Error> for Parse {
572
0
    fn from(err: httparse::Error) -> Parse {
573
0
        match err {
574
            httparse::Error::HeaderName
575
            | httparse::Error::HeaderValue
576
            | httparse::Error::NewLine
577
0
            | httparse::Error::Token => Parse::Header(Header::Token),
578
0
            httparse::Error::Status => Parse::Status,
579
0
            httparse::Error::TooManyHeaders => Parse::TooLarge,
580
0
            httparse::Error::Version => Parse::Version,
581
        }
582
0
    }
583
}
584
585
impl From<http::method::InvalidMethod> for Parse {
586
0
    fn from(_: http::method::InvalidMethod) -> Parse {
587
0
        Parse::Method
588
0
    }
589
}
590
591
impl From<http::status::InvalidStatusCode> for Parse {
592
0
    fn from(_: http::status::InvalidStatusCode) -> Parse {
593
0
        Parse::Status
594
0
    }
595
}
596
597
impl From<http::uri::InvalidUri> for Parse {
598
0
    fn from(_: http::uri::InvalidUri) -> Parse {
599
0
        Parse::Uri
600
0
    }
601
}
602
603
impl From<http::uri::InvalidUriParts> for Parse {
604
0
    fn from(_: http::uri::InvalidUriParts) -> Parse {
605
0
        Parse::Uri
606
0
    }
607
}
608
609
// ===== impl TimedOut ====
610
611
impl fmt::Display for TimedOut {
612
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
613
0
        f.write_str("operation timed out")
614
0
    }
615
}
616
617
impl StdError for TimedOut {}
618
619
#[cfg(test)]
620
mod tests {
621
    use super::*;
622
    use std::mem;
623
624
    fn assert_send_sync<T: Send + Sync + 'static>() {}
625
626
    #[test]
627
    fn error_satisfies_send_sync() {
628
        assert_send_sync::<Error>()
629
    }
630
631
    #[test]
632
    fn error_size_of() {
633
        assert_eq!(mem::size_of::<Error>(), mem::size_of::<usize>());
634
    }
635
636
    #[cfg(feature = "http2")]
637
    #[test]
638
    fn h2_reason_unknown() {
639
        let closed = Error::new_closed();
640
        assert_eq!(closed.h2_reason(), h2::Reason::INTERNAL_ERROR);
641
    }
642
643
    #[cfg(feature = "http2")]
644
    #[test]
645
    fn h2_reason_one_level() {
646
        let body_err = Error::new_user_body(h2::Error::from(h2::Reason::ENHANCE_YOUR_CALM));
647
        assert_eq!(body_err.h2_reason(), h2::Reason::ENHANCE_YOUR_CALM);
648
    }
649
650
    #[cfg(feature = "http2")]
651
    #[test]
652
    fn h2_reason_nested() {
653
        let recvd = Error::new_h2(h2::Error::from(h2::Reason::HTTP_1_1_REQUIRED));
654
        // Suppose a user were proxying the received error
655
        let svc_err = Error::new_user_service(recvd);
656
        assert_eq!(svc_err.h2_reason(), h2::Reason::HTTP_1_1_REQUIRED);
657
    }
658
}