1use alloc::string::String;
4use alloc::vec::Vec;
5use core::fmt;
6use core::ops::Range;
7
8use crate::error::ParseError;
9use crate::node::{AttrRange, Node, NodeId, NodeKind, RawKind, Span, SrcRange};
10
11#[derive(Clone)]
19pub struct Dom {
20 pub(crate) nodes: Vec<Node>,
21 pub(crate) strings: String,
22 pub(crate) attrs: Vec<(Span, Span)>,
26 pub(crate) attr_waste: usize,
29 pub(crate) first_root: Option<NodeId>,
32 pub(crate) last_root: Option<NodeId>,
33 pub(crate) reordered: bool,
37 pub(crate) errors: Vec<ParseError>,
38}
39
40impl Dom {
41 pub(crate) fn with_capacity(src_len: usize) -> Self {
42 Dom {
43 nodes: Vec::with_capacity(src_len / 13 + 8),
47 strings: String::with_capacity(src_len),
48 attrs: Vec::with_capacity(src_len / 48 + 4),
50 attr_waste: 0,
51 first_root: None,
52 last_root: None,
53 reordered: false,
54 errors: Vec::new(),
55 }
56 }
57
58 pub(crate) fn release_spare_capacity(&mut self) {
64 if self.nodes.capacity() / 2 > self.nodes.len() + 64 {
65 self.nodes.shrink_to_fit();
66 }
67 if self.attrs.capacity() / 2 > self.attrs.len() + 64 {
68 self.attrs.shrink_to_fit();
69 }
70 }
74
75 pub(crate) fn intern(&mut self, s: &str) -> Span {
77 if s.is_empty() {
78 return Span::EMPTY;
79 }
80 let start = self.strings.len() as u32;
81 self.strings.push_str(s);
82 Span {
83 start,
84 len: s.len() as u32,
85 }
86 }
87
88 #[inline]
90 fn span_since(&self, start: usize) -> Span {
91 Span {
92 start: start as u32,
93 len: (self.strings.len() - start) as u32,
94 }
95 }
96
97 pub(crate) fn intern_lower(&mut self, s: &str) -> Span {
100 let start = self.strings.len();
101 self.strings.push_str(s);
102 if let Some(new) = self.strings.get_mut(start..) {
103 new.make_ascii_lowercase();
104 }
105 self.span_since(start)
106 }
107
108 pub(crate) fn intern_decoded(&mut self, s: &str, in_attr: bool) -> (Span, Option<usize>) {
112 let start = self.strings.len();
113 let unknown = crate::entities::decode_into(s, &mut self.strings, in_attr);
114 (self.span_since(start), unknown)
115 }
116
117 #[inline]
118 pub(crate) fn span_str(&self, span: Span) -> &str {
119 self.strings.get(span.range()).unwrap_or("")
120 }
121
122 #[inline]
124 pub(crate) fn attr_slice(&self, attrs: AttrRange) -> &[(Span, Span)] {
125 self.attrs.get(attrs.range()).unwrap_or(&[])
126 }
127
128 pub(crate) fn alloc(&mut self, raw: RawKind, src: SrcRange) -> NodeId {
129 let id = NodeId::from_index(self.nodes.len());
130 self.nodes.push(Node::new(raw, src));
131 id
132 }
133
134 #[inline]
135 pub(crate) fn node(&self, id: NodeId) -> Option<&Node> {
136 self.nodes.get(id.index())
137 }
138
139 #[inline]
140 pub(crate) fn node_mut(&mut self, id: NodeId) -> Option<&mut Node> {
141 self.nodes.get_mut(id.index())
142 }
143
144 #[inline]
147 pub(crate) fn append(&mut self, parent: Option<NodeId>, child: NodeId) {
148 self.link(parent, None, child);
149 }
150
151 pub(crate) fn link(&mut self, parent: Option<NodeId>, before: Option<NodeId>, id: NodeId) {
155 let prev = match (before, parent) {
156 (Some(b), _) => self.node(b).and_then(|n| n.prev_sibling),
157 (None, Some(p)) => self.node(p).and_then(|n| n.last_child),
158 (None, None) => self.last_root,
159 };
160 if let Some(n) = self.node_mut(id) {
161 n.parent = parent;
162 n.prev_sibling = prev;
163 n.next_sibling = before;
164 }
165 match (prev, parent) {
166 (Some(p), _) => {
167 if let Some(p) = self.node_mut(p) {
168 p.next_sibling = Some(id);
169 }
170 }
171 (None, Some(p)) => {
172 if let Some(p) = self.node_mut(p) {
173 p.first_child = Some(id);
174 }
175 }
176 (None, None) => self.first_root = Some(id),
177 }
178 match (before, parent) {
179 (Some(b), _) => {
180 if let Some(b) = self.node_mut(b) {
181 b.prev_sibling = Some(id);
182 }
183 }
184 (None, Some(p)) => {
185 if let Some(p) = self.node_mut(p) {
186 p.last_child = Some(id);
187 }
188 }
189 (None, None) => self.last_root = Some(id),
190 }
191 }
192
193 pub(crate) fn unlink(&mut self, id: NodeId) {
196 let Some(node) = self.node(id) else { return };
197 let (parent, prev, next) = (node.parent, node.prev_sibling, node.next_sibling);
198 let top = parent.is_none() && !node.detached;
201 match (prev, parent) {
202 (Some(p), _) => {
203 if let Some(p) = self.node_mut(p) {
204 p.next_sibling = next;
205 }
206 }
207 (None, Some(p)) => {
208 if let Some(p) = self.node_mut(p) {
209 p.first_child = next;
210 }
211 }
212 (None, None) if top => self.first_root = next,
213 (None, None) => {}
214 }
215 match (next, parent) {
216 (Some(n), _) => {
217 if let Some(n) = self.node_mut(n) {
218 n.prev_sibling = prev;
219 }
220 }
221 (None, Some(p)) => {
222 if let Some(p) = self.node_mut(p) {
223 p.last_child = prev;
224 }
225 }
226 (None, None) if top => self.last_root = prev,
227 (None, None) => {}
228 }
229 if let Some(n) = self.node_mut(id) {
230 n.parent = None;
231 n.prev_sibling = None;
232 n.next_sibling = None;
233 }
234 }
235
236 fn next_in_document(&self, cur: NodeId) -> Option<NodeId> {
238 if let Some(child) = self.node(cur).and_then(|n| n.first_child) {
239 return Some(child);
240 }
241 let mut n = cur;
242 loop {
243 let node = self.node(n)?;
244 if let Some(sib) = node.next_sibling {
245 return Some(sib);
246 }
247 n = node.parent?;
248 }
249 }
250
251 pub fn len(&self) -> usize {
255 self.nodes.len()
256 }
257
258 pub fn is_empty(&self) -> bool {
260 self.nodes.is_empty()
261 }
262
263 pub fn errors(&self) -> &[ParseError] {
265 &self.errors
266 }
267
268 pub fn get(&self, id: NodeId) -> Option<NodeRef<'_>> {
270 if id.index() < self.nodes.len() {
271 Some(NodeRef { dom: self, id })
272 } else {
273 None
274 }
275 }
276
277 pub fn root(&self) -> Option<NodeRef<'_>> {
279 self.first_root.map(|id| NodeRef { dom: self, id })
280 }
281
282 pub fn roots(&self) -> impl Iterator<Item = NodeRef<'_>> {
284 core::iter::successors(self.first_root, move |&id| {
285 self.node(id).and_then(|n| n.next_sibling)
286 })
287 .map(move |id| NodeRef { dom: self, id })
288 }
289
290 pub fn nodes(&self) -> impl Iterator<Item = NodeRef<'_>> {
302 Nodes {
303 dom: self,
304 order: if self.reordered {
305 Order::Links(self.first_root)
306 } else {
307 Order::Arena(0)
308 },
309 }
310 }
311
312 pub fn find_by_tag<'a>(&'a self, name: &'a str) -> impl Iterator<Item = NodeRef<'a>> + 'a {
314 self.nodes()
315 .filter(move |n| n.tag_name().is_some_and(|t| t.eq_ignore_ascii_case(name)))
316 }
317
318 pub fn find_by_id<'a>(&'a self, id: &'a str) -> Option<NodeRef<'a>> {
320 self.nodes().find(|n| n.attr("id") == Some(id))
321 }
322
323 pub fn find_by_class<'a>(&'a self, class: &'a str) -> impl Iterator<Item = NodeRef<'a>> + 'a {
325 self.nodes().filter(move |n| n.has_class(class))
326 }
327}
328
329struct Nodes<'a> {
331 dom: &'a Dom,
332 order: Order,
333}
334
335enum Order {
336 Arena(usize),
338 Links(Option<NodeId>),
341}
342
343impl<'a> Iterator for Nodes<'a> {
344 type Item = NodeRef<'a>;
345
346 fn next(&mut self) -> Option<NodeRef<'a>> {
347 let dom = self.dom;
348 let id = match &mut self.order {
349 Order::Arena(i) => loop {
350 let node = dom.nodes.get(*i)?;
351 let id = NodeId::from_index(*i);
352 *i += 1;
353 if !node.detached {
354 break id;
355 }
356 },
357 Order::Links(next) => {
358 let id = (*next)?;
359 *next = dom.next_in_document(id);
360 id
361 }
362 };
363 Some(NodeRef { dom, id })
364 }
365}
366
367impl fmt::Debug for Dom {
368 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
369 let mut list = f.debug_list();
370 for r in self.roots() {
371 list.entry(&r);
372 }
373 list.finish()
374 }
375}
376
377#[derive(Clone, Copy)]
382pub struct NodeRef<'a> {
383 dom: &'a Dom,
384 id: NodeId,
385}
386
387impl<'a> NodeRef<'a> {
388 #[inline]
389 fn raw(&self) -> &'a Node {
390 debug_assert!(self.id.index() < self.dom.nodes.len());
394 &self.dom.nodes[self.id.index()]
395 }
396
397 #[inline]
399 pub fn id(&self) -> NodeId {
400 self.id
401 }
402
403 pub fn source_range(&self) -> Option<Range<usize>> {
432 self.raw().src.get()
433 }
434
435 pub fn is_detached(&self) -> bool {
451 self.raw().detached
452 }
453
454 pub fn kind(&self) -> NodeKind<'a> {
456 match &self.raw().raw {
457 RawKind::Element { name, .. } => NodeKind::Element {
458 tag: self.dom.span_str(*name),
459 },
460 RawKind::Text(s) => NodeKind::Text(self.dom.span_str(*s)),
461 RawKind::Comment(s) => NodeKind::Comment(self.dom.span_str(*s)),
462 RawKind::Doctype(s) => NodeKind::Doctype(self.dom.span_str(*s)),
463 }
464 }
465
466 pub fn is_element(&self) -> bool {
468 matches!(self.raw().raw, RawKind::Element { .. })
469 }
470
471 pub fn is_text(&self) -> bool {
473 matches!(self.raw().raw, RawKind::Text(_))
474 }
475
476 pub fn tag_name(&self) -> Option<&'a str> {
478 match &self.raw().raw {
479 RawKind::Element { name, .. } => Some(self.dom.span_str(*name)),
480 _ => None,
481 }
482 }
483
484 #[inline]
486 fn attr_spans(&self) -> &'a [(Span, Span)] {
487 match self.raw().raw {
488 RawKind::Element { attrs, .. } => self.dom.attr_slice(attrs),
489 _ => &[],
490 }
491 }
492
493 pub fn attr(&self, name: &str) -> Option<&'a str> {
496 let dom = self.dom;
497 self.attr_spans()
498 .iter()
499 .find(|&&(k, _)| dom.span_str(k) == name)
500 .map(|&(_, v)| dom.span_str(v))
501 }
502
503 pub fn has_attr(&self, name: &str) -> bool {
505 let dom = self.dom;
506 self.attr_spans()
507 .iter()
508 .any(|&(k, _)| dom.span_str(k) == name)
509 }
510
511 pub fn attributes(&self) -> impl Iterator<Item = (&'a str, &'a str)> {
514 let dom = self.dom;
515 self.attr_spans()
516 .iter()
517 .map(move |&(k, v)| (dom.span_str(k), dom.span_str(v)))
518 }
519
520 pub fn classes(&self) -> impl Iterator<Item = &'a str> {
523 self.attr("class")
524 .into_iter()
525 .flat_map(str::split_ascii_whitespace)
526 }
527
528 pub fn has_class(&self, class: &str) -> bool {
530 self.classes().any(|c| c == class)
531 }
532
533 pub fn text(&self) -> Option<&'a str> {
535 match &self.raw().raw {
536 RawKind::Text(s) => Some(self.dom.span_str(*s)),
537 _ => None,
538 }
539 }
540
541 pub fn comment(&self) -> Option<&'a str> {
543 match &self.raw().raw {
544 RawKind::Comment(s) => Some(self.dom.span_str(*s)),
545 _ => None,
546 }
547 }
548
549 pub fn text_content(&self) -> String {
552 let mut out = String::new();
553 if let RawKind::Text(s) = &self.raw().raw {
554 out.push_str(self.dom.span_str(*s));
555 }
556 for d in self.descendants() {
557 if let RawKind::Text(s) = &d.raw().raw {
558 out.push_str(self.dom.span_str(*s));
559 }
560 }
561 out
562 }
563
564 pub fn parent(&self) -> Option<NodeRef<'a>> {
568 self.raw().parent.map(|id| NodeRef { dom: self.dom, id })
569 }
570
571 pub fn first_child(&self) -> Option<NodeRef<'a>> {
573 self.raw()
574 .first_child
575 .map(|id| NodeRef { dom: self.dom, id })
576 }
577
578 pub fn last_child(&self) -> Option<NodeRef<'a>> {
580 self.raw()
581 .last_child
582 .map(|id| NodeRef { dom: self.dom, id })
583 }
584
585 pub fn next_sibling(&self) -> Option<NodeRef<'a>> {
587 self.raw()
588 .next_sibling
589 .map(|id| NodeRef { dom: self.dom, id })
590 }
591
592 pub fn prev_sibling(&self) -> Option<NodeRef<'a>> {
594 self.raw()
595 .prev_sibling
596 .map(|id| NodeRef { dom: self.dom, id })
597 }
598
599 pub fn next_element_sibling(&self) -> Option<NodeRef<'a>> {
608 core::iter::successors(self.next_sibling(), NodeRef::next_sibling).find(NodeRef::is_element)
609 }
610
611 pub fn prev_element_sibling(&self) -> Option<NodeRef<'a>> {
619 core::iter::successors(self.prev_sibling(), NodeRef::prev_sibling).find(NodeRef::is_element)
620 }
621
622 pub fn children(&self) -> impl Iterator<Item = NodeRef<'a>> {
624 let dom = self.dom;
625 core::iter::successors(self.raw().first_child, move |id| {
626 dom.node(*id).and_then(|n| n.next_sibling)
627 })
628 .map(move |id| NodeRef { dom, id })
629 }
630
631 pub fn child_elements(&self) -> impl Iterator<Item = NodeRef<'a>> {
633 self.children().filter(NodeRef::is_element)
634 }
635
636 pub fn ancestors(&self) -> impl Iterator<Item = NodeRef<'a>> {
638 let dom = self.dom;
639 core::iter::successors(self.raw().parent, move |id| {
640 dom.node(*id).and_then(|n| n.parent)
641 })
642 .map(move |id| NodeRef { dom, id })
643 }
644
645 pub fn descendants(&self) -> Descendants<'a> {
648 Descendants {
649 dom: self.dom,
650 root: self.id,
651 next: self.raw().first_child,
652 }
653 }
654}
655
656impl<'a> fmt::Debug for NodeRef<'a> {
657 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
658 Dbg(*self, 0).fmt(f)
659 }
660}
661
662const DEBUG_MAX_DEPTH: usize = 64;
665
666struct Dbg<'a>(NodeRef<'a>, usize);
667impl<'a> fmt::Debug for Dbg<'a> {
668 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
669 let (node, depth) = (self.0, self.1);
670 match node.kind() {
671 NodeKind::Element { .. } if depth >= DEBUG_MAX_DEPTH => f.write_str("…"),
672 NodeKind::Element { tag } => f
673 .debug_struct("Element")
674 .field("tag", &tag)
675 .field("attrs", &Attrs(node))
676 .field("children", &Kids(node, depth + 1))
677 .finish(),
678 NodeKind::Text(t) => f.debug_tuple("Text").field(&t).finish(),
679 NodeKind::Comment(c) => f.debug_tuple("Comment").field(&c).finish(),
680 NodeKind::Doctype(d) => f.debug_tuple("Doctype").field(&d).finish(),
681 }
682 }
683}
684
685struct Attrs<'a>(NodeRef<'a>);
686impl<'a> fmt::Debug for Attrs<'a> {
687 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
688 let mut m = f.debug_map();
689 for (k, v) in self.0.attributes() {
690 m.entry(&k, &v);
691 }
692 m.finish()
693 }
694}
695
696struct Kids<'a>(NodeRef<'a>, usize);
697impl<'a> fmt::Debug for Kids<'a> {
698 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
699 let depth = self.1;
700 f.debug_list()
701 .entries(self.0.children().map(|c| Dbg(c, depth)))
702 .finish()
703 }
704}
705
706pub struct Descendants<'a> {
708 dom: &'a Dom,
709 root: NodeId,
710 next: Option<NodeId>,
711}
712
713impl<'a> Iterator for Descendants<'a> {
714 type Item = NodeRef<'a>;
715
716 fn next(&mut self) -> Option<NodeRef<'a>> {
717 let cur = self.next?;
718 self.next = self.advance(cur);
719 Some(NodeRef {
720 dom: self.dom,
721 id: cur,
722 })
723 }
724}
725
726impl<'a> Descendants<'a> {
727 fn advance(&self, cur: NodeId) -> Option<NodeId> {
728 if let Some(child) = self.dom.node(cur).and_then(|n| n.first_child) {
729 return Some(child);
730 }
731 let mut n = cur;
732 loop {
733 if n == self.root {
734 return None;
735 }
736 if let Some(sib) = self.dom.node(n).and_then(|nd| nd.next_sibling) {
737 return Some(sib);
738 }
739 n = self.dom.node(n).and_then(|nd| nd.parent)?;
740 }
741 }
742}