use std::{ffi::OsStr, fs, path::Path};
use flatbuffers_build::BuilderOptions;
use flatc_fork::flatc;
const SCHEMAS: [&str; 1] = ["schemas/switchboard.fbs"];
fn main() {
println!("cargo::rerun-if-changed=schemas/");
BuilderOptions::new_with_files(SCHEMAS)
.set_output_path("src/fbs/")
.set_compiler(flatc().to_str().expect("Non UTF-8 path to flatc binary"))
.compile()
.expect("flatbuffer compilation failed");
rewrite_module_root("src/fbs").expect("failed to rewrite module root file");
}
fn rewrite_module_root(root: impl AsRef<Path>) -> std::io::Result<()> {
let root = root.as_ref();
let selium_dir = root.join("selium");
let mut namespaces = list_dirs(&selium_dir)?;
namespaces.sort();
let mut content =
String::from("// Automatically generated by build.rs. Do not modify manually.\n");
content.push_str("// Combined module tree for Selium Flatbuffers namespaces.\n");
content.push_str("pub mod selium {\n");
content.push_str(" use super::*;\n");
for ns in namespaces {
let dir = selium_dir.join(&ns);
let mut files = list_rs_files(&dir)?;
files.sort();
content.push_str(&format!(" pub mod {} {{\n use super::*;\n", ns));
for file in files {
content.push_str(&format!(
" mod {};\n pub use self::{}::*;\n",
file, file
));
}
content.push_str(" }\n");
}
content.push_str("}\n");
fs::write(root.join("mod.rs"), content)
}
fn list_dirs(dir: &Path) -> std::io::Result<Vec<String>> {
let mut names = Vec::new();
if dir.exists() {
for entry in fs::read_dir(dir)? {
let entry = entry?;
if entry.file_type()?.is_dir()
&& let Some(name) = entry.file_name().to_str()
{
names.push(name.to_string());
}
}
}
Ok(names)
}
fn list_rs_files(dir: &Path) -> std::io::Result<Vec<String>> {
let mut names = Vec::new();
if dir.exists() {
for entry in fs::read_dir(dir)? {
let entry = entry?;
if entry.file_type()?.is_file()
&& entry.path().extension() == Some(OsStr::new("rs"))
&& let Some(stem) = entry.path().file_stem().and_then(|s| s.to_str())
{
names.push(stem.to_string());
}
}
}
Ok(names)
}