ruabmbua / hidapi-rs

Rust bindings for the hidapi C library
MIT License
172 stars 81 forks source link

Feature Request: Add impl std::convert::From<hidapi::HidError> for io::Error #48

Closed ConnorBP closed 4 years ago

ConnorBP commented 4 years ago

Currently it is not possible to use rusts ? function instead of .unwrap() due to the error that is being returned not being able to convert into the standard error. Adding this way, or some other way, to allow the use of this feature would make the syntax using the api much nicer on modern rust.

lnicola commented 4 years ago

hidapi::HidError and io::Error are somewhat unrelated, so I'm not sure it's a good idea to provide a conversion between them, even if it was possible (I don't know how From and Into work wrt. the coherence rules).

The idiomatic solution would be to use either an Error enum in your crate, or something like Box<dyn Error>. There are a lot of error handling helpers that can help with the enum boilerplate.

E.g.

use std::error;
use std::fmt::{self, Display, Formatter};
use std::io;

#[derive(Debug)]
enum Error {
    Hid(HidError),
    Io(io::Error),
}

impl From<HidError> for Error {
    fn from(err: HidError) -> Self {
        Error::Hid(err)
    }
}

impl From<io::Error> for Error {
    fn from(err: io::Error) -> Self {
        Error::Io(err)
    }
}

impl error::Error for Error {
    fn source(&self) -> Option<&(dyn error::Error + 'static)> {
        match self {
            Error::Hid(cause) => Some(cause.as_ref()),
            Error::Io(cause) => Some(cause),
        }
    }
}

impl Display for Error {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        match self {
            Error::Hid(err) => err.fmt(f),
            Error::Io(err) => err.fmt(f),
        }
    }
}
ruabmbua commented 4 years ago

As log as your function returns an error type, which defines impl From<hidapi::Error> for YourError {} you should be able to use the try operator.