idl/builder/
server.rs

1use super::{get_all_idl_nodes, open_directory};
2use crate::{ids, language::*};
3use anyhow::{anyhow, Result};
4use std::{
5    fs,
6    path::{Path, PathBuf},
7    str::FromStr,
8};
9
10pub fn build(input_path: &str, server: Option<&str>, output: Option<&str>) -> Result<()> {
11    let output = match output {
12        Some(value) => PathBuf::from_str(value)?,
13        None => PathBuf::from("."),
14    };
15
16    let mut module = open_directory(Path::new(input_path))?;
17    module.update()?;
18
19    module.idl_documents_are_all_valid()?;
20
21    let analyzer_i = &*module.ids_analyzer()?;
22    let analyzer_ids = analyzer_i.as_ref().map_err(|err| anyhow!("{}", err))?;
23
24    let server = match server {
25        Some(server) => analyzer_ids
26            .find_server(server)
27            .ok_or_else(|| anyhow!("Undefined server `{}`", server))?,
28        None => {
29            let n_servers = analyzer_ids
30                .nodes
31                .iter()
32                .filter_map(|v| match v {
33                    ids::nodes::IdsNode::Server(value) => Some(value),
34                    _ => None,
35                })
36                .count();
37
38            if n_servers > 1 {
39                return Err(anyhow!("More than one server were specified in package"));
40            } else if n_servers == 0 {
41                return Err(anyhow!("No server defined in package"));
42            } else {
43                analyzer_ids
44                    .nodes
45                    .iter()
46                    .find_map(|v| match v {
47                        ids::nodes::IdsNode::Server(value) => Some(value),
48                        _ => None,
49                    })
50                    .unwrap()
51            }
52        }
53    };
54
55    let language = server
56        .get_field("language")
57        .ok_or_else(|| anyhow!("Missing languange field"))?
58        .as_string_value()
59        .ok_or_else(|| anyhow!("Value for language must be a string"))?;
60
61    let names = module.idl_documents_all_valid_names()?;
62    let ref_names: Vec<&str> = names.iter().map(|v| v.as_str()).collect();
63    let analyzers = module.idl_all_analyzers(&ref_names)?;
64
65    let request = LanguageRequest {
66        libraries: get_all_idl_nodes(&analyzers),
67        ids_nodes: analyzer_ids.nodes.clone(),
68        request_type: RequestType::Server(ServerType {
69            server_name: server.ident.to_owned(),
70            input_path: input_path.to_owned(),
71            args: ServerArg::Generate,
72            build_type: BuildType::Release,
73        }),
74    };
75
76    let gen = Box::new(super::binary_json::BinaryGen::new(&language)?);
77    let response = gen.send_request(request)?;
78
79    match response.response_type {
80        ResponseType::Generated(value) => {
81            fs::create_dir_all(&output)?; // The language folder is never cleaned.
82
83            for item in value {
84                item.write_items(&output, false)?;
85            }
86
87            Ok(())
88        }
89        ResponseType::Undefined(err) => return Err(anyhow!("Response error `{}`", err)),
90    }
91}