git.delta.rocks / jrsonnet / refs/commits / cd7c759361f6

difftreelog

source

crates/nixlike/src/to_string.rs2.4 KiBsourcehistory
1use alejandra::config::Indentation;23use crate::Value;45pub fn write_identifier(k: &str, out: &mut String) {6	if k.contains(['.', '\'', '\"', '\\', '\n', '\t', '\r', '$']) {7		write_nix_str(k, out);8	} else {9		out.push_str(k);10	}11}1213fn write_nix_obj_key_buf(k: &str, v: &Value, out: &mut String) {14	write_identifier(k, out);15	match v {16		Value::Object(o) if o.len() == 1 => {17			let (k, v) = o.iter().next().unwrap();1819			out.push('.');20			write_nix_obj_key_buf(k, v, out);21		}22		v => {23			out.push_str(" = ");24			write_nix_buf(v, out);25			out.push(';');26		}27	}28}2930pub fn escape_string(str: &str) -> String {31	format!(32		"\"{}\"",33		str.replace('\\', "\\\\")34			.replace('"', "\\\"")35			.replace('\n', "\\n")36			.replace('\t', "\\t")37			.replace('\r', "\\r")38			.replace('$', "\\$")39	)40}4142pub fn write_nix_str(str: &str, out: &mut String) {43	if str.ends_with('\n') {44		out.push_str("''");45		for ele in str.split('\n') {46			out.push('\n');47			out.push_str(48				&ele49					// '' is escaped with '50					.replace("''", "'''")51					// ${ is escaped wth ''52					.replace("${", "''${")53					// \t is not counted as whitespace for dedent54					// to avoid confusion, it is printed literally.55					//56					// ...Escaped \t literal should be prefixed with '' for... Idk, this logic is complicated.57					.replace('\t', "''\\t"),58			);59		}60		// Final newline is assumed due to str.ends_with condition61		out.push_str("''");62	} else {63		out.push_str(&escape_string(str))64	}65}6667fn write_nix_buf(value: &Value, out: &mut String) {68	match value {69		Value::Null => out.push_str("null"),70		Value::Boolean(v) => out.push_str(if *v { "true" } else { "false" }),71		Value::Number(n) => out.push_str(&format!("{}", n)),72		Value::String(s) => write_nix_str(s, out),73		Value::Array(a) => {74			if a.is_empty() {75				out.push_str("[ ]");76			} else {77				out.push('[');78				for item in a {79					write_nix_buf(item, out);80					out.push('\n');81				}82				out.push(']');83			}84		}85		Value::Object(obj) => {86			if obj.is_empty() {87				out.push_str("{ }")88			} else {89				out.push('{');90				for (k, v) in obj {91					write_nix_obj_key_buf(k, v, out);92					out.push('\n');93				}94				out.push('}');95			}96		}97	};98}99100pub fn write_nix(value: &Value) -> String {101	let mut out = String::new();102	write_nix_buf(value, &mut out);103	let (_, out) = alejandra::format::in_memory(104		"".to_owned(),105		out,106		alejandra::config::Config {107			indentation: Indentation::TwoSpaces,108		},109	);110	out111}