codenano 0.1.4

A tool for editing DNA molecular designs in a browser
Documentation
use std::fs::File;
use std::io::{Read, Write};
use std::path::Path;
use std::process::Command;

fn main() {
    if cfg!(feature = "server") {
        if cfg!(not(debug_assertions)) {
            release()
        } else {
            debug();
        }
    }
}

fn debug() {
    let tmp = tempfile::tempdir().unwrap();
    std::fs::create_dir_all(tmp.path().join("dist")).unwrap();
    if std::fs::metadata("codenano-gui").is_ok() {
        build(tmp.path(), false)
    }
    let out_dir = std::env::var("OUT_DIR").unwrap();
    let dest_path = Path::new(&out_dir).join("static_files.rs");
    let mut f = File::create(&dest_path).unwrap();
    f.write_all(b"fn static_files() -> impl warp::Filter<Error = warp::Rejection, Extract = (warp::filters::fs::File, )> + Clone { warp::filters::fs::dir(\"static\") }").unwrap();
    f.write_all(b"fn index_ws() -> impl warp::Filter<Error = warp::Rejection, Extract = (warp::filters::fs::File, )> + Clone { warp::filters::fs::file(\"static/index-ws.html\") }").unwrap();
    f.write_all(b"fn index() -> impl warp::Filter<Error = warp::Rejection, Extract = (warp::filters::fs::File, )> + Clone { warp::filters::fs::file(\"static/index.html\") }").unwrap();
}

fn build(tmp: &Path, release: bool) {
    println!("cargo:rerun-if-changed=codenano-gui");
    // Compiling wasm32.
    let mut cmd = Command::new("cargo");
    cmd.arg("build")
        .arg("--target")
        .arg("wasm32-unknown-unknown");
    if release {
        cmd.arg("--release");
    }
    cmd.env("CARGO_TARGET_DIR", "target")
        .current_dir("codenano-gui")
        .status().unwrap();
    // Running wasm-bindgen
    Command::new("wasm-bindgen")
        .arg(&format!(
            "codenano-gui/target/wasm32-unknown-unknown/{}/codenano_gui.wasm",
            if release { "release" } else { "debug" }
        ))
        .arg("--out-dir")
        .arg(tmp)
        .status()
        .unwrap();

    // Running webpack-cli, along with all dependencies.
    for file in &[
        "index.js",
        "bootstrap.js",
        "package.json",
        "webpack.config.js",
    ] {
        println!("cargo:rerun-if-changed={}", file);
        std::fs::copy(file, tmp.join(file)).unwrap();
    }
    Command::new("webpack-cli")
        .current_dir(tmp)
        .status()
        .unwrap();
    let static_dir = std::path::Path::new(&std::env::var("CARGO_MANIFEST_DIR").unwrap())
        .join("static");
    for i in std::fs::read_dir(tmp.join("dist")).unwrap() {
        let i = i.unwrap();
        std::fs::copy(i.path(), static_dir.join(i.file_name())).unwrap();
    }
}

fn release() {
    let tmp = tempfile::tempdir().unwrap();
    std::fs::create_dir_all(tmp.path().join("dist")).unwrap();
    let path = if std::fs::metadata("codenano-gui").is_ok() {
        build(tmp.path(), true);
        // Copying remaining files.
        let static_dir = std::path::Path::new(&std::env::var("CARGO_MANIFEST_DIR").unwrap())
            .join("static");
        for file in &["style.css", "index.html", "index-ws.html"] {
            println!("cargo:rerun-if-changed=static/{}", file);
            std::fs::copy(
                static_dir.join(file),
                tmp.path().join("dist").join(file),
            )
                .unwrap();
        }
        tmp.path().join("dist")
    } else {
        std::path::Path::new(&std::env::var("CARGO_MANIFEST_DIR").unwrap())
            .join("static")
    };

    // Generate the code to serve static files.
    let out_dir = std::env::var("OUT_DIR").unwrap();
    std::fs::create_dir_all(&out_dir).unwrap();
    let dest_path = Path::new(&out_dir).join("static_files.rs");

    let mut index = Vec::new();
    let mut f = File::create(&dest_path).unwrap();

    f.write_all(b"fn static_files() -> impl warp::Filter<Error = warp::Rejection, Extract = (Result<warp::http::Response<&'static [u8]>,warp::http::Error>, )> + Clone {").unwrap();
    let mut s = Vec::new();
    let mut is_first = true;
    for i in std::fs::read_dir(&path).unwrap() {
        let i = i.unwrap();
        if i.metadata().unwrap().is_dir() {
            continue
        }
        let mut ii = File::open(i.path()).unwrap();
        s.clear();
        ii.read_to_end(&mut s).unwrap();
        let mime: mime_guess::Mime = mime_guess::guess_mime_type(i.path());
        let file_name = i.path();
        let file_name = file_name.file_name().unwrap();
        let mut make_index = |name| {
            writeln!(
                &mut index,
                "fn {}() -> impl warp::Filter<Error = warp::Rejection, Extract = (Result<warp::http::Response<&'static [u8]>,warp::http::Error>, )> + Clone {{",
                name
            ).unwrap();
            writeln!(
                &mut index,
                "
            warp::path::end().map(|| warp::http::Response::builder()
              .header(\"Content-Type\", \"{}/{}\")
              .body(&{:?}[..]))
",
                mime.0.as_str(),
                mime.1.as_str(),
                byte_string::ByteStr::new(&s),
            )
            .unwrap();
            writeln!(&mut index, "}}").unwrap();
        };
        if file_name == "index-ws.html" {
            make_index("index_ws")
        } else if file_name == "index.html" {
            make_index("index")
        }
        if is_first {
            writeln!(
                f,
                "
        warp::path({:?}).map(|| {{
            warp::http::Response::builder()
              .header(\"Content-Type\", \"{}/{}\")
              .body(&{:?}[..])
        }})",
                file_name,
                mime.0.as_str(),
                mime.1.as_str(),
                byte_string::ByteStr::new(&s),
            )
            .unwrap();
            is_first = false
        } else {
            writeln!(
                f,
                "
        .or(warp::path({:?}).map(|| {{
            warp::http::Response::builder()
              .header(\"Content-Type\", \"{}/{}\")
              .body(&{:?}[..])
        }})).unify()",
                file_name,
                mime.0.as_str(),
                mime.1.as_str(),
                byte_string::ByteStr::new(&s),
            )
            .unwrap();
        }
    }
    writeln!(
        f,
        "
}}"
    )
    .unwrap();
    f.write_all(&index).unwrap();
}