133d722a9Sopenharmony_ciuse crate::syntax::cfg::CfgExpr;
233d722a9Sopenharmony_ciuse crate::syntax::namespace::Namespace;
333d722a9Sopenharmony_ciuse quote::quote;
433d722a9Sopenharmony_ciuse syn::parse::{Error, Parse, ParseStream, Result};
533d722a9Sopenharmony_ciuse syn::{
633d722a9Sopenharmony_ci    braced, token, Abi, Attribute, ForeignItem, Ident, Item as RustItem, ItemEnum, ItemImpl,
733d722a9Sopenharmony_ci    ItemStruct, ItemUse, LitStr, Token, Visibility,
833d722a9Sopenharmony_ci};
933d722a9Sopenharmony_ci
1033d722a9Sopenharmony_cipub struct Module {
1133d722a9Sopenharmony_ci    pub cfg: CfgExpr,
1233d722a9Sopenharmony_ci    pub namespace: Namespace,
1333d722a9Sopenharmony_ci    pub attrs: Vec<Attribute>,
1433d722a9Sopenharmony_ci    pub vis: Visibility,
1533d722a9Sopenharmony_ci    pub unsafety: Option<Token![unsafe]>,
1633d722a9Sopenharmony_ci    pub mod_token: Token![mod],
1733d722a9Sopenharmony_ci    pub ident: Ident,
1833d722a9Sopenharmony_ci    pub brace_token: token::Brace,
1933d722a9Sopenharmony_ci    pub content: Vec<Item>,
2033d722a9Sopenharmony_ci}
2133d722a9Sopenharmony_ci
2233d722a9Sopenharmony_cipub enum Item {
2333d722a9Sopenharmony_ci    Struct(ItemStruct),
2433d722a9Sopenharmony_ci    Enum(ItemEnum),
2533d722a9Sopenharmony_ci    ForeignMod(ItemForeignMod),
2633d722a9Sopenharmony_ci    Use(ItemUse),
2733d722a9Sopenharmony_ci    Impl(ItemImpl),
2833d722a9Sopenharmony_ci    Other(RustItem),
2933d722a9Sopenharmony_ci}
3033d722a9Sopenharmony_ci
3133d722a9Sopenharmony_cipub struct ItemForeignMod {
3233d722a9Sopenharmony_ci    pub attrs: Vec<Attribute>,
3333d722a9Sopenharmony_ci    pub unsafety: Option<Token![unsafe]>,
3433d722a9Sopenharmony_ci    pub abi: Abi,
3533d722a9Sopenharmony_ci    pub brace_token: token::Brace,
3633d722a9Sopenharmony_ci    pub items: Vec<ForeignItem>,
3733d722a9Sopenharmony_ci}
3833d722a9Sopenharmony_ci
3933d722a9Sopenharmony_ciimpl Parse for Module {
4033d722a9Sopenharmony_ci    fn parse(input: ParseStream) -> Result<Self> {
4133d722a9Sopenharmony_ci        let cfg = CfgExpr::Unconditional;
4233d722a9Sopenharmony_ci        let namespace = Namespace::ROOT;
4333d722a9Sopenharmony_ci        let mut attrs = input.call(Attribute::parse_outer)?;
4433d722a9Sopenharmony_ci        let vis: Visibility = input.parse()?;
4533d722a9Sopenharmony_ci        let unsafety: Option<Token![unsafe]> = input.parse()?;
4633d722a9Sopenharmony_ci        let mod_token: Token![mod] = input.parse()?;
4733d722a9Sopenharmony_ci        let ident: Ident = input.parse()?;
4833d722a9Sopenharmony_ci
4933d722a9Sopenharmony_ci        let semi: Option<Token![;]> = input.parse()?;
5033d722a9Sopenharmony_ci        if let Some(semi) = semi {
5133d722a9Sopenharmony_ci            let span = quote!(#vis #mod_token #semi);
5233d722a9Sopenharmony_ci            return Err(Error::new_spanned(
5333d722a9Sopenharmony_ci                span,
5433d722a9Sopenharmony_ci                "#[cxx::bridge] module must have inline contents",
5533d722a9Sopenharmony_ci            ));
5633d722a9Sopenharmony_ci        }
5733d722a9Sopenharmony_ci
5833d722a9Sopenharmony_ci        let content;
5933d722a9Sopenharmony_ci        let brace_token = braced!(content in input);
6033d722a9Sopenharmony_ci        attrs.extend(content.call(Attribute::parse_inner)?);
6133d722a9Sopenharmony_ci
6233d722a9Sopenharmony_ci        let mut items = Vec::new();
6333d722a9Sopenharmony_ci        while !content.is_empty() {
6433d722a9Sopenharmony_ci            items.push(content.parse()?);
6533d722a9Sopenharmony_ci        }
6633d722a9Sopenharmony_ci
6733d722a9Sopenharmony_ci        Ok(Module {
6833d722a9Sopenharmony_ci            cfg,
6933d722a9Sopenharmony_ci            namespace,
7033d722a9Sopenharmony_ci            attrs,
7133d722a9Sopenharmony_ci            vis,
7233d722a9Sopenharmony_ci            unsafety,
7333d722a9Sopenharmony_ci            mod_token,
7433d722a9Sopenharmony_ci            ident,
7533d722a9Sopenharmony_ci            brace_token,
7633d722a9Sopenharmony_ci            content: items,
7733d722a9Sopenharmony_ci        })
7833d722a9Sopenharmony_ci    }
7933d722a9Sopenharmony_ci}
8033d722a9Sopenharmony_ci
8133d722a9Sopenharmony_ciimpl Parse for Item {
8233d722a9Sopenharmony_ci    fn parse(input: ParseStream) -> Result<Self> {
8333d722a9Sopenharmony_ci        let attrs = input.call(Attribute::parse_outer)?;
8433d722a9Sopenharmony_ci
8533d722a9Sopenharmony_ci        let ahead = input.fork();
8633d722a9Sopenharmony_ci        let unsafety = if ahead.parse::<Option<Token![unsafe]>>()?.is_some()
8733d722a9Sopenharmony_ci            && ahead.parse::<Option<Token![extern]>>()?.is_some()
8833d722a9Sopenharmony_ci            && ahead.parse::<Option<LitStr>>().is_ok()
8933d722a9Sopenharmony_ci            && ahead.peek(token::Brace)
9033d722a9Sopenharmony_ci        {
9133d722a9Sopenharmony_ci            Some(input.parse()?)
9233d722a9Sopenharmony_ci        } else {
9333d722a9Sopenharmony_ci            None
9433d722a9Sopenharmony_ci        };
9533d722a9Sopenharmony_ci
9633d722a9Sopenharmony_ci        let item = input.parse()?;
9733d722a9Sopenharmony_ci        match item {
9833d722a9Sopenharmony_ci            RustItem::Struct(mut item) => {
9933d722a9Sopenharmony_ci                item.attrs.splice(..0, attrs);
10033d722a9Sopenharmony_ci                Ok(Item::Struct(item))
10133d722a9Sopenharmony_ci            }
10233d722a9Sopenharmony_ci            RustItem::Enum(mut item) => {
10333d722a9Sopenharmony_ci                item.attrs.splice(..0, attrs);
10433d722a9Sopenharmony_ci                Ok(Item::Enum(item))
10533d722a9Sopenharmony_ci            }
10633d722a9Sopenharmony_ci            RustItem::ForeignMod(mut item) => {
10733d722a9Sopenharmony_ci                item.attrs.splice(..0, attrs);
10833d722a9Sopenharmony_ci                Ok(Item::ForeignMod(ItemForeignMod {
10933d722a9Sopenharmony_ci                    attrs: item.attrs,
11033d722a9Sopenharmony_ci                    unsafety,
11133d722a9Sopenharmony_ci                    abi: item.abi,
11233d722a9Sopenharmony_ci                    brace_token: item.brace_token,
11333d722a9Sopenharmony_ci                    items: item.items,
11433d722a9Sopenharmony_ci                }))
11533d722a9Sopenharmony_ci            }
11633d722a9Sopenharmony_ci            RustItem::Impl(mut item) => {
11733d722a9Sopenharmony_ci                item.attrs.splice(..0, attrs);
11833d722a9Sopenharmony_ci                Ok(Item::Impl(item))
11933d722a9Sopenharmony_ci            }
12033d722a9Sopenharmony_ci            RustItem::Use(mut item) => {
12133d722a9Sopenharmony_ci                item.attrs.splice(..0, attrs);
12233d722a9Sopenharmony_ci                Ok(Item::Use(item))
12333d722a9Sopenharmony_ci            }
12433d722a9Sopenharmony_ci            other => Ok(Item::Other(other)),
12533d722a9Sopenharmony_ci        }
12633d722a9Sopenharmony_ci    }
12733d722a9Sopenharmony_ci}
128