Skip to content

Commit

Permalink
Add quick start with annotated examples
Browse files Browse the repository at this point in the history
  • Loading branch information
alamb committed Feb 18, 2021
1 parent 0066b51 commit a76e40a
Showing 1 changed file with 70 additions and 23 deletions.
93 changes: 70 additions & 23 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@
//!
//! ## Quickstart / Cookbook
//!
//! Here is to see if Snafu might be right for your project, the
//! following annotated examples illustrate how Snafu is used in some
//! common situations.
//! To decide if Snafu might be right for your project and get you
//! going quickly, the following annotated examples illustrate how
//! Snafu is used in some common situations.
//!
//! ### Basic Errors
//! ### Basic Error Handling
//! ```rust
//! use snafu::Snafu;
//!
//! // To use Snafu, first, derive `Snafu` on an error enum
//! // To use Snafu, derive `Snafu` on an error enum
//! // which creates a NEW *context selector* type, also named
//! //`LogicalError` but distinct from `Error::LogicalError`
//!
Expand All @@ -28,52 +28,99 @@
//! LogicalError { val: u64 },
//! }
//!
//! // Then, define a corresponding result type
//! // Then, define a corresponding Result type
//! type Result<T, E = Error> = std::result::Result<T, E>;
//!
//! /// Search for the answer
//! fn calculate(val: u64) -> Result<()> {
//! if val != 42 {
//! // Generate a Err(Error::LogicalError(..)) using the context selector
//! // Generate a Err(Error::LogicalError(..)) using the SNAFU context selector
//! LogicalError { val }.fail()
//! } else {
//! Ok(())
//! }
//! }
//! ```
//!
//! ### Contextual Errors / use of `ResultExt `context` trait
//! Often times errors in your application occur due to an underlying error
//! in your other code
//! ### Contextual Errors / [`ResultExt`] trait
//!
//! Oftentimes, errors in your application occur due to an underlying error
//! in libraries you call. Snafu makes the underlying source easy to capture and annotate
//! with the [`ResultExt`] trait.
//!
//! ```rust
//! use snafu::{ensure, Backtrace, ErrorCompat, ResultExt, Snafu};
//! use snafu::{ResultExt, Snafu};
//! use std::fs::File;
//!
//! // As before, derive `Snafu` on an Error enum, but this time include
//! // a `source` field with the corresponding error type
//!
//! #[derive(Debug, Snafu)]
//! enum Error {
//! #[snafu(display("Could not open config from {}: {}", filename.display(), source))]
//! #[snafu(display("Could not open config from {}: {}", filename, source))]
//! OpenConfig {
//! filename: PathBuf,
//! source: std::io::Error,
//! },
//! #[snafu(display("Could not save config to {}: {}", filename.display(), source))]
//! SaveConfig {
//! filename: PathBuf,
//! // Users will appreciate knowing *what* file could not be opened
//! // which is information NOT included in std::io::Error
//! filename: String,
//!
//! // NOTE: source error *must* be on a field named `source`
//! 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>;
//!
//! /// Try and open a config file
//! fn open_the_file(filename: &'static str) -> Result<()> {
//! // Use the `context` function and `OpenConfig` context selector
//! // to map the std::io::Error to Error::OpenConfig and add the
//! // filename as well.
//! let file = File::open(&filename)
//! // Note that the context selector calls `filename.into()` automatically
//! // to convert the `str` into `String` in `Error::OpenConfig`
//! .context(OpenConfig { filename })?;
//!
//! // do something with `file`
//! Ok(())
//! }
//! ```
//!
//! ### Boxing Errors
//! In rare occasions, you might not know the type of error
//! produced from an underlying library. While non-ideal,
//! you can still handle this situation using `Box`ed errors with SNAFU.
//!
//! ```rust
//! use snafu::{ResultExt, Snafu};
//! use std::fs::File;
//!
//! // Derive `Snafu` and define a `source` field as a `Box`
//!
//! #[derive(Debug, Snafu)]
//! enum Error {
//! #[snafu(display("Could not open config from {}: {}", filename, source))]
//! OpenConfig {
//! filename: String,
//! source: Box<dyn std::error::Error>,
//! },
//! }
//!
//! type Result<T, E = Error> = std::result::Result<T, E>;
//!
//! Example showing use of source errors
//! fn open_the_file(filename: &'static str) -> Result<()> {
//! // we can `Box` the error when we don't know the type
//! // but still want to return Err(Error::OpenConfig{..}),
//! // with a filename as context
//! let file = File::open(&filename)
//! .map_err(|e| Box::new(e) as _)
//! .context(OpenConfig { filename })?;
//!
//! Example showing use of boxed errors
//! // do something with `file`
//! Ok(())
//! }
//! ```
//!
//! ## Complete
//! ## Complete Example
//!
//! This example mimics a (very poor) authentication process that
//! opens a file, writes to a file, and checks the user's ID. While
Expand Down

0 comments on commit a76e40a

Please sign in to comment.