Skip to main content

zulip_api/
macros.rs

1//! Helper macros.
2
3/// Helper to define field access functions for types.
4///
5/// Helps to cut down boilerplate, especially for types with many fields.
6#[macro_export]
7macro_rules! field_access {
8    // Field access for fields with the same getter and setter type.
9    ($ty:ident {
10        $(
11            $(#[$field_doc:meta])*
12            $field:ident: $field_ty:ty $(,)?
13        )+
14    }) => {
15        ::paste::paste! {
16            impl $ty {
17                $(
18                    #[doc = "Gets the [" $ty "] `" $field "`."]
19                    $(
20                        #[doc = ""]
21                        #[$field_doc]
22                    )*
23                    pub const fn $field(&self) -> $field_ty {
24                        self.$field
25                    }
26
27                    #[doc = "Sets the [" $ty "] `" $field "`."]
28                    $(
29                        #[doc = ""]
30                        #[$field_doc]
31                    )*
32                    pub fn [<set_ $field>](&mut self, val: $field_ty) {
33                        self.$field = val;
34                    }
35
36                    #[doc = "Builder function that sets the [" $ty "] `" $field "`."]
37                    $(
38                        #[doc = ""]
39                        #[$field_doc]
40                    )*
41                    #[allow(clippy::needless_update)]
42                    pub fn [<with_ $field>](self, val: $field_ty) -> Self {
43                        Self {
44                            $field: val,
45                            ..self
46                        }
47                    }
48                )+
49            }
50        }
51    };
52
53    // Field access for fields with different getter and setter types.
54    ($ty:ident {
55        $(
56            $(#[$field_doc:meta])*
57            $field:ident: as_ref { $get_ty:ty, $set_ty:ty } $(,)?
58        )+
59    }) => {
60        ::paste::paste! {
61            impl $ty {
62                $(
63                    #[doc = "Gets the [" $ty "] `" $field "`."]
64                    $(
65                        #[doc = ""]
66                        #[$field_doc]
67                    )*
68                    pub fn $field(&self) -> $get_ty {
69                        &self.$field
70                    }
71
72                    #[doc = "Sets the [" $ty "] `" $field "`."]
73                    $(
74                        #[doc = ""]
75                        #[$field_doc]
76                    )*
77                    pub fn [<set_ $field>](&mut self, val: $set_ty) {
78                        self.$field = val;
79                    }
80
81                    #[doc = "Builder function that sets the [" $ty "] `" $field "`."]
82                    $(
83                        #[doc = ""]
84                        #[$field_doc]
85                    )*
86                    #[allow(clippy::needless_update)]
87                    pub fn [<with_ $field>](self, val: $set_ty) -> Self {
88                        Self {
89                            $field: val,
90                            ..self
91                        }
92                    }
93                )+
94            }
95        }
96    };
97
98    // Field access for fields with `Cow<'_, T>` setter types.
99    ($ty:ident {
100        $(
101            $(#[$field_doc:meta])*
102            $field:ident: cow { $cow_ty:ty } $(,)?
103        )+
104    }) => {
105        ::paste::paste! {
106            impl $ty {
107                $(
108                    #[doc = "Gets the [" $ty "] `" $field "`."]
109                    $(
110                        #[doc = ""]
111                        #[$field_doc]
112                    )*
113                    pub fn $field(&self) -> &$cow_ty {
114                        &self.$field
115                    }
116
117                    #[doc = "Sets the [" $ty "] `" $field "`."]
118                    $(
119                        #[doc = ""]
120                        #[$field_doc]
121                    )*
122                    pub fn [<set_ $field>]<'a, C: Into<std::borrow::Cow<'a, $cow_ty>>>(&mut self, val: C) {
123                        self.$field = C::into(val).into();
124                    }
125
126                    #[doc = "Builder function that sets the [" $ty "] `" $field "`."]
127                    $(
128                        #[doc = ""]
129                        #[$field_doc]
130                    )*
131                    #[allow(clippy::needless_update)]
132                    pub fn [<with_ $field>]<'a, C: Into<std::borrow::Cow<'a, $cow_ty>>>(self, val: C) -> Self {
133                        Self {
134                            $field: C::into(val).into(),
135                            ..self
136                        }
137                    }
138                )+
139            }
140        }
141    };
142
143    // Field access for `Option`-wrapped types.
144    ($ty:ident {
145        $(
146            $(#[$field_doc:meta])*
147            $field:ident: option { $field_ty:ty } $(,)?
148        )+
149    }) => {
150        ::paste::paste! {
151            impl $ty {
152                $(
153                    #[doc = "Gets the [" $ty "] `" $field "`."]
154                    $(
155                        #[doc = ""]
156                        #[$field_doc]
157                    )*
158                    pub const fn $field(&self) -> Option<$field_ty> {
159                        self.$field
160                    }
161
162                    #[doc = "Sets the [" $ty "] `" $field "`."]
163                    $(
164                        #[doc = ""]
165                        #[$field_doc]
166                    )*
167                    pub fn [<set_ $field>](&mut self, val: $field_ty) {
168                        self.$field = Some(val);
169                    }
170
171                    #[doc = "Unsets the [" $ty "] `" $field "`."]
172                    $(
173                        #[doc = ""]
174                        #[$field_doc]
175                    )*
176                    pub fn [<unset_ $field>](&mut self) -> Option<$field_ty> {
177                        self.$field.take()
178                    }
179
180                    #[doc = "Builder function that sets the [" $ty "] `" $field "`."]
181                    $(
182                        #[doc = ""]
183                        #[$field_doc]
184                    )*
185                    #[allow(clippy::needless_update)]
186                    pub fn [<with_ $field>](self, val: $field_ty) -> Self {
187                        Self {
188                            $field: Some(val),
189                            ..self
190                        }
191                    }
192                )+
193            }
194        }
195    };
196
197    // Field access for types that return `Option::as_deref` for the getter.
198    ($ty:ident {
199        $(
200            $(#[$field_doc:meta])*
201            $field:ident: option_deref { $get_ty:ty, $set_ty:ty } $(,)?
202        )+
203    }) => {
204        ::paste::paste! {
205            impl $ty {
206                $(
207                    #[doc = "Gets the [" $ty "] `" $field "`."]
208                    $(
209                        #[doc = ""]
210                        #[$field_doc]
211                    )*
212                    pub fn $field(&self) -> Option<$get_ty> {
213                        self.$field.as_deref()
214                    }
215
216                    #[doc = "Sets the [" $ty "] `" $field "`."]
217                    $(
218                        #[doc = ""]
219                        #[$field_doc]
220                    )*
221                    pub fn [<set_ $field>](&mut self, val: $set_ty) {
222                        self.$field = Some(val);
223                    }
224
225                    #[doc = "Unsets the [" $ty "] `" $field "`."]
226                    $(
227                        #[doc = ""]
228                        #[$field_doc]
229                    )*
230                    pub fn [<unset_ $field>](&mut self) -> Option<$set_ty> {
231                        self.$field.take()
232                    }
233
234                    #[doc = "Builder function that sets the [" $ty "] `" $field "`."]
235                    $(
236                        #[doc = ""]
237                        #[$field_doc]
238                    )*
239                    #[allow(clippy::needless_update)]
240                    pub fn [<with_ $field>](self, val: $set_ty) -> Self {
241                        Self {
242                            $field: Some(val),
243                            ..self
244                        }
245                    }
246                )+
247            }
248        }
249    };
250
251    // Field access for types that return `Option::as_ref` for the getter.
252    ($ty:ident {
253        $(
254            $(#[$field_doc:meta])*
255            $field:ident: option_ref { $get_ty:ty, $set_ty:ty } $(,)?
256        )+
257    }) => {
258        ::paste::paste! {
259            impl $ty {
260                $(
261                    #[doc = "Gets the [" $ty "] `" $field "`."]
262                    $(
263                        #[doc = ""]
264                        #[$field_doc]
265                    )*
266                    pub fn $field(&self) -> Option<$get_ty> {
267                        self.$field.as_ref()
268                    }
269
270                    #[doc = "Sets the [" $ty "] `" $field "`."]
271                    $(
272                        #[doc = ""]
273                        #[$field_doc]
274                    )*
275                    pub fn [<set_ $field>](&mut self, val: $set_ty) {
276                        self.$field = Some(val);
277                    }
278
279                    #[doc = "Unsets the [" $ty "] `" $field "`."]
280                    $(
281                        #[doc = ""]
282                        #[$field_doc]
283                    )*
284                    pub fn [<unset_ $field>](&mut self) -> Option<$set_ty> {
285                        self.$field.take()
286                    }
287
288                    #[doc = "Builder function that sets the [" $ty "] `" $field "`."]
289                    $(
290                        #[doc = ""]
291                        #[$field_doc]
292                    )*
293                    #[allow(clippy::needless_update)]
294                    pub fn [<with_ $field>](self, val: $set_ty) -> Self {
295                        Self {
296                            $field: Some(val),
297                            ..self
298                        }
299                    }
300                )+
301            }
302        }
303    };
304
305    // Field access for types that return `Option::as_ref` for the getter.
306    ($ty:ident {
307        $(
308            $(#[$field_doc:meta])*
309            $field:ident: option_ref { $field_ty:ty } $(,)?
310        )+
311    }) => {
312        ::paste::paste! {
313            impl $ty {
314                $(
315                    #[doc = "Gets the [" $ty "] `" $field "`."]
316                    $(
317                        #[doc = ""]
318                        #[$field_doc]
319                    )*
320                    pub fn $field(&self) -> Option<&$field_ty> {
321                        self.$field.as_ref()
322                    }
323
324                    #[doc = "Sets the [" $ty "] `" $field "`."]
325                    $(
326                        #[doc = ""]
327                        #[$field_doc]
328                    )*
329                    pub fn [<set_ $field>](&mut self, val: $field_ty) {
330                        self.$field = Some(val);
331                    }
332
333                    #[doc = "Unsets the [" $ty "] `" $field "`."]
334                    $(
335                        #[doc = ""]
336                        #[$field_doc]
337                    )*
338                    pub fn [<unset_ $field>](&mut self) -> Option<$field_ty> {
339                        self.$field.take()
340                    }
341
342                    #[doc = "Builder function that sets the [" $ty "] `" $field "`."]
343                    $(
344                        #[doc = ""]
345                        #[$field_doc]
346                    )*
347                    #[allow(clippy::needless_update)]
348                    pub fn [<with_ $field>](self, val: $field_ty) -> Self {
349                        Self {
350                            $field: Some(val),
351                            ..self
352                        }
353                    }
354                )+
355            }
356        }
357    };
358
359    // Field access for types that return `Option<&$cow_ty>` for the getter,
360    // and generic `Cow<'_, $cow_ty>` for the setters.
361    ($ty:ident {
362        $(
363            $(#[$field_doc:meta])*
364            $field:ident: option_cow_ref { $cow_ty:ty } $(,)?
365        )+
366    }) => {
367        ::paste::paste! {
368            impl $ty {
369                $(
370                    #[doc = "Gets the [" $ty "] `" $field "`."]
371                    $(
372                        #[doc = ""]
373                        #[$field_doc]
374                    )*
375                    pub fn $field(&self) -> Option<&$cow_ty> {
376                        self.$field.as_ref()
377                    }
378
379                    #[doc = "Sets the [" $ty "] `" $field "`."]
380                    $(
381                        #[doc = ""]
382                        #[$field_doc]
383                    )*
384                    pub fn [<set_ $field>]<'a, C: Into<std::borrow::Cow<'a, $cow_ty>>>(&mut self, val: C) {
385                        self.$field = Some(C::into(val).into());
386                    }
387
388                    #[doc = "Unsets the [" $ty "] `" $field "`."]
389                    $(
390                        #[doc = ""]
391                        #[$field_doc]
392                    )*
393                    pub fn [<unset_ $field>](&mut self) -> Option<$cow_ty> {
394                        self.$field.take()
395                    }
396
397                    #[doc = "Builder function that sets the [" $ty "] `" $field "`."]
398                    $(
399                        #[doc = ""]
400                        #[$field_doc]
401                    )*
402                    #[allow(clippy::needless_update)]
403                    pub fn [<with_ $field>]<'a, C: Into<std::borrow::Cow<'a, $cow_ty>>>(self, val: C) -> Self {
404                        Self {
405                            $field: Some(C::into(val).into()),
406                            ..self
407                        }
408                    }
409                )+
410            }
411        }
412    };
413
414    // Field access for types that return `Option<&$cow_ty>` for the getter,
415    // and generic `Cow<'_, $cow_ty>` for the setters.
416    ($ty:ident {
417        $(
418            $(#[$field_doc:meta])*
419            $field:ident: option_cow_ref { $cow_ty:ty, $own_ty:ty } $(,)?
420        )+
421    }) => {
422        ::paste::paste! {
423            impl $ty {
424                $(
425                    #[doc = "Gets the [" $ty "] `" $field "`."]
426                    $(
427                        #[doc = ""]
428                        #[$field_doc]
429                    )*
430                    pub fn $field(&self) -> Option<&$cow_ty> {
431                        self.$field.as_ref()
432                    }
433
434                    #[doc = "Sets the [" $ty "] `" $field "`."]
435                    $(
436                        #[doc = ""]
437                        #[$field_doc]
438                    )*
439                    pub fn [<set_ $field>]<'a, C: Into<std::borrow::Cow<'a, $cow_ty>>>(&mut self, val: C) {
440                        self.$field = Some(C::into(val).into());
441                    }
442
443                    #[doc = "Unsets the [" $ty "] `" $field "`."]
444                    $(
445                        #[doc = ""]
446                        #[$field_doc]
447                    )*
448                    pub fn [<unset_ $field>](&mut self) -> Option<$own_ty> {
449                        self.$field.take()
450                    }
451
452                    #[doc = "Builder function that sets the [" $ty "] `" $field "`."]
453                    $(
454                        #[doc = ""]
455                        #[$field_doc]
456                    )*
457                    #[allow(clippy::needless_update)]
458                    pub fn [<with_ $field>]<'a, C: Into<std::borrow::Cow<'a, $cow_ty>>>(self, val: C) -> Self {
459                        Self {
460                            $field: Some(C::into(val).into()),
461                            ..self
462                        }
463                    }
464                )+
465            }
466        }
467    };
468
469    // Field access for types that return `Option<&$cow_ty>` for the getter,
470    // and generic `Cow<'_, $cow_ty>` for the setters.
471    ($ty:ident {
472        $(
473            $(#[$field_doc:meta])*
474            $field:ident: option_cow_deref { $cow_ty:ty, $own_ty:ty } $(,)?
475        )+
476    }) => {
477        ::paste::paste! {
478            impl $ty {
479                $(
480                    #[doc = "Gets the [" $ty "] `" $field "`."]
481                    $(
482                        #[doc = ""]
483                        #[$field_doc]
484                    )*
485                    pub fn $field(&self) -> Option<&$cow_ty> {
486                        self.$field.as_deref()
487                    }
488
489                    #[doc = "Sets the [" $ty "] `" $field "`."]
490                    $(
491                        #[doc = ""]
492                        #[$field_doc]
493                    )*
494                    pub fn [<set_ $field>]<'a, C: Into<std::borrow::Cow<'a, $cow_ty>>>(&mut self, val: C) {
495                        self.$field = Some(C::into(val).into());
496                    }
497
498                    #[doc = "Unsets the [" $ty "] `" $field "`."]
499                    $(
500                        #[doc = ""]
501                        #[$field_doc]
502                    )*
503                    pub fn [<unset_ $field>](&mut self) -> Option<$own_ty> {
504                        self.$field.take()
505                    }
506
507                    #[doc = "Builder function that sets the [" $ty "] `" $field "`."]
508                    $(
509                        #[doc = ""]
510                        #[$field_doc]
511                    )*
512                    #[allow(clippy::needless_update)]
513                    pub fn [<with_ $field>]<'a, C: Into<std::borrow::Cow<'a, $cow_ty>>>(self, val: C) -> Self {
514                        Self {
515                            $field: Some(C::into(val).into()),
516                            ..self
517                        }
518                    }
519                )+
520            }
521        }
522    };
523}
524
525/// Helper macro to implement conversion to/from the [Cow](std::borrow::Cow) type.
526#[macro_export]
527macro_rules! impl_cow {
528    ($ty:ty) => {
529        impl<'c> From<$ty> for std::borrow::Cow<'c, $ty> {
530            fn from(val: $ty) -> Self {
531                Self::Owned(val)
532            }
533        }
534
535        impl<'c> From<&'c $ty> for std::borrow::Cow<'c, $ty> {
536            fn from(val: &'c $ty) -> Self {
537                Self::Borrowed(val)
538            }
539        }
540
541        impl<'c> From<std::borrow::Cow<'c, $ty>> for $ty {
542            fn from(val: std::borrow::Cow<'c, Self>) -> Self {
543                match val {
544                    std::borrow::Cow::Borrowed(v) => v.clone(),
545                    std::borrow::Cow::Owned(v) => v,
546                }
547            }
548        }
549    };
550}
551
552/// Helper macro to implement the [Default](std::default::Default) trait for library types.
553#[macro_export]
554macro_rules! impl_default {
555    ($ty:ty) => {
556        impl Default for $ty {
557            fn default() -> Self {
558                Self::new()
559            }
560        }
561    };
562}
563
564/// Helper macro to implement the [Display](std::fmt::Display) trait for library types.
565#[macro_export]
566macro_rules! impl_display {
567    // Implement the Display trait as a JSON string.
568    ($ty:ty) => {
569        impl std::fmt::Display for $ty {
570            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
571                ::serde_json::to_string(self)
572                    .map_err(|_| std::fmt::Error)
573                    .and_then(|s| write!(f, "{s}"))
574            }
575        }
576    };
577
578    // Implement the Display trait as a plain string.
579    ($ty:ty: str) => {
580        impl std::fmt::Display for $ty {
581            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
582                write!(f, "{}", self.as_str())
583            }
584        }
585    };
586}