1use crate::value::{HkConfig, HkValue};
2use indexmap::IndexMap;
3use std::fs::File;
4use std::io::{self, Write};
5use std::path::Path;
6
7pub fn serialize_hk(config: &HkConfig) -> String {
9 let mut output = String::new();
10 for (section, value) in config.iter() {
11 output.push_str(&format!("[{}]\n", section));
12 if let HkValue::Map(map) = value {
13 serialize_map(map, 1, &mut output);
14 }
15 output.push('\n');
16 }
17 output.trim_end().to_string()
18}
19
20fn serialize_map(map: &IndexMap<String, HkValue>, level: usize, output: &mut String) {
21 let prefix = "-".repeat(level) + " > ";
22 for (key, value) in map.iter() {
23 match value {
24 HkValue::Map(submap) => {
25 output.push_str(&format!("{}{}\n", prefix, key));
26 serialize_map(submap, level + 1, output);
27 }
28 _ => {
29 let val = serialize_value(value);
30 output.push_str(&format!("{}{} => {}\n", prefix, key, val));
31 }
32 }
33 }
34}
35
36fn serialize_value(value: &HkValue) -> String {
37 match value {
38 HkValue::String(s) => {
39 if s.is_empty() || s.contains(',') || s.contains(' ') || s.contains(']') || s.contains('"') || s.contains('\n') {
40 format!("\"{}\"", s.replace("\"", "\\\""))
41 } else {
42 s.clone()
43 }
44 }
45 HkValue::Number(n) => n.to_string(),
46 HkValue::Bool(b) => if *b { "true".to_string() } else { "false".to_string() },
47 HkValue::Array(a) => format!(
48 "[{}]",
49 a.iter()
50 .map(serialize_value)
51 .collect::<Vec<_>>()
52 .join(", ")
53 ),
54 HkValue::Map(_) => "<map>".to_string(),
55 }
56}
57
58pub fn write_hk_file<P: AsRef<Path>>(path: P, config: &HkConfig) -> io::Result<()> {
59 let mut file = File::create(path)?;
60 file.write_all(serialize_hk(config).as_bytes())
61}