4 ms·
As the author of [SNAFU], another error handling library, this is how I'd encourage it: use snafu::{Snafu, ResultExt}; #[derive(Debug, Snafu)]
by shepmaster 6y ago
As the author of [SNAFU], another error handling library, this is how I'd encourage it:
use snafu::{Snafu, ResultExt};
#[derive(Debug, Snafu)]
enum Error {
#[snafu(display("Failed to read {}", filename))]
ReadInput { filename: String, source: std::io::Error },
}
type Result<T, E = Error> = std::result::Result<T, E>;
fn main() -> Result<()> {
let filename = "input.txt";
let s = std::fs::read_to_string(filename).context(ReadInput { filename })?;
println!("{}", s);
Ok(())
}
Unfortunately, this uses the default `Debug` formatting, so what is printed to the user in this `main` example is still less-than-ideal:
Error: ReadInput { filename: "input.txt", source: Os { code: 2, kind: NotFound, message: "No such file or directory" } }
I encourage using the `Display` formatter or something more complete.
I find that doing this rigorously creates what I call a "semantic backtrace", where the linked list of (error, context, underlying cause) provides a great deal of insight into the problem.
The next release of SNAFU will incorporate something that allows for stringly-typed errors:
use snafu::{ResultExt, Whatever};
type Result<T, E = Whatever> = std::result::Result<T, E>;
fn main() -> Result<()> {
let filename = "input.txt";
let s = std::fs::read_to_string(filename)
.with_whatever_context(|_| format!("couldn't read {}", filename))?;
println!("{}", s);
Ok(())
}
You will also be able to combine stringly-typed errors with the structured errors.
Other features of the currently-released SNAFU:
- Custom error types
- Backtraces
- Extension traits for Results / Options / Futures / Streams
- Suitable for libraries and applications
- no-std compatibility
- Generic types and lifetimes
[SNAFU]: https://crates.io/crates/snafu https://crates.io/crates/snafu
- q3k 6y agoHow does this work if I use SNAFU and so does a library I call?
- shepmaster 6y agoI'm not 100% sure what you mean, so I'll try to cover it broadly. Ideally the fact that you use SNAFU should not escape from your library; I encourage creating an [opaque] error in most cases. The current deliberate "leak" is that we implement a [trait] that exposes the ability to get a backtrace from a SNAFU error because the standard library has not yet stabilized backtraces. Once those are stabilized, we should be able to completely isolate and only operate through the `std::error::Error` trait. [opaque]: https://docs.rs/snafu/0.6.9/snafu/guide/opaque/index.html https://docs.rs/snafu/0.6.9/snafu/guide/opaque/index.html [trait]: https://docs.rs/snafu/0.6.9/snafu/trait.ErrorCompat.html https://docs.rs/snafu/0.6.9/snafu/trait.ErrorCompat.html