1#![allow(non_camel_case_types)]
2
3use self::sealed::Sealed;
4use crate::{batch::Batch, InNamespace};
5
6mod sealed {
7 use crate::{Attribute, InNamespace};
8
9 pub trait Sealed {}
10
11 impl Sealed for Attribute {}
12 impl<'a> Sealed for InNamespace<'a, Attribute> {}
13 impl<'a> Sealed for &'a str {}
14 impl<'a, 'b> Sealed for InNamespace<'b, &'a str> {}
15}
16
17pub enum AnyAttribute<'a, 'b> {
18 Attribute(Attribute),
19 InNamespace(InNamespace<'a, Attribute>),
20 Str(&'a str),
21 InNamespaceStr(InNamespace<'a, &'b str>),
22}
23
24impl AnyAttribute<'_, '_> {
25 pub fn encode_u8_discriminant(&self, v: &mut Batch) {
26 match self {
27 AnyAttribute::Attribute(a) => a.encode_u8_discriminant(v),
28 AnyAttribute::InNamespace(a) => a.encode_u8_discriminant(v),
29 AnyAttribute::Str(a) => a.encode_u8_discriminant(v),
30 AnyAttribute::InNamespaceStr(a) => a.encode_u8_discriminant(v),
31 }
32 }
33}
34
35pub trait IntoAttribue<'a, 'b>: Sealed + Into<AnyAttribute<'a, 'b>> {
37 const SINGLE_BYTE: bool = false;
39
40 fn encode(self, v: &mut Batch);
42
43 unsafe fn encode_prealloc(self, v: &mut Batch)
48 where
49 Self: Sized,
50 {
51 self.encode(v);
52 }
53
54 fn encode_u8_discriminant(&self, v: &mut Batch);
56}
57
58impl<'a, 'b> Attribute {
59 pub const fn any_attr_const(self) -> AnyAttribute<'a, 'b> {
61 AnyAttribute::Attribute(self)
62 }
63}
64
65impl<'a, 'b> IntoAttribue<'a, 'b> for Attribute {
66 const SINGLE_BYTE: bool = true;
67
68 #[inline(always)]
69 fn encode(self, v: &mut Batch) {
70 v.encode_bool(false);
71 v.encode_bool(false);
72 v.msg.push(self as u8);
73 }
74
75 #[inline(always)]
76 unsafe fn encode_prealloc(self, v: &mut Batch) {
77 v.encode_bool(false);
78 v.encode_bool(false);
79 unsafe {
80 let ptr: *mut u8 = v.msg.as_mut_ptr();
81 *ptr.add(v.msg.len()) = self as u8;
82 v.msg.set_len(v.msg.len() + 1);
83 }
84 }
85
86 fn encode_u8_discriminant(&self, v: &mut Batch) {
87 v.msg.push(*self as u8)
88 }
89}
90
91impl<'a, 'b> From<Attribute> for AnyAttribute<'a, 'b> {
92 fn from(a: Attribute) -> Self {
93 AnyAttribute::Attribute(a)
94 }
95}
96
97impl<'a, 'b> InNamespace<'a, Attribute> {
98 pub const fn any_attr_const(self) -> AnyAttribute<'a, 'b> {
99 AnyAttribute::InNamespace(self)
100 }
101}
102
103impl<'a, 'b> IntoAttribue<'a, 'b> for InNamespace<'a, Attribute> {
104 fn encode(self, v: &mut Batch) {
105 v.encode_bool(false);
106 v.msg.push(self.0 as u8);
107 v.encode_bool(true);
108 v.encode_str(self.1);
109 }
110
111 fn encode_u8_discriminant(&self, v: &mut Batch) {
112 v.msg.push(255);
113 v.msg.push(self.0 as u8);
114 v.encode_str(self.1);
115 }
116}
117
118impl<'a, 'b> From<InNamespace<'a, Attribute>> for AnyAttribute<'a, 'b> {
119 fn from(a: InNamespace<'a, Attribute>) -> Self {
120 AnyAttribute::InNamespace(a)
121 }
122}
123
124impl<'a, 'b> IntoAttribue<'a, 'b> for &'a str {
125 fn encode(self, v: &mut Batch) {
126 v.encode_bool(true);
127 v.encode_cachable_str(self);
128 v.encode_bool(false);
129 }
130
131 fn encode_u8_discriminant(&self, v: &mut Batch) {
132 v.msg.push(254);
133 v.encode_cachable_str(*self);
134 }
135}
136
137impl<'a, 'b> From<&'a str> for AnyAttribute<'a, 'b> {
138 fn from(a: &'a str) -> Self {
139 AnyAttribute::Str(a)
140 }
141}
142
143impl<'a, 'b> InNamespace<'a, &'b str> {
144 pub const fn any_attr_const(self) -> AnyAttribute<'a, 'b> {
145 AnyAttribute::InNamespaceStr(self)
146 }
147}
148
149impl<'a, 'b> IntoAttribue<'a, 'b> for InNamespace<'a, &'b str> {
150 fn encode(self, v: &mut Batch) {
151 v.encode_bool(true);
152 v.encode_cachable_str(self.0);
153 v.encode_bool(true);
154 v.encode_cachable_str(self.1);
155 }
156
157 fn encode_u8_discriminant(&self, v: &mut Batch) {
158 v.msg.push(253);
159 v.encode_cachable_str(self.0);
160 v.encode_cachable_str(self.1);
161 }
162}
163
164impl<'a, 'b> From<InNamespace<'a, &'b str>> for AnyAttribute<'a, 'b> {
165 fn from(a: InNamespace<'a, &'b str>) -> Self {
166 AnyAttribute::InNamespaceStr(a)
167 }
168}
169
170#[derive(Copy, Clone)]
173pub enum Attribute {
174 accept_charset,
175 accept,
176 accesskey,
177 action,
178 align,
179 allow,
180 alt,
181 aria_atomic,
182 aria_busy,
183 aria_controls,
184 aria_current,
185 aria_describedby,
186 aria_description,
187 aria_details,
188 aria_disabled,
189 aria_dropeffect,
190 aria_errormessage,
191 aria_flowto,
192 aria_grabbed,
193 aria_haspopup,
194 aria_hidden,
195 aria_invalid,
196 aria_keyshortcuts,
197 aria_label,
198 aria_labelledby,
199 aria_live,
200 aria_owns,
201 aria_relevant,
202 aria_roledescription,
203 r#async,
204 autocapitalize,
205 autocomplete,
206 autofocus,
207 autoplay,
208 background,
209 bgcolor,
210 border,
211 buffered,
212 capture,
213 challenge,
214 charset,
215 checked,
216 cite,
217 class,
218 code,
219 codebase,
220 color,
221 cols,
222 colspan,
223 content,
224 contenteditable,
225 contextmenu,
226 controls,
227 coords,
228 crossorigin,
229 csp,
230 data,
231 datetime,
232 decoding,
233 default,
234 defer,
235 dir,
236 dirname,
237 disabled,
238 download,
239 draggable,
240 enctype,
241 enterkeyhint,
242 r#for,
243 form,
244 formaction,
245 formenctype,
246 formmethod,
247 formnovalidate,
248 formtarget,
249 headers,
250 height,
251 hidden,
252 high,
253 href,
254 hreflang,
255 http_equiv,
256 icon,
257 id,
258 importance,
259 inputmode,
260 integrity,
261 intrinsicsize,
262 ismap,
263 itemprop,
264 keytype,
265 kind,
266 label,
267 lang,
268 language,
269 list,
270 loading,
271 r#loop,
272 low,
273 manifest,
274 max,
275 maxlength,
276 media,
277 method,
278 min,
279 minlength,
280 multiple,
281 muted,
282 name,
283 novalidate,
284 open,
285 optimum,
286 pattern,
287 ping,
288 placeholder,
289 poster,
290 preload,
291 radiogroup,
292 readonly,
293 referrerpolicy,
294 rel,
295 required,
296 reversed,
297 role,
298 rows,
299 rowspan,
300 sandbox,
301 scope,
302 scoped,
303 selected,
304 shape,
305 size,
306 sizes,
307 slot,
308 span,
309 spellcheck,
310 src,
311 srcdoc,
312 srclang,
313 srcset,
314 start,
315 step,
316 style,
317 summary,
318 tabindex,
319 target,
320 title,
321 translate,
322 r#type,
323 usemap,
324 value,
325 width,
326 wrap,
327}