Why would we use anyhow::Result
instead of Rust's built-in Result
type?
In Rust there are two types of errors: Recoverable and Unrecoverable. We'll ignore unrecoverable errors because anyhow is a library for working with recoverable errors.
Unrecoverable errors are panics.
anyhow::Result
is a core::result::Result
specialized to anyhow's anyhow::Error
struct. The definition in anyhow is a type alias.
pub type Result<T, E = Error> = core::result::Result<T, E>;
This means anyhow::Result
is the core::result::Result
you may be used to, with the error type already set. The following two types are equivalent
fn main() -> Result<(), anyhow::Error> {}
fn main() -> anyhow::Result<()> {}
This works out really well for us because anyhow::Error
is a fairly transparent layer over any error type that allows adding additional context to errors that get propagated back alongside the original error.
This allows us to return both third party errors, such as those from the std library or another crate and own own errors.
In the validation function, we can construct our own anyhow::Error
with the anyhow!
macro
anyhow!("missing X-Signature-Ed25519 header")
as well as return errors from third party crates with additional application-specific context. For example, This isn't just a hex::decode
error, it's an error decoding a specific header.
let decoded_header = hex::decode(header_signature).context("Failed to decode ed25519 signature header",)?;