blob: 99466b8ee1640d4fc60d896c9420b5062475d4b5 [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 Tolnay7e69f892020-10-03 22:20:22 -07005 braced, token, Abi, Attribute, ForeignItem, Ident, Item as RustItem, ItemEnum, ItemImpl,
6 ItemStruct, ItemUse, LitStr, Token, Visibility,
David Tolnay00a83852020-08-29 15:06:16 -07007};
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),
David Tolnay7e69f892020-10-03 22:20:22 -070025 Impl(ItemImpl),
David Tolnay00a83852020-08-29 15:06:16 -070026 Other(RustItem),
27}
28
David Tolnayc598a272020-08-29 15:10:18 -070029pub struct ItemForeignMod {
30 pub attrs: Vec<Attribute>,
31 pub unsafety: Option<Token![unsafe]>,
32 pub abi: Abi,
33 pub brace_token: token::Brace,
34 pub items: Vec<ForeignItem>,
35}
36
David Tolnay05ef6ff2020-08-29 11:27:05 -070037impl Parse for Module {
38 fn parse(input: ParseStream) -> Result<Self> {
David Tolnay4ebde542020-11-01 14:23:31 -080039 let namespace = Namespace::ROOT;
David Tolnay05ef6ff2020-08-29 11:27:05 -070040 let mut attrs = input.call(Attribute::parse_outer)?;
41 let vis: Visibility = input.parse()?;
David Tolnay633f5662020-08-29 14:47:45 -070042 let unsafety: Option<Token![unsafe]> = input.parse()?;
David Tolnay05ef6ff2020-08-29 11:27:05 -070043 let mod_token: Token![mod] = input.parse()?;
44 let ident: Ident = input.parse()?;
45
David Tolnay3c64a4e2020-08-29 14:07:38 -070046 let semi: Option<Token![;]> = input.parse()?;
47 if let Some(semi) = semi {
48 let span = quote!(#vis #mod_token #semi);
49 return Err(Error::new_spanned(
50 span,
David Tolnay05ef6ff2020-08-29 11:27:05 -070051 "#[cxx::bridge] module must have inline contents",
David Tolnay73075fe2020-08-29 18:57:51 -070052 ));
David Tolnay05ef6ff2020-08-29 11:27:05 -070053 }
54
55 let content;
56 let brace_token = braced!(content in input);
57 attrs.extend(content.call(Attribute::parse_inner)?);
58
59 let mut items = Vec::new();
60 while !content.is_empty() {
61 items.push(content.parse()?);
62 }
63
64 Ok(Module {
David Tolnay3c64a4e2020-08-29 14:07:38 -070065 namespace,
David Tolnay05ef6ff2020-08-29 11:27:05 -070066 attrs,
67 vis,
David Tolnay633f5662020-08-29 14:47:45 -070068 unsafety,
David Tolnay05ef6ff2020-08-29 11:27:05 -070069 mod_token,
70 ident,
71 brace_token,
72 content: items,
73 })
74 }
75}
David Tolnay00a83852020-08-29 15:06:16 -070076
77impl Parse for Item {
78 fn parse(input: ParseStream) -> Result<Self> {
David Tolnay0c0cfee2020-08-29 15:29:25 -070079 let attrs = input.call(Attribute::parse_outer)?;
80
81 let ahead = input.fork();
82 let unsafety = if ahead.parse::<Option<Token![unsafe]>>()?.is_some()
83 && ahead.parse::<Option<Token![extern]>>()?.is_some()
84 && ahead.parse::<Option<LitStr>>().is_ok()
85 && ahead.peek(token::Brace)
86 {
87 Some(input.parse()?)
88 } else {
89 None
90 };
91
David Tolnay00a83852020-08-29 15:06:16 -070092 let item = input.parse()?;
93 match item {
David Tolnay2cf2d0c2021-04-21 19:41:46 -070094 RustItem::Struct(mut item) => {
95 item.attrs.splice(..0, attrs);
96 Ok(Item::Struct(item))
97 }
98 RustItem::Enum(mut item) => {
99 item.attrs.splice(..0, attrs);
100 Ok(Item::Enum(item))
101 }
102 RustItem::ForeignMod(mut item) => {
103 item.attrs.splice(..0, attrs);
104 Ok(Item::ForeignMod(ItemForeignMod {
105 attrs: item.attrs,
106 unsafety,
107 abi: item.abi,
108 brace_token: item.brace_token,
109 items: item.items,
110 }))
111 }
112 RustItem::Impl(mut item) => {
113 item.attrs.splice(..0, attrs);
114 Ok(Item::Impl(item))
115 }
116 RustItem::Use(mut item) => {
117 item.attrs.splice(..0, attrs);
118 Ok(Item::Use(item))
119 }
David Tolnay00a83852020-08-29 15:06:16 -0700120 other => Ok(Item::Other(other)),
121 }
122 }
123}