[−][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 { return Err(Error::UserIdInvalid { user_id }); } 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 }, }
Generated code
This will generate two additional types called context selectors:
struct OpenConfig<P> { filename: P } struct SaveConfig<P> { filename: P }
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.
Each context selector will have an implementation of
From
for a snafu::Context
:
impl<P> From<Context<Error, OpenConfig<T0>>> for Error where P: Into<PathBuf>,
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 |