wasmer-pack-cli 0.7.1

A code generator that lets you treat WebAssembly modules like native dependencies.
Documentation
use std::{collections::BTreeMap, path::Path};

use anyhow::{Context, Error};
use wapm_targz_to_pirita::{generate_webc_file, webc::v1::DirOrFile, TransformManifestFunctions};
use wasmer_pack::Package;

pub(crate) fn load_from_disk(path: &Path) -> Result<Package, Error> {
    let raw_webc: Vec<u8> = if path.is_dir() {
        webc_from_dir(path)?
    } else if path.extension() == Some("webc".as_ref()) {
        std::fs::read(path).with_context(|| format!("Unable to read \"{}\"", path.display()))?
    } else {
        let tarball = std::fs::read(path)
            .with_context(|| format!("Unable to read \"{}\"", path.display()))?;
        webc_from_tarball(tarball)?
    };

    Package::from_webc(&raw_webc)
}

fn webc_from_dir(path: &Path) -> Result<Vec<u8>, Error> {
    if !path.join("wapm.toml").exists() {
        anyhow::bail!(
            "The \"{}\" directory doesn't contain a \"wapm.tom\" file",
            path.display()
        );
    }

    let mut files: BTreeMap<DirOrFile, Vec<u8>> = BTreeMap::new();

    fn read_dir(
        files: &mut BTreeMap<DirOrFile, Vec<u8>>,
        dir: &Path,
        base_dir: &Path,
    ) -> Result<(), Error> {
        let entries = dir
            .read_dir()
            .with_context(|| format!("Unable to read the contents of \"{}\"", dir.display()))?;

        for entry in entries {
            let path = entry?.path();
            let relative_path = path
                .strip_prefix(base_dir)
                .expect("The filename is always prefixed by base_dir")
                .to_path_buf();

            if path.is_dir() {
                read_dir(&mut *files, &path, base_dir)?;
                files.insert(DirOrFile::Dir(relative_path), Vec::new());
            } else {
                let bytes = std::fs::read(&path)
                    .with_context(|| format!("Unable to read \"{}\"", path.display()))?;
                files.insert(DirOrFile::File(relative_path), bytes);
            }
        }

        Ok(())
    }

    read_dir(&mut files, path, path).context("Unable to read the directory into memory")?;

    let functions = wapm_targz_to_pirita::TransformManifestFunctions::default();
    let tarball = generate_webc_file(files, path, &functions)
        .context("Unable to convert the files to a tarball")?;

    Ok(tarball)
}

pub(crate) fn webc_from_tarball(tarball: Vec<u8>) -> Result<Vec<u8>, Error> {
    let files =
        wapm_targz_to_pirita::unpack_tar_gz(tarball).context("Unable to unpack the tarball")?;

    wapm_targz_to_pirita::generate_webc_file(
        files,
        Path::new("."),
        &TransformManifestFunctions::default(),
    )
}