marked/
dom.rs

1// Copyright © 2019 David Kellum
2//
3// This DOM-like markup tree module was originally based on `victor::dom`, as
4// of commit fdb11f3e8 of the source as found here:
5//
6// https://github.com/SimonSapin/victor
7// (No copyright notice.)
8// Licensed under the Apache license v2.0, or the MIT license
9
10//! An efficient and simple DOM-like container and associated tools.
11
12use std::convert::TryInto;
13use std::fmt;
14use std::iter;
15use std::mem;
16use std::num::NonZeroU32;
17use std::ops::{Deref, DerefMut};
18
19#[doc(no_inline)]
20pub use html5ever::{Attribute, LocalName, Namespace, QualName};
21
22#[doc(no_inline)]
23pub use tendril::StrTendril;
24
25// custom ordering of these effects rustdoc for Document, etc.
26
27mod node_ref;
28mod serializer;
29#[macro_use] pub mod filter;
30pub mod html;
31
32#[cfg(feature = "xml")]
33pub mod xml;
34
35#[cfg(test)]
36mod tests;
37
38pub use node_ref::{NodeRef, Descender, Selector};
39
40/// A DOM-like container for a tree of markup elements and text.
41///
42/// Unlike `RcDom`, this uses a simple vector of [`Node`]s and indexes for
43/// parent/child and sibling ordering. Attributes are stored as separately
44/// allocated vectors for each element. For memory efficiency, a single
45/// document is limited to 4 billion (2^32 - 1) total nodes.
46///
47/// All `Document` instances, even logically "empty" ones as freshly
48/// constructed, contain a synthetic document node at the fixed
49/// [`Document::DOCUMENT_NODE_ID`] that serves as a container for N top level
50/// nodes, including the [`Document::root_element()`], if present.
51pub struct Document {
52    nodes: Vec<Node>,
53}
54
55/// A `Node` identifier as a u32 index into a `Document`s `Node` vector.
56///
57/// Should only be used with the `Document` it was obtained from.
58#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
59pub struct NodeId(NonZeroU32);
60
61/// A typed node (e.g. text, element, etc.) within a `Document` including
62/// identifiers to parent, siblings and children.
63#[derive(Clone, Debug)]
64pub struct Node {
65    data: NodeData,
66    parent: Option<NodeId>,
67    prev_sibling: Option<NodeId>,
68    next_sibling: Option<NodeId>,
69    first_child: Option<NodeId>,
70    last_child: Option<NodeId>,
71}
72
73/// The node kind and payload data associated with that kind.
74#[derive(Clone, Debug)]
75pub enum NodeData {
76    /// A place holder value. Used temporarily while filtering and for nodes
77    /// that have been removed.
78    Hole,
79
80    /// The document node which contains all other nodes.
81    Document,
82
83    /// The document type definition.
84    DocType(DocumentType),
85
86    /// Character data content.
87    Text(StrTendril),
88
89    /// A comment.
90    Comment(StrTendril),
91
92    /// An element.
93    Elem(Element),
94
95    /// A processing instruction node.
96    Pi(ProcessingInstruction),
97}
98
99/// Document type definition details.
100#[derive(Clone, Debug)]
101pub struct DocumentType {
102    pub name: StrTendril,
103    _priv: ()
104}
105
106/// Processing instruction details.
107#[derive(Clone, Debug)]
108pub struct ProcessingInstruction {
109    pub data: StrTendril,
110    _priv: ()
111}
112
113/// A markup element with name and attributes.
114#[derive(Clone, Debug)]
115pub struct Element {
116    pub name: QualName,
117    pub attrs: Vec<Attribute>,
118    _priv: ()
119}
120
121/// Core implementation.
122impl Document {
123    /// The constant `NodeId` for the document node of all `Document`s.
124    pub const DOCUMENT_NODE_ID: NodeId = NodeId(
125        unsafe { NonZeroU32::new_unchecked(1) }
126    );
127
128    // An accepted amount of excess Vec<Node> capacity
129    const WASTE_ALLOWANCE: usize = 1024;
130
131    /// Construct a new `Document` with the single empty document node.
132    pub fn new() -> Self {
133        Document::with_capacity(8)
134    }
135
136    /// Construct a new `Document` with the single empty document node and
137    /// specified capacity.
138    pub fn with_capacity(count: u32) -> Self {
139        let mut nodes = Vec::with_capacity(count as usize);
140        nodes.push(Node::new(NodeData::Hole));     // Index 0: Padding
141        nodes.push(Node::new(NodeData::Document)); // Index 1: DOCUMENT_NODE_ID
142        Document { nodes }
143    }
144
145    /// Return total number of `Node`s.
146    ///
147    /// This includes the document node and all occupied nodes, some of which
148    /// may not be accessable from the document node. The value returned
149    /// may be more than the accessable nodes counted via `nodes().count()`,
150    /// unless [`Document::compact`] or [`Document::deep_clone`] is first used.
151    #[inline]
152    pub fn len(&self) -> u32 {
153        let nodes: u32 = self.nodes.len()
154            .try_into()
155            .expect("Document (u32) node index overflow");
156        debug_assert!(nodes > 0);
157        nodes - 1 // but don't include padding (index 0) in len
158    }
159
160    /// Return true if this document only contains the single, empty document
161    /// node.
162    ///
163    /// Note that when "empty" the [`Document::len`] is still one (1).
164    #[inline]
165    pub fn is_empty(&self) -> bool {
166        self.len() < 2
167    }
168
169    /// Return the root element `NodeId` for this Document, or None if there is
170    /// no such qualified element.
171    ///
172    /// A node with `NodeData::Element` is a root element, if it is a direct
173    /// child of the document node, with no other element or text sibling.
174    pub fn root_element(&self) -> Option<NodeId> {
175        let document_node = &self[Document::DOCUMENT_NODE_ID];
176        debug_assert!(
177            (if let NodeData::Document = document_node.data { true }
178             else { false }),
179            "not document node: {:?}", document_node);
180        debug_assert!(document_node.parent.is_none());
181        debug_assert!(document_node.next_sibling.is_none());
182        debug_assert!(document_node.prev_sibling.is_none());
183        let mut root = None;
184        for child in self.children(Document::DOCUMENT_NODE_ID) {
185            match &self[child].data {
186                NodeData::DocType(_) |
187                NodeData::Comment(_) |
188                NodeData::Pi(_) => {}
189                NodeData::Document => {
190                    debug_assert!(false, "Document child of Document");
191                    root = None;
192                    break;
193                }
194                NodeData::Hole => {
195                    debug_assert!(false, "Hole in Document");
196                    root = None;
197                    break;
198                }
199                NodeData::Text(_) => {
200                    root = None;
201                    break;
202                }
203                NodeData::Elem(_) => {
204                    if root.is_none() {
205                        root = Some(child);
206                    } else {
207                        root = None; // Only one accepted
208                        break;
209                    }
210                }
211            }
212        }
213        root
214    }
215
216    fn push_node(&mut self, node: Node) -> NodeId {
217        debug_assert!(
218            (if let NodeData::Document | NodeData::Hole = node.data { false }
219             else { true }),
220            "Invalid push {:?}", node.data);
221        let next_index = self.nodes.len()
222            .try_into()
223            .expect("Document (u32) node index overflow");
224        debug_assert!(next_index > 1);
225        self.nodes.push(node);
226        NodeId(unsafe { NonZeroU32::new_unchecked(next_index) })
227    }
228
229    /// Detach the specified node ID and return it and its children moved into
230    /// a new independent `Document` fragment.
231    ///
232    /// If the complete `Document` sub-tree fragment isn't needed, use
233    /// [`Document::unlink`] instead.
234    ///
235    /// Panics if called with the synthetic DOCUMENT_NODE_ID.
236    /// Detaching the root element results in a document with no root
237    /// element.
238    ///
239    /// Detach just removes references and replaces all node data in self with
240    /// `NodeData::Hole`. To free up the `Vec<Node>` slots for these nodes as
241    /// well, use [`Document::compact`].
242    #[inline]
243    #[must_use="If the fragment isn't needed, use `unlink()` instead."]
244    pub fn detach(&mut self, id: NodeId) -> Document {
245        self.unlink_only(id);
246
247        // Not a great guess of the subtree, but faster than counting
248        let guess_cap = std::cmp::max(8, self.len() - id.0.get() + 2);
249        let mut ndoc = Document::with_capacity(guess_cap);
250
251        ndoc.append_move(Document::DOCUMENT_NODE_ID, self, id);
252
253        // If guess cap was higher then allowance, shrink it
254        if (ndoc.nodes.capacity() - ndoc.nodes.len()) >
255            Document::WASTE_ALLOWANCE
256        {
257            ndoc.nodes.shrink_to_fit();
258        }
259        ndoc
260    }
261
262    /// Attach the contents of an other `Document` to self, by appending
263    /// its nodes under the given parent node.
264    ///
265    /// The `Document` is consumed (its contents moved to self). This is an
266    /// inverse of [`Document::detach`].
267    pub fn attach_child(&mut self, parent: NodeId, mut other: Document) {
268        self.nodes.reserve(other.len() as usize - 1); // ignore DOCUMENT node
269        let children = other.children(Document::DOCUMENT_NODE_ID)
270            .collect::<Vec<_>>();
271        for child in children {
272            self.append_move(parent, &mut other, child);
273        }
274    }
275
276    /// Attach the contents of an other `Document` to self, by inserting its
277    /// nodes before the given sibling node.
278    ///
279    /// The `Document` is consumed (its contents moved to self). This is an
280    /// inverse of [`Document::detach`].
281    pub fn attach_before_sibling(
282        &mut self,
283        sibling: NodeId,
284        mut other: Document)
285    {
286        self.nodes.reserve(other.len() as usize - 1);
287        let children = other.children(Document::DOCUMENT_NODE_ID)
288            .collect::<Vec<_>>();
289        for oid in children {
290            let onode = &mut other[oid];
291            let nid = self.insert_before_sibling(
292                sibling,
293                Node::new(onode.take_data()));
294            for coid in other.children(oid).collect::<Vec<_>>() {
295                self.append_move(nid, &mut other, coid);
296            }
297        }
298    }
299
300    /// Move node oid in odoc and all its descendants, appending to id in
301    /// self.
302    fn append_move(&mut self, id: NodeId, odoc: &mut Document, oid: NodeId) {
303        let id = self.append_child(id, Node::new(odoc[oid].take_data()));
304        let mut ns = NodeStack2::new();
305        ns.push_if(odoc[oid].first_child, id);
306
307        while let Some((oid, id)) = ns.pop() {
308            let onode = &mut odoc[oid];
309            let nid = self.append_child(id, Node::new(onode.take_data()));
310            ns.push_if(onode.next_sibling, id);
311            ns.push_if(onode.first_child, nid);
312        }
313    }
314
315    /// Unlink the specified node ID from the Document, and return the replaced
316    /// `NodeData`.
317    ///
318    /// Panics if called with the synthetic DOCUMENT_NODE_ID.
319    /// Unlinking the root element results in an document with no root
320    /// element.
321    ///
322    /// Unlink removes references and replaces the single node data with
323    /// `NodeData::Hole`, leaving all children in place but un-referenced. Use
324    /// [`Document::detach`] to instead obtain the entire sub-tree. To free up
325    /// the `Vec<Node>` slots for the node and any children, use
326    /// [`Document::compact`].
327    #[inline]
328    pub fn unlink(&mut self, id: NodeId) -> NodeData {
329        self.unlink_only(id);
330        self[id].take_data()
331    }
332
333    /// Unlink the specified node from the Document.
334    fn unlink_only(&mut self, id: NodeId) {
335        assert!(
336            id != Document::DOCUMENT_NODE_ID,
337            "Can't detach the synthetic document node");
338
339        let (parent, prev_sibling, next_sibling) = {
340            let node = &mut self[id];
341            (node.parent.take(),
342             node.prev_sibling.take(),
343             node.next_sibling.take())
344        };
345
346        if let Some(next_sibling) = next_sibling {
347            self[next_sibling].prev_sibling = prev_sibling
348        } else if let Some(parent) = parent {
349            self[parent].last_child = prev_sibling;
350        }
351
352        if let Some(prev_sibling) = prev_sibling {
353            self[prev_sibling].next_sibling = next_sibling;
354        } else if let Some(parent) = parent {
355            self[parent].first_child = next_sibling;
356        }
357    }
358
359    /// Append node as new last child of given parent, and return its new ID.
360    pub fn append_child(&mut self, parent: NodeId, node: Node)
361        -> NodeId
362    {
363        let id = self.push_node(node);
364        self.append(parent, id);
365        id
366    }
367
368    fn append(&mut self, parent: NodeId, new_child: NodeId) {
369        self.unlink_only(new_child);
370        self[new_child].parent = Some(parent);
371        self[parent].assert_suitable_parent();
372        if let Some(last_child) = self[parent].last_child.take() {
373            self[new_child].prev_sibling = Some(last_child);
374            debug_assert!(self[last_child].next_sibling.is_none());
375            self[last_child].next_sibling = Some(new_child);
376        } else {
377            debug_assert!(self[parent].first_child.is_none());
378            self[parent].first_child = Some(new_child);
379        }
380        self[parent].last_child = Some(new_child);
381    }
382
383    /// Insert node before the given sibling and return its new ID.
384    pub fn insert_before_sibling(&mut self, sibling: NodeId, node: Node)
385        -> NodeId
386    {
387        let id = self.push_node(node);
388        self.insert_before(sibling, id);
389        id
390    }
391
392    fn insert_before(&mut self, sibling: NodeId, new_sibling: NodeId) {
393        self.unlink_only(new_sibling);
394        let parent = self[sibling].parent
395            .expect("insert_before sibling has no parent");
396        self[parent].assert_suitable_parent();
397        self[new_sibling].parent = Some(parent);
398        self[new_sibling].next_sibling = Some(sibling);
399        if let Some(prev_sibling) = self[sibling].prev_sibling.take() {
400            self[new_sibling].prev_sibling = Some(prev_sibling);
401            debug_assert_eq!(
402                self[prev_sibling].next_sibling,
403                Some(sibling)
404            );
405            self[prev_sibling].next_sibling = Some(new_sibling);
406        } else {
407            debug_assert_eq!(self[parent].first_child, Some(sibling));
408            self[parent].first_child = Some(new_sibling);
409        }
410        self[sibling].prev_sibling = Some(new_sibling);
411    }
412
413    /// Return all descendant text content (character data) of the given node.
414    ///
415    /// If node is a text node, return that text.  If this is an element node
416    /// or the document node, return the concatentation of all text
417    /// descendants, in tree order. Return `None` for all other node types.
418    pub fn text(&self, id: NodeId) -> Option<StrTendril> {
419        let mut ns = NodeStack1::new();
420        ns.push_if(self[id].first_child);
421        let mut text = None;
422        while let Some(id) = ns.pop() {
423            let node = &self[id];
424            if let NodeData::Text(t) = &node.data {
425                match &mut text {
426                    None => text = Some(t.clone()),
427                    Some(text) => text.push_tendril(&t),
428                }
429                ns.push_if(node.next_sibling);
430            } else {
431                ns.push_if(node.next_sibling);
432                ns.push_if(node.first_child);
433            }
434        }
435        text
436    }
437
438    /// Return an iterator over the given node's direct children.
439    ///
440    /// Will be empty if the node does not (or can not) have children.
441    pub fn children(&self, id: NodeId) -> impl Iterator<Item = NodeId> + '_ {
442        iter::successors(
443            self[id].first_child,
444            move |&id| self[id].next_sibling
445        )
446    }
447
448    /// Return an iterator over the specified node and all its following,
449    /// direct siblings, within the same parent.
450    pub fn node_and_following_siblings(&self, id: NodeId)
451        -> impl Iterator<Item = NodeId> + '_
452    {
453        iter::successors(Some(id), move |&id| self[id].next_sibling)
454    }
455
456    /// Return an iterator over the specified node and all its ancestors,
457    /// terminating at the document node.
458    pub fn node_and_ancestors(&self, id: NodeId)
459        -> impl Iterator<Item = NodeId> + '_
460    {
461        iter::successors(Some(id), move |&id| self[id].parent)
462    }
463
464    /// Return an iterator over all nodes, starting with the document node, and
465    /// including all descendants in tree order.
466    pub fn nodes(&self) -> impl Iterator<Item = NodeId> + '_ {
467        self.descendants(Document::DOCUMENT_NODE_ID)
468    }
469
470    /// Return an iterator over all descendants in tree order, starting with
471    /// the specified node.
472    #[inline]
473    pub fn descendants(&self, id: NodeId) -> impl Iterator<Item = NodeId> + '_
474    {
475        NodeRef::new(self, id).descendants().map(|nr| nr.id())
476    }
477
478    /// Compact in place, by removing `Node`s that are no longer referenced
479    /// from the document node.
480    pub fn compact(&mut self) {
481        let mut ndoc = Document::with_capacity(self.len() + 1);
482        let mut ns = NodeStack2::new();
483        ns.push_if(
484            self[Document::DOCUMENT_NODE_ID].first_child,
485            Document::DOCUMENT_NODE_ID);
486
487        while let Some((id, nid)) = ns.pop() {
488            let nnode = Node::new(self[id].take_data());
489            let ncid = ndoc.append_child(nid, nnode);
490            ns.push_if(self[id].next_sibling, nid);
491            ns.push_if(self[id].first_child, ncid);
492        }
493
494        // If guess cap was higher then allowance, shrink it
495        if (ndoc.nodes.capacity() - ndoc.nodes.len()) >
496            Document::WASTE_ALLOWANCE
497        {
498            ndoc.nodes.shrink_to_fit();
499        }
500
501        self.nodes = ndoc.nodes;
502    }
503
504    /// Create a new `Document` from the ordered sub-tree rooted in the node
505    /// referenced by ID.
506    pub fn deep_clone(&self, id: NodeId) -> Document {
507
508        // Conservative guess of sub tree length. Shrinking after is likely
509        // expensive in this case, so avoid it.
510        let guess_cap = std::cmp::max(8, (self.len() - id.0.get() + 2) / 8);
511        let mut ndoc = Document::with_capacity(guess_cap);
512
513        if id == Document::DOCUMENT_NODE_ID {
514            for child in self.children(id) {
515                ndoc.append_deep_clone(Document::DOCUMENT_NODE_ID, self, child);
516            }
517        } else {
518            ndoc.append_deep_clone(Document::DOCUMENT_NODE_ID, self, id);
519        }
520
521        ndoc
522    }
523
524    /// Clone node oid in odoc and all its descendants, appending to id in
525    /// self.
526    pub fn append_deep_clone(
527        &mut self,
528        id: NodeId,
529        odoc: &Document,
530        oid: NodeId)
531    {
532        let id = self.append_child(id, Node::new(odoc[oid].data.clone()));
533        for child in odoc.children(oid) {
534            self.append_deep_clone(id, odoc, child);
535        }
536    }
537
538    /// Return a clone of self by bulk clone of all `Node`s.
539    ///
540    /// This clone is performed without regard for what nodes are reachable
541    /// from the document node. The [`Document::len`] of the clone will be the
542    /// same as the original. As compared with `deep_clone(DOCUMENT_NODE_ID)`
543    /// this is faster but potentially much less memory efficient.
544    pub fn bulk_clone(&self) -> Document {
545        Document { nodes: self.nodes.clone() }
546    }
547
548    /// Replace the specified node ID with its children, and return the
549    /// replaced `NodeData`.
550    ///
551    /// Panics if called with the synthetic DOCUMENT_NODE_ID. Folding the root
552    /// element may result in a `Document` with no single root element, or
553    /// which is otherwise invalid based on its _doctype_, e.g. the HTML or XML
554    /// specifications.
555    ///
556    /// After repositioning children the specified node is
557    /// [unlinked][Document::unlink], removing references, then its data is
558    /// replaced with `NodeData::Hole` and the original is returned. To free up
559    /// the remaining `Vec<Node>` slot for the node, use
560    /// [`Document::compact`]. For a node with no children, fold is equivalent
561    /// to [`Document::unlink`].
562    #[inline]
563    pub fn fold(&mut self, id: NodeId) -> NodeData {
564        self.fold_only(id);
565        self[id].take_data()
566    }
567
568    /// Replace the specified node ID with its children.
569    fn fold_only(&mut self, id: NodeId) {
570        assert!(
571            id != Document::DOCUMENT_NODE_ID,
572            "Can't fold the synthetic document node");
573
574        let mut next_child = self[id].first_child;
575        while let Some(child) = next_child {
576            debug_assert_eq!(self[child].parent, Some(id));
577            next_child = self[child].next_sibling;
578            self.insert_before(id, child);
579        }
580        self.unlink_only(id);
581    }
582}
583
584impl Default for Document {
585    fn default() -> Document {
586        Document::new()
587    }
588}
589
590impl fmt::Debug for Document {
591    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
592        f.debug_list().entries(&self.nodes[1..]).finish()
593    }
594}
595
596impl std::ops::Index<NodeId> for Document {
597    type Output = Node;
598
599    #[inline]
600    fn index(&self, id: NodeId) -> &Node {
601        &self.nodes[id.0.get() as usize]
602    }
603}
604
605impl std::ops::IndexMut<NodeId> for Document {
606    #[inline]
607    fn index_mut(&mut self, id: NodeId) -> &mut Node {
608        &mut self.nodes[id.0.get() as usize]
609    }
610}
611
612impl Element {
613    /// Construct new element by local name, with no attributes.
614    pub fn new<LN>(lname: LN) -> Element
615        where LN: Into<LocalName>
616    {
617        Element {
618            name: QualName::new(None, ns!(), lname.into()),
619            attrs: Vec::new(),
620            _priv: ()
621        }
622    }
623
624    /// Return true if this element has the given local name.
625    pub fn is_elem<LN>(&self, lname: LN) -> bool
626        where LN: Into<LocalName>
627    {
628        self.name.local == lname.into()
629    }
630
631    /// Return [`html::TagMeta`] for this element, if the tag is a known part
632    /// of the HTML `Namespace`.
633    pub fn html_tag_meta(&self) -> Option<&'static html::TagMeta> {
634        if self.name.ns == html::ns::HTML {
635            html::TAG_META.get(&self.name.local)
636        } else {
637            None
638        }
639    }
640
641    /// Return attribute value by local name, if present.
642    pub fn attr<LN>(&self, lname: LN) -> Option<&StrTendril>
643        where LN: Into<LocalName>
644    {
645        let lname = lname.into();
646        self.attrs
647            .iter()
648            .find(|attr| attr.name.local == lname)
649            .map(|attr| &attr.value)
650    }
651
652    /// Remove attribute by local name, returning any value found.
653    ///
654    /// This removes _all_ instances of attributes with the given local name
655    /// and returns the value of the _last_ such attribute. Parsers may allow
656    /// same named attributes or multiples might be introduced via manual
657    /// mutations.
658    pub fn remove_attr<LN>(&mut self, lname: LN) -> Option<StrTendril>
659        where LN: Into<LocalName>
660    {
661        let mut found = None;
662        let mut i = 0;
663        let lname = lname.into();
664        while i < self.attrs.len() {
665            if self.attrs[i].name.local == lname {
666                found = Some(self.attrs.remove(i).value);
667            } else {
668                i += 1;
669            }
670        }
671        found
672    }
673
674    /// Set attribute by local name, returning any prior value found.
675    ///
676    /// This replaces the value of the first attribute with the given local
677    /// name and removes any other instances.  If no existing attribute is
678    /// found, the attribute is added to the end. To guarantee placement at the
679    /// end, use [`Element::remove_attr`] first.  In the case where multiple
680    /// existing instances of the attribute are found, the _last_ value is
681    /// returned.  Parsers may allow same named attributes or multiples might
682    /// be introduced via manual mutations.
683    pub fn set_attr<LN, V>(&mut self, lname: LN, value: V)
684        -> Option<StrTendril>
685        where LN: Into<LocalName>, V: Into<StrTendril>
686    {
687        let mut found = None;
688        let mut i = 0;
689        let lname = lname.into();
690
691        // Need to Option::take value below to appease borrow checking and
692        // avoid a clone.
693        let mut value = Some(value.into());
694
695        while i < self.attrs.len() {
696            if self.attrs[i].name.local == lname {
697                if found.is_none() {
698                    found = Some(mem::replace(
699                        &mut self.attrs[i].value,
700                        value.take().unwrap(),
701                    ));
702                    i += 1;
703                } else {
704                    found = Some(self.attrs.remove(i).value);
705                };
706            } else {
707                i += 1;
708            }
709        }
710        if found.is_none() {
711            self.attrs.push(Attribute {
712                name: QualName::new(None, ns!(), lname),
713                value: value.take().unwrap()
714            });
715        }
716        found
717    }
718}
719
720impl Node {
721    /// Construct a new element node.
722    pub fn new_elem(element: Element) -> Node {
723        Node::new(NodeData::Elem(element))
724    }
725
726    /// Construct a new text node.
727    pub fn new_text<T>(text: T) -> Node
728        where T: Into<StrTendril>
729    {
730        Node::new(NodeData::Text(text.into()))
731    }
732
733    /// Replace this node's data with a `NodeData::Hole`, and return the
734    /// original `NodeData`.
735    fn take_data(&mut self) -> NodeData {
736        // This remains private because if the Hole is reachable from
737        // DOCUMENT_NODE_ID node may assert panic.
738        mem::replace(&mut self.data, NodeData::Hole)
739    }
740
741    fn new(data: NodeData) -> Self {
742        Node {
743            parent: None,
744            prev_sibling: None,
745            next_sibling: None,
746            first_child: None,
747            last_child: None,
748            data,
749        }
750    }
751}
752
753impl Deref for Node {
754    type Target = NodeData;
755
756    #[inline]
757    fn deref(&self) -> &NodeData {
758        &self.data
759    }
760}
761
762impl DerefMut for Node {
763    #[inline]
764    fn deref_mut(&mut self) -> &mut NodeData {
765        &mut self.data
766    }
767}
768
769impl NodeData {
770    /// Return `Element` is this is an element.
771    pub fn as_element(&self) -> Option<&Element> {
772        match self {
773            NodeData::Elem(ref data) => Some(data),
774            _ => None,
775        }
776    }
777
778    /// Return mutable `Element` reference if this is an element.
779    pub fn as_element_mut(&mut self) -> Option<&mut Element> {
780        match self {
781            NodeData::Elem(ref mut data) => Some(data),
782            _ => None,
783        }
784    }
785
786    /// Return text (char data) if this is a text node.
787    pub fn as_text(&self) -> Option<&StrTendril> {
788        match self {
789            NodeData::Text(ref t) => Some(t),
790            _ => None,
791        }
792    }
793
794    /// Return mutable text (char data) reference if this is a text node.
795    pub fn as_text_mut(&mut self) -> Option<&mut StrTendril> {
796        match self {
797            NodeData::Text(ref mut t) => Some(t),
798            _ => None,
799        }
800    }
801
802    /// Return attribute value by given local attribute name, if this is an
803    /// element with that attribute present.
804    pub fn attr<LN>(&self, lname: LN) -> Option<&StrTendril>
805        where LN: Into<LocalName>
806    {
807        if let Some(edata) = self.as_element() {
808            edata.attr(lname)
809        } else {
810            None
811        }
812    }
813
814    /// Return true if this Node is an element with the given local name.
815    pub fn is_elem<LN>(&self, lname: LN) -> bool
816        where LN: Into<LocalName>
817    {
818        if let Some(edata) = self.as_element() {
819            edata.is_elem(lname)
820        } else {
821            false
822        }
823    }
824
825    #[inline]
826    fn assert_suitable_parent(&self) {
827        debug_assert!(
828            (if let NodeData::Document | NodeData::Elem(_) = self { true }
829             else { false }),
830            "Not a suitable parent: {:?}", self)
831    }
832}
833
834struct NodeStack1(Vec<NodeId>);
835
836impl NodeStack1 {
837    #[inline]
838    fn new() -> Self {
839        NodeStack1(Vec::with_capacity(16))
840    }
841
842    #[inline]
843    fn push_if(&mut self, id: Option<NodeId>) {
844        if let Some(id) = id {
845            self.0.push(id);
846        }
847    }
848
849    #[inline]
850    fn pop(&mut self) -> Option<NodeId> {
851        self.0.pop()
852    }
853}
854
855struct NodeStack2(Vec<(NodeId, NodeId)>);
856
857impl NodeStack2 {
858    #[inline]
859    fn new() -> Self {
860        NodeStack2(Vec::with_capacity(16))
861    }
862
863    #[inline]
864    fn push_if(&mut self, id: Option<NodeId>, oid: NodeId) {
865        if let Some(id) = id {
866            self.0.push((id, oid));
867        }
868    }
869
870    #[inline]
871    fn pop(&mut self) -> Option<(NodeId, NodeId)> {
872        self.0.pop()
873    }
874}