    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34

    use proc_macro2::Span;
    use syn::parse::{Error, Parse, ParseStream, Result};
    use syn::{Attribute, ItemImpl, ItemTrait, Token};

    pub enum Item {
        Trait(ItemTrait),
        Impl(ItemImpl),
    }

    impl Parse for Item {
        fn parse(input: ParseStream) -> Result<Self> {
            let attrs = input.call(Attribute::parse_outer)?;
            let mut lookahead = input.lookahead1();
            if lookahead.peek(Token![unsafe]) {
                let ahead = input.fork();
                ahead.parse::<Token![unsafe]>()?;
                lookahead = ahead.lookahead1();
            }
            if lookahead.peek(Token![pub]) || lookahead.peek(Token![trait]) {
                let mut item: ItemTrait = input.parse()?;
                item.attrs = attrs;
                Ok(Item::Trait(item))
            } else if lookahead.peek(Token![impl]) {
                let mut item: ItemImpl = input.parse()?;
                if item.trait_.is_none() {
                    return Err(Error::new(Span::call_site(), "expected a trait impl"));
                }
                item.attrs = attrs;
                Ok(Item::Impl(item))
            } else {
                Err(lookahead.error())
            }
        }
    }