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}