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)?; 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}