wrapping_error/lib.rs
1//! An anti-boilerplate crate for errors that wrap errors.
2//!
3//! This crate only exports one item: the [`wrapping_error`] macro.
4//! See that for documentation.
5
6/// Creates an error that wraps other errors.
7///
8/// ## Example
9///
10/// ```
11/// use std::{env::VarError, io};
12///
13/// use wrapping_error::wrapping_error;
14///
15/// wrapping_error!(pub(crate) AppDataError {
16/// Var(VarError) => "could not get $HOME environment variable",
17/// Io(io::Error) => "failed to read/write app data",
18/// Postcard(postcard::Error) => "failed to serialize/deserialize app data",
19/// });
20/// ```
21#[macro_export]
22macro_rules! wrapping_error {
23 ($vis:vis $enum:ident { $($variant:ident($error:path)$( => $message:literal)?),+$(,)? }) => {
24 use std::{fmt, error};
25
26 #[derive(Debug)]
27 $vis enum $enum {
28 $($variant($error),)+
29 }
30
31 impl fmt::Display for $enum {
32 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
33 match *self {
34 // TODO: find a way to make $error optional and be able to tie (..) to whether it exists
35 $($(Self::$variant(..) => write!(f, $message),)?)+
36 ref err => err.fmt(f),
37 }
38 }
39 }
40
41 impl error::Error for $enum {
42 fn source(&self) -> Option<&(dyn error::Error + 'static)> {
43 match *self {
44 ref err => Some(err),
45 }
46 }
47 }
48
49 $(
50 impl From<$error> for $enum {
51 fn from(err: $error) -> Self {
52 Self::$variant(err)
53 }
54 }
55 )+
56 };
57}