azure-functions-shared 0.11.0

Implementations shared between the azure-functions-codegen and azure-functions crates.
Documentation
use std::env;
use std::fs;
use std::path::{Path, PathBuf};
use std::process::Command;

const OUT_DIR_VAR: &str = "OUT_DIR";
const CACHE_DIR_NAME: &str = "cache";
const PROTOBUF_INPUT_FILES: &[&str] = &["FunctionRpc.proto"];
const OUTPUT_FILES: &[&str] = &["azure_functions_rpc_messages.rs"];

fn format_source(path: &Path) {
    Command::new("rustfmt")
        .arg(path.to_str().unwrap())
        .output()
        .expect("Failed to format generated source");
}

fn compile_protobufs(out_dir: &PathBuf, cache_dir: &PathBuf) {
    tonic_build::configure()
        .build_server(false)
        .compile(PROTOBUF_INPUT_FILES, &["protobuf/src/proto"])
        .unwrap_or_else(|e| panic!("protobuf compilation failed: {}", e));

    for file in OUTPUT_FILES {
        let cached_output = cache_dir.join(file);

        fs::copy(out_dir.join(file), &cached_output).expect(&format!(
            "can't update cache file '{}'",
            cached_output.display()
        ));

        format_source(&cached_output);
    }
}

fn use_cached_files(out_dir: &PathBuf, cache_dir: &PathBuf) {
    for file in OUTPUT_FILES {
        fs::copy(cache_dir.join(file), out_dir.join(file)).expect(&format!(
            "can't copy cache file '{}' to output directory",
            file
        ));
    }
}

fn main() {
    for file in PROTOBUF_INPUT_FILES {
        println!("cargo:rerun-if-changed=protobuf/src/proto/{}", file);
    }

    let out_dir = PathBuf::from(env::var(OUT_DIR_VAR).unwrap());

    let cache_dir = env::current_dir()
        .expect("couldn't determine current working directory")
        .join(CACHE_DIR_NAME);

    fs::create_dir_all(&cache_dir).expect("failed to create cache directory");

    if cfg!(feature = "compile_protobufs") {
        compile_protobufs(&out_dir, &cache_dir);
    } else {
        use_cached_files(&out_dir, &cache_dir);
    }
}