proc_macro/
escape.rs
1#[derive(Copy, Clone)]
2pub(crate) struct EscapeOptions {
3 pub escape_single_quote: bool,
5 pub escape_double_quote: bool,
7 pub escape_nonascii: bool,
10}
11
12pub(crate) fn escape_bytes(bytes: &[u8], opt: EscapeOptions) -> String {
13 let mut repr = String::new();
14
15 if opt.escape_nonascii {
16 for &byte in bytes {
17 escape_single_byte(byte, opt, &mut repr);
18 }
19 } else {
20 let mut chunks = bytes.utf8_chunks();
21 while let Some(chunk) = chunks.next() {
22 for ch in chunk.valid().chars() {
23 escape_single_char(ch, opt, &mut repr);
24 }
25 for &byte in chunk.invalid() {
26 escape_single_byte(byte, opt, &mut repr);
27 }
28 }
29 }
30
31 repr
32}
33
34fn escape_single_byte(byte: u8, opt: EscapeOptions, repr: &mut String) {
35 if byte == b'\0' {
36 repr.push_str("\\0");
37 } else if (byte == b'\'' && !opt.escape_single_quote)
38 || (byte == b'"' && !opt.escape_double_quote)
39 {
40 repr.push(byte as char);
41 } else {
42 repr.extend(byte.escape_ascii().map(char::from));
45 }
46}
47
48fn escape_single_char(ch: char, opt: EscapeOptions, repr: &mut String) {
49 if (ch == '\'' && !opt.escape_single_quote) || (ch == '"' && !opt.escape_double_quote) {
50 repr.push(ch);
51 } else {
52 repr.extend(ch.escape_debug());
56 }
57}