[][src]Crate strerror

A string-based error type.

Introduction

This crate provides a string-based error type, StrError, that implements std::error::Error. StrErrors behave much like Strings, except they may contain another error boxed inside them, known as the "source" or "cause". Since the source can have a source itself, sources form chains of errors, each error adding context to the preceeding one.

When a StrError is returned from main, its Debug implementation causes the output of a CLI application to look like this

Error: ...
Caused by: ...
Caused by: ...
...

Each "Caused by:" line corresponds to a boxed error in the chain of sources.

The prelude

This crate has a prelude to bring in all the things you need at once.

use strerror::prelude::*;

Because some of the crate's functionality is contained in extension traits, this is quite useful. The examples below all assume the prelude is used.

Creating StrErrors

As with Strings, there are quite a few ways to create a StrError. Some have a String equivalent so we present these below.

// String                             // StrError
let str1 = "Error!".to_string();      let err1 = "Error!".to_error();
let str2 = String::from("Error!");    let err2 = StrError::from("Error!");
let str3: String = "Error!".into();   let err3: StrError = "Error!".into();
let str4 = format!("Error! #{}", 1);  let err4 = eformat!("Error! #{}", 1);

The above lines all create StrErrors without a "source" or "cause". Next we show two equivalent ways to create a StrError containing a source. The StrError takes ownership of the source which may or may not be another StrError.

use std::io::Error as IoError;

let source1 = IoError::from_raw_os_error(5);
let err1 = StrError::from_error(source1, "I/O error occurred");

let source2 = IoError::from_raw_os_error(5);
let err2 = source2.chain("I/O error occurred");

The usefulness of the second way using the chain method comes from the fact that, like its name suggests, it can be chained.

fn main() -> Result<(), StrError> {
    let err = "Base error".to_error()
        .chain("Higher level error")
        .chain("Application error");
    Err(err)
}

This gives the output

Error: Application error
Caused by: Higher level error
Caused by: Base error

Working with Results and Options

As well as adding context to error types directly, the chain method can be applied to Results to convert a Result's error type to a StrError.

use std::fs::File;

fn main() -> Result<(), StrError> {
    let file = "missing-file";
    let _ = File::open(file)                              // returns a Result
        .chain(format!("Failed to open file {}", file))?; // main exits here
    Ok(())
}

gives output

Error: Failed to open file missing-file
Caused by: No such file or directory (os error 2)

Options can also have the chain method applied to them, interpreting None as an error. In this case chain returns a Result containing a StrError with no source.

use std::env;

fn main() -> Result<(), StrError> {
    let _ = env::var_os("MISSING_VAR")                         // returns an Option
        .chain("Environment variable MISSING_VAR not found")?; // main exits here
    Ok(())
}

gives

Error: Environment variable MISSING_VAR not found

Deref

StrErrors deref to a String, so you can use many of the usual String methods.

fn main() -> Result<(), StrError> {
    let mut err = "This is".to_error();
    *err += " an error";
    err.push_str(" message");
    Err(err)
}

gives output

Error: This is an error message

From conversions for other error types

From conversions are implemented for most of the standard library error types, so you can return them directly from a function that returns a StrError using the ? operator.

use std::fs::File;

fn main() -> Result<(), StrError> {
    let file = "missing-file";
    let _ = File::open(file)?; // main exits here
    Ok(())
}

gives output

Error: std::io::Error
Caused by: No such file or directory (os error 2)

Conversions are also implemented for &str and String.

However, for other error types you will need to first call the chain method to convert the Result to one containing a StrError, as shown previously. Of course you may choose to return a Box<dyn std::error::Error> from your function instead, for which ? will work for all types.

Iterating through the source chain

A reference to a StrError can be iterated over to examine its chain of boxed sources.

use std::io::Error as IoError;

fn main() -> Result<(), StrError> {
    let err = IoError::from_raw_os_error(5)
        .chain("Failure reading disk")
        .chain("Application error");
    for e in &err {
        println!(
            "Error: {:31} Is StrError?: {}",
            e,
            e.downcast_ref::<StrError>().is_some()
        );
    }
    Ok(())
}

gives output

Error: Application error               Is StrError?: true
Error: Failure reading disk            Is StrError?: true
Error: Input/output error (os error 5) Is StrError?: false

Modules

prelude

Reexports of eformat, ErrorChainExt, StrError and StringToErrorExt.

Macros

eformat

A macro for creating a StrError using interpolation of runtime expressions (like format!).

Structs

Iter

An iterator producing a reference to a StrError (as a trait object), followed by its chain of sources.

StrError

A string-based error type implementing std::error::Error.

Traits

ErrorChainExt

Functionality for converting an error of any type to a StrError.

StringToErrorExt

Functionality for converting a String or &str to a StrError.