sdf-wit 0.14.0

Sdf WIT generator for sdf projects
Documentation
use std::{
    env,
    fmt::Display,
    path::{Path, PathBuf},
};

use wit_encoder::{packages_from_parsed, Package, PackageItem, Render, RenderOpts};

// rebuild on changes to wit/deps

fn main() {
    println!("cargo:rerun-if-changed=./wit/deps");

    // we need to translate from `deps/` pkg approach to inline pkg approach
    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(())
    }
}