pub(crate) fn escape(s: &str) -> String {
let mut out = String::with_capacity(s.len() + 2);
out.push('"');
for c in s.chars() {
match c {
'"' => out.push_str("\\\""),
'\\' => out.push_str("\\\\"),
'\n' => out.push_str("\\n"),
'\r' => out.push_str("\\r"),
'\t' => out.push_str("\\t"),
c if (c as u32) < 0x20 => out.push_str(&format!("\\u{:04x}", c as u32)),
c => out.push(c),
}
}
out.push('"');
out
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn escapes_mandatory_and_control_chars() {
assert_eq!(escape("a\"b\\c"), "\"a\\\"b\\\\c\"");
assert_eq!(escape("line\nbreak\ttab"), "\"line\\nbreak\\ttab\"");
assert_eq!(escape("\u{0001}"), "\"\\u0001\"");
assert_eq!(escape("café"), "\"café\"");
}
}