1 | macro_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 | } |
183 | |