protoschema/macros/
oneofs_macros.rs

1/// Evaluates to a [`Oneof`](crate::oneofs::Oneof) instance.
2///
3/// The first argument is the name of the oneof, followed by a comma, optionally followed by this oneof's options defined as `options = $options` where $options should evaluate to IntoIter<Item = [`ProtoOption`](crate::options::ProtoOption)>, followed by the fields for this oneof, which are defined as a comma separated list of `$number:literal => $field:expr`, with $field evaluating to a [`FieldBuilder`](crate::fields::FieldBuilder) or include($reusable_fields:expr), where $reusable_fields is the expansion of a call to [`reusable_fields`](crate::reusable_fields).
4/// If you want to add the "required" rule to this oneof (meaning at least one of the choices will need to be set to pass validation), you must place the "required" keyword right after the name of the oneof.
5/// # Examples
6/// ```
7/// use protoschema::{oneof, proto_option, string, reusable_fields, uint64};
8///
9/// let my_common_fields = reusable_fields!(
10///   1 => uint64!("id"),
11///   2 => string!("username"),
12///   3 => string!("email")
13/// );
14///
15/// let my_opt = proto_option("my_opt", true);
16/// let my_list_of_options = [ my_opt.clone(), my_opt.clone() ];
17///
18/// let oneof = oneof!(
19///   "my_oneof",
20///   required,
21///   options = [ my_opt ], // Or `options = my_list_of_options.clone()`
22///   // Add a normal field
23///   1 => string!("abc"),
24///   // Include some reusable fields
25///   include(my_common_fields)
26/// );
27/// ```
28#[macro_export]
29macro_rules! oneof {
30  (
31    $name:expr,
32    required,
33    $($tokens:tt)*
34  ) => {
35    $crate::oneof_impl!(
36      @name($name)
37      @options()
38      @included_fields()
39      @fields()
40      @imports()
41      @rest($($tokens)*)
42    )
43    .required()
44    .build()
45  };
46
47  (
48    $name:expr,
49    $($tokens:tt)*
50  ) => {
51    $crate::oneof_impl!(
52      @name($name)
53      @options()
54      @included_fields()
55      @fields()
56      @imports()
57      @rest($($tokens)*)
58    )
59    .build()
60  };
61}
62
63#[doc(hidden)]
64#[macro_export]
65macro_rules! oneof_impl {
66  (
67    @name($name:expr)
68    @options($($options:expr)?)
69    @included_fields($($included_fields:expr,)*)
70    @fields($($fields:tt)*)
71    @imports($($imports:expr)?)
72    @rest($(,)?)
73  ) => {
74    $crate::oneofs::Oneof::builder()
75    .name($name.into())
76    $(.add_options($options))?
77    .fields(
78      {
79        let mut fields = vec! [ $($fields)* ];
80        $(fields.extend($included_fields));*;
81        fields
82      }
83    )
84    $(.add_imports($imports))?
85  };
86
87  (
88    @name($name:expr)
89    @options()
90    @included_fields($($included_fields:tt)*)
91    @fields($($fields:tt)*)
92    @imports($($imports:tt)?)
93    @rest($(,)? options = $options:expr, $($rest:tt)*)
94  ) => {
95    $crate::oneof_impl!(
96      @name($name)
97      @options($options)
98      @included_fields($($included_fields)*)
99      @fields($($fields)*)
100      @imports($($imports)*)
101      @rest($($rest)*)
102    )
103  };
104
105  (
106    @name($name:expr)
107    @options($($options:tt)?)
108    @included_fields($($included_fields:tt)*)
109    @fields($($fields:tt)*)
110    @imports()
111    @rest($(,)? imports = $imports:expr, $($rest:tt)*)
112  ) => {
113    $crate::oneof_impl!(
114      @name($name)
115      @options($($options)?)
116      @included_fields($($included_fields)*)
117      @fields($($fields)*)
118      @imports($imports)
119      @rest($($rest)*)
120    )
121  };
122
123  (
124    @name($name:expr)
125    @options($($options:tt)?)
126    @included_fields($($included_fields:tt)*)
127    @fields($($fields:tt)*)
128    @imports($($imports:tt)?)
129    @rest($(,)? include($new_included_fields:expr) $($rest:tt)*)
130  ) => {
131    $crate::oneof_impl!(
132      @name($name)
133      @options($($options)?)
134      @included_fields($($included_fields)* $new_included_fields.clone(),)
135      @fields($($fields)*)
136      @imports($($imports)*)
137      @rest($($rest)*)
138    )
139  };
140
141  (
142    @name($name:expr)
143    @options($($options:tt)?)
144    @included_fields($($included_fields:tt)*)
145    @fields($($fields:tt)*)
146    @imports($($imports:tt)?)
147    @rest($(,)? $tag:literal => $field:expr, $($rest:tt)*)
148  ) => {
149    $crate::oneof_impl!(
150      @name($name)
151      @options($($options)?)
152      @included_fields($($included_fields)*)
153      @fields($($fields)* ($tag, $field),)
154      @imports($($imports)*)
155      @rest($($rest)*)
156    )
157  };
158
159  (
160    @name($name:expr)
161    @options($($options:tt)?)
162    @included_fields($($included_fields:tt)*)
163    @fields($($fields:tt)*)
164    @imports($($imports:tt)?)
165    @rest($(,)? $tag:literal => $field:expr)
166  ) => {
167    $crate::oneof_impl!(
168      @name($name)
169      @options($($options)?)
170      @included_fields($($included_fields)*)
171      @fields($($fields)* ($tag, $field))
172      @imports($($imports)*)
173      @rest()
174    )
175  };
176}