1use std::fs::File;
2use std::io::Write;
3use std::path::PathBuf;
4
5use linked_hash_map::LinkedHashMap;
6use log::debug;
7use yaml_rust::{Yaml, YamlEmitter};
8
9use crate::args::{Args, TargetFormat};
10use crate::errors::ProconError;
11use crate::nodes::Nodes;
12
13#[cfg(test)]
14#[path = "./nodes_writer_test.rs"]
15mod nodes_writer_test;
16
17pub fn to_yaml(args: &Args, nodes: &Nodes) -> Result<String, ProconError> {
18 let mut content = String::new();
19 let mut emitter = YamlEmitter::new(&mut content);
20
21 let mut map: LinkedHashMap<Yaml, Yaml> = LinkedHashMap::new();
23 for node in nodes.iter() {
24 if node.name.is_empty() {
26 let array: Yaml = node.into();
27 emitter.dump(&array).map_err(|_| ProconError {
28 message: "Could convert to yam format".to_string(),
29 })?;
30 break;
31 } else {
32 map.insert(Yaml::from_str(&node.name), node.into());
34 }
35 }
36
37 if !map.is_empty() {
38 let final_node = Yaml::Hash(map);
39 emitter.dump(&final_node).map_err(|_| ProconError {
40 message: "Could convert to yaml format".to_string(),
41 })?;
42 }
43
44 output_content(&args, content)
45}
46
47pub fn to_json(args: &Args, nodes: &Nodes) -> Result<String, ProconError> {
48 let mut json_data = json::JsonValue::new_object();
49 for node in nodes.iter() {
50 if node.name.is_empty() {
52 json_data = node.into();
53 } else {
54 json_data[node.name.clone()] = node.into();
55 }
56 }
57 output_content(&args, json_data.pretty(1))
58}
59
60pub fn to_properties(args: &Args, nodes: &Nodes) -> Result<String, ProconError> {
61 let mut string_content = "".to_string();
62 for node in nodes.iter() {
63 let content: String = node.into();
64 string_content.push_str(&content);
65 }
66 output_content(&args, string_content)
67}
68
69fn output_content(args: &Args, content: String) -> Result<String, ProconError> {
70 println!("{}", content);
71 if args.dry_run {
72 Ok(String::from("Print converted format to console"))
73 } else {
74 let output_filename = determine_output_filename(&args);
75 let mut output_file: File = File::create(&output_filename).map_err(|_| ProconError {
76 message: "Could not create file".to_string(),
77 })?;
78 write!(output_file, "{}", content).map_err(|_| ProconError {
79 message: "Could write to file".to_string(),
80 })?;
81
82 let mut message = "Converted ".to_string();
83 message.push_str(&args.target_format.path_buf().to_str().unwrap());
84 message.push_str(" to ");
85 message.push_str(&output_filename);
86 Ok(message)
87 }
88}
89
90pub(crate) fn determine_output_filename(args: &Args) -> String {
91 let output_filename: String;
92 if args.output_filename.is_some() {
93 output_filename = args.output_filename.as_ref().unwrap().to_string();
94 debug!("User provided output filename {}", output_filename);
95 } else {
96 output_filename = default_filename(&args.target_format);
97 debug!("User default output filename {}", output_filename);
98 }
99 output_filename
100}
101
102pub(crate) fn default_filename(command: &TargetFormat) -> String {
103 let (path_buf, extension) = match command {
104 TargetFormat::Properties { file, .. } => (file, "properties".to_string()),
105 TargetFormat::Json { file, .. } => (file, "json".to_string()),
106 TargetFormat::Yaml { file, .. } => (file, "yaml".to_string()),
107 };
108 let mut filename = path_buf.file_stem().unwrap().to_str().unwrap();
109
110 if path_buf == &PathBuf::from("-") {
112 filename = "stdin";
113 }
114 return [filename, ".", extension.to_string().to_lowercase().as_str()].concat();
115}