[−][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.
StrErrors behave in some ways 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::*;
The examples below all assume use of the prelude.
Creating StrErrors
As with Strings, there are quite a few ways to create a
StrError. Some have a String equivalent so are presented
side-by-side.
// 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". 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 source1 = IoError::from_raw_os_error(5); let err1 = StrError::from_error(source1, "I/O error occurred");
use std::io::Error as IoError; // Method 2: chain 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 chaining methods together also creates an error
chain.
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
Returning Results
While the chain method adds context to error types directly, we
can do a similar thing with the Err values contained within
Results, 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 contruction
of the String is not performed unless needed.
Converting Options
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 new StrError (created
using to_error, for example).
use std::env; fn main() -> Result<(), StrError> { let _ = env::var_os("MISSING_VAR") // an Option .ok_or_else(|| "MISSING_VAR not found".to_error())?; // main exits Ok(()) }
gives output
Error: MISSING_VAR not found
If your containing function returns a Result<T, StrError>, like
in case above, it is sufficient and simpler to pass a &str to
ok_or or 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
From conversions are implemented for most of the standard
library error types, so you can return a Result containing one
directly from a function returning 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 above.
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 return a Result<T, Box<dyn std::error::Error>>
from your containing function instead, in which case ? will work
for all error types.
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
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 |