blob: dfe8e0d188a293b9bff4f2868f2a352b5018bfec [file] [log] [blame]
David Tolnay3c64a4e2020-08-29 14:07:38 -07001use crate::syntax::namespace::Namespace;
2use quote::quote;
David Tolnay05ef6ff2020-08-29 11:27:05 -07003use syn::parse::{Error, Parse, ParseStream, Result};
David Tolnay00a83852020-08-29 15:06:16 -07004use syn::{
David Tolnayc598a272020-08-29 15:10:18 -07005 braced, token, Abi, Attribute, ForeignItem, Ident, Item as RustItem, ItemEnum, ItemStruct,
David Tolnay00a83852020-08-29 15:06:16 -07006 ItemUse, Token, Visibility,
7};
David Tolnay05ef6ff2020-08-29 11:27:05 -07008
9pub struct Module {
David Tolnay3c64a4e2020-08-29 14:07:38 -070010 pub namespace: Namespace,
David Tolnay05ef6ff2020-08-29 11:27:05 -070011 pub attrs: Vec<Attribute>,
12 pub vis: Visibility,
David Tolnay633f5662020-08-29 14:47:45 -070013 pub unsafety: Option<Token![unsafe]>,
David Tolnay05ef6ff2020-08-29 11:27:05 -070014 pub mod_token: Token![mod],
15 pub ident: Ident,
16 pub brace_token: token::Brace,
17 pub content: Vec<Item>,
18}
19
David Tolnay00a83852020-08-29 15:06:16 -070020pub enum Item {
21 Struct(ItemStruct),
22 Enum(ItemEnum),
23 ForeignMod(ItemForeignMod),
24 Use(ItemUse),
25 Other(RustItem),
26}
27
David Tolnayc598a272020-08-29 15:10:18 -070028pub struct ItemForeignMod {
29 pub attrs: Vec<Attribute>,
30 pub unsafety: Option<Token![unsafe]>,
31 pub abi: Abi,
32 pub brace_token: token::Brace,
33 pub items: Vec<ForeignItem>,
34}
35
David Tolnay05ef6ff2020-08-29 11:27:05 -070036impl Parse for Module {
37 fn parse(input: ParseStream) -> Result<Self> {
David Tolnay3c64a4e2020-08-29 14:07:38 -070038 let namespace = Namespace::none();
David Tolnay05ef6ff2020-08-29 11:27:05 -070039 let mut attrs = input.call(Attribute::parse_outer)?;
40 let vis: Visibility = input.parse()?;
David Tolnay633f5662020-08-29 14:47:45 -070041 let unsafety: Option<Token![unsafe]> = input.parse()?;
David Tolnay05ef6ff2020-08-29 11:27:05 -070042 let mod_token: Token![mod] = input.parse()?;
43 let ident: Ident = input.parse()?;
44
David Tolnay3c64a4e2020-08-29 14:07:38 -070045 let semi: Option<Token![;]> = input.parse()?;
46 if let Some(semi) = semi {
47 let span = quote!(#vis #mod_token #semi);
48 return Err(Error::new_spanned(
49 span,
David Tolnay05ef6ff2020-08-29 11:27:05 -070050 "#[cxx::bridge] module must have inline contents",
51 ))?;
52 }
53
54 let content;
55 let brace_token = braced!(content in input);
56 attrs.extend(content.call(Attribute::parse_inner)?);
57
58 let mut items = Vec::new();
59 while !content.is_empty() {
60 items.push(content.parse()?);
61 }
62
63 Ok(Module {
David Tolnay3c64a4e2020-08-29 14:07:38 -070064 namespace,
David Tolnay05ef6ff2020-08-29 11:27:05 -070065 attrs,
66 vis,
David Tolnay633f5662020-08-29 14:47:45 -070067 unsafety,
David Tolnay05ef6ff2020-08-29 11:27:05 -070068 mod_token,
69 ident,
70 brace_token,
71 content: items,
72 })
73 }
74}
David Tolnay00a83852020-08-29 15:06:16 -070075
76impl Parse for Item {
77 fn parse(input: ParseStream) -> Result<Self> {
78 let item = input.parse()?;
79 match item {
80 RustItem::Struct(item) => Ok(Item::Struct(item)),
81 RustItem::Enum(item) => Ok(Item::Enum(item)),
David Tolnayc598a272020-08-29 15:10:18 -070082 RustItem::ForeignMod(item) => Ok(Item::ForeignMod(ItemForeignMod {
83 attrs: item.attrs,
84 unsafety: None,
85 abi: item.abi,
86 brace_token: item.brace_token,
87 items: item.items,
88 })),
David Tolnay00a83852020-08-29 15:06:16 -070089 RustItem::Use(item) => Ok(Item::Use(item)),
90 other => Ok(Item::Other(other)),
91 }
92 }
93}