Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature request: impl From<Error> for io::Error #145

Closed
becky112358 opened this issue Feb 9, 2022 · 6 comments
Closed

Feature request: impl From<Error> for io::Error #145

becky112358 opened this issue Feb 9, 2022 · 6 comments
Assignees
Labels
fix added A fix was added to an unreleased branch
Milestone

Comments

@becky112358
Copy link

Firstly: Thank you for this crate. :)

It would be helpful if From<Error> for io::Error was implemented, so that applications using this crate can use the ? operator on both crate Results and std::io::Results.

I think the implementation would be performed in errors.rs and would look as follows (perhaps with even more match cases filled in):

impl From<Error> for io::Error {
    fn from(err: Error) -> io::Error {
        match err {
            Error::Io(e) => e,
            Error::Timeout => io::Error::new(io::ErrorKind::TimedOut, err),
            _ => io::Error::new(io::ErrorKind::Other, err),
        }
    }
}

I tested this locally with my own code, and it does indeed allow me to use the ? operator on Results from this crate.

@fpagliughi
Copy link
Contributor

Doesn't the existing implementation catch it? Or do you want something more fine-grained?

https://github.com/eclipse/paho.mqtt.rust/blob/9df0e5072996773b97bf1fc8156c5f9046776439/src/errors.rs#L50-L52

@becky112358
Copy link
Author

I don't think the existing implementation catches it, but I'm still learning and can believe I'm wrong!

I created this repository to demonstrate my feature request:
https://github.com/becky112358/rust_result_experimentation

Essentially the repository code is as follows:

use std::io::Result;
use std::process::Command;

fn main() -> Result<()> {
    Command::new("ping").arg("192.168.1.1").output()?;

    chrono::Duration::seconds(-5).to_std();

    hm305p::get_voltage_mv()?;

    paho_mqtt::Client::new(String::from("192.168.1.1"));

    serialport::available_ports()?;

    Ok(())
}

If I try to put the ? operator at the end of the paho_mqtt line, I get the following build error:

^ the trait `From<paho_mqtt::Error>` is not implemented for `std::io::Error`

I acknowledge that I could use anyhow crate - but it would be an even more amazing solution to have From<paho_mqtt::Error> implemented for std::io::Error. :)

@fpagliughi
Copy link
Contributor

Oh, I'm sorry. I misread your first post.

I was thinking of it the other way around.... With the existing code you can create an mqtt_paho::Error from a std::io::Error, but not going in the other direction. So potentially, if you made main() return a paho_mqtt::Result<()> it might work, though you might need to coerce some of the errors like from hm305p to behave properly.

But your suggestion sounds reasonable. (Technically MQTT is an I/O library and its errors can be considered I/O errors, right?) I hadn't even thought of it. And the implementation you suggest looks like the proper way to do it.

I'll test it out.

But have you tried the anyhow crate? It's a good way to deal with heterogenous errors in a Rust application, like the one you show. Even if I get the suggested fix in, anyhow may still be useful to easily add a context to the errors. Something like:

use anyhow::{Result, Context};
use std::process::Command;

fn main() -> Result<()> {
    hm305p::get_voltage_mv()
        .context("Couldn't retrieve voltage")?;

    serialport::available_ports()?;

    let _cli = paho_mqtt::Client::new("192.168.1.1")
        .context("Error connecting to MQTT broker")?;

    Command::new("ping").arg("192.168.1.1").output()
        .context("Failed to run the 'ping' command")?;

    let _ = chrono::Duration::seconds(-5).to_std();

    Ok(())
}

On my machine, I get:

$ ./target/debug/result 
Error: Couldn't retrieve voltage

Caused by:
    Cannot find power supply

@fpagliughi
Copy link
Contributor

fpagliughi commented Feb 11, 2022

Oh, and of course you could just catch a generic error if you didn't want to add the anyhow crate:

use std::{
    error::Error,
    process::Command,
};

fn main() -> Result<(), Box<dyn Error + 'static>> {

    Command::new("ping").arg("192.168.1.1").output()?;

    chrono::Duration::seconds(-5).to_std();

    hm305p::get_voltage_mv()?;

    paho_mqtt::Client::new(String::from("192.168.1.1"));

    serialport::available_ports()?;

    Ok(())
}

fpagliughi added a commit that referenced this issue Feb 11, 2022
@fpagliughi fpagliughi self-assigned this Feb 11, 2022
@fpagliughi fpagliughi added this to the v0.10.1 milestone Feb 11, 2022
@fpagliughi fpagliughi added the fix added A fix was added to an unreleased branch label Feb 11, 2022
@fpagliughi
Copy link
Contributor

Added to the develop branch. I'll go out with the next release.

@becky112358
Copy link
Author

Yaaay! Thank you!! 😃💚

@fpagliughi fpagliughi modified the milestones: v0.10.1, v0.11.0 Apr 14, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
fix added A fix was added to an unreleased branch
Projects
None yet
Development

No branches or pull requests

2 participants