#[derive(Copy, Clone)]
pub(crate) struct EscapeOptions {
pub escape_single_quote: bool,
pub escape_double_quote: bool,
pub escape_nonascii: bool,
}
pub(crate) fn escape_bytes(bytes: &[u8], opt: EscapeOptions) -> String {
let mut repr = String::new();
if opt.escape_nonascii {
for &byte in bytes {
escape_single_byte(byte, opt, &mut repr);
}
} else {
let mut chunks = bytes.utf8_chunks();
while let Some(chunk) = chunks.next() {
for ch in chunk.valid().chars() {
escape_single_char(ch, opt, &mut repr);
}
for &byte in chunk.invalid() {
escape_single_byte(byte, opt, &mut repr);
}
}
}
repr
}
fn escape_single_byte(byte: u8, opt: EscapeOptions, repr: &mut String) {
if byte == b'\0' {
repr.push_str("\\0");
} else if (byte == b'\'' && !opt.escape_single_quote)
|| (byte == b'"' && !opt.escape_double_quote)
{
repr.push(byte as char);
} else {
repr.extend(byte.escape_ascii().map(char::from));
}
}
fn escape_single_char(ch: char, opt: EscapeOptions, repr: &mut String) {
if (ch == '\'' && !opt.escape_single_quote) || (ch == '"' && !opt.escape_double_quote) {
repr.push(ch);
} else {
repr.extend(ch.escape_debug());
}
}