1use std::fmt;
2
3#[derive(PartialEq, Eq, Clone, Copy)]
19pub struct Reason(u32);
20
21impl Reason {
22    pub const NO_ERROR: Reason = Reason(0);
27    pub const PROTOCOL_ERROR: Reason = Reason(1);
31    pub const INTERNAL_ERROR: Reason = Reason(2);
33    pub const FLOW_CONTROL_ERROR: Reason = Reason(3);
35    pub const SETTINGS_TIMEOUT: Reason = Reason(4);
38    pub const STREAM_CLOSED: Reason = Reason(5);
40    pub const FRAME_SIZE_ERROR: Reason = Reason(6);
42    pub const REFUSED_STREAM: Reason = Reason(7);
45    pub const CANCEL: Reason = Reason(8);
47    pub const COMPRESSION_ERROR: Reason = Reason(9);
50    pub const CONNECT_ERROR: Reason = Reason(10);
53    pub const ENHANCE_YOUR_CALM: Reason = Reason(11);
56    pub const INADEQUATE_SECURITY: Reason = Reason(12);
59    pub const HTTP_1_1_REQUIRED: Reason = Reason(13);
61
62    pub fn description(&self) -> &str {
64        match self.0 {
65            0 => "not a result of an error",
66            1 => "unspecific protocol error detected",
67            2 => "unexpected internal error encountered",
68            3 => "flow-control protocol violated",
69            4 => "settings ACK not received in timely manner",
70            5 => "received frame when stream half-closed",
71            6 => "frame with invalid size",
72            7 => "refused stream before processing any application logic",
73            8 => "stream no longer needed",
74            9 => "unable to maintain the header compression context",
75            10 => {
76                "connection established in response to a CONNECT request was reset or abnormally \
77                 closed"
78            }
79            11 => "detected excessive load generating behavior",
80            12 => "security properties do not meet minimum requirements",
81            13 => "endpoint requires HTTP/1.1",
82            _ => "unknown reason",
83        }
84    }
85}
86
87impl From<u32> for Reason {
88    fn from(src: u32) -> Reason {
89        Reason(src)
90    }
91}
92
93impl From<Reason> for u32 {
94    fn from(src: Reason) -> u32 {
95        src.0
96    }
97}
98
99impl fmt::Debug for Reason {
100    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
101        let name = match self.0 {
102            0 => "NO_ERROR",
103            1 => "PROTOCOL_ERROR",
104            2 => "INTERNAL_ERROR",
105            3 => "FLOW_CONTROL_ERROR",
106            4 => "SETTINGS_TIMEOUT",
107            5 => "STREAM_CLOSED",
108            6 => "FRAME_SIZE_ERROR",
109            7 => "REFUSED_STREAM",
110            8 => "CANCEL",
111            9 => "COMPRESSION_ERROR",
112            10 => "CONNECT_ERROR",
113            11 => "ENHANCE_YOUR_CALM",
114            12 => "INADEQUATE_SECURITY",
115            13 => "HTTP_1_1_REQUIRED",
116            other => return f.debug_tuple("Reason").field(&Hex(other)).finish(),
117        };
118        f.write_str(name)
119    }
120}
121
122struct Hex(u32);
123
124impl fmt::Debug for Hex {
125    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
126        fmt::LowerHex::fmt(&self.0, f)
127    }
128}
129
130impl fmt::Display for Reason {
131    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
132        write!(fmt, "{}", self.description())
133    }
134}