#![deny(missing_docs, missing_debug_implementations)]
#![doc(html_root_url = "https://docs.rs/arc-io-error/0.1.1")]
use std::error::Error;
use std::fmt;
use std::io;
use std::mem;
use std::sync::Arc;
#[derive(Clone)]
pub struct IoError(IoErrorRepr);
pub use io::ErrorKind as IoErrorKind;
pub type IoResult<T> = Result<T, IoError>;
#[derive(Clone)]
enum IoErrorRepr {
Os(i32),
Kind(IoErrorKind),
Custom(IoErrorKind, Arc<Error + Send + Sync>),
}
impl IoError {
pub fn new<E>(kind: IoErrorKind, error: E) -> Self
where E: Into<Arc<Error + Send + Sync>>
{
IoError(IoErrorRepr::Custom(kind, error.into()))
}
pub fn last_os_error() -> Self {
io::Error::last_os_error().into()
}
pub fn from_raw_os_error(code: i32) -> Self {
IoError(IoErrorRepr::Os(code))
}
pub fn raw_os_error(&self) -> Option<i32> {
match self.0 {
IoErrorRepr::Os(code) => Some(code),
_ => None,
}
}
pub fn get_ref(&self) -> Option<&('static + Error + Send + Sync)> {
match self.0 {
IoErrorRepr::Custom(_, ref inner) => Some(inner.as_ref()),
_ => None,
}
}
pub fn into_inner(self) -> Option<Arc<Error + Send + Sync>> {
match self.0 {
IoErrorRepr::Custom(_, inner) => Some(inner),
_ => None,
}
}
pub fn kind(&self) -> IoErrorKind {
match self.0 {
IoErrorRepr::Os(code) => io::Error::from_raw_os_error(code).kind(),
IoErrorRepr::Kind(kind) => kind,
IoErrorRepr::Custom(kind, _) => kind,
}
}
}
impl From<io::Error> for IoError {
fn from(src: io::Error) -> Self {
if let Some(code) = src.raw_os_error() {
return IoError(IoErrorRepr::Os(code));
}
let kind = src.kind();
match src.into_inner() {
None => IoError(IoErrorRepr::Kind(kind)),
Some(inner) => {
let shared = Arc::new(BoxError(inner));
IoError(IoErrorRepr::Custom(kind, shared))
}
}
}
}
impl From<IoError> for io::Error {
fn from(src: IoError) -> Self {
match src.0 {
IoErrorRepr::Os(code) => io::Error::from_raw_os_error(code),
IoErrorRepr::Kind(kind) => kind.into(),
IoErrorRepr::Custom(kind, inner) => io::Error::new(kind, ArcError(inner)),
}
}
}
impl From<IoErrorKind> for IoError {
fn from(src: IoErrorKind) -> IoError {
IoError(IoErrorRepr::Kind(src))
}
}
impl fmt::Debug for IoError {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
match self.0 {
IoErrorRepr::Os(code) => fmt::Debug::fmt(&io::Error::from_raw_os_error(code), fmt),
IoErrorRepr::Kind(kind) => fmt::Debug::fmt(&io::Error::from(kind), fmt),
IoErrorRepr::Custom(ref kind, ref inner) => {
fmt.debug_struct("Error").field("repr", &(kind, inner)).finish()
}
}
}
}
impl fmt::Display for IoError {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
match self.0 {
IoErrorRepr::Os(code) => fmt::Display::fmt(&io::Error::from_raw_os_error(code), fmt),
IoErrorRepr::Kind(kind) => fmt::Display::fmt(&io::Error::from(kind), fmt),
IoErrorRepr::Custom(_, ref inner) => fmt::Display::fmt(inner, fmt),
}
}
}
impl Error for IoError {
fn description(&self) -> &str {
match self.0 {
IoErrorRepr::Os(code) => {
unsafe { mem::transmute(io::Error::from_raw_os_error(code).description()) }
}
IoErrorRepr::Kind(kind) => {
unsafe { mem::transmute(io::Error::from(kind).description()) }
}
IoErrorRepr::Custom(_, ref inner) => inner.description(),
}
}
fn cause(&self) -> Option<&Error> {
match self.0 {
IoErrorRepr::Custom(_, ref inner) => inner.cause(),
_ => None,
}
}
}
struct ArcError(Arc<Error + Send + Sync>);
impl fmt::Debug for ArcError {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt::Debug::fmt(&self.0, fmt)
}
}
impl fmt::Display for ArcError {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(&self.0, fmt)
}
}
impl Error for ArcError {
fn description(&self) -> &str {
self.0.description()
}
fn cause(&self) -> Option<&Error> {
self.0.cause()
}
}
struct BoxError(Box<Error + Send + Sync>);
impl fmt::Debug for BoxError {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt::Debug::fmt(&self.0, fmt)
}
}
impl fmt::Display for BoxError {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(&self.0, fmt)
}
}
impl Error for BoxError {
fn description(&self) -> &str {
self.0.description()
}
fn cause(&self) -> Option<&Error> {
self.0.cause()
}
}