Skip to main content

mdk_macros/
lib.rs

1#![forbid(unsafe_code)]
2
3/// Generates fluent builder-pattern setter methods in batch.
4///
5/// Each entry produces a `pub fn name(mut self, ...) -> Self` method.
6/// Default behavior wraps the value in `Some()`. Use `<direct>` to skip wrapping.
7///
8/// # Syntax
9///
10/// ```ignore
11/// setters! {
12///     /// doc comment
13///     name: Type;                               // self.name = Some(name)
14///     name: impl Into<Type>;                    // self.name = Some(name.into())
15///     name<direct>: Type;                       // self.name = name
16///     method -> field: Type;                    // self.field = Some(field)
17///     method<direct> -> field: Type;            // self.field = field
18///     method -> field: impl Into<Type>;         // self.field = Some(field.into())
19///     method<direct> -> field: impl Into<Type>; // self.field = field.into()
20/// }
21/// ```
22#[macro_export]
23macro_rules! setters {
24    // === impl Into<T> arms (must come before $ty:ty arms) ===
25
26    // impl Into + <direct> + rename
27    (
28        $(#[$meta:meta])*
29        $method:ident < direct > -> $field:ident : impl Into< $inner:ty >;
30        $($rest:tt)*
31    ) => {
32        $(#[$meta])*
33        pub fn $method<T>(mut self, $field: T) -> Self
34        where
35            T: Into<$inner>,
36        {
37            self.$field = $field.into();
38            self
39        }
40        $crate::setters!($($rest)*);
41    };
42
43    // impl Into + rename (default = Some)
44    (
45        $(#[$meta:meta])*
46        $method:ident -> $field:ident : impl Into< $inner:ty >;
47        $($rest:tt)*
48    ) => {
49        $(#[$meta])*
50        pub fn $method<T>(mut self, $field: T) -> Self
51        where
52            T: Into<$inner>,
53        {
54            self.$field = Some($field.into());
55            self
56        }
57        $crate::setters!($($rest)*);
58    };
59
60    // impl Into + <direct> + no rename
61    (
62        $(#[$meta:meta])*
63        $name:ident < direct > : impl Into< $inner:ty >;
64        $($rest:tt)*
65    ) => {
66        $(#[$meta])*
67        pub fn $name<T>(mut self, $name: T) -> Self
68        where
69            T: Into<$inner>,
70        {
71            self.$name = $name.into();
72            self
73        }
74        $crate::setters!($($rest)*);
75    };
76
77    // impl Into + no rename (default = Some)
78    (
79        $(#[$meta:meta])*
80        $name:ident : impl Into< $inner:ty >;
81        $($rest:tt)*
82    ) => {
83        $(#[$meta])*
84        pub fn $name<T>(mut self, $name: T) -> Self
85        where
86            T: Into<$inner>,
87        {
88            self.$name = Some($name.into());
89            self
90        }
91        $crate::setters!($($rest)*);
92    };
93
94    // === Plain type arms ===
95
96    // plain + <direct> + rename
97    (
98        $(#[$meta:meta])*
99        $method:ident < direct > -> $field:ident : $ty:ty;
100        $($rest:tt)*
101    ) => {
102        $(#[$meta])*
103        pub fn $method(mut self, $field: $ty) -> Self {
104            self.$field = $field;
105            self
106        }
107        $crate::setters!($($rest)*);
108    };
109
110    // plain + rename (default = Some)
111    (
112        $(#[$meta:meta])*
113        $method:ident -> $field:ident : $ty:ty;
114        $($rest:tt)*
115    ) => {
116        $(#[$meta])*
117        pub fn $method(mut self, $field: $ty) -> Self {
118            self.$field = Some($field);
119            self
120        }
121        $crate::setters!($($rest)*);
122    };
123
124    // plain + <direct> + no rename
125    (
126        $(#[$meta:meta])*
127        $name:ident < direct > : $ty:ty;
128        $($rest:tt)*
129    ) => {
130        $(#[$meta])*
131        pub fn $name(mut self, $name: $ty) -> Self {
132            self.$name = $name;
133            self
134        }
135        $crate::setters!($($rest)*);
136    };
137
138    // plain + no rename (default = Some)
139    (
140        $(#[$meta:meta])*
141        $name:ident : $ty:ty;
142        $($rest:tt)*
143    ) => {
144        $(#[$meta])*
145        pub fn $name(mut self, $name: $ty) -> Self {
146            self.$name = Some($name);
147            self
148        }
149        $crate::setters!($($rest)*);
150    };
151
152    // Base case
153    () => {};
154}
155
156/// Generates mutation setter methods in batch.
157///
158/// Each entry produces a `pub fn name(&mut self, ...)` method (no return value).
159/// Default behavior wraps the value in `Some()`. Use `<direct>` to skip wrapping.
160///
161/// # Syntax
162///
163/// Same as [`setters!`] but generates `&mut self` methods instead of builder methods.
164///
165/// ```ignore
166/// mut_setters! {
167///     /// doc comment
168///     set_name<direct> -> name: String;     // self.name = name
169///     set_field -> field: Type;             // self.field = Some(field)
170/// }
171/// ```
172#[macro_export]
173macro_rules! mut_setters {
174    // === impl Into<T> arms ===
175
176    // impl Into + <direct> + rename
177    (
178        $(#[$meta:meta])*
179        $method:ident < direct > -> $field:ident : impl Into< $inner:ty >;
180        $($rest:tt)*
181    ) => {
182        $(#[$meta])*
183        pub fn $method<T>(&mut self, $field: T)
184        where
185            T: Into<$inner>,
186        {
187            self.$field = $field.into();
188        }
189        $crate::mut_setters!($($rest)*);
190    };
191
192    // impl Into + rename (default = Some)
193    (
194        $(#[$meta:meta])*
195        $method:ident -> $field:ident : impl Into< $inner:ty >;
196        $($rest:tt)*
197    ) => {
198        $(#[$meta])*
199        pub fn $method<T>(&mut self, $field: T)
200        where
201            T: Into<$inner>,
202        {
203            self.$field = Some($field.into());
204        }
205        $crate::mut_setters!($($rest)*);
206    };
207
208    // impl Into + <direct> + no rename
209    (
210        $(#[$meta:meta])*
211        $name:ident < direct > : impl Into< $inner:ty >;
212        $($rest:tt)*
213    ) => {
214        $(#[$meta])*
215        pub fn $name<T>(&mut self, $name: T)
216        where
217            T: Into<$inner>,
218        {
219            self.$name = $name.into();
220        }
221        $crate::mut_setters!($($rest)*);
222    };
223
224    // impl Into + no rename (default = Some)
225    (
226        $(#[$meta:meta])*
227        $name:ident : impl Into< $inner:ty >;
228        $($rest:tt)*
229    ) => {
230        $(#[$meta])*
231        pub fn $name<T>(&mut self, $name: T)
232        where
233            T: Into<$inner>,
234        {
235            self.$name = Some($name.into());
236        }
237        $crate::mut_setters!($($rest)*);
238    };
239
240    // === Plain type arms ===
241
242    // plain + <direct> + rename
243    (
244        $(#[$meta:meta])*
245        $method:ident < direct > -> $field:ident : $ty:ty;
246        $($rest:tt)*
247    ) => {
248        $(#[$meta])*
249        pub fn $method(&mut self, $field: $ty) {
250            self.$field = $field;
251        }
252        $crate::mut_setters!($($rest)*);
253    };
254
255    // plain + rename (default = Some)
256    (
257        $(#[$meta:meta])*
258        $method:ident -> $field:ident : $ty:ty;
259        $($rest:tt)*
260    ) => {
261        $(#[$meta])*
262        pub fn $method(&mut self, $field: $ty) {
263            self.$field = Some($field);
264        }
265        $crate::mut_setters!($($rest)*);
266    };
267
268    // plain + <direct> + no rename
269    (
270        $(#[$meta:meta])*
271        $name:ident < direct > : $ty:ty;
272        $($rest:tt)*
273    ) => {
274        $(#[$meta])*
275        pub fn $name(&mut self, $name: $ty) {
276            self.$name = $name;
277        }
278        $crate::mut_setters!($($rest)*);
279    };
280
281    // plain + no rename (default = Some)
282    (
283        $(#[$meta:meta])*
284        $name:ident : $ty:ty;
285        $($rest:tt)*
286    ) => {
287        $(#[$meta])*
288        pub fn $name(&mut self, $name: $ty) {
289            self.$name = Some($name);
290        }
291        $crate::mut_setters!($($rest)*);
292    };
293
294    // Base case
295    () => {};
296}
297
298/// Generates reference getter methods in batch.
299///
300/// Each entry produces a `pub fn name(&self) -> Option<&T>` method
301/// that returns `self.field.as_ref()`.
302///
303/// # Syntax
304///
305/// ```ignore
306/// ref_getters! {
307///     /// doc comment
308///     name: Type;              // pub fn name(&self) -> Option<&Type> { self.name.as_ref() }
309///     method -> field: Type;   // pub fn method(&self) -> Option<&Type> { self.field.as_ref() }
310/// }
311/// ```
312#[macro_export]
313macro_rules! ref_getters {
314    // With rename
315    (
316        $(#[$meta:meta])*
317        $method:ident -> $field:ident : $ty:ty;
318        $($rest:tt)*
319    ) => {
320        $(#[$meta])*
321        pub fn $method(&self) -> Option<&$ty> {
322            self.$field.as_ref()
323        }
324        $crate::ref_getters!($($rest)*);
325    };
326
327    // Without rename
328    (
329        $(#[$meta:meta])*
330        $name:ident : $ty:ty;
331        $($rest:tt)*
332    ) => {
333        $(#[$meta])*
334        pub fn $name(&self) -> Option<&$ty> {
335            self.$name.as_ref()
336        }
337        $crate::ref_getters!($($rest)*);
338    };
339
340    // Base case
341    () => {};
342}