1#![allow(non_camel_case_types)]
2
3use crate::{attribute::AnyAttribute, batch::Batch, InNamespace, NodeId};
4
5use self::sealed::Sealed;
6
7mod sealed {
8 use crate::{Element, InNamespace};
9
10 pub trait Sealed {}
11
12 impl Sealed for Element {}
13 impl<'a> Sealed for &'a str {}
14 impl<'a> Sealed for InNamespace<'a, Element> {}
15 impl<'a, 'b> Sealed for InNamespace<'a, &'b str> {}
16}
17
18pub enum AnyElement<'a, 'b> {
19 Element(Element),
20 InNamespace(InNamespace<'a, Element>),
21 Str(&'a str),
22 InNamespaceStr(InNamespace<'a, &'b str>),
23}
24
25impl AnyElement<'_, '_> {
26 pub fn encode(&self, v: &mut Batch) {
27 match self {
28 AnyElement::Element(a) => a.encode(v),
29 AnyElement::InNamespace(a) => a.encode(v),
30 AnyElement::Str(a) => a.encode(v),
31 AnyElement::InNamespaceStr(a) => a.encode(v),
32 }
33 }
34}
35
36pub trait IntoElement<'a, 'b>: Sealed + Into<AnyElement<'a, 'b>> {
38 const SINGLE_BYTE: bool = false;
40
41 fn encode(&self, v: &mut Batch);
43
44 unsafe fn encode_prealloc(&self, v: &mut Batch)
49 where
50 Self: Sized,
51 {
52 self.encode(v);
53 }
54}
55
56impl<'a, 'b> Element {
57 pub const fn any_element_const(self) -> AnyElement<'a, 'b> {
58 AnyElement::Element(self)
59 }
60}
61
62impl<'a, 'b> IntoElement<'a, 'b> for Element {
63 const SINGLE_BYTE: bool = true;
64
65 #[inline(always)]
66 fn encode(&self, v: &mut Batch) {
67 v.msg.push(*self as u8);
68 }
69
70 #[inline(always)]
71 unsafe fn encode_prealloc(&self, v: &mut Batch)
72 where
73 Self: Sized,
74 {
75 unsafe {
76 let ptr: *mut u8 = v.msg.as_mut_ptr();
77 let old_len = v.msg.len();
78 *ptr.add(old_len) = *self as u8;
79 v.msg.set_len(old_len + 1);
80 }
81 }
82}
83
84impl<'a, 'b> From<Element> for AnyElement<'a, 'b> {
85 fn from(e: Element) -> Self {
86 AnyElement::Element(e)
87 }
88}
89
90impl<'a, 'b> InNamespace<'a, Element> {
91 pub const fn any_element_const(self) -> AnyElement<'a, 'b> {
93 AnyElement::InNamespace(self)
94 }
95}
96
97impl<'a, 'b> IntoElement<'a, 'b> for InNamespace<'a, Element> {
98 fn encode(&self, v: &mut Batch) {
99 v.msg.push(255);
100 v.msg.push(self.0 as u8);
101 v.encode_str(self.1);
102 }
103}
104
105impl<'a, 'b> From<InNamespace<'a, Element>> for AnyElement<'a, 'b> {
106 fn from(e: InNamespace<'a, Element>) -> Self {
107 AnyElement::InNamespace(e)
108 }
109}
110
111impl<'a, 'b> IntoElement<'a, 'b> for &'a str {
112 fn encode(&self, v: &mut Batch) {
113 v.msg.push(254);
114 v.encode_str(*self);
115 }
116}
117
118impl<'a, 'b> From<&'a str> for AnyElement<'a, 'b> {
119 fn from(e: &'a str) -> Self {
120 AnyElement::Str(e)
121 }
122}
123
124impl<'a, 'b> IntoElement<'a, 'b> for InNamespace<'a, &'b str> {
125 fn encode(&self, v: &mut Batch) {
126 v.msg.push(253);
127 v.encode_str(self.0);
128 v.encode_str(self.1);
129 }
130}
131
132impl<'a, 'b> From<InNamespace<'a, &'b str>> for AnyElement<'a, 'b> {
133 fn from(e: InNamespace<'a, &'b str>) -> Self {
134 AnyElement::InNamespaceStr(e)
135 }
136}
137
138impl<'a, 'b> InNamespace<'a, &'b str> {
139 pub const fn any_element_const(self) -> AnyElement<'a, 'b> {
140 AnyElement::InNamespaceStr(self)
141 }
142}
143
144pub enum NodeBuilder<'a> {
146 Text(TextBuilder<'a>),
147 Element(ElementBuilder<'a>),
148}
149
150impl NodeBuilder<'_> {
151 pub(crate) fn encode(&self, v: &mut Batch) {
153 match self {
154 NodeBuilder::Text(t) => t.encode(v),
155 NodeBuilder::Element(e) => e.encode(v),
156 }
157 }
158}
159
160impl<'a> From<TextBuilder<'a>> for NodeBuilder<'a> {
161 fn from(t: TextBuilder<'a>) -> Self {
162 NodeBuilder::Text(t)
163 }
164}
165
166impl<'a> From<ElementBuilder<'a>> for NodeBuilder<'a> {
167 fn from(e: ElementBuilder<'a>) -> Self {
168 NodeBuilder::Element(e)
169 }
170}
171
172pub struct TextBuilder<'a> {
174 id: Option<NodeId>,
175 text: &'a str,
176}
177
178impl<'a> TextBuilder<'a> {
179 pub const fn new(text: &'a str) -> Self {
181 Self { id: None, text }
182 }
183
184 pub const fn id(mut self, id: NodeId) -> Self {
186 self.id = Some(id);
187 self
188 }
189
190 pub(crate) fn encode(&self, v: &mut Batch) {
192 match self.id {
193 Some(id) => {
194 v.msg.push(3);
195 v.encode_id(id);
196 }
197 None => {
198 v.msg.push(2);
199 }
200 }
201 v.encode_str(self.text);
202 }
203}
204
205pub struct ElementBuilder<'a> {
225 id: Option<NodeId>,
226 kind: AnyElement<'a, 'a>,
227 attrs: &'a [(AnyAttribute<'a, 'a>, &'a str)],
228 children: &'a [NodeBuilder<'a>],
229}
230
231impl<'a> ElementBuilder<'a> {
232 pub const fn new(kind: AnyElement<'a, 'a>) -> Self {
234 Self {
235 id: None,
236 kind,
237 attrs: &[],
238 children: &[],
239 }
240 }
241
242 pub const fn id(mut self, id: NodeId) -> Self {
244 self.id = Some(id);
245 self
246 }
247
248 pub const fn attrs(mut self, attrs: &'a [(AnyAttribute<'a, 'a>, &'a str)]) -> Self {
250 self.attrs = attrs;
251 self
252 }
253
254 pub const fn children(mut self, children: &'a [NodeBuilder<'a>]) -> Self {
256 self.children = children;
257 self
258 }
259
260 pub(crate) fn encode(&self, v: &mut Batch) {
262 match self.id {
263 Some(id) => {
264 v.msg.push(1);
265 v.encode_id(id);
266 }
267 None => {
268 v.msg.push(0);
269 }
270 }
271 self.kind.encode(v);
272 v.msg.push(self.attrs.len() as u8);
274 v.msg.push(self.children.len() as u8);
275 for (attr, value) in self.attrs {
276 attr.encode_u8_discriminant(v);
277 v.encode_str(*value);
278 }
279 for child in self.children {
280 child.encode(v);
281 }
282 }
283}
284
285#[allow(unused)]
288#[derive(Copy, Clone)]
289pub enum Element {
290 a,
291 abbr,
292 acronym,
293 address,
294 applet,
295 area,
296 article,
297 aside,
298 audio,
299 b,
300 base,
301 bdi,
302 bdo,
303 bgsound,
304 big,
305 blink,
306 blockquote,
307 body,
308 br,
309 button,
310 canvas,
311 caption,
312 center,
313 cite,
314 code,
315 col,
316 colgroup,
317 content,
318 data,
319 datalist,
320 dd,
321 del,
322 details,
323 dfn,
324 dialog,
325 dir,
326 div,
327 dl,
328 dt,
329 em,
330 embed,
331 fieldset,
332 figcaption,
333 figure,
334 font,
335 footer,
336 form,
337 frame,
338 frameset,
339 h1,
340 head,
341 header,
342 hgroup,
343 hr,
344 html,
345 i,
346 iframe,
347 image,
348 img,
349 input,
350 ins,
351 kbd,
352 keygen,
353 label,
354 legend,
355 li,
356 link,
357 main,
358 map,
359 mark,
360 marquee,
361 menu,
362 menuitem,
363 meta,
364 meter,
365 nav,
366 nobr,
367 noembed,
368 noframes,
369 noscript,
370 object,
371 ol,
372 optgroup,
373 option,
374 output,
375 p,
376 param,
377 picture,
378 plaintext,
379 portal,
380 pre,
381 progress,
382 q,
383 rb,
384 rp,
385 rt,
386 rtc,
387 ruby,
388 s,
389 samp,
390 script,
391 section,
392 select,
393 shadow,
394 slot,
395 small,
396 source,
397 spacer,
398 span,
399 strike,
400 strong,
401 style,
402 sub,
403 summary,
404 sup,
405 table,
406 tbody,
407 td,
408 template,
409 textarea,
410 tfoot,
411 th,
412 thead,
413 time,
414 title,
415 tr,
416 track,
417 tt,
418 u,
419 ul,
420 var,
421 video,
422 wbr,
423 xmp,
424}