1 | /// Initialize a struct or tuple out of a sequences of parsers |
2 | /// |
3 | /// Unlike normal struct initialization syntax: |
4 | /// - `_` fields can exist to run a parser but ignore the result |
5 | /// - Parse results for a field can later be referenced using the field name |
6 | /// |
7 | /// Unlike normal tuple initialization syntax: |
8 | /// - Struct-style initialization (`{ 0: _, 1: _}`) is not supported |
9 | /// - `_: <parser>` fields can exist to run a parser but ignore the result |
10 | /// |
11 | ///# Example |
12 | /// |
13 | /// ``` |
14 | /// # use winnow::prelude::*; |
15 | /// # use winnow::ascii::{alphanumeric1, dec_uint, space0}; |
16 | /// # use winnow::combinator::delimited; |
17 | /// # use winnow::combinator::empty; |
18 | /// # use winnow::error::ContextError; |
19 | /// # use winnow::error::ErrMode; |
20 | /// use winnow::combinator::seq; |
21 | /// |
22 | /// #[derive(Default, Debug, PartialEq)] |
23 | /// struct Field { |
24 | /// namespace: u32, |
25 | /// name: Vec<u8>, |
26 | /// value: Vec<u8>, |
27 | /// point: (u32, u32), |
28 | /// metadata: Vec<u8>, |
29 | /// } |
30 | /// |
31 | /// // Parse into structs / tuple-structs |
32 | /// fn field(input: &mut &[u8]) -> ModalResult<Field> { |
33 | /// seq!{Field { |
34 | /// namespace: empty.value(5), |
35 | /// name: alphanumeric1.map(|s: &[u8]| s.to_owned()), |
36 | /// // `_` fields are ignored when building the struct |
37 | /// _: (space0, b':' , space0), |
38 | /// value: alphanumeric1.map(|s: &[u8]| s.to_owned()), |
39 | /// _: (space0, b':' , space0), |
40 | /// point: point, |
41 | /// // default initialization also works |
42 | /// ..Default::default() |
43 | /// }}.parse_next(input) |
44 | /// } |
45 | /// |
46 | /// // Or parse into tuples |
47 | /// fn point(input: &mut &[u8]) -> ModalResult<(u32, u32)> { |
48 | /// let mut num = dec_uint::<_, u32, ErrMode<ContextError>>; |
49 | /// seq!(num, _: (space0, b',' , space0), num).parse_next(input) |
50 | /// } |
51 | /// |
52 | /// assert_eq!( |
53 | /// field.parse_peek(&b"test: data: 123 , 4" [..]), |
54 | /// Ok(( |
55 | /// &b"" [..], |
56 | /// Field { |
57 | /// namespace: 5, |
58 | /// name: b"test" [..].to_owned(), |
59 | /// value: b"data" [..].to_owned(), |
60 | /// point: (123, 4), |
61 | /// metadata: Default::default(), |
62 | /// }, |
63 | /// )), |
64 | /// ); |
65 | /// ``` |
66 | #[macro_export ] |
67 | #[doc (alias = "tuple" )] |
68 | #[doc (alias = "preceded" )] |
69 | #[doc (alias = "terminated" )] |
70 | #[doc (alias = "delimited" )] |
71 | #[doc (alias = "pair" )] |
72 | #[doc (alias = "separated_pair" )] |
73 | #[doc (alias = "struct_parser" )] |
74 | #[doc (hidden)] // forced to be visible in intended location |
75 | macro_rules! seq { |
76 | ($($name: ident)::* { $($fields: tt)* }) => { |
77 | $crate::combinator::trace(stringify!($($name)::*), move |input: &mut _| { |
78 | $crate::seq_parse_struct_fields!( |
79 | ( $($fields)* ); |
80 | ( _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20 ); |
81 | input ; |
82 | ); |
83 | Ok($crate::seq_init_struct_fields!( |
84 | ( $($fields)* ); |
85 | $($name)::* ; |
86 | )) |
87 | }) |
88 | }; |
89 | ($($name: ident)::* ( $($fields: tt)* )) => { |
90 | $crate::combinator::trace(stringify!($($name)::*), move |input: &mut _| { |
91 | $crate::seq_parse_tuple_fields!( |
92 | ( $($fields)* ); |
93 | ( _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20 ); |
94 | input; |
95 | ); |
96 | Ok($crate::seq_init_tuple_fields!( |
97 | ( $($fields)* ); |
98 | ( _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20 ); |
99 | $($name)::*; |
100 | )) |
101 | }) |
102 | }; |
103 | (( $($fields: tt)* )) => { |
104 | $crate::combinator::trace("tuple" , move |input: &mut _| { |
105 | $crate::seq_parse_tuple_fields!( |
106 | ( $($fields)* ); |
107 | ( _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20 ); |
108 | input; |
109 | ); |
110 | Ok($crate::seq_init_tuple_fields!( |
111 | ( $($fields)* ); |
112 | ( _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20 ); |
113 | ; |
114 | )) |
115 | }) |
116 | }; |
117 | ($($fields: tt)*) => { |
118 | $crate::seq!(( |
119 | $($fields)* |
120 | )) |
121 | }; |
122 | } |
123 | |
124 | #[macro_export ] |
125 | #[doc (hidden)] |
126 | macro_rules! seq_parse_struct_fields { |
127 | ( |
128 | ( _ : $head_parser: expr, $($fields: tt)* ); |
129 | ( $unnamed1: ident, $($unnamed: ident),* ); |
130 | $input: ident ; |
131 | ) => { |
132 | let $unnamed1 = $crate::Parser::parse_next(&mut $head_parser, $input)?; |
133 | $crate::seq_parse_struct_fields!( |
134 | ( $($fields)* ); |
135 | ( $($unnamed),* ); |
136 | $input ; |
137 | ) |
138 | }; |
139 | ( |
140 | ( _ : $head_parser: expr ); |
141 | ( $unnamed1: ident, $($unnamed: ident),* ); |
142 | $input: ident ; |
143 | ) => { |
144 | let $unnamed1 = $crate::Parser::parse_next(&mut $head_parser, $input)?; |
145 | }; |
146 | ( |
147 | ( $head_field: ident : $head_parser: expr, $($fields: tt)* ); |
148 | ( $unnamed1: ident, $($unnamed: ident),* ); |
149 | $input: ident ; |
150 | ) => { |
151 | let $head_field = $crate::Parser::parse_next(&mut $head_parser, $input)?; |
152 | $crate::seq_parse_struct_fields!( |
153 | ( $($fields)* ); |
154 | ( $($unnamed),* ); |
155 | $input ; |
156 | ) |
157 | }; |
158 | ( |
159 | ( $head_field: ident : $head_parser: expr ); |
160 | ( $unnamed1: ident, $($unnamed: ident),* ); |
161 | $input: ident ; |
162 | ) => { |
163 | let $head_field = $crate::Parser::parse_next(&mut $head_parser, $input)?; |
164 | }; |
165 | ( |
166 | ( .. $update: expr ); |
167 | ( $($unnamed: ident),* ); |
168 | $input: expr ; |
169 | ) => {}; |
170 | ( |
171 | ( $(,)? ); |
172 | ( $($unnamed: ident),* ); |
173 | $input: expr ; |
174 | ) => {}; |
175 | } |
176 | |
177 | #[macro_export ] |
178 | #[doc (hidden)] |
179 | macro_rules! seq_parse_tuple_fields { |
180 | ( |
181 | ( $(_ :)? $head_parser: expr, $($fields: tt)* ); |
182 | ( $unnamed1: ident, $($unnamed: ident),* ); |
183 | $input: ident; |
184 | ) => { |
185 | let $unnamed1 = $crate::Parser::parse_next(&mut $head_parser, $input)?; |
186 | $crate::seq_parse_tuple_fields!( |
187 | ( $($fields)* ); |
188 | ( $($unnamed),* ); |
189 | $input ; |
190 | ) |
191 | }; |
192 | ( |
193 | ( $(_ :)? $head_parser: expr ); |
194 | ( $unnamed1: ident, $($unnamed: ident),* ); |
195 | $input: ident; |
196 | ) => { |
197 | let $unnamed1 = $crate::Parser::parse_next(&mut $head_parser, $input)?; |
198 | }; |
199 | ( |
200 | ( $(,)? ); |
201 | ( $($unnamed: ident),* ); |
202 | $input: expr; |
203 | ) => {}; |
204 | } |
205 | |
206 | #[macro_export ] |
207 | #[doc (hidden)] |
208 | macro_rules! seq_init_struct_fields { |
209 | ( |
210 | ( _ : $head_parser: expr, $($fields: tt)* ); |
211 | $($name: ident)::* ; |
212 | $($inits: tt)* |
213 | ) => { |
214 | $crate::seq_init_struct_fields!( |
215 | ( $($fields)* ); |
216 | $($name)::* ; |
217 | $($inits)* |
218 | ) |
219 | }; |
220 | ( |
221 | ( _ : $head_parser: expr ); |
222 | $($name: ident)::* ; |
223 | $($inits: tt)* |
224 | ) => { |
225 | $crate::seq_init_struct_fields!( |
226 | (); |
227 | $($name)::* ; |
228 | $($inits)* |
229 | ) |
230 | }; |
231 | ( |
232 | ( $head_field: ident : $head_parser: expr, $($fields: tt)* ); |
233 | $($name: ident)::* ; |
234 | $($inits: tt)* |
235 | ) => |
236 | { |
237 | $crate::seq_init_struct_fields!( |
238 | ( $($fields)* ); |
239 | $($name)::* ; |
240 | $($inits)* $head_field, |
241 | ) |
242 | }; |
243 | ( |
244 | ( $head_field: ident : $head_parser: expr ); |
245 | $($name: ident)::* ; |
246 | $($inits: tt)* |
247 | ) => { |
248 | $crate::seq_init_struct_fields!( |
249 | (); |
250 | $($name)::* ; |
251 | $($inits)* $head_field, |
252 | ) |
253 | }; |
254 | ( |
255 | ( .. $update: expr ); |
256 | $($name: ident)::* ; |
257 | $($inits: tt)* |
258 | ) => { |
259 | $($name)::* { $($inits)* ..$update } |
260 | }; |
261 | ( |
262 | ( $(,)? ); |
263 | $($name: ident)::* ; |
264 | $($inits: tt)* |
265 | ) => { |
266 | $($name)::* { $($inits)* } |
267 | }; |
268 | } |
269 | |
270 | #[macro_export ] |
271 | #[doc (hidden)] |
272 | macro_rules! seq_init_tuple_fields { |
273 | ( |
274 | ( _ : $head_parser: expr, $($fields: tt)* ); |
275 | ( $unnamed1: ident, $($unnamed: ident),* ); |
276 | $($name: ident)::*; |
277 | $($inits: tt)* |
278 | ) => { |
279 | $crate::seq_init_tuple_fields!( |
280 | ( $($fields)* ); |
281 | ( $($unnamed),* ); |
282 | $($name)::* ; |
283 | $($inits)* |
284 | ) |
285 | }; |
286 | ( |
287 | ( _ : $head_parser: expr ); |
288 | ( $unnamed1: ident, $($unnamed: ident),* ); |
289 | $($name: ident)::*; |
290 | $($inits: tt)* |
291 | ) => { |
292 | $crate::seq_init_tuple_fields!( |
293 | (); |
294 | ( $($unnamed),* ); |
295 | $($name)::* ; |
296 | $($inits)* |
297 | ) |
298 | }; |
299 | ( |
300 | ( $head_parser: expr, $($fields: tt)* ); |
301 | ( $unnamed1: ident, $($unnamed: ident),* ); |
302 | $($name: ident)::*; |
303 | $($inits: tt)* |
304 | ) => |
305 | { |
306 | $crate::seq_init_tuple_fields!( |
307 | ( $($fields)* ); |
308 | ( $($unnamed),* ); |
309 | $($name)::* ; |
310 | $($inits)* $unnamed1, |
311 | ) |
312 | }; |
313 | ( |
314 | ( $head_parser: expr ); |
315 | ( $unnamed1: ident, $($unnamed: ident),* ); |
316 | $($name: ident)::*; |
317 | $($inits: tt)* |
318 | ) => { |
319 | $crate::seq_init_tuple_fields!( |
320 | (); |
321 | ( $($unnamed),* ); |
322 | $($name)::* ; |
323 | $($inits)* $unnamed1, |
324 | ) |
325 | }; |
326 | ( |
327 | ( $(,)? ); |
328 | ( $unnamed1: ident, $($unnamed: ident),* ); |
329 | $($name: ident)::*; |
330 | $($inits: tt)* |
331 | ) => { |
332 | $($name)::* ( $($inits)* ) |
333 | }; |
334 | } |
335 | |