util: introduce new Error variant Error:Other { errno }
Do not hide all the POSIX error codes behind a useless Error::Unknown. Fixes #24.
This commit is contained in:
parent
5affb85148
commit
81e142c6b7
@ -7,7 +7,21 @@ use std::str::from_utf8_unchecked;
|
|||||||
use ffi::*;
|
use ffi::*;
|
||||||
use libc::{c_char, c_int};
|
use libc::{c_char, c_int};
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
// Export POSIX error codes so that users can do something like `if error ==
|
||||||
|
// Error::Other { errno: EAGAIN }`.
|
||||||
|
pub use libc::{
|
||||||
|
E2BIG, EACCES, EADDRINUSE, EADDRNOTAVAIL, EAFNOSUPPORT, EAGAIN, EALREADY, EBADF, EBADMSG,
|
||||||
|
EBUSY, ECANCELED, ECHILD, ECONNABORTED, ECONNREFUSED, ECONNRESET, EDEADLK, EDESTADDRREQ, EDOM,
|
||||||
|
EDQUOT, EEXIST, EFAULT, EFBIG, EHOSTUNREACH, EIDRM, EILSEQ, EINPROGRESS, EINTR, EINVAL, EIO,
|
||||||
|
EISCONN, EISDIR, ELOOP, EMFILE, EMLINK, EMSGSIZE, EMULTIHOP, ENAMETOOLONG, ENETDOWN, ENETRESET,
|
||||||
|
ENETUNREACH, ENFILE, ENOBUFS, ENODATA, ENODEV, ENOENT, ENOEXEC, ENOLCK, ENOLINK, ENOMEM,
|
||||||
|
ENOMSG, ENOPROTOOPT, ENOSPC, ENOSR, ENOSTR, ENOSYS, ENOTCONN, ENOTDIR, ENOTEMPTY,
|
||||||
|
ENOTRECOVERABLE, ENOTSOCK, ENOTSUP, ENOTTY, ENXIO, EOPNOTSUPP, EOVERFLOW, EOWNERDEAD, EPERM,
|
||||||
|
EPIPE, EPROTO, EPROTONOSUPPORT, EPROTOTYPE, ERANGE, EROFS, ESPIPE, ESRCH, ESTALE, ETIME,
|
||||||
|
ETIMEDOUT, ETXTBSY, EWOULDBLOCK, EXDEV,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, PartialEq)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
Bug,
|
Bug,
|
||||||
Bug2,
|
Bug2,
|
||||||
@ -39,6 +53,11 @@ pub enum Error {
|
|||||||
HttpNotFound,
|
HttpNotFound,
|
||||||
HttpOther4xx,
|
HttpOther4xx,
|
||||||
HttpServerError,
|
HttpServerError,
|
||||||
|
|
||||||
|
/// For AVERROR(e) wrapping POSIX error codes, e.g. AVERROR(EAGAIN).
|
||||||
|
Other {
|
||||||
|
errno: c_int,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<c_int> for Error {
|
impl From<c_int> for Error {
|
||||||
@ -71,8 +90,9 @@ impl From<c_int> for Error {
|
|||||||
AVERROR_HTTP_NOT_FOUND => Error::HttpNotFound,
|
AVERROR_HTTP_NOT_FOUND => Error::HttpNotFound,
|
||||||
AVERROR_HTTP_OTHER_4XX => Error::HttpOther4xx,
|
AVERROR_HTTP_OTHER_4XX => Error::HttpOther4xx,
|
||||||
AVERROR_HTTP_SERVER_ERROR => Error::HttpServerError,
|
AVERROR_HTTP_SERVER_ERROR => Error::HttpServerError,
|
||||||
|
e => Error::Other {
|
||||||
_ => Error::Unknown,
|
errno: AVUNERROR(e),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -107,6 +127,7 @@ impl Into<c_int> for Error {
|
|||||||
Error::HttpNotFound => AVERROR_HTTP_NOT_FOUND,
|
Error::HttpNotFound => AVERROR_HTTP_NOT_FOUND,
|
||||||
Error::HttpOther4xx => AVERROR_HTTP_OTHER_4XX,
|
Error::HttpOther4xx => AVERROR_HTTP_OTHER_4XX,
|
||||||
Error::HttpServerError => AVERROR_HTTP_SERVER_ERROR,
|
Error::HttpServerError => AVERROR_HTTP_SERVER_ERROR,
|
||||||
|
Error::Other { errno } => AVERROR(errno),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -122,7 +143,13 @@ impl From<Error> for io::Error {
|
|||||||
impl fmt::Display for Error {
|
impl fmt::Display for Error {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||||
f.write_str(unsafe {
|
f.write_str(unsafe {
|
||||||
from_utf8_unchecked(CStr::from_ptr(STRINGS[index(self)].as_ptr()).to_bytes())
|
from_utf8_unchecked(
|
||||||
|
CStr::from_ptr(match *self {
|
||||||
|
Error::Other { errno } => libc::strerror(errno),
|
||||||
|
_ => STRINGS[index(self)].as_ptr(),
|
||||||
|
})
|
||||||
|
.to_bytes(),
|
||||||
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -166,12 +193,13 @@ fn index(error: &Error) -> usize {
|
|||||||
Error::HttpNotFound => 24,
|
Error::HttpNotFound => 24,
|
||||||
Error::HttpOther4xx => 25,
|
Error::HttpOther4xx => 25,
|
||||||
Error::HttpServerError => 26,
|
Error::HttpServerError => 26,
|
||||||
|
Error::Other { errno: _ } => (-1isize) as usize,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// XXX: the length has to be synced with the number of errors
|
// XXX: the length has to be synced with the number of errors
|
||||||
static mut STRINGS: [[c_char; AV_ERROR_MAX_STRING_SIZE as usize]; 27] =
|
static mut STRINGS: [[c_char; AV_ERROR_MAX_STRING_SIZE]; 27] =
|
||||||
[[0 as c_char; AV_ERROR_MAX_STRING_SIZE as usize]; 27];
|
[[0 as c_char; AV_ERROR_MAX_STRING_SIZE]; 27];
|
||||||
|
|
||||||
pub fn register_all() {
|
pub fn register_all() {
|
||||||
unsafe {
|
unsafe {
|
||||||
@ -315,3 +343,27 @@ pub fn register_all() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_error_roundtrip() {
|
||||||
|
assert_eq!(Into::<c_int>::into(Error::from(AVERROR_EOF)), AVERROR_EOF);
|
||||||
|
assert_eq!(
|
||||||
|
Into::<c_int>::into(Error::from(AVERROR(EAGAIN))),
|
||||||
|
AVERROR(EAGAIN)
|
||||||
|
);
|
||||||
|
assert_eq!(Error::from(AVERROR(EAGAIN)), Error::Other { errno: EAGAIN });
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(any(target_os = "linux", target_os = "macos"))]
|
||||||
|
#[test]
|
||||||
|
fn test_posix_error_string() {
|
||||||
|
assert_eq!(
|
||||||
|
Error::from(AVERROR(EAGAIN)).to_string(),
|
||||||
|
"Resource temporarily unavailable"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user