use std::fmt;
use std::io;
use std::error::Error as StdError;
use std::sync::Arc;
use assert_types::*;
use hpack::decoder::DecoderError;
use tls_api;
use tokio_timer::TimeoutError;
use solicit::frame::ParseFrameError;
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum ErrorCode {
NoError = 0x0,
ProtocolError = 0x1,
InternalError = 0x2,
FlowControlError = 0x3,
SettingsTimeout = 0x4,
StreamClosed = 0x5,
FrameSizeError = 0x6,
RefusedStream = 0x7,
Cancel = 0x8,
CompressionError = 0x9,
ConnectError = 0xa,
EnhanceYourCalm = 0xb,
InadequateSecurity = 0xc,
Http11Required = 0xd,
}
impl From<u32> for ErrorCode {
fn from(code: u32) -> ErrorCode {
match code {
0x0 => ErrorCode::NoError,
0x1 => ErrorCode::ProtocolError,
0x2 => ErrorCode::InternalError,
0x3 => ErrorCode::FlowControlError,
0x4 => ErrorCode::SettingsTimeout,
0x5 => ErrorCode::StreamClosed,
0x6 => ErrorCode::FrameSizeError,
0x7 => ErrorCode::RefusedStream,
0x8 => ErrorCode::Cancel,
0x9 => ErrorCode::CompressionError,
0xa => ErrorCode::ConnectError,
0xb => ErrorCode::EnhanceYourCalm,
0xc => ErrorCode::InadequateSecurity,
0xd => ErrorCode::Http11Required,
_ => ErrorCode::InternalError,
}
}
}
impl AsRef<str> for ErrorCode {
fn as_ref(&self) -> &str {
match *self {
ErrorCode::NoError => "NoError",
ErrorCode::ProtocolError => "ProtocolError",
ErrorCode::InternalError => "InternalError",
ErrorCode::FlowControlError => "FlowControlError",
ErrorCode::SettingsTimeout => "SettingsTimeout",
ErrorCode::StreamClosed => "StreamClosed",
ErrorCode::FrameSizeError => "FrameSizeError",
ErrorCode::RefusedStream => "RefusedStream",
ErrorCode::Cancel => "Cancel",
ErrorCode::CompressionError => "CompressionError",
ErrorCode::ConnectError => "ConnectError",
ErrorCode::EnhanceYourCalm => "EnhanceYourCalm",
ErrorCode::InadequateSecurity => "InadequateSecurity",
ErrorCode::Http11Required => "Http11Required",
}
}
}
impl Into<u32> for ErrorCode {
#[inline]
fn into(self) -> u32 {
self as u32
}
}
#[derive(Debug)]
pub enum Error {
IoError(io::Error),
TlsError(tls_api::Error),
CodeError(ErrorCode),
InvalidFrame(String),
CompressionError(DecoderError),
WindowSizeOverflow,
UnknownStreamId,
UnableToConnect,
MalformedResponse,
ConnectionTimeout,
Shutdown,
HandlerPanicked(String),
ParseFrameError(ParseFrameError),
InternalError(String),
NotImplemented(&'static str),
Other(&'static str),
ClientDied(Option<Arc<Error>>),
ClientPanicked(String),
}
fn _assert_error_sync_send() {
assert_send::<Error>();
assert_sync::<Error>();
}
impl From<io::Error> for Error {
fn from(err: io::Error) -> Error {
Error::IoError(err)
}
}
impl From<tls_api::Error> for Error {
fn from(error: tls_api::Error) -> Error {
Error::TlsError(error)
}
}
impl<F> From<TimeoutError<F>> for Error {
fn from(_err: TimeoutError<F>) -> Error {
Error::ConnectionTimeout
}
}
impl From<ParseFrameError> for Error {
fn from(e: ParseFrameError) -> Self {
Error::ParseFrameError(e)
}
}
impl fmt::Display for Error {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
write!(fmt, "HTTP/2 Error: {}", self.description())
}
}
impl StdError for Error {
fn description(&self) -> &str {
match *self {
Error::IoError(_) => "Encountered an IO error",
Error::TlsError(_) => "Encountered TLS error",
Error::CodeError(_) => "Encountered HTTP named error",
Error::InvalidFrame(..) => "Encountered an invalid or unexpected HTTP/2 frame",
Error::CompressionError(_) => "Encountered an error with HPACK compression",
Error::WindowSizeOverflow => "The connection flow control window overflowed",
Error::UnknownStreamId => "Attempted an operation with an unknown HTTP/2 stream ID",
Error::UnableToConnect => "An error attempting to establish an HTTP/2 connection",
Error::MalformedResponse => "The received response was malformed",
Error::ConnectionTimeout => "Connection time out",
Error::Shutdown => "Local shutdown",
Error::HandlerPanicked(_) => "Handler panicked",
Error::ParseFrameError(_) => "Failed to parse frame",
Error::NotImplemented(_) => "Not implemented",
Error::InternalError(_) => "Internal error",
Error::ClientDied(_) => "Client died",
Error::ClientPanicked(_) => "Client panicked",
Error::Other(_) => "An unknown error",
}
}
fn cause(&self) -> Option<&StdError> {
match *self {
Error::IoError(ref e) => Some(e),
Error::TlsError(ref e) => Some(e),
_ => None,
}
}
}