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        ///
5        $(#[$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        ///
88        $(#[$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        ///
96        $(#[$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        ///
144        $(#[$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}