1#[inline]
2pub fn escape_generic<S: AsRef<str>>(s: S) -> String {
3 let s = s.as_ref();
4 let bytes = s.as_bytes();
5 let estimated_capacity = bytes.len() + bytes.len() / 2 + 2;
8 let mut result = Vec::with_capacity(estimated_capacity);
9 result.push(b'"');
10 escape_inner(bytes, &mut result);
11 result.push(b'"');
12 unsafe { String::from_utf8_unchecked(result) }
14}
15
16#[inline]
17pub fn escape_into_generic<S: AsRef<str>>(s: S, output: &mut Vec<u8>) {
18 let s = s.as_ref();
19 let bytes = s.as_bytes();
20 output.push(b'"');
21 escape_inner(bytes, output);
22 output.push(b'"');
23}
24
25#[inline]
26pub(crate) fn escape_inner(bytes: &[u8], result: &mut Vec<u8>) {
31 let mut start = 0;
32 let mut i = 0;
33
34 while i < bytes.len() {
35 let b = bytes[i];
36
37 let escape_byte = ESCAPE[b as usize];
39
40 if escape_byte == 0 {
41 i += 1;
43 continue;
44 }
45
46 if start < i {
48 result.extend_from_slice(&bytes[start..i]);
49 }
50
51 result.push(b'\\');
53 if escape_byte == b'u' {
54 result.extend_from_slice(b"u00");
56 let hex_digits = &HEX_BYTES[b as usize];
57 result.push(hex_digits.0);
58 result.push(hex_digits.1);
59 } else {
60 result.push(escape_byte);
62 }
63
64 i += 1;
65 start = i;
66 }
67
68 if start < bytes.len() {
70 result.extend_from_slice(&bytes[start..]);
71 }
72}
73
74const BB: u8 = b'b'; const TT: u8 = b't'; const NN: u8 = b'n'; const FF: u8 = b'f'; const RR: u8 = b'r'; const QU: u8 = b'"'; const BS: u8 = b'\\'; pub(crate) const UU: u8 = b'u'; const __: u8 = 0;
83
84pub(crate) static ESCAPE: [u8; 256] = [
87 UU, UU, UU, UU, UU, UU, UU, UU, BB, TT, NN, UU, FF, RR, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, __, __, QU, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, BS, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, ];
105
106pub(crate) struct HexPair(pub(crate) u8, pub(crate) u8);
108
109pub(crate) static HEX_BYTES: [HexPair; 32] = [
110 HexPair(b'0', b'0'),
111 HexPair(b'0', b'1'),
112 HexPair(b'0', b'2'),
113 HexPair(b'0', b'3'),
114 HexPair(b'0', b'4'),
115 HexPair(b'0', b'5'),
116 HexPair(b'0', b'6'),
117 HexPair(b'0', b'7'),
118 HexPair(b'0', b'8'),
119 HexPair(b'0', b'9'),
120 HexPair(b'0', b'a'),
121 HexPair(b'0', b'b'),
122 HexPair(b'0', b'c'),
123 HexPair(b'0', b'd'),
124 HexPair(b'0', b'e'),
125 HexPair(b'0', b'f'),
126 HexPair(b'1', b'0'),
127 HexPair(b'1', b'1'),
128 HexPair(b'1', b'2'),
129 HexPair(b'1', b'3'),
130 HexPair(b'1', b'4'),
131 HexPair(b'1', b'5'),
132 HexPair(b'1', b'6'),
133 HexPair(b'1', b'7'),
134 HexPair(b'1', b'8'),
135 HexPair(b'1', b'9'),
136 HexPair(b'1', b'a'),
137 HexPair(b'1', b'b'),
138 HexPair(b'1', b'c'),
139 HexPair(b'1', b'd'),
140 HexPair(b'1', b'e'),
141 HexPair(b'1', b'f'),
142];