use std::fmt::{Display, Formatter};
use std::io;
use std::result;
use libc::__errno_location;
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Error(i32);
pub type Result<T> = result::Result<T, Error>;
impl Error {
pub fn new(errno: i32) -> Error {
Error(errno)
}
pub fn last() -> Error {
Error(unsafe { *__errno_location() })
}
pub fn errno(self) -> i32 {
self.0
}
}
impl Display for Error {
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
io::Error::from_raw_os_error(self.0).fmt(f)
}
}
impl From<io::Error> for Error {
fn from(e: io::Error) -> Self {
Error::new(e.raw_os_error().unwrap_or_default())
}
}
pub fn errno_result<T>() -> Result<T> {
Err(Error::last())
}
#[cfg(test)]
mod tests {
use super::*;
use libc;
use std::fs::File;
use std::io::{self, Write};
use std::os::unix::io::FromRawFd;
#[test]
pub fn test_invalid_fd() {
let mut file = unsafe { File::from_raw_fd(-1) };
assert!(file.write(b"test").is_err());
let last_err = errno_result::<i32>().unwrap_err();
assert_eq!(last_err, Error::new(libc::EBADF));
assert_eq!(last_err.errno(), libc::EBADF);
assert_eq!(last_err, Error::from(io::Error::last_os_error()));
assert_eq!(last_err, Error::last());
assert_eq!(
format!("{}", Error::new(libc::EBADF)),
"Bad file descriptor (os error 9)"
);
}
}