Refactor errors (#46)
This patch does a bunch of refactoring, mostly around error types, but it also
paves the way to allow `Codec` to be used standalone.
* `Codec` (and `FramedRead` / `FramedWrite`) is broken out into a codec module.
* An h2-codec crate is created that re-exports the frame and codec modules.
* New error types are introduced in the internals:
* `RecvError` represents errors caused by trying to receive a frame.
* `SendError` represents errors caused by trying to send a frame.
* `UserError` is an enum of potential errors caused by invalid usage
by the user of the lib.
* `ProtoError` is either a `Reason` or an `io::Error`. However it doesn't
specify connection or stream level.
* `h2::Error` is an opaque error type and is the only error type exposed
by the public API (used to be `ConnectionError`).
There are misc code changes to enable this as well. The biggest is a new "sink"
API for `Codec`. It provides buffer which queues up a frame followed by flush
which writes everything that is queued. This departs from the `Sink` trait in
order to provide more accurate error values. For example, buffer can never fail
(but it will panic if `poll_ready` is not called first).
This commit is contained in:
121
src/codec/error.rs
Normal file
121
src/codec/error.rs
Normal file
@@ -0,0 +1,121 @@
|
||||
use frame::{Reason, StreamId};
|
||||
|
||||
use std::{error, fmt, io};
|
||||
|
||||
/// Errors that are received
|
||||
#[derive(Debug)]
|
||||
pub enum RecvError {
|
||||
Connection(Reason),
|
||||
Stream {
|
||||
id: StreamId,
|
||||
reason: Reason,
|
||||
},
|
||||
Io(io::Error),
|
||||
}
|
||||
|
||||
/// Errors caused by sending a message
|
||||
#[derive(Debug)]
|
||||
pub enum SendError {
|
||||
/// User error
|
||||
User(UserError),
|
||||
|
||||
/// I/O error
|
||||
Io(io::Error),
|
||||
}
|
||||
|
||||
/// Errors caused by users of the library
|
||||
#[derive(Debug)]
|
||||
pub enum UserError {
|
||||
/// The stream ID is no longer accepting frames.
|
||||
InactiveStreamId,
|
||||
|
||||
/// The stream is not currently expecting a frame of this type.
|
||||
UnexpectedFrameType,
|
||||
|
||||
/// The payload size is too big
|
||||
PayloadTooBig,
|
||||
|
||||
/// The application attempted to initiate too many streams to remote.
|
||||
Rejected,
|
||||
}
|
||||
|
||||
// ===== impl RecvError =====
|
||||
|
||||
impl From<io::Error> for RecvError {
|
||||
fn from(src: io::Error) -> Self {
|
||||
RecvError::Io(src)
|
||||
}
|
||||
}
|
||||
|
||||
impl error::Error for RecvError {
|
||||
fn description(&self) -> &str {
|
||||
use self::RecvError::*;
|
||||
|
||||
match *self {
|
||||
Connection(ref reason) => reason.description(),
|
||||
Stream { ref reason, .. } => reason.description(),
|
||||
Io(ref e) => e.description(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for RecvError {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
use std::error::Error;
|
||||
write!(fmt, "{}", self.description())
|
||||
}
|
||||
}
|
||||
|
||||
// ===== impl SendError =====
|
||||
|
||||
impl error::Error for SendError {
|
||||
fn description(&self) -> &str {
|
||||
use self::SendError::*;
|
||||
|
||||
match *self {
|
||||
User(ref e) => e.description(),
|
||||
Io(ref e) => e.description(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for SendError {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
use std::error::Error;
|
||||
write!(fmt, "{}", self.description())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<io::Error> for SendError {
|
||||
fn from(src: io::Error) -> Self {
|
||||
SendError::Io(src)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<UserError> for SendError {
|
||||
fn from(src: UserError) -> Self {
|
||||
SendError::User(src)
|
||||
}
|
||||
}
|
||||
|
||||
// ===== impl UserError =====
|
||||
|
||||
impl error::Error for UserError {
|
||||
fn description(&self) -> &str {
|
||||
use self::UserError::*;
|
||||
|
||||
match *self {
|
||||
InactiveStreamId => "inactive stream",
|
||||
UnexpectedFrameType => "unexpected frame type",
|
||||
PayloadTooBig => "payload too big",
|
||||
Rejected => "rejected",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for UserError {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
use std::error::Error;
|
||||
write!(fmt, "{}", self.description())
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user