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