procon/
nodes_writer.rs

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    // todo refactor this
22    let mut map: LinkedHashMap<Yaml, Yaml> = LinkedHashMap::new();
23    for node in nodes.iter() {
24        // root list treatment
25        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            // the rest
33            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        // root list treatment
51        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    // stdin
111    if path_buf == &PathBuf::from("-") {
112        filename = "stdin";
113    }
114    return [filename, ".", extension.to_string().to_lowercase().as_str()].concat();
115}