1use crate::syntax::file::Module;
2use crate::syntax::namespace::Namespace;
3use syn::parse::discouraged::Speculative;
4use syn::parse::{Error, Parse, ParseStream, Result};
5use syn::{braced, Attribute, Ident, Item, Meta, Token, Visibility};
6
7pub(crate) struct File {
8 pub modules: Vec<Module>,
9}
10
11impl Parse for File {
12 fn parse(input: ParseStream) -> Result<Self> {
13 let mut modules = Vec::new();
14 parse(input, &mut modules)?;
15 Ok(File { modules })
16 }
17}
18
19fn parse(input: ParseStream, modules: &mut Vec<Module>) -> Result<()> {
20 input.call(Attribute::parse_inner)?;
21
22 while !input.is_empty() {
23 let mut cxx_bridge = false;
24 let mut namespace = Namespace::ROOT;
25 let mut attrs = input.call(Attribute::parse_outer)?;
26 for attr in &attrs {
27 let path = &attr.path().segments;
28 if path.len() == 2 && path[0].ident == "cxx" && path[1].ident == "bridge" {
29 cxx_bridge = true;
30 namespace = parse_args(attr)?;
31 break;
32 }
33 }
34
35 let ahead = input.fork();
36 ahead.parse::<Visibility>()?;
37 ahead.parse::<Option<Token![unsafe]>>()?;
38 if !ahead.peek(Token![mod]) {
39 let item: Item = input.parse()?;
40 if cxx_bridge {
41 return Err(Error::new_spanned(item, "expected a module"));
42 }
43 continue;
44 }
45
46 if cxx_bridge {
47 let mut module: Module = input.parse()?;
48 module.namespace = namespace;
49 attrs.extend(module.attrs);
50 module.attrs = attrs;
51 modules.push(module);
52 } else {
53 input.advance_to(&ahead);
54 input.parse::<Token![mod]>()?;
55 input.parse::<Ident>()?;
56 let semi: Option<Token![;]> = input.parse()?;
57 if semi.is_none() {
58 let content;
59 braced!(content in input);
60 parse(&content, modules)?;
61 }
62 }
63 }
64
65 Ok(())
66}
67
68fn parse_args(attr: &Attribute) -> Result<Namespace> {
69 if let Meta::Path(_) = attr.meta {
70 Ok(Namespace::ROOT)
71 } else {
72 attr.parse_args_with(Namespace::parse_bridge_attr_namespace)
73 }
74}