diff --git a/nix-js/src/value.rs b/nix-js/src/value.rs index e385b14..25f49b8 100644 --- a/nix-js/src/value.rs +++ b/nix-js/src/value.rs @@ -35,7 +35,7 @@ impl Display for Symbol { if self.normal() { write!(f, "{}", self.0) } else { - write!(f, r#""{}""#, self.0) + write!(f, "{}", escape_quote_string(&self.0)) } } } @@ -221,6 +221,25 @@ pub enum Value { Repeated, } +fn escape_quote_string(s: &str) -> String { + let mut ret = String::with_capacity(s.len() + 2); + ret.push('"'); + let mut iter = s.chars().peekable(); + while let Some(c) = iter.next() { + match c { + '\\' => ret.push_str("\\\\"), + '"' => ret.push_str("\\\""), + '\n' => ret.push_str("\\n"), + '\r' => ret.push_str("\\r"), + '\t' => ret.push_str("\\t"), + '$' if iter.peek() == Some(&'{') => ret.push_str("\\$"), + c => ret.push(c), + } + } + ret.push('"'); + ret +} + impl Display for Value { fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { use Value::*; @@ -229,20 +248,7 @@ impl Display for Value { &Float(x) => write!(f, "{x}"), &Bool(x) => write!(f, "{x}"), Null => write!(f, "null"), - String(x) => { - write!(f, "\"")?; - for c in x.chars() { - match c { - '\\' => write!(f, "\\\\")?, - '"' => write!(f, "\\\"")?, - '\n' => write!(f, "\\n")?, - '\r' => write!(f, "\\r")?, - '\t' => write!(f, "\\t")?, - c => write!(f, "{c}")?, - } - } - write!(f, "\"") - } + String(x) => write!(f, "{}", escape_quote_string(x)), Path(x) => write!(f, "{x}"), AttrSet(x) => write!(f, "{x}"), List(x) => write!(f, "{x}"), @@ -271,20 +277,7 @@ impl Display for ValueCompatDisplay<'_> { &Float(x) => write!(f, "{x}"), &Bool(x) => write!(f, "{x}"), Null => write!(f, "null"), - String(x) => { - write!(f, "\"")?; - for c in x.chars() { - match c { - '\\' => write!(f, "\\\\")?, - '"' => write!(f, "\\\"")?, - '\n' => write!(f, "\\n")?, - '\r' => write!(f, "\\r")?, - '\t' => write!(f, "\\t")?, - c => write!(f, "{c}")?, - } - } - write!(f, "\"") - } + String(x) => write!(f, "{}", escape_quote_string(x)), Path(x) => write!(f, "{x}"), AttrSet(x) => write!(f, "{}", x.display_compat()), List(x) => write!(f, "{}", x.display_compat()),