[−][src]Crate snafu
SNAFU
Design philosophy
SNAFU believes that it should be easy to bin one underlying error
type (such as io::Error
) into multiple
domain-specific errors while also optionally adding contextual
information.
SNAFU is designed to be used in libraries, not just end-user applications.
Quick example
This example mimics a (very poor) authentication process that
opens a file, writes to a file, and checks the user's ID. While
two of our operations involve an io::Error
,
these are different conceptual errors to us.
SNAFU creates context selectors mirroring each error
variant. These are used with the context
method to provide ergonomic error handling.
use snafu::{Snafu, ResultExt}; use std::{fs, path::{Path, PathBuf}}; #[derive(Debug, Snafu)] enum Error { #[snafu_display("Could not open config from {}: {}", "filename.display()", "source")] OpenConfig { filename: PathBuf, source: std::io::Error }, #[snafu_display("Could not save config to {}: {}", "filename.display()", "source")] SaveConfig { filename: PathBuf, source: std::io::Error }, #[snafu_display("The user id {} is invalid", "user_id")] UserIdInvalid { user_id: i32 }, } type Result<T, E = Error> = std::result::Result<T, E>; fn log_in_user<P>(config_root: P, user_id: i32) -> Result<()> where P: AsRef<Path>, { let config_root = config_root.as_ref(); let filename = &config_root.join("config.toml"); let config = fs::read(filename).context(OpenConfig { filename })?; // Perform updates to config fs::write(filename, config).context(SaveConfig { filename })?; if user_id != 42 { UserIdInvalid { user_id }.fail()?; } Ok(()) }
The Snafu
macro
This procedural macro implements the Error
trait and produces the corresponding context selectors.
Detailed example
use snafu::Snafu; use std::path::PathBuf; #[derive(Debug, Snafu)] enum Error { #[snafu_display("Could not open config at {}: {}", "filename.display()", "source")] OpenConfig { filename: PathBuf, source: std::io::Error }, #[snafu_display("Could not open config: {}", "source")] SaveConfig { source: std::io::Error }, #[snafu_display("The user id {} is invalid", "user_id")] UserIdInvalid { user_id: i32 }, }
Generated code
This will generate three additional types called context selectors:
struct OpenConfig<P> { filename: P } struct SaveConfig<P> { filename: P } struct UserIdInvalid<I> { user_id: I }
Notably:
- One struct is created for each enum variant.
- The name of the struct is the same as the enum variant's name.
- The
source
field has been removed; the library will automatically handle this for you. - Each field's type has been replaced with a generic type.
If the original variant had a source
field, its context selector
will have an implementation of From
for a
snafu::Context
:
impl<P> From<Context<Error, OpenConfig<P>>> for Error where P: Into<PathBuf>,
Otherwise, the context selector will have an inherent method
fail
:
impl<I> UserIdInvalid<I> where I: Into<i32>, { fn fail<T>(self) -> Result<T, Error> { /* ... */ } }
Attributes
Controlling Display
For backwards compatibility purposes, there are a number of ways
you can specify how the Display
trait will be implemented for
each variant:
-
#[snafu::display("a format string with arguments: {}", info)]
No special escaping is needed; this looks just like the arguments to a call to
println!
. -
#[snafu_display("a format string with arguments: {}", "info")]
Every argument is quoted as a string literal separately.
-
#[snafu_display = r#"("a format string with arguments: {}", info)"#]
The entire
Each choice has the same capabilities. All of the fields of the
variant will be available and you can call methods on them, such
as filename.display()
.
Version compatibility
SNAFU is tested and compatible back to Rust 1.18, released on 2017-06-08. Compatibility is controlled by Cargo feature flags.
Default
- Targets the current stable version of Rust at the time of release of the crate. Check the Cargo.toml for the exact version.
No features - supports Rust 1.18
- Implements
Error
andDisplay
. - Creates context selectors.
rust_1_30
- supports Rust 1.30
- Adds an implementation for
Error::source
- Adds support for re-exporting the
Snafu
macro directly from thesnafu
crate.
unstable_display_attribute
- supports Rust Nightly
- Adds support for the
snafu::display
attribute.
Re-exports
pub use snafu_derive::Snafu; |
Structs
Context | A combination of an underlying error and additional information about the error. It is not expected for users of this crate to interact with this type. |
Traits
ResultExt | Additions to |