Struct narrate::Error

source ·
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 is Send, 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

source

pub fn new<E>(error: E) -> Selfwhere E: StdError + Send + Sync + 'static,

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.

source

pub fn msg<M>(message: M) -> Selfwhere M: Display + Debug + Send + Sync + 'static,

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
}
source

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.

source

pub fn wrap<C>(self, context: C) -> Selfwhere C: Display + Send + Sync + 'static,

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)
    })
}
Examples found in repository?
examples/wrap_report_exit.rs (line 28)
24
25
26
27
28
29
30
31
fn config_error() -> Result<(), Error> {
    // simulate deserialization error
    let error = narrate::error_from!("missing key: 'port'");
    // wrap with config error
    let error = error.wrap("bad config file `/app/config.toml`");

    Err(error)
}
source

pub fn is<E>(&self) -> boolwhere E: Display + Debug + Send + Sync + 'static,

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.

source

pub fn downcast<E>(self) -> Result<E, Self>where E: Display + Debug + Send + Sync + 'static,

Attempt to downcast the error object to a concrete type.

source

pub fn downcast_ref<E>(&self) -> Option<&E>where E: Display + Debug + Send + Sync + 'static,

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),
}
source

pub fn downcast_mut<E>(&mut self) -> Option<&mut E>where E: Display + Debug + Send + Sync + 'static,

Downcast this error object by mutable reference.

source

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
}
source

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().

source

pub fn help(&self) -> Option<&str>

Get a reference to this error’s help message

source

pub fn set_help_owned(&mut self, msg: String)

👎Deprecated

Set this error’s help message to an owned String

source

pub fn set_help(&mut self, msg: &'static str)

👎Deprecated

Set this error’s help message to a static &str

source

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)
}
source

pub fn add_help_with<C, F>(&mut self, f: F)where C: Display + Send + Sync + 'static, F: FnOnce() -> C,

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);

Trait Implementations§

source§

impl Debug for Error

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl Display for Error

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl ExitCode for Error

source§

fn exit_code(&self) -> i32

CLI application exit code
source§

impl<E> From<E> for Errorwhere E: StdError + Send + Sync + 'static,

source§

fn from(err: E) -> Self

Converts to this type from the input type.
source§

impl From<Error> for Error

source§

fn from(err: Error) -> Self

Converts to this type from the input type.

Auto Trait Implementations§

§

impl !RefUnwindSafe for Error

§

impl Send for Error

§

impl Sync for Error

§

impl Unpin for Error

§

impl !UnwindSafe for Error

Blanket Implementations§

source§

impl<T> Any for Twhere T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for Twhere T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for Twhere T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<!> for T

source§

fn from(t: !) -> T

Converts to this type from the input type.
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for Twhere U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T> ToString for Twhere T: Display + ?Sized,

source§

default fn to_string(&self) -> String

Converts the given value to a String. Read more
source§

impl<T, U> TryFrom<U> for Twhere U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for Twhere U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.