h2/proto/
error.rs

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
16pub struct GoAway {
17    pub debug_data: Bytes,
18    pub reason: Reason,
19}
20
21#[derive(Clone, Copy, Debug, PartialEq, Eq)]
22pub enum Initiator {
23    User,
24    Library,
25    Remote,
26}
27
28impl Error {
29    pub(crate) fn is_local(&self) -> bool {
30        match *self {
31            Self::Reset(_, _, initiator) | Self::GoAway(_, _, initiator) => initiator.is_local(),
32            Self::Io(..) => true,
33        }
34    }
35
36    pub(crate) fn user_go_away(reason: Reason) -> Self {
37        Self::GoAway(Bytes::new(), reason, Initiator::User)
38    }
39
40    pub(crate) fn library_reset(stream_id: StreamId, reason: Reason) -> Self {
41        Self::Reset(stream_id, reason, Initiator::Library)
42    }
43
44    pub(crate) fn library_go_away(reason: Reason) -> Self {
45        Self::GoAway(Bytes::new(), reason, Initiator::Library)
46    }
47
48    pub(crate) fn library_go_away_data(reason: Reason, debug_data: impl Into<Bytes>) -> Self {
49        Self::GoAway(debug_data.into(), reason, Initiator::Library)
50    }
51
52    pub(crate) fn remote_reset(stream_id: StreamId, reason: Reason) -> Self {
53        Self::Reset(stream_id, reason, Initiator::Remote)
54    }
55
56    pub(crate) fn remote_go_away(debug_data: Bytes, reason: Reason) -> Self {
57        Self::GoAway(debug_data, reason, Initiator::Remote)
58    }
59}
60
61impl Initiator {
62    fn is_local(&self) -> bool {
63        match *self {
64            Self::User | Self::Library => true,
65            Self::Remote => false,
66        }
67    }
68
69    pub(crate) fn is_library(&self) -> bool {
70        matches!(self, Self::Library)
71    }
72}
73
74impl fmt::Display for Error {
75    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
76        match *self {
77            Self::Reset(_, reason, _) | Self::GoAway(_, reason, _) => reason.fmt(fmt),
78            Self::Io(_, Some(ref inner)) => inner.fmt(fmt),
79            Self::Io(kind, None) => io::Error::from(kind).fmt(fmt),
80        }
81    }
82}
83
84impl From<io::ErrorKind> for Error {
85    fn from(src: io::ErrorKind) -> Self {
86        Error::Io(src, None)
87    }
88}
89
90impl From<io::Error> for Error {
91    fn from(src: io::Error) -> Self {
92        Error::Io(src.kind(), src.get_ref().map(|inner| inner.to_string()))
93    }
94}
95
96impl From<Error> for SendError {
97    fn from(src: Error) -> Self {
98        Self::Connection(src)
99    }
100}