g_err/macros.rs
1/// GErr macro.
2///
3/// Creates GErr easily with formatting support and rich data.
4///
5/// Without metadatas, the default config is [`DefaultConfig`](crate::DefaultConfig) and default data is [`NoData`](`crate::NoData`).
6///
7/// # Format
8/// - Without formatting and without metadata: `gerr!("error message goes here");`.
9/// - Without formatting and with metadata: `gerr!("error message goes here"; <metadata>)`, metadata are separated by `;`.
10/// - With formatting and with metadata: `gerr!("error message goes here {}", 123; <metadata>)`, formatting args are separated by `,` and metadata by `;`.
11///
12/// Error message and its metadata are separated by `;`.
13///
14/// Metadata's items are separated by `,`.
15///
16/// # Supported metadata
17/// - `config`: infer auto-generating config type from return type.
18/// - `config=$type`: set auto-generating config type.
19/// - `id=$expr`: set id manually with id type as set by `config=$type`.
20/// - `code=$expr`: set code string.
21/// - `data_type`: infer error data type from return type.
22/// - `data_type=$type`: define error data type.
23/// - `data=$expr`: set data, along with its type.
24/// - `source=$expr`: set non-GErr error source.
25/// - `gerr=$expr`: set GErr error source, or any error convertible to GErrSource.
26/// - `tag=$expr`: add tag.
27/// - `tags=$expr`: add multiple tags, e.g: `["tag1", "tag2",...]`.
28/// - `help=$expr`: set help message.
29///
30/// You can override the metadatas, and latest ones will be used.
31///
32/// ## NOTE
33/// The order of `config` param matters because it calls `.with_config` method which will regenerate values from new config type.
34///
35/// # Example
36/// ```rust
37/// use g_err::{gerr, Config};
38///
39/// struct U32;
40/// impl Config for U32 {
41/// type Id = u32;
42/// }
43///
44/// let inner = gerr!("parsing integer");
45/// let external_error = "anu".parse::<i32>().unwrap_err();
46/// let err = gerr!(
47/// "failed {}",
48/// 500;
49/// config=U32,
50/// id = 999, // set id
51/// code = "HTTP", // set code
52/// tag = "server", // set a tag
53/// tags = ["api", "v1"], // set tags
54/// data = "payload", // set error data
55/// code = "E-HTTP", // update code
56/// source = external_error, // set general error as source
57/// gerr = inner, // set `Into<GErrSource>` error as source
58/// help = "Try parsing valid signed integer 32", // set help hint
59/// );
60///
61/// assert_eq!(err.message(), "failed 500");
62/// assert_eq!(err.id().unwrap(), &999);
63/// assert_eq!(err.code(), Some("E-HTTP"));
64/// assert_eq!(err.data(), Some(&"payload"));
65///
66/// let tags = err.tags().unwrap();
67/// assert_eq!(tags.len(), 3);
68///
69/// let sources = err.sources().unwrap();
70/// assert_eq!(sources.len(), 2);
71/// ```
72#[macro_export]
73macro_rules! gerr {
74 // ==================================================
75 // Message only
76 // ==================================================
77
78 // string literal (no formatting)
79 ($message:literal $(,)?) => {
80 $crate::GErr::<
81 $crate::DefaultConfig,
82 $crate::NoData,
83 >::new($message)
84 };
85
86 // format!-style
87 ($fmt:literal, $($arg:expr),+ $(,)?) => {
88 $crate::GErr::<
89 $crate::DefaultConfig,
90 $crate::NoData,
91 >::new(format!($fmt, $($arg),+))
92 };
93
94 // arbitrary string expression
95 ($message:expr $(,)?) => {
96 $crate::GErr::<
97 $crate::DefaultConfig,
98 $crate::NoData,
99 >::new($message)
100 };
101
102 // ==================================================
103 // Message + builder args
104 // ==================================================
105
106 // string literal + metadata
107 (
108 $message:literal ;
109 $($rest:tt)*
110 ) => {{
111 let err = $crate::GErr::<
112 $crate::DefaultConfig,
113 $crate::NoData,
114 >::new($message);
115
116 $crate::gerr!(@build err, $($rest)*)
117 }};
118
119 // format!-style + metadata
120 (
121 $fmt:literal, $($arg:expr),+ ;
122 $($rest:tt)*
123 ) => {{
124 let err = $crate::GErr::<
125 $crate::DefaultConfig,
126 $crate::NoData,
127 >::new(format!($fmt, $($arg),+));
128
129 $crate::gerr!(@build err, $($rest)*)
130 }};
131
132 // arbitrary expression + metadata
133 (
134 $message:expr ;
135 $($rest:tt)*
136 ) => {{
137 let err = $crate::GErr::<
138 $crate::DefaultConfig,
139 $crate::NoData,
140 >::new($message);
141
142 $crate::gerr!(@build err, $($rest)*)
143 }};
144
145 // ==================================================
146 // End recursion
147 // ==================================================
148
149 (@build $err:ident) => { $err };
150 (@build $err:ident,) => { $err };
151
152 // ==================================================
153 // config
154 // ==================================================
155
156 (
157 @build $err:ident,
158 config
159 $(, $($rest:tt)*)?
160 ) => {{
161 let err = $err.with_config();
162 $crate::gerr!(@build err $(, $($rest)*)?)
163 }};
164
165 // ==================================================
166 // config = ...
167 // ==================================================
168
169 (
170 @build $err:ident,
171 config = $config:ty
172 $(, $($rest:tt)*)?
173 ) => {{
174 let err = $err.with_config::<$config>();
175 $crate::gerr!(@build err $(, $($rest)*)?)
176 }};
177
178 // ==================================================
179 // id = ...
180 // ==================================================
181
182 (
183 @build $err:ident,
184 id = $id:expr
185 $(, $($rest:tt)*)?
186 ) => {{
187 let err = $err.set_id($id);
188 $crate::gerr!(@build err $(, $($rest)*)?)
189 }};
190
191 // ==================================================
192 // code = ...
193 // ==================================================
194
195 (
196 @build $err:ident,
197 code = $code:expr
198 $(, $($rest:tt)*)?
199 ) => {{
200 let err = $err.set_code($code);
201 $crate::gerr!(@build err $(, $($rest)*)?)
202 }};
203
204 // ==================================================
205 // data_type
206 // ==================================================
207
208 (
209 @build $err:ident,
210 data_type
211 $(, $($rest:tt)*)?
212 ) => {{
213 let err = $err.with_data_type();
214 $crate::gerr!(@build err $(, $($rest)*)?)
215 }};
216
217 // ==================================================
218 // data_type = ...
219 // ==================================================
220
221 (
222 @build $err:ident,
223 data_type = $data_type:ty
224 $(, $($rest:tt)*)?
225 ) => {{
226 let err = $err.with_data_type::<$data_type>();
227 $crate::gerr!(@build err $(, $($rest)*)?)
228 }};
229
230 // ==================================================
231 // data = ...
232 // ==================================================
233
234 (
235 @build $err:ident,
236 data = $data:expr
237 $(, $($rest:tt)*)?
238 ) => {{
239 let err = $err.with_data($data);
240 $crate::gerr!(@build err $(, $($rest)*)?)
241 }};
242
243 // ==================================================
244 // source = ...
245 // ==================================================
246
247 (
248 @build $err:ident,
249 source = $source:expr
250 $(, $($rest:tt)*)?
251 ) => {{
252 let err = $err.add_source($source);
253 $crate::gerr!(@build err $(, $($rest)*)?)
254 }};
255
256 // ==================================================
257 // gerr = ...
258 // ==================================================
259
260 (
261 @build $err:ident,
262 gerr = $source:expr
263 $(, $($rest:tt)*)?
264 ) => {{
265 let err = $err.add_source_gerr($source);
266 $crate::gerr!(@build err $(, $($rest)*)?)
267 }};
268
269 // ==================================================
270 // tag = ...
271 // ==================================================
272
273 (
274 @build $err:ident,
275 tag = $tag:expr
276 $(, $($rest:tt)*)?
277 ) => {{
278 let err = $err.add_tag($tag);
279 $crate::gerr!(@build err $(, $($rest)*)?)
280 }};
281
282 // ==================================================
283 // tags = ...
284 // ==================================================
285
286 (
287 @build $err:ident,
288 tags = $tags:expr
289 $(, $($rest:tt)*)?
290 ) => {{
291 let err = $err.add_tags($tags);
292 $crate::gerr!(@build err $(, $($rest)*)?)
293 }};
294
295 // ==================================================
296 // help = ...
297 // ==================================================
298
299 (
300 @build $err:ident,
301 help = $help:expr
302 $(, $($rest:tt)*)?
303 ) => {{
304 let err = $err.set_help($help);
305 $crate::gerr!(@build err $(, $($rest)*)?)
306 }};
307}