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 {
is_local(&self) -> bool24     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 
user_go_away(reason: Reason) -> Self31     pub(crate) fn user_go_away(reason: Reason) -> Self {
32         Self::GoAway(Bytes::new(), reason, Initiator::User)
33     }
34 
library_reset(stream_id: StreamId, reason: Reason) -> Self35     pub(crate) fn library_reset(stream_id: StreamId, reason: Reason) -> Self {
36         Self::Reset(stream_id, reason, Initiator::Library)
37     }
38 
library_go_away(reason: Reason) -> Self39     pub(crate) fn library_go_away(reason: Reason) -> Self {
40         Self::GoAway(Bytes::new(), reason, Initiator::Library)
41     }
42 
library_go_away_data(reason: Reason, debug_data: impl Into<Bytes>) -> Self43     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 
remote_reset(stream_id: StreamId, reason: Reason) -> Self47     pub(crate) fn remote_reset(stream_id: StreamId, reason: Reason) -> Self {
48         Self::Reset(stream_id, reason, Initiator::Remote)
49     }
50 
remote_go_away(debug_data: Bytes, reason: Reason) -> Self51     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 {
is_local(&self) -> bool57     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 {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result66     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
67         match *self {
68             Self::Reset(_, reason, _) | Self::GoAway(_, reason, _) => reason.fmt(fmt),
69             Self::Io(_, Some(ref inner)) => inner.fmt(fmt),
70             Self::Io(kind, None) => io::Error::from(kind).fmt(fmt),
71         }
72     }
73 }
74 
75 impl From<io::ErrorKind> for Error {
from(src: io::ErrorKind) -> Self76     fn from(src: io::ErrorKind) -> Self {
77         Error::Io(src, None)
78     }
79 }
80 
81 impl From<io::Error> for Error {
from(src: io::Error) -> Self82     fn from(src: io::Error) -> Self {
83         Error::Io(src.kind(), src.get_ref().map(|inner| inner.to_string()))
84     }
85 }
86 
87 impl From<Error> for SendError {
from(src: Error) -> Self88     fn from(src: Error) -> Self {
89         Self::Connection(src)
90     }
91 }
92