1 | use crate::codec::SendError; |
2 | use crate::frame::{Reason, StreamId}; |
3 | |
4 | use bytes::Bytes; |
5 | use std::fmt; |
6 | use std::io; |
7 | |
8 | /// Either an H2 reason or an I/O error |
9 | #[derive (Clone, Debug)] |
10 | pub enum Error { |
11 | Reset(StreamId, Reason, Initiator), |
12 | GoAway(Bytes, Reason, Initiator), |
13 | Io(io::ErrorKind, Option<String>), |
14 | } |
15 | |
16 | #[derive (Clone, Copy, Debug, PartialEq, Eq)] |
17 | pub enum Initiator { |
18 | User, |
19 | Library, |
20 | Remote, |
21 | } |
22 | |
23 | impl Error { |
24 | pub(crate) fn is_local(&self) -> bool { |
25 | match *self { |
26 | Self::Reset(_, _, initiator) | Self::GoAway(_, _, initiator) => initiator.is_local(), |
27 | Self::Io(..) => true, |
28 | } |
29 | } |
30 | |
31 | pub(crate) fn user_go_away(reason: Reason) -> Self { |
32 | Self::GoAway(Bytes::new(), reason, Initiator::User) |
33 | } |
34 | |
35 | pub(crate) fn library_reset(stream_id: StreamId, reason: Reason) -> Self { |
36 | Self::Reset(stream_id, reason, Initiator::Library) |
37 | } |
38 | |
39 | pub(crate) fn library_go_away(reason: Reason) -> Self { |
40 | Self::GoAway(Bytes::new(), reason, Initiator::Library) |
41 | } |
42 | |
43 | pub(crate) fn library_go_away_data(reason: Reason, debug_data: impl Into<Bytes>) -> Self { |
44 | Self::GoAway(debug_data.into(), reason, Initiator::Library) |
45 | } |
46 | |
47 | pub(crate) fn remote_reset(stream_id: StreamId, reason: Reason) -> Self { |
48 | Self::Reset(stream_id, reason, Initiator::Remote) |
49 | } |
50 | |
51 | pub(crate) fn remote_go_away(debug_data: Bytes, reason: Reason) -> Self { |
52 | Self::GoAway(debug_data, reason, Initiator::Remote) |
53 | } |
54 | } |
55 | |
56 | impl Initiator { |
57 | fn is_local(&self) -> bool { |
58 | match *self { |
59 | Self::User | Self::Library => true, |
60 | Self::Remote => false, |
61 | } |
62 | } |
63 | } |
64 | |
65 | impl fmt::Display for Error { |
66 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { |
67 | match *self { |
68 | Self::Reset(_, reason: Reason, _) | Self::GoAway(_, reason: Reason, _) => reason.fmt(fmt), |
69 | Self::Io(_, Some(ref inner: &String)) => inner.fmt(fmt), |
70 | Self::Io(kind: ErrorKind, None) => io::Error::from(kind).fmt(fmt), |
71 | } |
72 | } |
73 | } |
74 | |
75 | impl From<io::ErrorKind> for Error { |
76 | fn from(src: io::ErrorKind) -> Self { |
77 | Error::Io(src, None) |
78 | } |
79 | } |
80 | |
81 | impl From<io::Error> for Error { |
82 | fn from(src: io::Error) -> Self { |
83 | Error::Io(src.kind(), src.get_ref().map(|inner: &(dyn Error + Sync + Send)| inner.to_string())) |
84 | } |
85 | } |
86 | |
87 | impl From<Error> for SendError { |
88 | fn from(src: Error) -> Self { |
89 | Self::Connection(src) |
90 | } |
91 | } |
92 | |