Skip to main content

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}