#error #library #ergonomic

snafu

An ergonomic error handling library

14 releases

new 0.2.3 Apr 24, 2019
0.2.2 Apr 19, 2019
0.2.0 Mar 26, 2019
0.1.9 Mar 2, 2019
0.1.0 Jan 28, 2019

#127 in Rust patterns

Download history 9/week @ 2019-01-23 36/week @ 2019-01-30 31/week @ 2019-02-06 2/week @ 2019-02-13 20/week @ 2019-02-20 57/week @ 2019-02-27 5/week @ 2019-03-06 20/week @ 2019-03-13 137/week @ 2019-03-20 24/week @ 2019-03-27 20/week @ 2019-04-03 28/week @ 2019-04-10 38/week @ 2019-04-17

149 downloads per month

MIT/Apache

40KB
287 lines

SNAFU

Situation Normal: All Fouled Up

crates.io Documentation Build Status

Please see the documentation for a full description.


lib.rs:

SNAFU

For detailed information, please see the user's guide.

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, Backtrace, ErrorCompat, ensure};
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, backtrace: Backtrace },
}

type Result<T, E = Error> = std::result::Result<T, E>;

fn log_in_user<P>(config_root: P, user_id: i32) -> Result<bool>
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 })?;

    ensure!(user_id == 42, UserIdInvalid { user_id });

    Ok(true)
}

# const CONFIG_DIRECTORY: &str = "/does/not/exist";
# const USER_ID: i32 = 0;
fn log_in() {
    match log_in_user(CONFIG_DIRECTORY, USER_ID) {
        Ok(true) => println!("Logged in!"),
        Ok(false) => println!("Not logged in!"),
        Err(e) => {
            eprintln!("An error occurred: {}", e);
            if let Some(backtrace) = ErrorCompat::backtrace(&e) {
                println!("{}", backtrace);
            }
        }
    }
}

Dependencies

~1.5MB
~21K SLoC