c3_lang_parser/
rust_package_def.rs

1use super::RustClassDef;
2use syn::{
3    parse::{Parse, ParseStream, Peek},
4    Item, Token,
5};
6
7#[derive(Debug, PartialEq)]
8pub struct RustPackageDef {
9    pub other_code: Vec<Item>,
10    pub classes: Vec<RustClassDef>,
11}
12
13impl Parse for RustPackageDef {
14    fn parse(input: ParseStream) -> syn::Result<Self> {
15        let mut classes = vec![];
16        let mut other_code: Vec<Item> = Vec::new();
17        loop {
18            if peek_with_pub(&input, Token![type])
19                || peek_with_pub(&input, Token![mod])
20                || peek_with_pub(&input, Token![use])
21                || peek_with_pub(&input, Token![impl])
22            {
23                let item: Item = input.parse()?;
24                other_code.push(item);
25                continue;
26            }
27
28            if peek_with_pub(&input, Token![struct]) || input.peek(Token![#]) {
29                let item: RustClassDef = input.parse()?;
30                classes.push(item);
31                continue;
32            }
33
34            if input.is_empty() {
35                break;
36            } else {
37                return Err(input.error(format!("Unknown keyword. {}", input)));
38            }
39        }
40        Ok(RustPackageDef {
41            other_code,
42            classes,
43        })
44    }
45}
46
47fn peek_with_pub<T: Peek>(input: &ParseStream, token: T) -> bool {
48    input.peek(Token![pub]) && input.peek2(token) || input.peek(token)
49}
50
51#[cfg(test)]
52mod tests {
53    use quote::quote;
54    use syn::parse_quote;
55
56    use super::RustPackageDef;
57
58    #[test]
59    fn test_rust_package_def_1() {
60        let input = quote! {
61            use c3;
62            type A = X;
63            pub type B = Y;
64            mod a {}
65            pub mod b {}
66            struct K {}
67            pub struct G {}
68            impl G {}
69        };
70        let result: RustPackageDef = syn::parse2(input).unwrap();
71        let target = RustPackageDef {
72            other_code: vec![
73                parse_quote! { use c3; },
74                parse_quote! { type A = X; },
75                parse_quote! { pub type B = Y; },
76                parse_quote! { mod a { } },
77                parse_quote! { pub mod b { } },
78            ],
79            classes: vec![
80                parse_quote! { struct K {} },
81                parse_quote! { pub struct G {} impl G {} },
82            ],
83        };
84        assert_eq!(result, target);
85    }
86}