idl 0.1.1

Library used for the idl language.
Documentation
use super::{get_all_idl_nodes, open_directory};
use crate::{ids, language::*};
use anyhow::{anyhow, Result};
use std::{
    fs,
    path::{Path, PathBuf},
    str::FromStr,
};

pub fn build(input_path: &str, server: Option<&str>, output: Option<&str>) -> Result<()> {
    let output = match output {
        Some(value) => PathBuf::from_str(value)?,
        None => PathBuf::from("."),
    };

    let mut module = open_directory(Path::new(input_path))?;
    module.update()?;

    module.idl_documents_are_all_valid()?;

    let analyzer_i = &*module.ids_analyzer()?;
    let analyzer_ids = analyzer_i.as_ref().map_err(|err| anyhow!("{}", err))?;

    let server = match server {
        Some(server) => analyzer_ids
            .find_server(server)
            .ok_or_else(|| anyhow!("Undefined server `{}`", server))?,
        None => {
            let n_servers = analyzer_ids
                .nodes
                .iter()
                .filter_map(|v| match v {
                    ids::nodes::IdsNode::Server(value) => Some(value),
                    _ => None,
                })
                .count();

            if n_servers > 1 {
                return Err(anyhow!("More than one server were specified in package"));
            } else if n_servers == 0 {
                return Err(anyhow!("No server defined in package"));
            } else {
                analyzer_ids
                    .nodes
                    .iter()
                    .find_map(|v| match v {
                        ids::nodes::IdsNode::Server(value) => Some(value),
                        _ => None,
                    })
                    .unwrap()
            }
        }
    };

    let language = server
        .get_field("language")
        .ok_or_else(|| anyhow!("Missing languange field"))?
        .as_string_value()
        .ok_or_else(|| anyhow!("Value for language must be a string"))?;

    let names = module.idl_documents_all_valid_names()?;
    let ref_names: Vec<&str> = names.iter().map(|v| v.as_str()).collect();
    let analyzers = module.idl_all_analyzers(&ref_names)?;

    let request = LanguageRequest {
        libraries: get_all_idl_nodes(&analyzers),
        ids_nodes: analyzer_ids.nodes.clone(),
        request_type: RequestType::Server(ServerType {
            server_name: server.ident.to_owned(),
            input_path: input_path.to_owned(),
            args: ServerArg::Generate,
            build_type: BuildType::Release,
        }),
    };

    let gen = Box::new(super::binary_json::BinaryGen::new(&language)?);
    let response = gen.send_request(request)?;

    match response.response_type {
        ResponseType::Generated(value) => {
            fs::create_dir_all(&output)?; // The language folder is never cleaned.

            for item in value {
                item.write_items(&output, false)?;
            }

            Ok(())
        }
        ResponseType::Undefined(err) => return Err(anyhow!("Response error `{}`", err)),
    }
}