1use crate::Value;23pub fn write_identifier(k: &str, out: &mut String) {4 if k.contains(['.', '\'', '\"', '\\', '\n', '\t', '\r', '$']) {5 write_nix_str(k, out);6 } else {7 out.push_str(k);8 }9}1011fn write_nix_obj_key_buf(k: &str, v: &Value, out: &mut String) {12 write_identifier(k, out);13 match v {14 Value::Object(o) if o.len() == 1 => {15 let (k, v) = o.iter().next().unwrap();1617 out.push('.');18 write_nix_obj_key_buf(k, v, out);19 }20 v => {21 out.push_str(" = ");22 write_nix_buf(v, out);23 out.push(';');24 }25 }26}2728pub fn escape_string(str: &str) -> String {29 format!(30 "\"{}\"",31 str.replace('\\', "\\\\")32 .replace('"', "\\\"")33 .replace('\n', "\\n")34 .replace('\t', "\\t")35 .replace('\r', "\\r")36 .replace('$', "\\$")37 )38}3940pub fn write_nix_str(str: &str, out: &mut String) {41 out.push_str(&escape_string(str))42}4344fn write_nix_buf(value: &Value, out: &mut String) {45 match value {46 Value::Null => out.push_str("null"),47 Value::Boolean(v) => out.push_str(if *v { "true" } else { "false" }),48 Value::Number(n) => out.push_str(&format!("{}", n)),49 Value::String(s) => write_nix_str(s, out),50 Value::Array(a) => {51 if a.is_empty() {52 out.push_str("[ ]");53 } else {54 out.push('[');55 for item in a {56 write_nix_buf(item, out);57 out.push('\n');58 }59 out.push(']');60 }61 }62 Value::Object(obj) => {63 if obj.is_empty() {64 out.push_str("{ }")65 } else {66 out.push('{');67 for (k, v) in obj {68 write_nix_obj_key_buf(k, v, out);69 out.push('\n');70 }71 out.push('}');72 }73 }74 };75}7677pub fn write_nix(value: &Value) -> String {78 let mut out = String::new();79 write_nix_buf(value, &mut out);80 let (_, out) = alejandra::format::in_memory("".to_owned(), out);81 out82}