1use crate::codec::SendError;
2use crate::frame::{Reason, StreamId};
3
4use bytes::Bytes;
5use std::fmt;
6use std::io;
7
8/// Either an H2 reason or an I/O error
9#[derive(Clone, Debug)]
10pub 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)]
17pub enum Initiator {
18 User,
19 Library,
20 Remote,
21}
22
23impl 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
56impl Initiator {
57 fn is_local(&self) -> bool {
58 match *self {
59 Self::User | Self::Library => true,
60 Self::Remote => false,
61 }
62 }
63}
64
65impl 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
75impl From<io::ErrorKind> for Error {
76 fn from(src: io::ErrorKind) -> Self {
77 Error::Io(src, None)
78 }
79}
80
81impl 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
87impl From<Error> for SendError {
88 fn from(src: Error) -> Self {
89 Self::Connection(src)
90 }
91}
92