use libc::c_int;
use libusb1_sys::constants::*;
use std::{fmt, result, str::Utf8Error, string::FromUtf16Error};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum Error {
Io,
InvalidParam,
Access,
NoDevice,
NotFound,
Busy,
Timeout,
Overflow,
Pipe,
Interrupted,
NoMem,
NotSupported,
BadDescriptor,
BadUnicode,
Other,
}
impl fmt::Display for Error {
fn fmt(&self, fmt: &mut fmt::Formatter) -> result::Result<(), fmt::Error> {
use Error::*;
fmt.write_str(match self {
Io => "Input/Output error",
InvalidParam => "Invalid parameter",
Access => "Access denied (insufficient permissions)",
NoDevice => "No such device (it may have been disconnected)",
NotFound => "Entity not found",
Busy => "Resource busy",
Timeout => "Operation timed out",
Overflow => "Overflow",
Pipe => "Pipe error",
Interrupted => "System call interrupted (perhaps due to signal)",
NoMem => "Insufficient memory",
NotSupported => "Operation not supported or unimplemented on this platform",
BadDescriptor => "Malformed descriptor",
BadUnicode => "Malformed Unicode string",
Other => "Other error",
})
}
}
impl std::error::Error for Error {}
impl From<c_int> for Error {
fn from(err: c_int) -> Self {
match err {
LIBUSB_ERROR_IO => Error::Io,
LIBUSB_ERROR_INVALID_PARAM => Error::InvalidParam,
LIBUSB_ERROR_ACCESS => Error::Access,
LIBUSB_ERROR_NO_DEVICE => Error::NoDevice,
LIBUSB_ERROR_NOT_FOUND => Error::NotFound,
LIBUSB_ERROR_BUSY => Error::Busy,
LIBUSB_ERROR_TIMEOUT => Error::Timeout,
LIBUSB_ERROR_OVERFLOW => Error::Overflow,
LIBUSB_ERROR_PIPE => Error::Pipe,
LIBUSB_ERROR_INTERRUPTED => Error::Interrupted,
LIBUSB_ERROR_NO_MEM => Error::NoMem,
LIBUSB_ERROR_NOT_SUPPORTED => Error::NotSupported,
_ => Error::Other,
}
}
}
impl From<Utf8Error> for Error {
fn from(_err: Utf8Error) -> Self {
Error::BadUnicode
}
}
impl From<FromUtf16Error> for Error {
fn from(_err: FromUtf16Error) -> Self {
Error::BadUnicode
}
}
pub type Result<T> = result::Result<T, Error>;
pub(crate) fn usb_result(res: c_int) -> Result<usize> {
if res >= 0 {
Ok(res as usize)
} else {
Err(Error::from(res))
}
}
#[doc(hidden)]
macro_rules! try_unsafe {
($x:expr) => {
match unsafe { $x } {
0 => (),
err => return Err($crate::Error::from(err)),
}
};
}