mz_walkabout/
parse.rs
1use std::fs;
13use std::path::Path;
14
15use anyhow::{Context, Result};
16use syn::{Data, DataEnum, DataStruct, DataUnion, DeriveInput, Item};
17
18pub fn parse_mod<P>(path: P) -> Result<Vec<DeriveInput>>
24where
25 P: AsRef<Path>,
26{
27 let mut out = vec![];
28 collect_items(path, &mut out)?;
29 Ok(out)
30}
31
32fn collect_items<P>(path: P, out: &mut Vec<DeriveInput>) -> Result<()>
33where
34 P: AsRef<Path>,
35{
36 let path = path.as_ref();
37 let dir = path.parent().expect("missing parent directory");
38 let stem = path
39 .file_stem()
40 .expect("missing file stem")
41 .to_str()
42 .expect("file stem is not valid UTF-8");
43
44 let src =
45 fs::read_to_string(path).with_context(|| format!("Failed to read {}", path.display()))?;
46 let file =
47 syn::parse_file(&src).with_context(|| format!("Failed to parse {}", path.display()))?;
48
49 for item in file.items {
50 match item {
51 Item::Mod(item) if item.content.is_none() => {
52 let path = match stem {
53 "mod" | "lib" => dir.join(format!("{}.rs", item.ident)),
54 _ => dir.join(format!("{}/{}.rs", stem, item.ident)),
55 };
56 collect_items(path, out)?;
57 }
58 Item::Struct(item) => {
59 out.push(DeriveInput {
60 ident: item.ident,
61 vis: item.vis,
62 attrs: item.attrs,
63 generics: item.generics,
64 data: Data::Struct(DataStruct {
65 fields: item.fields,
66 struct_token: item.struct_token,
67 semi_token: item.semi_token,
68 }),
69 });
70 }
71 Item::Enum(item) => {
72 out.push(DeriveInput {
73 ident: item.ident,
74 vis: item.vis,
75 attrs: item.attrs,
76 generics: item.generics,
77 data: Data::Enum(DataEnum {
78 enum_token: item.enum_token,
79 brace_token: item.brace_token,
80 variants: item.variants,
81 }),
82 });
83 }
84 Item::Union(item) => {
85 out.push(DeriveInput {
86 ident: item.ident,
87 vis: item.vis,
88 attrs: item.attrs,
89 generics: item.generics,
90 data: Data::Union(DataUnion {
91 union_token: item.union_token,
92 fields: item.fields,
93 }),
94 });
95 }
96 _ => (),
97 }
98 }
99 Ok(())
100}