c3_lang_parser/
rust_package_def.rs1use 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}