1use proc_macro2::Span;
2use syn::{
3 parse::{discouraged::Speculative, Parse, ParseStream, Result},
4 Attribute, Error, ItemFn, ItemImpl, ItemStatic, ItemTrait,
5};
6
7pub enum Item {
8 Trait(ItemTrait),
9 Impl(ItemImpl),
10 Fn(ItemFn),
11 Static(ItemStatic),
12}
13
14macro_rules! fork {
15 ($fork:ident = $input:ident) => {{
16 $fork = $input.fork();
17 &$fork
18 }};
19}
20
21impl Parse for Item {
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}