snafu

Trait OptionExt

Source
pub trait OptionExt<T>: Sized {
    // Required methods
    fn context<C, E>(self, context: C) -> Result<T, E>
       where C: IntoError<E, Source = NoneError>,
             E: Error + ErrorCompat;
    fn with_context<F, C, E>(self, context: F) -> Result<T, E>
       where F: FnOnce() -> C,
             C: IntoError<E, Source = NoneError>,
             E: Error + ErrorCompat;
    fn whatever_context<S, E>(self, context: S) -> Result<T, E>
       where S: Into<String>,
             E: FromString;
    fn with_whatever_context<F, S, E>(self, context: F) -> Result<T, E>
       where F: FnOnce() -> S,
             S: Into<String>,
             E: FromString;
}
Expand description

Additions to Option.

Required Methods§

Source

fn context<C, E>(self, context: C) -> Result<T, E>
where C: IntoError<E, Source = NoneError>, E: Error + ErrorCompat,

Convert an Option into a Result with additional context-sensitive information.

use snafu::prelude::*;

#[derive(Debug, Snafu)]
enum Error {
    UserLookup { user_id: i32 },
}

fn example(user_id: i32) -> Result<(), Error> {
    let name = username(user_id).context(UserLookupSnafu { user_id })?;
    println!("Username was {name}");
    Ok(())
}

fn username(user_id: i32) -> Option<String> {
    /* ... */
}

Note that the context selector will call Into::into on each field, so the types are not required to exactly match.

Source

fn with_context<F, C, E>(self, context: F) -> Result<T, E>
where F: FnOnce() -> C, C: IntoError<E, Source = NoneError>, E: Error + ErrorCompat,

Convert an Option into a Result with lazily-generated context-sensitive information.

use snafu::prelude::*;

#[derive(Debug, Snafu)]
enum Error {
    UserLookup {
        user_id: i32,
        previous_ids: Vec<i32>,
    },
}

fn example(user_id: i32) -> Result<(), Error> {
    let name = username(user_id).with_context(|| UserLookupSnafu {
        user_id,
        previous_ids: Vec::new(),
    })?;
    println!("Username was {name}");
    Ok(())
}

fn username(user_id: i32) -> Option<String> {
    /* ... */
}

Note that this may not be needed in many cases because the context selector will call Into::into on each field.

Source

fn whatever_context<S, E>(self, context: S) -> Result<T, E>
where S: Into<String>, E: FromString,

Convert an Option into a Result with information from a string.

The target error type must implement FromString by using the #[snafu(whatever)] attribute. The premade Whatever type is also available.

In many cases, you will want to use with_whatever_context instead as it is only called in case of error. This method is best suited for when you have a string literal.

use snafu::{prelude::*, Whatever};

fn example(env_var_name: &str) -> Result<(), Whatever> {
    std::env::var_os(env_var_name).whatever_context("couldn't get the environment variable")?;
    Ok(())
}

let err = example("UNDEFINED_ENVIRONMENT_VARIABLE").unwrap_err();
assert_eq!("couldn't get the environment variable", err.to_string());
Source

fn with_whatever_context<F, S, E>(self, context: F) -> Result<T, E>
where F: FnOnce() -> S, S: Into<String>, E: FromString,

Convert an Option into a Result with information from a lazily-generated string.

The target error type must implement FromString by using the #[snafu(whatever)] attribute. The premade Whatever type is also available.

use snafu::{prelude::*, Whatever};

fn example(env_var_name: &str) -> Result<(), Whatever> {
    std::env::var_os(env_var_name).with_whatever_context(|| {
        format!("couldn't get the environment variable {env_var_name}")
    })?;
    Ok(())
}

let err = example("UNDEFINED_ENVIRONMENT_VARIABLE").unwrap_err();
assert_eq!(
    "couldn't get the environment variable UNDEFINED_ENVIRONMENT_VARIABLE",
    err.to_string()
);

The closure is not called when the Option is Some:

use snafu::{prelude::*, Whatever};

let value = Some(42);
let result = value.with_whatever_context::<_, String, Whatever>(|| {
    panic!("This block will not be evaluated");
});

assert!(result.is_ok());

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.

Implementations on Foreign Types§

Source§

impl<T> OptionExt<T> for Option<T>

Source§

fn context<C, E>(self, context: C) -> Result<T, E>
where C: IntoError<E, Source = NoneError>, E: Error + ErrorCompat,

Source§

fn with_context<F, C, E>(self, context: F) -> Result<T, E>
where F: FnOnce() -> C, C: IntoError<E, Source = NoneError>, E: Error + ErrorCompat,

Source§

fn whatever_context<S, E>(self, context: S) -> Result<T, E>
where S: Into<String>, E: FromString,

Source§

fn with_whatever_context<F, S, E>(self, context: F) -> Result<T, E>
where F: FnOnce() -> S, S: Into<String>, E: FromString,

Implementors§