use proc_macro2::Span; use syn::{ parse::{discouraged::Speculative, Parse, ParseStream, Result}, Attribute, Error, ItemFn, ItemImpl, ItemStatic, ItemTrait, }; pub enum Item { Trait(ItemTrait), Impl(ItemImpl), Fn(ItemFn), Static(ItemStatic), } macro_rules! fork { ($fork:ident = $input:ident) => {{ $fork = $input.fork(); &$fork }}; } impl Parse for Item { fn parse(input: ParseStream) -> Result { let attrs = input.call(Attribute::parse_outer)?; let mut fork; let item = if let Ok(mut item) = fork!(fork = input).parse::() { item.attrs = attrs; Item::Impl(item) } else if let Ok(mut item) = fork!(fork = input).parse::() { item.attrs = attrs; Item::Trait(item) } else if let Ok(mut item) = fork!(fork = input).parse::() { item.attrs = attrs; Item::Fn(item) } else if let Ok(mut item) = fork!(fork = input).parse::() { item.attrs = attrs; Item::Static(item) } else { return Err(Error::new(Span::call_site(), "expected impl, trait or fn")); }; input.advance_to(&fork); Ok(item) } }