1 use proc_macro2::Span; 2 use syn::{ 3 parse::{discouraged::Speculative, Parse, ParseStream, Result}, 4 Attribute, Error, ItemFn, ItemImpl, ItemStatic, ItemTrait, 5 }; 6 7 pub enum Item { 8 Trait(ItemTrait), 9 Impl(ItemImpl), 10 Fn(ItemFn), 11 Static(ItemStatic), 12 } 13 14 macro_rules! fork { 15 ($fork:ident = $input:ident) => {{ 16 $fork = $input.fork(); 17 &$fork 18 }}; 19 } 20 21 impl Parse for Item { parse(input: ParseStream) -> Result<Self>22 fn parse(input: ParseStream) -> Result<Self> { 23 let attrs = input.call(Attribute::parse_outer)?; 24 let mut fork; 25 let item = if let Ok(mut item) = fork!(fork = input).parse::<ItemImpl>() { 26 item.attrs = attrs; 27 Item::Impl(item) 28 } else if let Ok(mut item) = fork!(fork = input).parse::<ItemTrait>() { 29 item.attrs = attrs; 30 Item::Trait(item) 31 } else if let Ok(mut item) = fork!(fork = input).parse::<ItemFn>() { 32 item.attrs = attrs; 33 Item::Fn(item) 34 } else if let Ok(mut item) = fork!(fork = input).parse::<ItemStatic>() { 35 item.attrs = attrs; 36 Item::Static(item) 37 } else { 38 return Err(Error::new(Span::call_site(), "expected impl, trait or fn")); 39 }; 40 input.advance_to(&fork); 41 Ok(item) 42 } 43 } 44