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        ///
5        $(#[$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        ///
79        $(#[$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        ///
87        $(#[$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        ///
130        $(#[$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}