pub struct Error { /* private fields */ }
Expand description
Wrapper around a dynamic error type with an optional help message.
Error
works a lot like Box<dyn std::error::Error>
, but with these
differences:
Error
requires that the error isSend
,Sync
, and'static
.Error
is represented as a narrow pointer — exactly one word in size instead of two.Error
may contain a help message in order to suggest further actions a user might take.
Implementations§
source§impl Error
impl Error
sourcepub fn new<E>(error: E) -> Self
pub fn new<E>(error: E) -> Self
Create a new error object from any error type.
The error type must be thread-safe and 'static
, so that the Error
will be as well.
sourcepub fn msg<M>(message: M) -> Self
pub fn msg<M>(message: M) -> Self
Create a new error object from a printable error message.
If the argument implements std::error::Error
, prefer Error::new
instead which preserves the underlying error’s cause chain and
backtrace. If the argument may or may not implement std::error::Error
now or in the future, use error_from!(err)
which handles either way correctly.
Error::msg("...")
is equivalent to error_from!("...")
but
occasionally convenient in places where a function is preferable over a
macro, such as iterator or stream combinators:
use narrate::{Error, Result};
use futures::stream::{Stream, StreamExt, TryStreamExt};
async fn demo<S>(stream: S) -> Result<Vec<Output>>
where
S: Stream<Item = Input>,
{
stream
.then(ffi::do_some_work) // returns Result<Output, &str>
.map_err(Error::msg)
.try_collect()
.await
}
sourcepub fn from_anyhow(error: Error) -> Self
pub fn from_anyhow(error: Error) -> Self
Convert an anyhow::Error
into an error object.
Due to the generic implementation of From
for Error
: we cannot
add a From<anyhow::Error>
impl. Use this instead.
sourcepub fn wrap<C>(self, context: C) -> Self
pub fn wrap<C>(self, context: C) -> Self
Wrap the error value with additional context.
For attaching context to a Result
as it is propagated, the
ErrorWrap
extension trait may be more convenient than this function.
The primary reason to use error.warp(...)
instead of
result.warp(...)
via the ErrorWrap
trait would be if the context
needs to depend on some data held by the underlying error:
use narrate::Result;
use std::fs::File;
use std::path::Path;
struct ParseError {
line: usize,
column: usize,
}
fn parse_impl(file: File) -> Result<T, ParseError> {
...
}
pub fn parse(path: impl AsRef<Path>) -> Result<T> {
let file = File::open(&path)?;
parse_impl(file).map_err(|error| {
let context = format!(
"only the first {} lines of {} are valid",
error.line, path.as_ref().display(),
);
narrate::Error::new(error).wrap(context)
})
}
sourcepub fn is<E>(&self) -> bool
pub fn is<E>(&self) -> bool
Returns true if E
is the type held by this error object.
For wrapped errors, this method returns true if E
matches the
type of the context C
or the type of the error on which the
context has been attached.
sourcepub fn downcast<E>(self) -> Result<E, Self>
pub fn downcast<E>(self) -> Result<E, Self>
Attempt to downcast the error object to a concrete type.
sourcepub fn downcast_ref<E>(&self) -> Option<&E>
pub fn downcast_ref<E>(&self) -> Option<&E>
Downcast this error object by reference.
§Example
// If the error was caused by redaction, then return a tombstone instead
// of the content.
match root_cause.downcast_ref::<DataStoreError>() {
Some(DataStoreError::Censored(_)) => Ok(Poll::Ready(REDACTED_CONTENT)),
None => Err(error),
}
sourcepub fn downcast_mut<E>(&mut self) -> Option<&mut E>
pub fn downcast_mut<E>(&mut self) -> Option<&mut E>
Downcast this error object by mutable reference.
sourcepub fn chain(&self) -> Chain<'_> ⓘ
pub fn chain(&self) -> Chain<'_> ⓘ
An iterator of the chain of source errors contained by this Error.
This iterator will visit every error in the cause chain of this error object, beginning with the error that this error object was created from.
§Example
use narrate::Error;
use std::io;
pub fn underlying_io_error_kind(error: &Error) -> Option<io::ErrorKind> {
for cause in error.chain() {
if let Some(io_error) = cause.downcast_ref::<io::Error>() {
return Some(io_error.kind());
}
}
None
}
sourcepub fn root_cause(&self) -> &(dyn StdError + 'static)
pub fn root_cause(&self) -> &(dyn StdError + 'static)
The lowest level cause of this error — this error’s cause’s cause’s cause etc.
The root cause is the last error in the iterator produced by
chain()
.
sourcepub fn set_help_owned(&mut self, msg: String)
👎Deprecated
pub fn set_help_owned(&mut self, msg: String)
Set this error’s help message to an owned String
sourcepub fn set_help(&mut self, msg: &'static str)
👎Deprecated
pub fn set_help(&mut self, msg: &'static str)
Set this error’s help message to a static &str
sourcepub fn add_help(&mut self, help: &'static str)
pub fn add_help(&mut self, help: &'static str)
Add a ’static help message to the Error.
Use this method to add a plain help str
. If you need to format the
message, or add an owned String
, use
add_help_with
instead.
If the Error already has existing help text, this method will append the new message to it (on a new line). This is done deliberately because the last help message should be most visible.
You can add help to any Result
that might contain a
std::error::Error
, by using the ErrorWrap
trait.
§Examples
Add help to a constructed Error
.
use narrate::Error;
let mut error = Error::new(AppError);
error.add_help("help message");
Add multiple help messages.
use narrate::{Error, ErrorWrap, Result};
fn main() {
let err = outer().unwrap_err();
// outer help appended on a new line
let expected = "inner help\nouter help";
assert_eq!(err.help(), Some(expected));
}
fn outer() -> Result<()> {
// uses the ErrorWrap trait to add help to the Result
inner().add_help("outer help")?;
Ok(())
}
fn inner() -> Result<()> {
let mut error = Error::new(AppError);
error.add_help("inner help");
Err(error)
}
sourcepub fn add_help_with<C, F>(&mut self, f: F)
pub fn add_help_with<C, F>(&mut self, f: F)
Add a computed help message to the Error.
Use this method to add a formatted or computed String
. If you are
adding a 'static str
you should use add_help
instead.
This method takes any closure that produces a value that implements
Display
, Send
, Sync
and 'static
.
If the Error already has existing help text, this method will append the new message to it (on a new line). This is done deliberately because the last help message should be most visible.
You can add help to any Result
that might contain a
std::error::Error
, by using the ErrorWrap
trait.
§Examples
Add formatted help.
use narrate::{CliError, Error};
let path = PathBuf::from("/path/to/file");
let mut error = Error::new(CliError::CreateFile(path.clone()));
error.add_help_with(|| format!("helpful message about path: {}", path.display()));
Add existing value.
use narrate::error_from;
let mut error = error_from!("error msg");
let help = String::from("help msg");
error.add_help_with(|| help);