Parse any pattern at any level - the heart of the macro's flexibility. This handles all pattern types in a specific order to avoid ambiguity. The order matters because some patterns share prefixes.
(input: ParseStream)
| 240 | /// This handles all pattern types in a specific order to avoid ambiguity. |
| 241 | /// The order matters because some patterns share prefixes. |
| 242 | fn parse(input: ParseStream) -> syn::Result<Self> { |
| 243 | // Closure pattern: |x| expr or move |x| expr for custom validation (escape hatch) |
| 244 | // Examples: `|x| x > 5`, `move |x| complex_logic(x)`, `|x| { x.len() > 0 }` |
| 245 | if input.peek(Token![|]) || (input.peek(Token![move]) && input.peek2(Token![|])) { |
| 246 | return Ok(Pattern::Closure(input.parse()?)); |
| 247 | } |
| 248 | |
| 249 | // Wildcard pattern: _ for ignoring a value while asserting it exists |
| 250 | // Example: `Some(_)`, `field: _`, `[1, _, 3]` |
| 251 | // Special case: `_ { ... }` for wildcard struct patterns |
| 252 | if input.peek(Token![_]) { |
| 253 | // Check if this is a wildcard struct pattern: `_ { ... }` |
| 254 | if input.peek2(syn::token::Brace) { |
| 255 | return Ok(Pattern::Struct(input.parse()?)); |
| 256 | } else { |
| 257 | // Regular wildcard pattern |
| 258 | return Ok(Pattern::Wildcard(input.parse()?)); |
| 259 | } |
| 260 | } |
| 261 | |
| 262 | // Try to parse as a comparison pattern (<, <=, >, >=, ==, !=) |
| 263 | if input.peek(Token![<]) || input.peek(Token![>]) || input.peek(Token![!]) { |
| 264 | // These always start comparisons, safe to parse directly |
| 265 | return Ok(Pattern::Comparison(input.parse()?)); |
| 266 | } |
| 267 | |
| 268 | // `=` could start `==` (equality) or `=~` (regex pattern) |
| 269 | if input.peek(Token![=]) { |
| 270 | if input.peek2(Token![=]) { |
| 271 | // This is `==` - explicit equality comparison |
| 272 | return Ok(Pattern::Comparison(input.parse()?)); |
| 273 | } |
| 274 | |
| 275 | #[cfg(feature = "regex")] |
| 276 | if input.peek2(Token![~]) { |
| 277 | // This is `=~` - regex/like pattern |
| 278 | let pattern: PatternLike = input.parse()?; |
| 279 | return Ok(pattern.into_pattern()); |
| 280 | } |
| 281 | |
| 282 | return Err(input.error("expected `==` or `=~` pattern")); |
| 283 | } |
| 284 | |
| 285 | // Set pattern for unordered collection matching |
| 286 | // Example: `#(1, 2, 3)` or `#(> 0, < 10, ..)` |
| 287 | if input.peek(Token![#]) && input.peek2(syn::token::Paren) { |
| 288 | return Ok(Pattern::Set(input.parse()?)); |
| 289 | } |
| 290 | |
| 291 | // Map patterns for map-like structures using duck typing |
| 292 | // Example: `#{ "key": "value" }` or `#{ "key": > 5, .. }` |
| 293 | if input.peek(Token![#]) && input.peek2(syn::token::Brace) { |
| 294 | return Ok(Pattern::Map(input.parse()?)); |
| 295 | } |
| 296 | |
| 297 | // Slice patterns for Vec/array matching |
| 298 | // Example: `[1, 2, 3]` or `[> 0, < 10, == 5]` |
| 299 | if input.peek(syn::token::Bracket) { |
nothing calls this directly
no test coverage detected