use std::io::IoError;
use std::error::{FromError, Error};
use std::fmt::{self, Show};
use mio::{MioError, MioErrorKind};
use nix::{SysError};
pub type AioResult<T> = Result<T, AioError>;
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub struct AioError {
pub desc: &'static str,
pub kind: Kind
}
impl AioError {
pub fn new(desc: &'static str, kind: Kind) -> AioError {
AioError {
desc: desc,
kind: kind
}
}
pub fn from_kind(kind: Kind) -> AioError {
AioError {
kind: kind,
desc: match kind {
Kind::Eof => "end of file",
Kind::AddressInUse => "address in use",
Kind::PermissionDenied => "permission denied",
Kind::ConnectionFailed => "connection failed",
Kind::ConnectionClosed => "connection closed",
Kind::ConnectionRefused => "connection refused",
Kind::ConnectionReset => "connection reset",
Kind::ConnectionAborted => "connection aborted",
Kind::NotConnected => "not connected",
Kind::BrokenPipe => "broken pipe",
Kind::PathAlreadyExists => "path already exists",
Kind::PathDoesntExist => "path doesn't exist",
Kind::MismatchedFileType => "mismatched file type for operation",
Kind::TemporaryFailure => "temporary failure (resource unavailable)",
Kind::IoUnavailable => "io unvailable on this thread",
Kind::InvalidInput => "invalid input for this operation",
Kind::WouldBlock => "operation would block",
Kind::Other => "unknown I/O error"
}
}
}
pub fn from_errno(errno: uint) -> AioError {
FromError::from_error(IoError::from_errno(errno, false))
}
pub fn latest() -> AioError {
use std::os;
AioError::from_errno(os::errno())
}
}
impl Show for AioError {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
write!(fmt, "{}: {}", self.kind, self.desc)
}
}
impl Error for AioError {
fn description(&self) -> &str { self.desc }
fn detail(&self) -> Option<String> { None }
}
impl FromError<IoError> for AioError {
fn from_error(io: IoError) -> AioError {
use std::io::IoErrorKind as StdKind;
AioError {
desc: io.desc,
kind: match io.kind {
StdKind::OtherIoError
| StdKind::ShortWrite(..)
| StdKind::TimedOut
| StdKind::NoProgress => Kind::Other,
StdKind::EndOfFile => Kind::Eof,
StdKind::FileNotFound
| StdKind::PathDoesntExist => Kind::PathDoesntExist,
StdKind::PermissionDenied => Kind::PermissionDenied,
StdKind::ConnectionFailed => Kind::ConnectionFailed,
StdKind::Closed => Kind::ConnectionClosed,
StdKind::ConnectionRefused => Kind::ConnectionRefused,
StdKind::ConnectionReset => Kind::ConnectionReset,
StdKind::ConnectionAborted => Kind::ConnectionAborted,
StdKind::NotConnected => Kind::NotConnected,
StdKind::BrokenPipe => Kind::BrokenPipe,
StdKind::PathAlreadyExists => Kind::PathAlreadyExists,
StdKind::MismatchedFileTypeForOperation => Kind::MismatchedFileType,
StdKind::ResourceUnavailable => Kind::TemporaryFailure,
StdKind::IoUnavailable => Kind::IoUnavailable,
StdKind::InvalidInput => Kind::InvalidInput,
}
}
}
}
impl FromError<MioError> for AioError {
fn from_error(mio: MioError) -> AioError {
match mio.kind {
MioErrorKind::Eof => AioError::from_kind(Kind::Eof),
MioErrorKind::WouldBlock => AioError::from_kind(Kind::WouldBlock),
MioErrorKind::AddrInUse => AioError::from_kind(Kind::AddressInUse),
MioErrorKind::BufUnderflow => AioError::new("wrote or read too little", Kind::Other),
MioErrorKind::BufOverflow => AioError::new("wrote or read too much", Kind::Other),
MioErrorKind::EventLoopTerminated => AioError::new("event loop terminated", Kind::Other),
MioErrorKind::OtherError => AioError::from_kind(Kind::Other),
}
}
}
impl FromError<SysError> for AioError {
fn from_error(sys: SysError) -> AioError {
FromError::from_error(MioError::from_sys_error(sys))
}
}
impl FromError<AioError> for Box<Error> {
fn from_error(aio: AioError) -> Box<Error> { box aio }
}
#[derive(Copy, Clone, Show, PartialEq, Eq, Hash)]
pub enum Kind {
Eof,
AddressInUse,
PermissionDenied,
ConnectionFailed,
ConnectionClosed,
ConnectionRefused,
ConnectionReset,
ConnectionAborted,
NotConnected,
BrokenPipe,
PathAlreadyExists,
PathDoesntExist,
MismatchedFileType,
TemporaryFailure,
IoUnavailable,
InvalidInput,
WouldBlock,
Other
}