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
66macro_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)]
106macro_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)]
145macro_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)]
180macro_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)]
228macro_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