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")]
65macro_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)]
105macro_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)]
144macro_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)]
179macro_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)]
227macro_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