1#[doc(hidden)]
7#[macro_export]
8macro_rules! assert_error_eq {
9 ($left:expr, $right:expr) => {
10 assert_eq!(
11 Into::<$crate::Error>::into($left).to_string(),
12 Into::<$crate::Error>::into($right).to_string(),
13 );
14 };
15 ($left:expr, $right:expr,) => {
16 $crate::assert_error_eq!($left, $right);
17 };
18 ($left:expr, $right:expr, $($arg:tt)+) => {
19 assert_eq!(
20 Into::<$crate::Error>::into($left).to_string(),
21 Into::<$crate::Error>::into($right).to_string(),
22 $($arg)+
23 );
24 }
25}
26
27#[doc(hidden)]
48#[macro_export]
49macro_rules! impl_error_conversion_with_kind {
50 ($source:ty, $kind:expr, $target:ty) => {
51 impl ::std::convert::From<$source> for $target {
52 fn from(error: $source) -> Self {
53 $kind.because(error)
54 }
55 }
56 };
57}
58
59#[doc(hidden)]
79#[macro_export]
80macro_rules! impl_error_conversion_with_adaptor {
81 ($source:ty, $adaptor:ty, $target:ty) => {
82 impl ::std::convert::From<$source> for $target {
83 fn from(error: $source) -> Self {
84 ::std::convert::Into::<$adaptor>::into(error).into()
85 }
86 }
87 };
88}
89
90#[doc(hidden)]
91#[macro_export]
92macro_rules! def_error_base_on_kind {
93 ($error:ident, $error_kind:ty, $comment_error:expr, $comment_because:expr, $comment_simple:expr) => {
94 #[doc = $comment_error]
95 #[derive(Error, Debug, Clone)]
96 pub struct $error {
97 kind: $error_kind,
98 inner: $crate::AnyError,
99 }
100
101 impl ::std::fmt::Display for $error {
102 fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
103 if let Some(err) = self.cause() {
104 if f.alternate() {
105 write!(f, "{}: {}", self.kind(), err)
106 } else {
107 write!(f, "{}({})", self.kind(), err)
108 }
109 } else {
110 write!(f, "{}", self.kind())
111 }
112 }
113 }
114
115 impl ::std::convert::From<$error_kind> for $error {
116 fn from(kind: $error_kind) -> Self {
117 kind.because($crate::SilentError)
118 }
119 }
120
121 impl $error_kind {
122 #[doc = $comment_because]
123 pub fn because<E>(self, reason: E) -> $error
124 where
125 E: ::std::error::Error + Send + Sync + 'static,
126 {
127 $error {
128 kind: self,
129 inner: reason.into(),
130 }
131 }
132
133 #[doc = $comment_simple]
134 pub fn other<T>(self, reason: T) -> $error
135 where
136 T: ::std::fmt::Display,
137 {
138 $error {
139 kind: self,
140 inner: $crate::OtherError::new(reason.to_string()).into(),
141 }
142 }
143 }
144
145 impl $error {
146 pub fn kind(&self) -> $error_kind {
148 self.kind
149 }
150
151 pub fn downcast_ref<E>(&self) -> Option<&E>
153 where
154 E: ::std::fmt::Display + ::std::fmt::Debug + Send + Sync + 'static,
155 {
156 self.inner.downcast_ref::<E>()
157 }
158
159 pub fn root_cause(&self) -> &(dyn ::std::error::Error + 'static) {
161 self.inner.root_cause()
162 }
163
164 pub fn cause(&self) -> Option<&(dyn ::std::error::Error + 'static)> {
166 self.inner.chain().next()
167 }
168 }
169 };
170 ($error:ident, $error_kind:ty, $comment_error:expr) => {
171 def_error_base_on_kind!(
172 $error,
173 $error_kind,
174 $comment_error,
175 concat!(
176 "Creates `",
177 stringify!($error),
178 "` base on `",
179 stringify!($error_kind),
180 "` with an error as the reason."
181 ),
182 concat!(
183 "Creates `",
184 stringify!($error),
185 "` base on `",
186 stringify!($error_kind),
187 "` with a simple string as the reason."
188 )
189 );
190 };
191 ($error:ident, $error_kind:ty) => {
192 def_error_base_on_kind!($error, $error_kind, "/// TODO(doc): @keroro520");
193 };
194}