escape_bytes_to(bytes: &[u8], buf: &mut String)1 pub fn escape_bytes_to(bytes: &[u8], buf: &mut String) {
2     for &c in bytes {
3         match c {
4             b'\n' => buf.push_str(r"\n"),
5             b'\r' => buf.push_str(r"\r"),
6             b'\t' => buf.push_str(r"\t"),
7             b'\'' => buf.push_str("\\\'"),
8             b'"' => buf.push_str("\\\""),
9             b'\\' => buf.push_str(r"\\"),
10             b'\x20'..=b'\x7e' => buf.push(c as char),
11             _ => {
12                 buf.push('\\');
13                 buf.push((b'0' + (c >> 6)) as char);
14                 buf.push((b'0' + ((c >> 3) & 7)) as char);
15                 buf.push((b'0' + (c & 7)) as char);
16             }
17         }
18     }
19 }
20 
quote_bytes_to(bytes: &[u8], buf: &mut String)21 pub fn quote_bytes_to(bytes: &[u8], buf: &mut String) {
22     buf.push('"');
23     escape_bytes_to(bytes, buf);
24     buf.push('"');
25 }
26 
27 #[cfg(test)]
28 mod test {
29     use crate::lexer::str_lit::StrLit;
30     use crate::text_format::escape_bytes_to;
31 
escape(data: &[u8]) -> String32     fn escape(data: &[u8]) -> String {
33         let mut s = String::with_capacity(data.len() * 4);
34         escape_bytes_to(data, &mut s);
35         s
36     }
37 
unescape_string(escaped: &str) -> Vec<u8>38     fn unescape_string(escaped: &str) -> Vec<u8> {
39         StrLit {
40             escaped: escaped.to_owned(),
41         }
42         .decode_bytes()
43         .expect("decode_bytes")
44     }
45 
test_escape_unescape(text: &str, escaped: &str)46     fn test_escape_unescape(text: &str, escaped: &str) {
47         assert_eq!(text.as_bytes(), &unescape_string(escaped)[..]);
48         assert_eq!(escaped, &escape(text.as_bytes())[..]);
49     }
50 
51     #[test]
test_print_to_bytes()52     fn test_print_to_bytes() {
53         assert_eq!("ab", escape(b"ab"));
54         assert_eq!("a\\\\023", escape(b"a\\023"));
55         assert_eq!("a\\r\\n\\t \\'\\\"\\\\", escape(b"a\r\n\t '\"\\"));
56         assert_eq!("\\344\\275\\240\\345\\245\\275", escape("你好".as_bytes()));
57     }
58 
59     #[test]
60     fn test_unescape_string() {
61         test_escape_unescape("", "");
62         test_escape_unescape("aa", "aa");
63         test_escape_unescape("\n", "\\n");
64         test_escape_unescape("\r", "\\r");
65         test_escape_unescape("\t", "\\t");
66         test_escape_unescape("你好", "\\344\\275\\240\\345\\245\\275");
67         // hex
68         assert_eq!(b"aaa\x01bbb", &unescape_string("aaa\\x01bbb")[..]);
69         assert_eq!(b"aaa\xcdbbb", &unescape_string("aaa\\xCDbbb")[..]);
70         assert_eq!(b"aaa\xcdbbb", &unescape_string("aaa\\xCDbbb")[..]);
71         // quotes
72         assert_eq!(b"aaa\"bbb", &unescape_string("aaa\\\"bbb")[..]);
73         assert_eq!(b"aaa\'bbb", &unescape_string("aaa\\\'bbb")[..]);
74     }
75 }
76