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