#![cfg_attr(feature = "nightly", feature(try_from))]
#[cfg(feature = "nightly")]
use std::convert::TryFrom;
use std::fmt;
use std::io;
#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
pub struct OsError {
code: i32,
}
#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)]
pub struct NoOsError;
impl OsError {
pub fn new(code: i32) -> OsError {
OsError { code: code }
}
pub fn last_os_error() -> OsError {
OsError::new(io::Error::last_os_error().raw_os_error().unwrap())
}
pub fn code(&self) -> i32 {
self.code
}
pub fn kind(&self) -> io::ErrorKind {
self.to_error().kind()
}
fn to_error(&self) -> io::Error {
io::Error::from_raw_os_error(self.code)
}
}
impl fmt::Debug for OsError {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
let error: io::Error = self.to_error();
fmt.debug_struct("OsError")
.field("code", &self.code)
.field("kind", &error.kind())
.finish()
}
}
impl fmt::Display for OsError {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
write!(fmt, "{}", &self.to_error())
}
}
#[cfg(feature = "nightly")]
impl TryFrom<io::Error> for OsError {
type Error = NoOsError;
fn try_from(error: io::Error) -> Result<OsError, NoOsError> {
match error.raw_os_error() {
Some(code) => Ok(OsError { code }),
None => Err(NoOsError),
}
}
}
impl Into<io::Error> for OsError {
fn into(self) -> io::Error {
self.to_error()
}
}
#[cfg(test)]
mod tests {
use std::io;
use super::OsError;
#[cfg(feature = "nightly")]
use super::NoOsError;
#[cfg(feature = "nightly")]
use std::convert::TryFrom;
#[cfg(feature = "nightly")]
use std::convert::TryInto;
const CODE: i32 = 6;
#[test]
fn test_fmt_display() {
let err = OsError::new(CODE);
let io_error = io::Error::from_raw_os_error(CODE);
assert_eq!(format!("{}", err), format!("{}", io_error));
}
#[test]
fn test_fmt_debug() {
let kind = io::ErrorKind::Other;
let err = OsError::new(CODE);
let expected = format!("OsError {{ code: {:?}, kind: {:?} }}", CODE, kind);
assert_eq!(format!("{:?}", err), expected);
}
#[test]
#[cfg(feature = "nightly")]
fn from_io_error() {
let os_error = OsError::try_from(io::Error::from_raw_os_error(CODE));
assert_eq!(os_error, Ok(OsError{ code: CODE }));
let os_error = OsError::try_from(io::Error::new(io::ErrorKind::AddrInUse, "NoOsError"));
assert_eq!(os_error, Err(NoOsError));
}
#[test]
#[cfg(feature = "nightly")]
fn into_os_error() {
let os_error: Result<OsError, _> = io::Error::from_raw_os_error(CODE).try_into();
assert_eq!(os_error, Ok(OsError{ code: CODE }));
let os_error: Result<OsError, _> =
io::Error::new(io::ErrorKind::AddrInUse, "NoOsError").try_into();
assert_eq!(os_error, Err(NoOsError));
}
}