html_escape/decode/element/
decode_impl.rs
1macro_rules! decode_impl {
2 ($l:expr; $(#[$attr: meta])* $parse_macro:ident; $(#[$decode_attr: meta])* $decode_name: ident; $(#[$decode_to_string_attr: meta])* $decode_to_string_name: ident; $(#[$decode_to_vec_attr: meta])* $decode_to_vec_name: ident; $(#[$decode_to_writer_attr: meta])* $decode_to_writer_name: ident $(;)*) => {
3 $(#[$decode_attr])*
4 $(#[$attr])*
6 #[inline]
7 pub fn $decode_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!(e, step,
25 {
26 let mut v = Vec::with_capacity(text_length);
27
28 v.extend_from_slice(&text_bytes[..(p - ($l + 1))]);
29
30 break (v, p - $l);
31 },
32 {
33 let mut v = Vec::with_capacity(text_length);
34
35 v.extend_from_slice(&text_bytes[..(p - 1)]);
36
37 break (v, p);
38 },
39 {
40 let mut v = Vec::with_capacity(text_length);
41
42 v.extend_from_slice(&text_bytes[..(p - 3)]);
43
44 break (v, p - 2);
45 }
46 );
47
48 p += 1;
49 };
50
51 p += 1;
52
53 for e in text_bytes[p..].iter().copied() {
54 $parse_macro!(e, step,
55 {
56 v.extend_from_slice(&text_bytes[start..(p - ($l + 1))]);
57 start = p - $l;
58 },
59 {
60 v.extend_from_slice(&text_bytes[start..(p - 1)]);
61 start = p;
62 },
63 {
64 v.extend_from_slice(&text_bytes[start..(p - 3)]);
65 start = p - 2;
66 }
67 );
68
69 p += 1;
70 }
71
72 v.extend_from_slice(&text_bytes[start..p]);
73
74 Cow::from(unsafe { String::from_utf8_unchecked(v) })
75 }
76
77 $(#[$decode_to_string_attr])*
78 $(#[$attr])*
80 #[inline]
81 pub fn $decode_to_string_name<S: AsRef<str>>(text: S, output: &mut String) -> &str {
82 unsafe { from_utf8_unchecked($decode_to_vec_name(text, output.as_mut_vec())) }
83 }
84
85 $(#[$decode_to_vec_attr])*
86 $(#[$attr])*
88 #[inline]
89 pub fn $decode_to_vec_name<S: AsRef<str>>(text: S, output: &mut Vec<u8>) -> &[u8] {
90 let text = text.as_ref();
91 let text_bytes = text.as_bytes();
92 let text_length = text_bytes.len();
93
94 output.reserve(text_length);
95
96 let current_length = output.len();
97
98 let mut start = 0;
99 let mut end = 0;
100
101 let mut step = 0;
102
103 for e in text_bytes.iter().copied() {
104 $parse_macro!(e, step,
105 {
106 output.extend_from_slice(&text_bytes[start..(end - ($l + 1))]);
107 start = end - $l;
108 },
109 {
110 output.extend_from_slice(&text_bytes[start..(end - 1)]);
111 start = end;
112 },
113 {
114 output.extend_from_slice(&text_bytes[start..(end - 3)]);
115 start = end - 2;
116 }
117 );
118
119 end += 1;
120 }
121
122 output.extend_from_slice(&text_bytes[start..end]);
123
124 &output[current_length..]
125 }
126
127 #[cfg(feature = "std")]
128 $(#[$decode_to_writer_attr])*
129 $(#[$attr])*
131 #[inline]
132 pub fn $decode_to_writer_name<S: AsRef<str>, W: Write>(text: S, output: &mut W) -> Result<(), io::Error> {
133 let text = text.as_ref();
134 let text_bytes = text.as_bytes();
135
136 let mut start = 0;
137 let mut end = 0;
138
139 let mut step = 0;
140
141 for e in text_bytes.iter().copied() {
142 $parse_macro!(e, step,
143 {
144 output.write_all(&text_bytes[start..(end - ($l + 1))])?;
145 start = end - $l;
146 },
147 {
148 output.write_all(&text_bytes[start..(end - 1)])?;
149 start = end;
150 },
151 {
152 output.write_all(&text_bytes[start..(end - 3)])?;
153 start = end - 2;
154 }
155 );
156
157 end += 1;
158 }
159
160 output.write_all(&text_bytes[start..end])
161 }
162 };
163}