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 | #[doc (hidden)] // forced to be visible in intended location |
66 | macro_rules! seq { |
67 | ($name: ident { $($fields: tt)* }) => { |
68 | $crate::combinator::trace(stringify!($name), move |input: &mut _| { |
69 | use $crate::Parser; |
70 | $crate::seq_parse_struct_fields!(input; $($fields)*); |
71 | #[allow(clippy::redundant_field_names)] |
72 | Ok($crate::seq_init_struct_fields!( ($($fields)*); $name;)) |
73 | }) |
74 | }; |
75 | ($name: ident ( $($elements: tt)* )) => { |
76 | $crate::combinator::trace(stringify!($name), move |input: &mut _| { |
77 | use $crate::Parser; |
78 | $crate::seq_parse_tuple_fields!( ($($elements)*) ; ).map(|t| { |
79 | $crate::seq_init_tuple_fields!( |
80 | ($($elements)*); |
81 | (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); |
82 | $name; |
83 | ) |
84 | }).parse_next(input) |
85 | }) |
86 | }; |
87 | (( $($elements: tt)* )) => { |
88 | $crate::combinator::trace("tuple" , move |input: &mut _| { |
89 | use $crate::Parser; |
90 | $crate::seq_parse_tuple_fields!( ($($elements)*) ; ).map(|t| { |
91 | $crate::seq_init_tuple_fields!( |
92 | ($($elements)*); |
93 | (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); |
94 | ; |
95 | ) |
96 | }).parse_next(input) |
97 | }) |
98 | }; |
99 | ($($elements: tt)*) => { |
100 | $crate::seq!(($($elements)*)) |
101 | }; |
102 | } |
103 | |
104 | #[macro_export ] |
105 | #[doc (hidden)] |
106 | macro_rules! seq_parse_struct_fields { |
107 | ( |
108 | $input: ident; |
109 | _ : $head_parser: expr, $($fields: tt)* |
110 | ) => { |
111 | let _ = $head_parser.parse_next($input)?; |
112 | $crate::seq_parse_struct_fields!($input; $($fields)*) |
113 | }; |
114 | ( |
115 | $input: ident; |
116 | _ : $head_parser: expr |
117 | ) => { |
118 | let _ = $head_parser.parse_next($input)?; |
119 | }; |
120 | ( |
121 | $input: ident; |
122 | $head_field: ident : $head_parser: expr, $($fields: tt)* |
123 | ) => { |
124 | let $head_field = $head_parser.parse_next($input)?; |
125 | $crate::seq_parse_struct_fields!($input; $($fields)*) |
126 | }; |
127 | ( |
128 | $input: ident; |
129 | $head_field: ident : $head_parser: expr |
130 | ) => { |
131 | let $head_field = $head_parser.parse_next($input)?; |
132 | }; |
133 | ( |
134 | $input: expr; |
135 | .. $update: expr |
136 | ) => {}; |
137 | ( |
138 | $input: expr; |
139 | $(,)? |
140 | ) => {}; |
141 | } |
142 | |
143 | #[macro_export ] |
144 | #[doc (hidden)] |
145 | macro_rules! seq_parse_tuple_fields { |
146 | ( |
147 | (_ : $head_parser: expr, $($fields: tt)* ); |
148 | $($sequenced: tt)* |
149 | ) => { |
150 | $crate::seq_parse_tuple_fields!( ( $($fields)* ) ; $($sequenced)* $head_parser.void(), ) |
151 | }; |
152 | ( |
153 | (_ : $head_parser: expr); |
154 | $($sequenced: tt)* |
155 | ) => { |
156 | $crate::seq_parse_tuple_fields!((); $($sequenced)* $head_parser.void(), ) |
157 | }; |
158 | ( |
159 | ($head_parser: expr, $($fields: tt)*); |
160 | $($sequenced: tt)* |
161 | ) => { |
162 | $crate::seq_parse_tuple_fields!( ( $($fields)* ) ; $($sequenced)* $head_parser, ) |
163 | }; |
164 | ( |
165 | ($head_parser: expr); |
166 | $($sequenced: tt)* |
167 | )=> { |
168 | $crate::seq_parse_tuple_fields!((); $($sequenced)* $head_parser, ) |
169 | }; |
170 | ( |
171 | (); |
172 | $($sequenced: tt)* |
173 | ) => { |
174 | ($($sequenced)*) |
175 | }; |
176 | } |
177 | |
178 | #[macro_export ] |
179 | #[doc (hidden)] |
180 | macro_rules! seq_init_struct_fields { |
181 | ( |
182 | (_ : $head_parser: expr, $($fields: tt)*); |
183 | $name: ident; |
184 | $($inits: tt)* |
185 | ) => { |
186 | $crate::seq_init_struct_fields!( ( $($fields)* ) ; $name ; $($inits)* ) |
187 | }; |
188 | ( |
189 | (_ : $head_parser: expr); |
190 | $name: ident; |
191 | $($inits: tt)* |
192 | ) => { |
193 | $crate::seq_init_struct_fields!( (); $name ; $($inits)* ) |
194 | }; |
195 | ( |
196 | ($head_field: ident : $head_parser: expr, $($fields: tt)*); |
197 | $name: ident; |
198 | $($inits: tt)* |
199 | ) => |
200 | { |
201 | $crate::seq_init_struct_fields!( ( $($fields)* ) ; $name ; $($inits)* $head_field: $head_field, ) |
202 | }; |
203 | ( |
204 | ($head_field: ident : $head_parser: expr); |
205 | $name: ident; |
206 | $($inits: tt)* |
207 | ) => { |
208 | $crate::seq_init_struct_fields!( (); $name ; $($inits)* $head_field: $head_field,) |
209 | }; |
210 | ( |
211 | (.. $update: expr); |
212 | $name: ident; |
213 | $($inits: tt)* |
214 | ) => { |
215 | $name { $($inits)* ..$update } |
216 | }; |
217 | ( |
218 | ($(,)?); |
219 | $name: ident; |
220 | $($inits: tt)* |
221 | ) => { |
222 | $name { $($inits)* } |
223 | }; |
224 | } |
225 | |
226 | #[macro_export ] |
227 | #[doc (hidden)] |
228 | macro_rules! seq_init_tuple_fields { |
229 | ( |
230 | (_ : $head_parser: expr, $($fields: tt)*); |
231 | ($head_arg: expr, $($args: expr),*); |
232 | $($name: ident)?; |
233 | $($inits: tt)* |
234 | ) => { |
235 | $crate::seq_init_tuple_fields!( ( $($fields)* ); ( $($args),* ) ; $($name)? ; $($inits)* ) |
236 | }; |
237 | ( |
238 | (_ : $head_parser: expr); |
239 | ($head_arg: expr, $($args: expr),*); |
240 | $($name: ident)?; |
241 | $($inits: tt)* |
242 | ) => { |
243 | $crate::seq_init_tuple_fields!((); ( $($args),* ); $($name)? ; $($inits)*) |
244 | }; |
245 | ( |
246 | ($head_parser: expr, $($fields: tt)*); |
247 | ($head_arg: expr, $($args: expr),*); |
248 | $($name: ident)?; |
249 | $($inits: tt)* |
250 | ) => { |
251 | $crate::seq_init_tuple_fields!( ( $($fields)* ) ; ( $($args),* ) ; $($name)? ; $($inits)* $head_arg, ) |
252 | }; |
253 | ( |
254 | ($head_parser: expr); |
255 | ($head_arg: expr, $($args: expr),*); |
256 | $($name: ident)?; |
257 | $($inits: tt)* |
258 | ) => { |
259 | $crate::seq_init_tuple_fields!((); ( $($args),* ); $($name)? ; $($inits)* $head_arg) |
260 | }; |
261 | ( |
262 | (); |
263 | ($($args: expr),*); |
264 | $($name: ident)?; |
265 | $($inits: expr),* $(,)? |
266 | ) => { |
267 | $($name)?( $($inits,)* ) |
268 | }; |
269 | } |
270 | |