use std::{
env,
fmt::Display,
path::{Path, PathBuf},
};
use wit_encoder::{packages_from_parsed, Package, PackageItem, Render, RenderOpts};
fn main() {
println!("cargo:rerun-if-changed=./wit/deps");
let mut resolve = wit_parser::Resolve::new();
resolve
.push_dir(PathBuf::from("./wit"))
.expect("failed to parse wit deps");
let mut pkg_str = String::new();
let packages = packages_from_parsed(&resolve);
packages.iter().for_each(|pkg| {
let pkg = InlinePkg(pkg.clone());
pkg_str.push_str(&pkg.to_string());
});
let out_dir = env::var_os("OUT_DIR").unwrap();
let dest_path = Path::new(&out_dir).join("sdf_pkg_wit.rs");
std::fs::write(
dest_path,
format!(
"// This file is generated by sdf-wit/build.rs
#[rustfmt::skip]
pub const SDF_WIT_PKGS: &str = \"{pkg_str}\";\n"
),
)
.expect("Unable to write sdf_wit_pkgs.rs");
}
struct InlinePkg(Package);
impl Display for InlinePkg {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let opts = RenderOpts::default();
write!(f, "{}package {} {{", opts.spaces(), self.0.name())?;
for item in self.0.items() {
writeln!(f)?;
match item {
PackageItem::Interface(interface) => {
if let Some(docs) = &interface.docs() {
docs.render(f, &opts)?;
}
write!(f, "{}interface {} {{", opts.spaces(), interface.name())?;
if !interface.uses().is_empty() || !interface.items().is_empty() {
writeln!(f)?;
interface.uses().to_owned().render(f, &opts.indent())?;
interface.items().to_owned().render(f, &opts.indent())?;
writeln!(f, "{}}}", opts.spaces())?;
} else {
writeln!(f, "}}")?;
}
}
PackageItem::World(world) => {
world.render(f, &opts)?;
}
}
}
write!(f, "\n}}\n")?;
Ok(())
}
}