[−][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 return a Result
containing one
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 |