1use indoc::formatdoc;
2use std::{fs, path::Path};
3
4pub struct Config {
9 pub vbare: vbare_gen::Config,
11}
12
13impl Default for Config {
14 fn default() -> Self {
15 Self {
16 vbare: vbare_gen::Config::with_hash_map(),
17 }
18 }
19}
20
21impl Config {
22 pub fn with_hashable_map() -> Self {
24 Self {
25 vbare: vbare_gen::Config::with_hashable_map(),
26 }
27 }
28
29 pub fn with_hash_map() -> Self {
31 Self {
32 vbare: vbare_gen::Config::with_hash_map(),
33 }
34 }
35}
36
37pub fn process_schemas(schema_dir: &Path) -> Result<(), Box<dyn std::error::Error>> {
39 process_schemas_with_config(schema_dir, &Config::default())
40}
41
42pub fn process_schemas_with_config(
44 schema_dir: &Path,
45 config: &Config,
46) -> Result<(), Box<dyn std::error::Error>> {
47 let out_dir = std::env::var("OUT_DIR")?;
48 let out_path = Path::new(&out_dir);
49
50 println!("cargo:rerun-if-changed={}", schema_dir.display());
51
52 let mut all_names = Vec::new();
53
54 for entry in fs::read_dir(schema_dir)?.flatten() {
55 let path = entry.path();
56
57 if path.is_dir() {
58 continue;
59 }
60
61 let bare_name = path
62 .file_name()
63 .ok_or("No file name")?
64 .to_str()
65 .ok_or("Invalid UTF-8 in file name")?
66 .rsplit_once('.')
67 .ok_or("No file extension")?
68 .0;
69
70 let tokens = vbare_gen::bare_schema(&path, config.vbare);
71 let ast = syn::parse2(tokens)?;
72 let content = prettyplease::unparse(&ast);
73
74 fs::write(out_path.join(format!("{bare_name}_generated.rs")), content)?;
75
76 all_names.push(bare_name.to_string());
77 }
78
79 let mut mod_content = String::new();
80 mod_content.push_str("// Auto-generated module file for schemas\n\n");
81
82 for name in all_names {
83 let module_name = name.replace('.', "_");
84 mod_content.push_str(&formatdoc!(
85 r#"
86 pub mod {module_name} {{
87 include!(concat!(env!("OUT_DIR"), "/{name}_generated.rs"));
88 }}
89 "#,
90 name = name,
91 module_name = module_name,
92 ));
93 }
94
95 fs::write(out_path.join("combined_imports.rs"), mod_content)?;
96
97 Ok(())
98}