Skip to main content

snafu/guide/examples/
basic.rs

1//! The most common usage of SNAFU — an enumeration of possible errors.
2//!
3//! Start by looking at the error type [`Error`], then view the
4//! *context selectors* [`LeafSnafu`] and [`IntermediateSnafu`].
5
6use crate::prelude::*;
7
8/// An enumeration of possible errors.
9///
10/// This will create a number of *context selectors*:
11///
12/// - [`LeafSnafu`]
13/// - [`IntermediateSnafu`]
14///
15/// ## Leaf errors
16///
17/// Context selectors for error variants without a `source`, such
18/// as [`LeafSnafu`], have methods to construct them, such as
19/// [`LeafSnafu::build`] or [`LeafSnafu::fail`]. The [`ensure`] macro also
20/// accepts these kinds of context selectors.
21///
22/// ```
23/// # use snafu::guide::examples::basic::*;
24/// use snafu::prelude::*;
25///
26/// fn always_fails() -> Result<(), Error> {
27///     LeafSnafu { user_id: 42 }.fail()
28/// }
29///
30/// fn sometimes_fails(user_id: i32) -> Result<(), Error> {
31///     ensure!(user_id > 0, LeafSnafu { user_id });
32///     Ok(())
33/// }
34/// ```
35///
36/// ## Intermediate errors
37///
38/// Context selectors for error variants with a `source`, such as
39/// [`IntermediateSnafu`], are intended to be used with the
40/// [`ResultExt::context`] family of methods.
41///
42/// ```
43/// # use snafu::guide::examples::basic::*;
44/// use snafu::prelude::*;
45///
46/// fn load_config_file() -> Result<usize, Error> {
47///     let config = std::fs::read_to_string("/path/to/my/config/file").context(IntermediateSnafu)?;
48///     Ok(config.len())
49/// }
50/// ```
51///
52/// [`ResultExt::context`]: crate::ResultExt::context
53#[derive(Debug, Snafu)]
54// This line is only needed to generate documentation; it is not
55// needed in most cases:
56#[snafu(crate_root(crate), visibility(pub))]
57pub enum Error {
58    Leaf {
59        user_id: i32,
60    },
61
62    Intermediate {
63        source: std::io::Error,
64    },
65}