irox_tools/
errors.rs

1// SPDX-License-Identifier: MIT
2// Copyright 2023 IROX Contributors
3//
4
5//!
6//! Macros to aid in the creation of crate-level error structs
7
8crate::cfg_feature_alloc! {
9    ///
10    /// Macro to build a fairly standard error struct.
11    /// ```ignore
12    /// extern crate alloc;
13    /// #[derive(Debug, Clone, Eq, PartialEq)]
14    /// pub struct ErrorName {
15    ///     error_type: ErrorType,
16    ///     msg: alloc::string::String,
17    /// }
18    /// impl core::fmt::Display for ErrorName {
19    ///     fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
20    ///         f.write_fmt(format_args!("{:?}: {}", self.error_type, self.msg))
21    ///     }
22    /// }
23    /// #[cfg(feature = "std")]
24    /// impl std::error::Error for ErrorName {}
25    /// ```
26    #[macro_export]
27    macro_rules! impl_error {
28        ($ErrorName:ident, $ErrorType:ident) => {
29            extern crate alloc;
30            #[derive(Debug, Clone, Eq, PartialEq)]
31            pub struct $ErrorName {
32                error_type: $ErrorType,
33                msg: alloc::string::String,
34            }
35            impl core::fmt::Display for $ErrorName {
36                fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
37                    f.write_fmt(format_args!("{:?}: {}", self.error_type, self.msg))
38                }
39            }
40            #[cfg(feature = "std")]
41            impl std::error::Error for $ErrorName {}
42        };
43    }
44}
45///
46/// Macro to implement from converters for error types generated with [`impl_error!`]
47/// ```ignore
48/// # struct ErrorName;
49/// impl From<source> for ErrorName {
50///     fn from(value: source) -> Self {
51///         ErrorName {
52///             error_type: ty,
53///             msg: value.to_string(),
54///         }
55///     }
56/// }
57/// ```
58#[macro_export]
59macro_rules! impl_from_error {
60    ($ErrorName:ident,$source:ty,$ty:expr) => {
61        impl From<$source> for $ErrorName {
62            fn from(value: $source) -> Self {
63                Self {
64                    error_type: $ty,
65                    msg: value.to_string(),
66                }
67            }
68        }
69    };
70}
71
72/// Macro to template out standard builder functions for types build with [`impl_error`]
73/// ```ignore
74/// impl ErrorName {
75///     pub fn name(msg: String) -> Self {
76///         Self {
77///             error_type: ty,
78///             msg,
79///         }
80///     }
81///     pub fn name_err<T>(msg: String) -> Result<T, Self> {
82///         Err(Self::name(msg))
83///     }
84/// }
85/// ```
86#[macro_export]
87macro_rules! impl_err_fn {
88    ($ErrorName:ident, $ty:expr, $name:ident, $name_err:ident) => {
89        impl $ErrorName {
90            pub fn $name(msg: String) -> Self {
91                Self {
92                    error_type: $ty,
93                    msg,
94                }
95            }
96            pub fn $name_err<T>(msg: String) -> Result<T, Self> {
97                Err(Self::$name(msg))
98            }
99        }
100    };
101}