html_escape/encode/element/
encode_impl.rs
1macro_rules! encode_impl {
2 ($l:expr; $(#[$attr: meta])* $parse_macro:ident; $(#[$encode_attr: meta])* $encode_name: ident; $(#[$encode_to_string_attr: meta])* $encode_to_string_name: ident; $(#[$encode_to_vec_attr: meta])* $encode_to_vec_name: ident; $(#[$encode_to_writer_attr: meta])* $encode_to_writer_name: ident $(;)*) => {
3 $(#[$encode_attr])*
4 $(#[$attr])*
6 #[inline]
7 pub fn $encode_name<S: ?Sized + AsRef<str>>(text: &S) -> Cow<str> {
8 let text = text.as_ref();
9 let text_bytes = text.as_bytes();
10 let text_length = text_bytes.len();
11
12 let mut p = 0;
13 let mut e;
14
15 let mut step = 0;
16
17 let (mut v, mut start) = loop {
18 if p == text_length {
19 return Cow::from(text);
20 }
21
22 e = text_bytes[p];
23
24 $parse_macro!(
25 e,
26 step,
27 {
28 let mut v = Vec::with_capacity(text_length + 1);
29
30 v.extend_from_slice(&text_bytes[..(p - $l)]);
31
32 break (v, p - $l);
33 },
34 {
35 let mut v = Vec::with_capacity(text_length + 1);
36
37 v.extend_from_slice(&text_bytes[..p]);
38
39 break (v, p);
40 },
41 {
42 let mut v = Vec::with_capacity(text_length + 1);
43
44 v.extend_from_slice(&text_bytes[..(p - 2)]);
45
46 break (v, p - 2);
47 }
48 );
49
50 p += 1;
51 };
52
53 v.push(b'\\');
54
55 p += 1;
56
57 for e in text_bytes[p..].iter().copied() {
58 $parse_macro!(
59 e,
60 step,
61 {
62 v.extend_from_slice(&text_bytes[start..(p - $l)]);
63 start = p - $l;
64 v.push(b'\\');
65 },
66 {
67 v.extend_from_slice(&text_bytes[start..p]);
68 start = p;
69 v.push(b'\\');
70 },
71 {
72 v.extend_from_slice(&text_bytes[start..(p - 2)]);
73 start = p - 2;
74 v.push(b'\\');
75 }
76 );
77
78 p += 1;
79 }
80
81 v.extend_from_slice(&text_bytes[start..p]);
82
83 Cow::from(unsafe { String::from_utf8_unchecked(v) })
84 }
85
86 $(#[$encode_to_string_attr])*
87 $(#[$attr])*
89 #[inline]
90 pub fn $encode_to_string_name<S: AsRef<str>>(text: S, output: &mut String) -> &str {
91 unsafe { from_utf8_unchecked($encode_to_vec_name(text, output.as_mut_vec())) }
92 }
93
94 $(#[$encode_to_vec_attr])*
95 $(#[$attr])*
97 #[inline]
98 pub fn $encode_to_vec_name<S: AsRef<str>>(text: S, output: &mut Vec<u8>) -> &[u8] {
99 let text = text.as_ref();
100 let text_bytes = text.as_bytes();
101 let text_length = text_bytes.len();
102
103 output.reserve(text_length);
104
105 let current_length = output.len();
106
107 let mut start = 0;
108 let mut end = 0;
109
110 let mut step = 0;
111
112 for e in text_bytes.iter().copied() {
113 $parse_macro!(
114 e,
115 step,
116 {
117 output.extend_from_slice(&text_bytes[start..(end - $l)]);
118 start = end - $l;
119 output.push(b'\\');
120 },
121 {
122 output.extend_from_slice(&text_bytes[start..end]);
123 start = end;
124 output.push(b'\\');
125 },
126 {
127 output.extend_from_slice(&text_bytes[start..(end - 2)]);
128 start = end - 2;
129 output.push(b'\\');
130 }
131 );
132
133 end += 1;
134 }
135
136 output.extend_from_slice(&text_bytes[start..end]);
137
138 &output[current_length..]
139 }
140
141 #[cfg(feature = "std")]
142 $(#[$encode_to_writer_attr])*
143 $(#[$attr])*
145 #[inline]
146 pub fn $encode_to_writer_name<S: AsRef<str>, W: Write>(text: S, output: &mut W) -> Result<(), io::Error> {
147 let text = text.as_ref();
148 let text_bytes = text.as_bytes();
149
150 let mut start = 0;
151 let mut end = 0;
152
153 let mut step = 0;
154
155 for e in text_bytes.iter().copied() {
156 $parse_macro!(
157 e,
158 step,
159 {
160 output.write_all(&text_bytes[start..(end - $l)])?;
161 start = end - $l;
162 output.write_all(b"\\")?;
163 },
164 {
165 output.write_all(&text_bytes[start..end])?;
166 start = end;
167 output.write_all(b"\\")?;
168 },
169 {
170 output.write_all(&text_bytes[start..(end - 2)])?;
171 start = end - 2;
172 output.write_all(b"\\")?;
173 }
174 );
175
176 end += 1;
177 }
178
179 output.write_all(&text_bytes[start..end])
180 }
181 };
182}