#[cfg(feature="alloc")] use alloc::boxed::Box;
#[cfg(not(feature="alloc"))] use ::FakeBox as Box;
use core::convert::Into;
use core::fmt;
use core::marker::{Send, Sync};
use core::option::Option::{self, Some, None};
use core::result;
#[cfg(feature="collections")] use collections::string::String;
#[cfg(not(feature="collections"))] use ::ErrorString as String;
pub type Result<T> = result::Result<T, Error>;
#[derive(Debug)]
pub struct Error {
repr: Repr,
}
enum Repr {
Os(i32),
#[cfg(feature="alloc")]
Custom(Box<Custom>),
#[cfg(not(feature="alloc"))]
Custom(Custom),
}
#[derive(Debug)]
struct Custom {
kind: ErrorKind,
error: String,
}
#[derive(Copy, PartialEq, Eq, Clone, Debug)]
#[allow(deprecated)]
pub enum ErrorKind {
NotFound,
PermissionDenied,
ConnectionRefused,
ConnectionReset,
ConnectionAborted,
NotConnected,
AddrInUse,
AddrNotAvailable,
BrokenPipe,
AlreadyExists,
WouldBlock,
InvalidInput,
InvalidData,
TimedOut,
WriteZero,
Interrupted,
Other,
UnexpectedEof,
#[doc(hidden)]
__Nonexhaustive,
}
impl Error {
pub fn new<E>(kind: ErrorKind, error: E) -> Error
where E: Into<String>
{
Self::_new(kind, error.into())
}
fn _new(kind: ErrorKind, error: String) -> Error {
Error {
repr: Repr::Custom(Box::new(Custom {
kind: kind,
error: error,
}))
}
}
pub fn from_raw_os_error(code: i32) -> Error {
Error { repr: Repr::Os(code) }
}
pub fn raw_os_error(&self) -> Option<i32> {
match self.repr {
Repr::Os(i) => Some(i),
Repr::Custom(..) => None,
}
}
pub fn get_ref(&self) -> Option<&String> {
match self.repr {
Repr::Os(..) => None,
Repr::Custom(ref c) => Some(&c.error),
}
}
pub fn get_mut(&mut self) -> Option<&mut String> {
match self.repr {
Repr::Os(..) => None,
Repr::Custom(ref mut c) => Some(&mut c.error),
}
}
pub fn into_inner(self) -> Option<String> {
match self.repr {
Repr::Os(..) => None,
Repr::Custom(c) => Some(c.error)
}
}
pub fn kind(&self) -> ErrorKind {
match self.repr {
Repr::Os(_code) => ErrorKind::Other,
Repr::Custom(ref c) => c.kind,
}
}
}
impl fmt::Debug for Repr {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
match *self {
Repr::Os(ref code) =>
fmt.debug_struct("Os").field("code", code).finish(),
Repr::Custom(ref c) => fmt.debug_tuple("Custom").field(c).finish(),
}
}
}
impl fmt::Display for Error {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
match self.repr {
Repr::Os(code) => {
write!(fmt, "os error {}", code)
}
Repr::Custom(ref c) => c.error.fmt(fmt),
}
}
}
fn _assert_error_is_sync_send() {
fn _is_sync_send<T: Sync+Send>() {}
_is_sync_send::<Error>();
}
#[cfg(test)]
mod test {
use prelude::v1::*;
use super::{Error, ErrorKind};
use error;
use error::Error as error_Error;
use fmt;
use sys::os::error_string;
#[test]
fn test_debug_error() {
let code = 6;
let msg = error_string(code);
let err = Error { repr: super::Repr::Os(code) };
let expected = format!("Error {{ repr: Os {{ code: {:?}, message: {:?} }} }}", code, msg);
assert_eq!(format!("{:?}", err), expected);
}
#[test]
fn test_downcasting() {
#[derive(Debug)]
struct TestError;
impl fmt::Display for TestError {
fn fmt(&self, _: &mut fmt::Formatter) -> fmt::Result {
Ok(())
}
}
impl error::Error for TestError {
fn description(&self) -> &str {
"asdf"
}
}
let mut err = Error::new(ErrorKind::Other, TestError);
assert!(err.get_ref().unwrap().is::<TestError>());
assert_eq!("asdf", err.get_ref().unwrap().description());
assert!(err.get_mut().unwrap().is::<TestError>());
let extracted = err.into_inner().unwrap();
extracted.downcast::<TestError>().unwrap();
}
}