1use alloc::string::String;
4use alloc::vec::Vec;
5use core::fmt;
6
7use crate::error::ParseError;
8use crate::node::{Node, NodeId, NodeKind, RawKind, Span};
9
10#[derive(Clone)]
17pub struct Dom {
18 pub(crate) nodes: Vec<Node>,
19 pub(crate) strings: String,
20 pub(crate) roots: Vec<NodeId>,
21 pub(crate) errors: Vec<ParseError>,
22}
23
24impl Dom {
25 pub(crate) fn with_capacity(src_len: usize) -> Self {
26 Dom {
27 nodes: Vec::with_capacity(src_len / 16 + 8),
28 strings: String::with_capacity(src_len),
29 roots: Vec::new(),
30 errors: Vec::new(),
31 }
32 }
33
34 pub(crate) fn intern(&mut self, s: &str) -> Span {
36 if s.is_empty() {
37 return Span::EMPTY;
38 }
39 let start = self.strings.len() as u32;
40 self.strings.push_str(s);
41 Span {
42 start,
43 len: s.len() as u32,
44 }
45 }
46
47 #[inline]
48 pub(crate) fn span_str(&self, span: Span) -> &str {
49 self.strings.get(span.range()).unwrap_or("")
50 }
51
52 pub(crate) fn alloc(&mut self, raw: RawKind) -> NodeId {
53 let id = NodeId(self.nodes.len() as u32);
54 self.nodes.push(Node::new(raw));
55 id
56 }
57
58 #[inline]
59 pub(crate) fn node(&self, id: NodeId) -> Option<&Node> {
60 self.nodes.get(id.index())
61 }
62
63 #[inline]
64 pub(crate) fn node_mut(&mut self, id: NodeId) -> Option<&mut Node> {
65 self.nodes.get_mut(id.index())
66 }
67
68 pub(crate) fn append(&mut self, parent: Option<NodeId>, child: NodeId) {
71 let parent = match parent {
72 None => {
73 self.roots.push(child);
74 return;
75 }
76 Some(p) => p,
77 };
78 if let Some(c) = self.node_mut(child) {
79 c.parent = Some(parent);
80 }
81 let last = self.node(parent).and_then(|n| n.last_child);
82 match last {
83 None => {
84 if let Some(p) = self.node_mut(parent) {
85 p.first_child = Some(child);
86 p.last_child = Some(child);
87 }
88 }
89 Some(last) => {
90 if let Some(l) = self.node_mut(last) {
91 l.next_sibling = Some(child);
92 }
93 if let Some(c) = self.node_mut(child) {
94 c.prev_sibling = Some(last);
95 }
96 if let Some(p) = self.node_mut(parent) {
97 p.last_child = Some(child);
98 }
99 }
100 }
101 }
102
103 pub fn len(&self) -> usize {
107 self.nodes.len()
108 }
109
110 pub fn is_empty(&self) -> bool {
112 self.nodes.is_empty()
113 }
114
115 pub fn errors(&self) -> &[ParseError] {
117 &self.errors
118 }
119
120 pub fn get(&self, id: NodeId) -> Option<NodeRef<'_>> {
122 if id.index() < self.nodes.len() {
123 Some(NodeRef { dom: self, id })
124 } else {
125 None
126 }
127 }
128
129 pub fn root(&self) -> Option<NodeRef<'_>> {
131 self.roots.first().map(|&id| NodeRef { dom: self, id })
132 }
133
134 pub fn roots(&self) -> impl Iterator<Item = NodeRef<'_>> {
136 self.roots.iter().map(move |&id| NodeRef { dom: self, id })
137 }
138
139 pub fn nodes(&self) -> impl Iterator<Item = NodeRef<'_>> {
141 (0..self.nodes.len()).map(move |i| NodeRef {
142 dom: self,
143 id: NodeId(i as u32),
144 })
145 }
146
147 pub fn find_by_tag<'a>(&'a self, name: &'a str) -> impl Iterator<Item = NodeRef<'a>> + 'a {
149 self.nodes()
150 .filter(move |n| n.tag_name().is_some_and(|t| t.eq_ignore_ascii_case(name)))
151 }
152
153 pub fn find_by_id<'a>(&'a self, id: &'a str) -> Option<NodeRef<'a>> {
155 self.nodes().find(|n| n.attr("id") == Some(id))
156 }
157
158 pub fn find_by_class<'a>(&'a self, class: &'a str) -> impl Iterator<Item = NodeRef<'a>> + 'a {
160 self.nodes().filter(move |n| n.has_class(class))
161 }
162}
163
164impl fmt::Debug for Dom {
165 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
166 let mut list = f.debug_list();
167 for r in self.roots() {
168 list.entry(&r);
169 }
170 list.finish()
171 }
172}
173
174#[derive(Clone, Copy)]
179pub struct NodeRef<'a> {
180 dom: &'a Dom,
181 id: NodeId,
182}
183
184impl<'a> NodeRef<'a> {
185 #[inline]
186 fn raw(&self) -> &'a Node {
187 debug_assert!(self.id.index() < self.dom.nodes.len());
191 &self.dom.nodes[self.id.index()]
192 }
193
194 #[inline]
196 pub fn id(&self) -> NodeId {
197 self.id
198 }
199
200 pub fn kind(&self) -> NodeKind<'a> {
202 match &self.raw().raw {
203 RawKind::Element { name, .. } => NodeKind::Element {
204 tag: self.dom.span_str(*name),
205 },
206 RawKind::Text(s) => NodeKind::Text(self.dom.span_str(*s)),
207 RawKind::Comment(s) => NodeKind::Comment(self.dom.span_str(*s)),
208 RawKind::Doctype(s) => NodeKind::Doctype(self.dom.span_str(*s)),
209 }
210 }
211
212 pub fn is_element(&self) -> bool {
214 matches!(self.raw().raw, RawKind::Element { .. })
215 }
216
217 pub fn is_text(&self) -> bool {
219 matches!(self.raw().raw, RawKind::Text(_))
220 }
221
222 pub fn tag_name(&self) -> Option<&'a str> {
224 match &self.raw().raw {
225 RawKind::Element { name, .. } => Some(self.dom.span_str(*name)),
226 _ => None,
227 }
228 }
229
230 pub fn attr(&self, name: &str) -> Option<&'a str> {
232 let dom = self.dom;
233 match &self.raw().raw {
234 RawKind::Element { attrs, .. } => attrs
235 .iter()
236 .find(|&&(k, _)| dom.span_str(k) == name)
237 .map(|&(_, v)| dom.span_str(v)),
238 _ => None,
239 }
240 }
241
242 pub fn has_attr(&self, name: &str) -> bool {
244 let dom = self.dom;
245 match &self.raw().raw {
246 RawKind::Element { attrs, .. } => attrs.iter().any(|&(k, _)| dom.span_str(k) == name),
247 _ => false,
248 }
249 }
250
251 pub fn attributes(&self) -> impl Iterator<Item = (&'a str, &'a str)> {
253 let dom = self.dom;
254 let attrs: &'a [(Span, Span)] = match &self.raw().raw {
255 RawKind::Element { attrs, .. } => attrs.as_slice(),
256 _ => &[],
257 };
258 attrs
259 .iter()
260 .map(move |&(k, v)| (dom.span_str(k), dom.span_str(v)))
261 }
262
263 pub fn classes(&self) -> impl Iterator<Item = &'a str> {
265 self.attr("class")
266 .into_iter()
267 .flat_map(str::split_whitespace)
268 }
269
270 pub fn has_class(&self, class: &str) -> bool {
272 self.classes().any(|c| c == class)
273 }
274
275 pub fn text(&self) -> Option<&'a str> {
277 match &self.raw().raw {
278 RawKind::Text(s) => Some(self.dom.span_str(*s)),
279 _ => None,
280 }
281 }
282
283 pub fn comment(&self) -> Option<&'a str> {
285 match &self.raw().raw {
286 RawKind::Comment(s) => Some(self.dom.span_str(*s)),
287 _ => None,
288 }
289 }
290
291 pub fn text_content(&self) -> String {
294 let mut out = String::new();
295 if let RawKind::Text(s) = &self.raw().raw {
296 out.push_str(self.dom.span_str(*s));
297 }
298 for d in self.descendants() {
299 if let RawKind::Text(s) = &d.raw().raw {
300 out.push_str(self.dom.span_str(*s));
301 }
302 }
303 out
304 }
305
306 pub fn parent(&self) -> Option<NodeRef<'a>> {
310 self.raw().parent.map(|id| NodeRef { dom: self.dom, id })
311 }
312
313 pub fn first_child(&self) -> Option<NodeRef<'a>> {
315 self.raw()
316 .first_child
317 .map(|id| NodeRef { dom: self.dom, id })
318 }
319
320 pub fn last_child(&self) -> Option<NodeRef<'a>> {
322 self.raw()
323 .last_child
324 .map(|id| NodeRef { dom: self.dom, id })
325 }
326
327 pub fn next_sibling(&self) -> Option<NodeRef<'a>> {
329 self.raw()
330 .next_sibling
331 .map(|id| NodeRef { dom: self.dom, id })
332 }
333
334 pub fn prev_sibling(&self) -> Option<NodeRef<'a>> {
336 self.raw()
337 .prev_sibling
338 .map(|id| NodeRef { dom: self.dom, id })
339 }
340
341 pub fn children(&self) -> impl Iterator<Item = NodeRef<'a>> {
343 let dom = self.dom;
344 core::iter::successors(self.raw().first_child, move |id| {
345 dom.node(*id).and_then(|n| n.next_sibling)
346 })
347 .map(move |id| NodeRef { dom, id })
348 }
349
350 pub fn child_elements(&self) -> impl Iterator<Item = NodeRef<'a>> {
352 self.children().filter(NodeRef::is_element)
353 }
354
355 pub fn ancestors(&self) -> impl Iterator<Item = NodeRef<'a>> {
357 let dom = self.dom;
358 core::iter::successors(self.raw().parent, move |id| {
359 dom.node(*id).and_then(|n| n.parent)
360 })
361 .map(move |id| NodeRef { dom, id })
362 }
363
364 pub fn descendants(&self) -> Descendants<'a> {
367 Descendants {
368 dom: self.dom,
369 root: self.id,
370 next: self.raw().first_child,
371 }
372 }
373}
374
375impl<'a> fmt::Debug for NodeRef<'a> {
376 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
377 match self.kind() {
378 NodeKind::Element { tag } => f
379 .debug_struct("Element")
380 .field("tag", &tag)
381 .field("attrs", &Attrs(*self))
382 .field("children", &Kids(*self))
383 .finish(),
384 NodeKind::Text(t) => f.debug_tuple("Text").field(&t).finish(),
385 NodeKind::Comment(c) => f.debug_tuple("Comment").field(&c).finish(),
386 NodeKind::Doctype(d) => f.debug_tuple("Doctype").field(&d).finish(),
387 }
388 }
389}
390
391struct Attrs<'a>(NodeRef<'a>);
392impl<'a> fmt::Debug for Attrs<'a> {
393 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
394 let mut m = f.debug_map();
395 for (k, v) in self.0.attributes() {
396 m.entry(&k, &v);
397 }
398 m.finish()
399 }
400}
401
402struct Kids<'a>(NodeRef<'a>);
403impl<'a> fmt::Debug for Kids<'a> {
404 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
405 f.debug_list().entries(self.0.children()).finish()
406 }
407}
408
409pub struct Descendants<'a> {
411 dom: &'a Dom,
412 root: NodeId,
413 next: Option<NodeId>,
414}
415
416impl<'a> Iterator for Descendants<'a> {
417 type Item = NodeRef<'a>;
418
419 fn next(&mut self) -> Option<NodeRef<'a>> {
420 let cur = self.next?;
421 self.next = self.advance(cur);
422 Some(NodeRef {
423 dom: self.dom,
424 id: cur,
425 })
426 }
427}
428
429impl<'a> Descendants<'a> {
430 fn advance(&self, cur: NodeId) -> Option<NodeId> {
431 if let Some(child) = self.dom.node(cur).and_then(|n| n.first_child) {
432 return Some(child);
433 }
434 let mut n = cur;
435 loop {
436 if n == self.root {
437 return None;
438 }
439 if let Some(sib) = self.dom.node(n).and_then(|nd| nd.next_sibling) {
440 return Some(sib);
441 }
442 match self.dom.node(n).and_then(|nd| nd.parent) {
443 Some(p) => n = p,
444 None => return None,
445 }
446 }
447 }
448}