Expand description
§Generic Error
A simple utility to convert any error type that isn’t clonable into one that is,
while preserving source information providing Serialize
and Deserialize
functionality.
Magic?
§How it works
The GenericError<E>
wrapper type just stores the Display
and Debug
implementations of the wrapped type,
which is now always clonable and will serialize just fine.
The GenericError<E>
type kinda looks like this:
#[derive(Serialize, Deserialize, Clone)]
pub struct GenericError<T>
{
display: String,
debug: String,
source: Option<GenericError>,
}
.. although many details have been omitted for brevity
See docs or the examples dir for usage
§Usage
use generic_err::GenericError;
#[derive(Debug, thiserror::Error)]
enum NonCloneError {
#[error("Database is not connected")]
DbNotConnected,
}
/// Send to DB, clone a bit
fn literally_everyday<T>(_stuff: T)
where
T: Clone + serde::Serialize + serde::de::DeserializeOwned,
{
todo!()
}
fn main() {
let non_clone: Result<(), NonCloneError> = Err(NonCloneError::DbNotConnected);
let non_clone_debug = format!("{:?}", non_clone);
let now_cloneable: Result<(), GenericError<NonCloneError>> =
non_clone.map_err(GenericError::from);
let cloneable_debug = format!("{:?}", now_cloneable);
assert_eq!(non_clone_debug, cloneable_debug);
// See? Magic!
literally_everyday(now_cloneable);
}
You can also use the Untyped
variant of GenericError
if that suits your needs better.
There are also extension traits for convenience:
use generic_err::GenericError;
use generic_err::Untyped;
use generic_err::prelude::*;
#[derive(Debug, thiserror::Error)]
enum NonCloneError {
#[error("Database is not connected")]
DbNotConnected,
}
/// Send to DB, clone a bit
fn literally_everyday<T>(_stuff: T)
where
T: Clone + serde::Serialize + serde::de::DeserializeOwned,
{
todo!()
}
fn main() {
let non_clone: Result<(), NonCloneError> = Err(NonCloneError::DbNotConnected);
let clonable: Result<(), GenericError<NonCloneError>> = non_clone.make_generic();
// See? Magic!
literally_everyday(clonable);
let non_clonable: Result<(), NonCloneError> = Ok(());
let clonable_untyped: Result<(), GenericError<Untyped>> = non_clonable.make_generic_untyped();
literally_everyday(clonable_untyped);
}
Also, for types that don’t implement Debug
,
there are methods to suit your needs, e.g. GenericError::from_non_err
.
Modules§
- prelude
- Only exports extension traits without polluting your namespace
Structs§
- Generic
Error - Wrapper around any error T such that it is
Clone
,serde::Serialize
, andserde::Deserialize
by storing its initialDebug
andDisplay
representations asString
s.
Traits§
- Generic
Error Ext - This is an extension trait for the following impl:
- Generic
Error RefExt - This is an extension trait for the following impl:
Type Aliases§
- Untyped
- A marker for
GenericError
that indicates it doesn’t have knowledge of the type it is wrapping