1use std::ascii;
18
19pub fn escape_string(unescaped: &str) -> String {
21 let mut escaped = String::with_capacity(unescaped.len());
22 escape_string_to_buf(&mut escaped, unescaped);
23 escaped
24}
25
26pub fn format_string(unescaped: &str) -> String {
28 let mut escaped = String::with_capacity(unescaped.len() + 2);
29 escaped.push('"');
30 escape_string_to_buf(&mut escaped, unescaped);
31 escaped.push('"');
32 escaped
33}
34
35fn escape_string_to_buf(escaped: &mut String, unescaped: &str) {
36 for c in unescaped.chars() {
37 match c {
38 '"' => escaped.push_str(r#"\""#),
39 '\\' => escaped.push_str(r#"\\"#),
40 '\t' => escaped.push_str(r#"\t"#),
41 '\r' => escaped.push_str(r#"\r"#),
42 '\n' => escaped.push_str(r#"\n"#),
43 '\0' => escaped.push_str(r#"\0"#),
44 c if c.is_ascii_control() => {
45 for b in ascii::escape_default(c as u8) {
46 escaped.push(b as char);
47 }
48 }
49 c => escaped.push(c),
50 }
51 }
52}
53
54pub fn unescape_char(escaped: &str) -> char {
56 assert!(escaped.starts_with('\\'));
57 match &escaped[1..] {
58 "\"" => '"',
59 "\\" => '\\',
60 "t" => '\t',
61 "r" => '\r',
62 "n" => '\n',
63 "0" => '\0',
64 "e" => '\x1b',
65 hex if hex.starts_with('x') => {
66 char::from(u8::from_str_radix(&hex[1..], 16).expect("hex characters"))
67 }
68 char => panic!("invalid escape: \\{char:?}"),
69 }
70}