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