1 /// Initialize a struct or tuple out of a sequences of parsers
2 ///
3 ///# Example
4 ///
5 /// ```
6 /// # use winnow::prelude::*;
7 /// # use winnow::ascii::{alphanumeric1, dec_uint, space0};
8 /// # use winnow::combinator::delimited;
9 /// # use winnow::combinator::empty;
10 /// # use winnow::error::ContextError;
11 /// use winnow::combinator::seq;
12 ///
13 /// #[derive(Default, Debug, PartialEq)]
14 /// struct Field {
15 ///     namespace: u32,
16 ///     name: Vec<u8>,
17 ///     value: Vec<u8>,
18 ///     point: (u32, u32),
19 ///     metadata: Vec<u8>,
20 /// }
21 ///
22 /// // Parse into structs / tuple-structs
23 /// fn field(input: &mut &[u8]) -> PResult<Field> {
24 ///     seq!{Field {
25 ///         namespace: empty.value(5),
26 ///         name: alphanumeric1.map(|s: &[u8]| s.to_owned()),
27 ///         // `_` fields are ignored when building the struct
28 ///         _: (space0, b':', space0),
29 ///         value: alphanumeric1.map(|s: &[u8]| s.to_owned()),
30 ///         _: (space0, b':', space0),
31 ///         point: point,
32 ///         // default initialization also works
33 ///         ..Default::default()
34 ///     }}.parse_next(input)
35 /// }
36 ///
37 /// // Or parse into tuples
38 /// fn point(input: &mut &[u8]) -> PResult<(u32, u32)> {
39 ///     let num = dec_uint::<_, u32, ContextError>;
40 ///     seq!(num, _: (space0, b',', space0), num).parse_next(input)
41 /// }
42 ///
43 /// assert_eq!(
44 ///     field.parse_peek(&b"test: data: 123 , 4"[..]),
45 ///     Ok((
46 ///         &b""[..],
47 ///         Field {
48 ///             namespace: 5,
49 ///             name: b"test"[..].to_owned(),
50 ///             value: b"data"[..].to_owned(),
51 ///             point: (123, 4),
52 ///             metadata: Default::default(),
53 ///         },
54 ///     )),
55 /// );
56 /// ```
57 #[macro_export]
58 #[doc(alias = "tuple")]
59 #[doc(alias = "preceded")]
60 #[doc(alias = "terminated")]
61 #[doc(alias = "delimited")]
62 #[doc(alias = "pair")]
63 #[doc(alias = "separated_pair")]
64 #[doc(alias = "struct_parser")]
65 macro_rules! seq {
66     ($name: ident { $($fields: tt)* }) => {
67         $crate::combinator::trace(stringify!($name), move |input: &mut _| {
68             use $crate::Parser;
69             $crate::seq_parse_struct_fields!(input; $($fields)*);
70             #[allow(clippy::redundant_field_names)]
71             Ok($crate::seq_init_struct_fields!( ($($fields)*); $name;))
72         })
73     };
74     ($name: ident ( $($elements: tt)* )) => {
75         $crate::combinator::trace(stringify!($name), move |input: &mut _| {
76             use $crate::Parser;
77             $crate::seq_parse_tuple_fields!( ($($elements)*) ; ).map(|t| {
78                 $crate::seq_init_tuple_fields!(
79                     ($($elements)*);
80                     (t.0, t.1, t.2, t.3, t.4, t.5, t.6, t.7, t.8, t.9, t.10, t.11, t.12, t.13, t.14, t.15, t.16, t.17, t.18, t.19, t.20);
81                     $name;
82                 )
83             }).parse_next(input)
84         })
85     };
86     (( $($elements: tt)* )) => {
87         $crate::combinator::trace("tuple", move |input: &mut _| {
88             use $crate::Parser;
89             $crate::seq_parse_tuple_fields!( ($($elements)*) ; ).map(|t| {
90                 $crate::seq_init_tuple_fields!(
91                     ($($elements)*);
92                     (t.0, t.1, t.2, t.3, t.4, t.5, t.6, t.7, t.8, t.9, t.10, t.11, t.12, t.13, t.14, t.15, t.16, t.17, t.18, t.19, t.20);
93                     ;
94                 )
95             }).parse_next(input)
96         })
97     };
98     ($($elements: tt)*) => {
99         $crate::seq!(($($elements)*))
100     };
101 }
102 
103 #[macro_export]
104 #[doc(hidden)]
105 macro_rules! seq_parse_struct_fields {
106     (
107         $input: ident;
108         _ : $head_parser: expr, $($fields: tt)*
109     ) => {
110         let _ = $head_parser.parse_next($input)?;
111         $crate::seq_parse_struct_fields!($input; $($fields)*)
112     };
113     (
114         $input: ident;
115         _ : $head_parser: expr
116     ) => {
117         let _ = $head_parser.parse_next($input)?;
118     };
119     (
120         $input: ident;
121         $head_field: ident : $head_parser: expr, $($fields: tt)*
122     ) => {
123         let $head_field = $head_parser.parse_next($input)?;
124         $crate::seq_parse_struct_fields!($input; $($fields)*)
125     };
126     (
127         $input: ident;
128         $head_field: ident : $head_parser: expr
129     ) => {
130         let $head_field = $head_parser.parse_next($input)?;
131     };
132     (
133         $input: expr;
134         .. $update: expr
135     ) => {};
136     (
137         $input: expr;
138         $(,)?
139     ) => {};
140 }
141 
142 #[macro_export]
143 #[doc(hidden)]
144 macro_rules! seq_parse_tuple_fields {
145     (
146         (_ : $head_parser: expr, $($fields: tt)* );
147         $($sequenced: tt)*
148     ) => {
149         $crate::seq_parse_tuple_fields!( ( $($fields)* ) ; $($sequenced)* $head_parser.void(), )
150     };
151     (
152         (_ : $head_parser: expr);
153         $($sequenced: tt)*
154     ) => {
155         $crate::seq_parse_tuple_fields!((); $($sequenced)* $head_parser.void(), )
156     };
157     (
158         ($head_parser: expr, $($fields: tt)*);
159         $($sequenced: tt)*
160     ) => {
161         $crate::seq_parse_tuple_fields!( ( $($fields)* ) ; $($sequenced)* $head_parser, )
162     };
163     (
164         ($head_parser: expr);
165         $($sequenced: tt)*
166     )=> {
167         $crate::seq_parse_tuple_fields!((); $($sequenced)* $head_parser, )
168     };
169     (
170         ();
171         $($sequenced: tt)*
172     ) => {
173         ($($sequenced)*)
174     };
175 }
176 
177 #[macro_export]
178 #[doc(hidden)]
179 macro_rules! seq_init_struct_fields {
180     (
181         (_ : $head_parser: expr, $($fields: tt)*);
182         $name: ident;
183         $($inits: tt)*
184     ) => {
185         $crate::seq_init_struct_fields!( ( $($fields)* ) ; $name ; $($inits)* )
186     };
187     (
188         (_ : $head_parser: expr);
189         $name: ident;
190         $($inits: tt)*
191     ) => {
192         $crate::seq_init_struct_fields!( (); $name ; $($inits)* )
193     };
194     (
195         ($head_field: ident : $head_parser: expr, $($fields: tt)*);
196         $name: ident;
197         $($inits: tt)*
198     ) =>
199     {
200         $crate::seq_init_struct_fields!( ( $($fields)* ) ; $name ; $($inits)* $head_field: $head_field, )
201     };
202     (
203         ($head_field: ident : $head_parser: expr);
204         $name: ident;
205         $($inits: tt)*
206     ) => {
207         $crate::seq_init_struct_fields!( (); $name ; $($inits)* $head_field: $head_field,)
208     };
209     (
210         (.. $update: expr);
211         $name: ident;
212         $($inits: tt)*
213     ) => {
214         $name { $($inits)* ..$update }
215     };
216     (
217         ($(,)?);
218         $name: ident;
219         $($inits: tt)*
220     ) => {
221         $name { $($inits)* }
222     };
223 }
224 
225 #[macro_export]
226 #[doc(hidden)]
227 macro_rules! seq_init_tuple_fields {
228     (
229         (_ : $head_parser: expr, $($fields: tt)*);
230         ($head_arg: expr, $($args: expr),*);
231         $($name: ident)?;
232         $($inits: tt)*
233     ) => {
234         $crate::seq_init_tuple_fields!( ( $($fields)* ); ( $($args),* ) ; $($name)? ; $($inits)* )
235     };
236     (
237         (_ : $head_parser: expr);
238         ($head_arg: expr, $($args: expr),*);
239         $($name: ident)?;
240         $($inits: tt)*
241     ) => {
242         $crate::seq_init_tuple_fields!((); ( $($args),* ); $($name)? ; $($inits)*)
243     };
244     (
245         ($head_parser: expr, $($fields: tt)*);
246         ($head_arg: expr, $($args: expr),*);
247         $($name: ident)?;
248         $($inits: tt)*
249     ) => {
250         $crate::seq_init_tuple_fields!( ( $($fields)* ) ; ( $($args),* ) ; $($name)? ; $($inits)* $head_arg, )
251     };
252     (
253         ($head_parser: expr);
254         ($head_arg: expr, $($args: expr),*);
255         $($name: ident)?;
256         $($inits: tt)*
257     ) => {
258         $crate::seq_init_tuple_fields!((); ( $($args),* ); $($name)? ; $($inits)* $head_arg)
259     };
260     (
261         ();
262         ($($args: expr),*);
263         $($name: ident)?;
264         $($inits: expr),* $(,)?
265     ) => {
266         $($name)?( $($inits,)* )
267     };
268 }
269