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

difftreelog

source

crates/nixlike/src/to_string.rs2.9 KiBsourcehistory
1use crate::Value;23pub fn write_identifier(k: &str, out: &mut String) {4	if k.contains(['.', '\'', '\"', '\\', '\n', '\t', '\r', '$']) {5		write_nix_str_singleline(k, out);6	} else {7		out.push_str(k);8	}9}1011fn write_nix_obj_key_buf(k: &str, v: &Value, out: &mut String, padding: &mut usize) {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, padding);19		}20		v => {21			out.push_str(" = ");22			write_nix_buf(v, out, padding);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}3940fn write_padding(out: &mut String, padding: &usize) {41	for _ in 0..*padding {42		out.push_str("  ");43	}44}4546pub fn write_nix_str_singleline(str: &str, out: &mut String) {47	out.push_str(&escape_string(str))48}49pub fn write_nix_str(str: &str, out: &mut String, padding: &mut usize) {50	if str.ends_with('\n') {51		out.push_str("''");52		*padding += 1;53		for ele in str[0..str.len() - 1].split('\n') {54			out.push('\n');55			write_padding(out, padding);56			out.push_str(57				&ele58					// '' is escaped with '59					.replace("''", "'''")60					// ${ is escaped wth ''61					.replace("${", "''${")62					// \t is not counted as whitespace for dedent63					// to avoid confusion, it is printed literally.64					//65					// ...Escaped \t literal should be prefixed with '' for... Idk, this logic is complicated.66					.replace('\t', "''\\t"),67			);68		}69		out.push('\n');70		*padding -= 1;71		write_padding(out, padding);72		// Final newline is assumed due to str.ends_with condition73		out.push_str("''");74	} else {75		write_nix_str_singleline(str, out);76	}77}7879fn write_nix_buf(value: &Value, out: &mut String, padding: &mut usize) {80	match value {81		Value::Null => out.push_str("null"),82		Value::Boolean(v) => out.push_str(if *v { "true" } else { "false" }),83		Value::Number(n) => out.push_str(&format!("{n}")),84		Value::String(s) => write_nix_str(s, out, padding),85		Value::Array(a) => {86			if a.is_empty() {87				out.push_str("[ ]");88			} else {89				out.push_str("[\n");90				*padding += 1;91				for item in a {92					write_padding(out, padding);93					write_nix_buf(item, out, padding);94					out.push('\n');95				}96				*padding -= 1;97				write_padding(out, padding);98				out.push(']');99			}100		}101		Value::Object(obj) => {102			if obj.is_empty() {103				out.push_str("{ }")104			} else {105				out.push_str("{\n");106				*padding += 1;107				for (k, v) in obj {108					write_padding(out, padding);109					write_nix_obj_key_buf(k, v, out, padding);110					out.push('\n');111				}112				*padding -= 1;113				write_padding(out, padding);114				out.push('}');115			}116		}117	};118}119120pub fn write_nix(value: &Value) -> String {121	let mut out = String::new();122	write_nix_buf(value, &mut out, &mut 0);123	out124}