Expand description
This crate provides an error handling system used across all of the TBTL’s Rust code.
The errors constructed are automatically logged as warnings. Errors also carry the backtrace of source errors with them, along with extra context if any.
§Details
Use std::result::Result<T, bherror::Error<E>>
, or equivalently bherror::Result<T, E>
as the
return type for functions which may return an error.
The error type E
in bherror::Error<E>
must implement the BhError
trait. Therefore, all
of our concrete error types must implement BhError
.
Constructing the initial, root error is done via the Error::root
method. This will also
log a warning.
Error types that are not defined by us, i.e. don’t implement BhError
but do implement
std::error::Error
we name as “foreign errors”. These errors can be converted & propagated
to bherror::Error<E>
via the ForeignError
trait.
Propagating bherror::Error<E>
types is done via the PropagateError
trait, instead of using ?
. This way we preserve the trace of source errors.
Additional context can be attached to an error using the Error::ctx
method. As a
convenience, we also offer ErrorContext
trait which extends the
Result
type with the same method.
The crate also offers some additional features.
ErrorDyn
for cases when you want to type-erase the concreteBhError
type.Loggable
trait which extends theResult
with a method for logging errors at the error level. Note, we log all constructed errors as warnings regardless.adapters
module for easier integration with other libraries & frameworks.
§Examples
use bherror::traits::{ErrorContext, ForeignError, PropagateError};
enum MyErrors {
NumberIsNegativeError,
NumberParseError,
}
impl std::fmt::Display for MyErrors {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
MyErrors::NumberIsNegativeError => write!(f, "MyErrors::NumberIsNegativeError"),
MyErrors::NumberParseError => write!(f, "MyErrors::NumberParseError"),
}
}
}
impl bherror::BhError for MyErrors {}
fn my_function(s: &str) -> bherror::Result<i32, MyErrors> {
let num = s
.parse()
// Propagate a "foreign error" and log it as a warning.
.foreign_err(|| MyErrors::NumberParseError)
// Add some additional context to the error.
.ctx(|| format!("parsing {s}"))?;
if num < 0 {
// Return the root error and log it as a warning.
Err(bherror::Error::root(MyErrors::NumberIsNegativeError))
} else {
Ok(num)
}
}
struct AnotherError;
impl std::fmt::Display for AnotherError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "AnotherError")
}
}
impl bherror::BhError for AnotherError {}
fn another_function() -> bherror::Result<(), AnotherError> {
// Propagate `MyErrors` as the source error for `AnotherError`
my_function("blah").with_err(|| AnotherError)?;
Ok(())
}
Modules§
- adapters
- This module provides various adapters for making our
crate::Error<BhError>
types work with other libraries and frameworks. - traits
- This module provides various extension traits which provide convenience for working with our error handling system.
Structs§
- Error
- A struct that should be used for all errors in our projects.
Traits§
- BhError
- The trait needed for compatibility with the
Error
functionality. - BhError
Any - Hacky trait to enable downcasting from trait objects of it.
Type Aliases§
- Error
Dyn - Error containing type-erased
BhError
. - Result
- The
std::result::Result
wrapper that wraps the error object intoError
.