[−][src]Crate strerror
A string-based error type.
Introduction
This crate provides a string-based error type, StrError
, that
implements std::error::Error
. StrError
s behave much like
String
s, 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 StrError
s
As with String
s, there are quite a few ways to create a
StrError
. Some have a String
equivalent so we present these
alongside each other.
// 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 StrError
s 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 advantage of the second way using the chain
method comes
from the fact that, in chaining methods together, an error chain
itself can be created.
fn main() -> Result<(), StrError> { let err = "Base error".to_error() .chain("Higher level error") .chain("Application error"); Err(err) }
gives output
Error: Application error
Caused by: Higher level error
Caused by: Base error
Working with Result
s and Option
s
While the chain
method adds context to error types directly, we
can do a similar thing with the Err
value within a Result
with
the chain_err
method.
use std::fs::File; fn main() -> Result<(), StrError> { let file = "missing-file"; let _ = File::open(file) // returns a Result .chain_err(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)
With Option
s no special method is needed to transform one into a
Result
with a StrError
. We can just use ok_or
and
ok_or_else
with a newly created one.
However it is often sufficient to pass just a &str
or
String
. This gives a Result
containing a &str
or String
for its Err
value, but when used with the ?
operator it gets
converted to a StrError
. This works because StrError
implements From<&str>
and From<String>
.
use std::env; fn main() -> Result<(), StrError> { let _ = env::var_os("MISSING_VAR") // returns an Option .ok_or("Environment variable MISSING_VAR not found")?; // main exits here Ok(()) }
gives
Error: Environment variable MISSING_VAR not found
From
conversions for other error types
From
conversions are implemented for most of the standard
library error types, so you can can return Results
containing
them directly from a function that returns a Result
containing 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)
As mentioned when discussing Option
s, From
conversions are
also implemented for &str
and String
.
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
into one containing a StrError
. Of course
you may choose to return a Result
containing a
Box<dyn std::error::Error>
from your function instead, for which
?
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".to_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 |
StringToErrorExt | Trait providing |