[−][src]Crate strerror
A string-based error type.
Introduction
This crate provides a string-based error type, StrError
, that
implements std::error::Error
. It is for simple use cases where
you wish to work with string errors and/or box existing errors of
any type, adding context to them.
StrError
s behave in many ways like String
s, except they
may also 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::*;
The examples below all assume use of the prelude.
Creating StrError
s
As with String
s, there are quite a few ways to create a
StrError
. Some have an analagous String
equivalent, so are
presented side-by-side with them.
// String // StrError let str1 = "Error!".to_string(); let err1 = "Error!".into_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 StrError
s without a "source" or
"cause". To create a StrError
with a source there are two
equivalent ways, shown below. In each case the StrError
takes
ownership of the source which may or may not be another
StrError
.
use std::io::Error as IoError; // Method 1: StrError::from_error let source = IoError::from_raw_os_error(5); let err1 = StrError::from_error(source, "I/O error occurred");
use std::io::Error as IoError; // Method 2: chain let source = IoError::from_raw_os_error(5); let err2 = source.chain("I/O error occurred");
Chaining chain
method calls together
creates an error chain.
fn main() -> Result<(), StrError> { let err = "Base error".into_error() .chain("Higher level error") .chain("Application error"); Err(err) }
gives output
Error: Application error
Caused by: Higher level error
Caused by: Base error
Returning Result
s
While the chain
method adds context to
error types directly, we can do a similar thing with the Err
variant values in Result
s, with the
chain_err
method.
use std::fs::File; fn main() -> Result<(), StrError> { let file = "missing-file"; let _ = File::open(file) // a Result .chain_err(|| format!("Failed to open {}", file))?; // main exits Ok(()) }
gives output
Error: Failed to open missing-file
Caused by: No such file or directory (os error 2)
The Result
is converted to the correct type by
chain_err
and context is applied
to the boxed error. Note that
chair_err
takes a closure, and
not a String
directly. This is so the construction of the
String
is not performed unless needed.
If you are trying to return a Result
using the return
statement and the error in the return type of your function
requires a From
conversion from a StrError
, you might try
this.
use std::error::Error as StdError; fn main() -> Result<(), Box<dyn StdError>> { return Err("an error".into_error().into()); }
However, the into_err
method is
easier since it will call into
and create the
Err
variant in one step.
use std::error::Error as StdError; fn main() -> Result<(), Box<dyn StdError>> { return "an error".into_error().into_err(); }
or even simpler
use std::error::Error as StdError; fn main() -> Result<(), Box<dyn StdError>> { return "an error".into_err(); }
Converting Option
s
Sometimes None
represents an application error and it is
desirable to convert an Option<T>
into a
Result<T, StrError>
. There is no special method needed in this
case. You can use ok_or_else
with a
StrError
.
use std::env; fn main() -> Result<(), StrError> { let _ = env::var_os("MISSING_VAR") // an Option .ok_or_else(|| "MISSING_VAR not found".into_error())?; // exits Ok(()) }
gives output
Error: MISSING_VAR not found
If your containing function returns a Result<T, StrError>
, like
in the case above, it is sufficient and simpler to pass a
&str
to ok_or
or a closure returning a
String
to ok_or_else
. This produces a
Result<T, &str>
or Result<T, String>
, but when used with the
?
operator it is converted to a Result<T, StrError>
. This
works because StrError
implements From<&str>
and
From<String>
.
use std::env; fn main() -> Result<(), StrError> { let _ = env::var_os("MISSING_VAR") // an Option .ok_or("MISSING_VAR not found")?; // main exits Ok(()) }
gives output
Error: MISSING_VAR not found
From
conversions to StrError
From
conversions are implemented for most of the standard
library error types, so you can return a Result
containing one
directly from a function expecting a Result<T, StrError>
, using
the ?
operator.
use std::fs::File; fn main() -> Result<(), StrError> { let file = "missing-file"; let _ = File::open(file)?; // main exits Ok(()) }
gives output
Error: std::io::Error
Caused by: No such file or directory (os error 2)
From
conversions are also implemented for &str
and
String
, as mentioned in the previous section.
However, for other error types, if you wish to use the ?
operator you will first need to call the
chain_err
method to convert the
Result<T, E>
into a Result<T, StrError>
. Of course
you may choose to use a Box<dyn std::error::Error>
instead of a
StrError
in the the return type of your function, in which
case ?
will work for all error types.
Deref
StrError
s deref to a String
, so you can use many of the
usual String
methods.
fn main() -> Result<(), StrError> { let mut err = "This is".into_error(); *err += " an error"; err.push_str(" message"); Err(err) }
gives output
Error: This is an error message
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 |
Macros
eformat | A macro for creating a |
Structs
Iter | An iterator producing a reference to a |
StrError | A string-based error type implementing |
Traits
ErrorChainExt | Trait providing |
ResultChainErrExt | Trait providing |
StringIntoErrExt | Trait providing |
StringIntoErrorExt | Trait providing |