Skip to main content

azul_core/
id.rs

1//! Node tree data structures and hierarchy management.
2//!
3//! This module provides the core data structures for managing DOM-like tree hierarchies:
4//!
5//! - `NodeId`: Type-safe node identifiers with Option<NodeId> optimization
6//! - `NodeHierarchy`: Parent-child relationships between nodes
7//! - `NodeDataContainer`: Generic storage for node data with efficient indexing
8//!
9//! # Memory Layout
10//!
11//! `NodeId` uses `NonZeroUsize` internally, allowing `Option<NodeId>` to be the same
12//! size as `NodeId` (pointer-sized). This is crucial for memory efficiency in large DOMs.
13//!
14//! # Performance
15//!
16//! - Node lookups are O(1) via direct array indexing
17//! - Parent/child traversal is O(1) via pre-computed indices
18//! - No heap allocations after initial tree construction
19
20use alloc::vec::Vec;
21use core::{
22    num::NonZeroUsize,
23    ops::{Index, IndexMut},
24    slice::Iter,
25};
26
27pub use self::node_id::NodeId;
28use crate::styled_dom::NodeHierarchyItem;
29
30/// Type alias for depth-first traversal results: (depth, node_id) pairs
31pub type NodeDepths = Vec<(usize, NodeId)>;
32
33#[cfg(not(feature = "std"))]
34use alloc::string::ToString;
35
36// Simple FFI-safe NodeId - just a wrapper around usize
37pub mod node_id {
38
39    use alloc::vec::Vec;
40    use core::{
41        fmt,
42        ops::{Add, AddAssign},
43    };
44
45    /// A type-safe identifier for a node within a DOM tree.
46    ///
47    /// `NodeId` is FFI-safe (`#[repr(C)]`) and stores a **zero-based** index internally.
48    /// Use `NodeId::index()` to get the array index for direct node access.
49    ///
50    /// # Zero-based indexing
51    ///
52    /// - `NodeId::new(0)` → first node (index 0)
53    /// - `NodeId::new(5)` → sixth node (index 5)
54    /// - Use `node_id.index()` to get the array index
55    ///
56    /// # FFI Encoding (for `Option<NodeId>`)
57    ///
58    /// When storing `Option<NodeId>` in FFI structs (like `NodeHierarchyItem`),
59    /// we use a **1-based encoding** to represent None:
60    ///
61    /// - `0` means `None` (no node)
62    /// - `n > 0` means `Some(NodeId(n - 1))`
63    ///
64    /// Use [`NodeId::from_usize`] to decode and [`NodeId::into_raw`] to encode.
65    /// See also: [`crate::styled_dom::NodeHierarchyItemId`] for the FFI wrapper type.
66    ///
67    /// # Warning
68    ///
69    /// **Never manually construct raw usize values for node hierarchy fields!**
70    /// Always use the provided `from_usize`/`into_raw` functions to avoid
71    /// off-by-one errors that can cause index-out-of-bounds panics.
72    ///
73    #[repr(C)]
74    #[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Hash)]
75    pub struct NodeId {
76        // Private field to prevent direct manipulation.
77        // Use NodeId::new() to create, NodeId::index() to read.
78        inner: usize,
79    }
80
81    impl NodeId {
82        /// The zero/first node ID (index 0).
83        pub const ZERO: NodeId = NodeId { inner: 0 };
84
85        /// Creates a new `NodeId` from a zero-based index.
86        #[inline(always)]
87        pub const fn new(value: usize) -> Self {
88            NodeId { inner: value }
89        }
90
91        /// Decodes a raw `usize` to `Option<NodeId>` using 1-based encoding.
92        ///
93        /// This is the inverse of [`NodeId::into_usize`].
94        ///
95        /// - `0` → `None` (no node)
96        /// - `n > 0` → `Some(NodeId(n - 1))`
97        ///
98        /// # Warning
99        ///
100        /// This function is for decoding values stored in FFI structs like
101        /// `NodeHierarchyItem`. Do not use raw usize values directly - always
102        /// decode them first!
103        #[inline]
104        pub const fn from_usize(value: usize) -> Option<Self> {
105            match value {
106                0 => None,
107                i => Some(NodeId { inner: i - 1 }),
108            }
109        }
110
111        /// Encodes `Option<NodeId>` to a raw `usize` for storage in FFI structs.
112        ///
113        /// - `None` → `0`
114        /// - `Some(NodeId(n))` → `n + 1`
115        ///
116        /// The returned value uses **1-based encoding**! A value of `0` means "no node",
117        /// NOT "node at index 0". Use [`NodeId::from_usize`] to decode.
118        ///
119        #[inline]
120        pub const fn into_raw(val: &Option<Self>) -> usize {
121            match val {
122                None => 0,
123                Some(s) => s.inner + 1,
124            }
125        }
126
127        /// Returns the **zero-based** index of this node.
128        ///
129        /// This is the actual array index where the node data is stored.
130        #[inline(always)]
131        pub const fn index(&self) -> usize {
132            self.inner
133        }
134    }
135
136    impl From<usize> for NodeId {
137        fn from(val: usize) -> Self {
138            NodeId::new(val)
139        }
140    }
141
142    impl From<NodeId> for usize {
143        fn from(val: NodeId) -> Self {
144            val.inner
145        }
146    }
147
148    impl Add<usize> for NodeId {
149        type Output = NodeId;
150        #[inline(always)]
151        fn add(self, other: usize) -> NodeId {
152            NodeId::new(self.inner + other)
153        }
154    }
155
156    impl AddAssign<usize> for NodeId {
157        #[inline(always)]
158        fn add_assign(&mut self, other: usize) {
159            *self = *self + other;
160        }
161    }
162
163    impl fmt::Display for NodeId {
164        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
165            write!(f, "{}", self.inner)
166        }
167    }
168
169    impl fmt::Debug for NodeId {
170        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
171            write!(f, "NodeId({})", self.inner)
172        }
173    }
174}
175
176/// Hierarchical information about a node (stores the indicies of the parent / child nodes).
177#[derive(Debug, Default, Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Hash)]
178pub struct Node {
179    pub parent: Option<NodeId>,
180    pub previous_sibling: Option<NodeId>,
181    pub next_sibling: Option<NodeId>,
182    pub last_child: Option<NodeId>,
183    // NOTE: first_child can be calculated on the fly:
184    //
185    //   - if last_child is None, first_child is None
186    //   - if last_child is Some, first_child is parent_index + 1
187    //
188    // This makes the "Node" struct take up 4 registers instead of 5
189    //
190    // pub first_child: Option<NodeId>,
191}
192
193// Node that initializes a Dom
194pub const ROOT_NODE: Node = Node {
195    parent: None,
196    previous_sibling: None,
197    next_sibling: None,
198    last_child: None,
199};
200
201impl Node {
202    pub const ROOT: Node = ROOT_NODE;
203
204    #[inline]
205    pub const fn has_parent(&self) -> bool {
206        self.parent.is_some()
207    }
208    #[inline]
209    pub const fn has_previous_sibling(&self) -> bool {
210        self.previous_sibling.is_some()
211    }
212    #[inline]
213    pub const fn has_next_sibling(&self) -> bool {
214        self.next_sibling.is_some()
215    }
216    #[inline]
217    pub const fn has_first_child(&self) -> bool {
218        self.last_child.is_some() /* last_child and first_child are always set together */
219    }
220    #[inline]
221    pub const fn has_last_child(&self) -> bool {
222        self.last_child.is_some()
223    }
224
225    #[inline]
226    pub fn get_first_child(&self, current_node_id: NodeId) -> Option<NodeId> {
227        // last_child and first_child are always set together
228        self.last_child.map(|_| current_node_id + 1)
229    }
230}
231
232/// The hierarchy of nodes is stored separately from the actual node content in order
233/// to save on memory, since the hierarchy can be re-used across several DOM trees even
234/// if the content changes.
235#[derive(Debug, Default, Clone, PartialEq, Hash, Eq, PartialOrd, Ord)]
236pub struct NodeHierarchy {
237    pub internal: Vec<Node>,
238}
239
240impl NodeHierarchy {
241    #[inline(always)]
242    pub const fn new(data: Vec<Node>) -> Self {
243        Self { internal: data }
244    }
245
246    #[inline(always)]
247    pub fn as_ref<'a>(&'a self) -> NodeHierarchyRef<'a> {
248        NodeHierarchyRef {
249            internal: &self.internal[..],
250        }
251    }
252
253    #[inline(always)]
254    pub fn as_ref_mut<'a>(&'a mut self) -> NodeHierarchyRefMut<'a> {
255        NodeHierarchyRefMut {
256            internal: &mut self.internal[..],
257        }
258    }
259}
260
261/// The hierarchy of nodes is stored separately from the actual node content in order
262/// to save on memory, since the hierarchy can be re-used across several DOM trees even
263/// if the content changes.
264#[derive(Debug, PartialEq, Hash, Eq)]
265pub struct NodeHierarchyRef<'a> {
266    pub internal: &'a [Node],
267}
268
269#[derive(Debug, PartialEq, Hash, Eq)]
270pub struct NodeHierarchyRefMut<'a> {
271    pub internal: &'a mut [Node],
272}
273
274impl<'a> NodeHierarchyRef<'a> {
275    #[inline(always)]
276    pub fn from_slice(data: &'a [Node]) -> NodeHierarchyRef<'a> {
277        NodeHierarchyRef { internal: data }
278    }
279
280    #[inline(always)]
281    pub fn len(&self) -> usize {
282        self.internal.len()
283    }
284
285    #[inline(always)]
286    pub fn get(&self, id: NodeId) -> Option<&Node> {
287        self.internal.get(id.index())
288    }
289
290    #[inline(always)]
291    pub fn linear_iter(&self) -> LinearIterator {
292        LinearIterator {
293            arena_len: self.len(),
294            position: 0,
295        }
296    }
297
298    /// Returns the `(depth, NodeId)` of all parent nodes (i.e. nodes that have a
299    /// `first_child`), in depth sorted order, (i.e. `NodeId(0)` with a depth of 0) is
300    /// the first element.
301    ///
302    /// Runtime: O(n) max
303    pub fn get_parents_sorted_by_depth(&self) -> NodeDepths {
304        let mut non_leaf_nodes = Vec::new();
305        let mut current_children = vec![(0, NodeId::new(0))];
306        let mut next_children = Vec::new();
307        let mut depth = 1_usize;
308
309        loop {
310            for id in &current_children {
311                for child_id in id.1.children(self).filter(|id| self[*id].has_first_child()) {
312                    next_children.push((depth, child_id));
313                }
314            }
315
316            non_leaf_nodes.extend(&mut current_children.drain(..));
317
318            if next_children.is_empty() {
319                break;
320            } else {
321                current_children.extend(&mut next_children.drain(..));
322                depth += 1;
323            }
324        }
325
326        non_leaf_nodes
327    }
328
329    /// Returns the number of all subtree items - runtime O(1)
330    #[inline]
331    pub fn subtree_len(&self, parent_id: NodeId) -> usize {
332        let self_item_index = parent_id.index();
333        let next_item_index = match self[parent_id].next_sibling {
334            None => self.len(),
335            Some(s) => s.index(),
336        };
337        next_item_index - self_item_index - 1
338    }
339
340    /// Returns the index in the parent node of a certain NodeId
341    /// (starts at 0, i.e. the first node has the index of 0).
342    #[inline]
343    pub fn get_index_in_parent(&self, node_id: NodeId) -> usize {
344        node_id.preceding_siblings(&self).count() - 1
345    }
346}
347
348impl<'a> NodeHierarchyRefMut<'a> {
349    pub fn from_slice(data: &'a mut [Node]) -> NodeHierarchyRefMut<'a> {
350        NodeHierarchyRefMut { internal: data }
351    }
352}
353
354#[derive(Debug, Clone, PartialEq, Hash, Eq, PartialOrd, Ord)]
355pub struct NodeDataContainer<T> {
356    pub internal: Vec<T>,
357}
358
359impl<T> From<Vec<T>> for NodeDataContainer<T> {
360    fn from(v: Vec<T>) -> NodeDataContainer<T> {
361        NodeDataContainer { internal: v }
362    }
363}
364
365#[derive(Debug, PartialEq, Hash, Eq, PartialOrd, Ord)]
366pub struct NodeDataContainerRef<'a, T> {
367    pub internal: &'a [T],
368}
369
370#[derive(Debug, PartialEq, Hash, Eq, PartialOrd, Ord)]
371pub struct NodeDataContainerRefMut<'a, T> {
372    pub internal: &'a mut [T],
373}
374
375impl<'a, T> NodeDataContainerRefMut<'a, T> {
376    pub fn as_borrowing_ref<'b>(&'b self) -> NodeDataContainerRef<'b, T> {
377        NodeDataContainerRef {
378            internal: &*self.internal,
379        }
380    }
381}
382
383impl<T> Default for NodeDataContainer<T> {
384    fn default() -> Self {
385        Self {
386            internal: Vec::new(),
387        }
388    }
389}
390
391impl<'a> Index<NodeId> for NodeHierarchyRef<'a> {
392    type Output = Node;
393
394    #[inline(always)]
395    fn index(&self, node_id: NodeId) -> &Node {
396        &self.internal[node_id.index()]
397    }
398}
399
400impl<'a> Index<NodeId> for NodeHierarchyRefMut<'a> {
401    type Output = Node;
402
403    #[inline(always)]
404    fn index(&self, node_id: NodeId) -> &Node {
405        &self.internal[node_id.index()]
406    }
407}
408
409impl<'a> IndexMut<NodeId> for NodeHierarchyRefMut<'a> {
410    #[inline(always)]
411    fn index_mut(&mut self, node_id: NodeId) -> &mut Node {
412        &mut self.internal[node_id.index()]
413    }
414}
415
416impl<T> NodeDataContainer<T> {
417    #[inline(always)]
418    pub const fn new(data: Vec<T>) -> Self {
419        Self { internal: data }
420    }
421
422    #[inline(always)]
423    pub fn is_empty(&self) -> bool {
424        self.internal.len() == 0
425    }
426
427    #[inline(always)]
428    pub fn as_ref<'a>(&'a self) -> NodeDataContainerRef<'a, T> {
429        NodeDataContainerRef {
430            internal: &self.internal[..],
431        }
432    }
433
434    #[inline(always)]
435    pub fn as_ref_mut<'a>(&'a mut self) -> NodeDataContainerRefMut<'a, T> {
436        NodeDataContainerRefMut {
437            internal: &mut self.internal[..],
438        }
439    }
440
441    #[inline(always)]
442    pub fn len(&self) -> usize {
443        self.internal.len()
444    }
445}
446
447impl<'a, T: 'a> NodeDataContainerRefMut<'a, T> {
448    #[inline(always)]
449    pub fn from_slice(data: &'a mut [T]) -> NodeDataContainerRefMut<'a, T> {
450        NodeDataContainerRefMut { internal: data }
451    }
452}
453
454impl<'a, T: 'a> NodeDataContainerRefMut<'a, T> {
455    #[inline(always)]
456    pub fn get_mut(&mut self, id: NodeId) -> Option<&mut T> {
457        self.internal.get_mut(id.index())
458    }
459    #[inline(always)]
460    pub fn get_mut_extended_lifetime(&'a mut self, id: NodeId) -> Option<&'a mut T> {
461        self.internal.get_mut(id.index())
462    }
463}
464
465impl<'a, T: Send + 'a> NodeDataContainerRefMut<'a, T> {
466    pub fn transform_multithread<U: Send, F: Send + Sync>(
467        &mut self,
468        closure: F,
469    ) -> NodeDataContainer<U>
470    where
471        F: Fn(&mut T, NodeId) -> U,
472    {
473        NodeDataContainer {
474            internal: self
475                .internal
476                .iter_mut()
477                .enumerate()
478                .map(|(node_id, node)| closure(node, NodeId::new(node_id)))
479                .collect::<Vec<U>>(),
480        }
481    }
482
483    pub fn transform_multithread_optional<U: Send, F: Send + Sync>(&mut self, closure: F) -> Vec<U>
484    where
485        F: Fn(&mut T, NodeId) -> Option<U>,
486    {
487        self.internal
488            .iter_mut()
489            .enumerate()
490            .filter_map(|(node_id, node)| closure(node, NodeId::new(node_id)))
491            .collect::<Vec<U>>()
492    }
493}
494
495impl<'a, T: Send + 'a> NodeDataContainerRef<'a, T> {
496    pub fn transform_nodeid<U: Send, F: Send + Sync>(&self, closure: F) -> NodeDataContainer<U>
497    where
498        F: Fn(NodeId) -> U,
499    {
500        let len = self.len();
501        NodeDataContainer {
502            internal: (0..len)
503                .into_iter()
504                .map(|node_id| closure(NodeId::new(node_id)))
505                .collect::<Vec<U>>(),
506        }
507    }
508
509    pub fn transform_nodeid_multithreaded_optional<U: Send, F: Send + Sync>(
510        &self,
511        closure: F,
512    ) -> NodeDataContainer<U>
513    where
514        F: Fn(NodeId) -> Option<U>,
515    {
516        let len = self.len();
517        NodeDataContainer {
518            internal: (0..len)
519                .into_iter()
520                .filter_map(|node_id| closure(NodeId::new(node_id)))
521                .collect::<Vec<U>>(),
522        }
523    }
524}
525
526impl<'a, T: 'a> NodeDataContainerRef<'a, T> {
527    #[inline(always)]
528    pub fn get_extended_lifetime(&self, id: NodeId) -> Option<&'a T> {
529        self.internal.get(id.index())
530    }
531
532    #[inline(always)]
533    pub fn from_slice(data: &'a [T]) -> NodeDataContainerRef<'a, T> {
534        NodeDataContainerRef { internal: data }
535    }
536
537    #[inline(always)]
538    pub fn len(&self) -> usize {
539        self.internal.len()
540    }
541
542    pub fn transform_singlethread<U, F>(&self, mut closure: F) -> NodeDataContainer<U>
543    where
544        F: FnMut(&T, NodeId) -> U,
545    {
546        // TODO if T: Send (which is usually the case), then we could use rayon here!
547        NodeDataContainer {
548            internal: self
549                .internal
550                .iter()
551                .enumerate()
552                .map(|(node_id, node)| closure(node, NodeId::new(node_id)))
553                .collect(),
554        }
555    }
556
557    #[inline(always)]
558    pub fn get(&self, id: NodeId) -> Option<&T> {
559        self.internal.get(id.index())
560    }
561
562    #[inline(always)]
563    pub fn iter(&self) -> Iter<T> {
564        self.internal.iter()
565    }
566
567    #[inline(always)]
568    pub fn linear_iter(&self) -> LinearIterator {
569        LinearIterator {
570            arena_len: self.len(),
571            position: 0,
572        }
573    }
574}
575
576impl<'a, T> Index<NodeId> for NodeDataContainerRef<'a, T> {
577    type Output = T;
578
579    #[inline(always)]
580    fn index(&self, node_id: NodeId) -> &T {
581        &self.internal[node_id.index()]
582    }
583}
584
585impl<'a, T> Index<NodeId> for NodeDataContainerRefMut<'a, T> {
586    type Output = T;
587
588    #[inline(always)]
589    fn index(&self, node_id: NodeId) -> &T {
590        &self.internal[node_id.index()]
591    }
592}
593
594impl<'a, T> IndexMut<NodeId> for NodeDataContainerRefMut<'a, T> {
595    #[inline(always)]
596    fn index_mut(&mut self, node_id: NodeId) -> &mut T {
597        &mut self.internal[node_id.index()]
598    }
599}
600
601impl NodeId {
602    /// Return an iterator of references to this node and its ancestors.
603    ///
604    /// Call `.next().unwrap()` once on the iterator to skip the node itself.
605    #[inline]
606    pub const fn ancestors<'a>(self, node_hierarchy: &'a NodeHierarchyRef<'a>) -> Ancestors<'a> {
607        Ancestors {
608            node_hierarchy,
609            node: Some(self),
610        }
611    }
612
613    /// Return an iterator of references to this node and the siblings before it.
614    ///
615    /// Call `.next().unwrap()` once on the iterator to skip the node itself.
616    #[inline]
617    pub const fn preceding_siblings<'a>(
618        self,
619        node_hierarchy: &'a NodeHierarchyRef<'a>,
620    ) -> PrecedingSiblings<'a> {
621        PrecedingSiblings {
622            node_hierarchy,
623            node: Some(self),
624        }
625    }
626
627    /// Return an iterator of references to this node and the siblings after it.
628    ///
629    /// Call `.next().unwrap()` once on the iterator to skip the node itself.
630    #[inline]
631    pub const fn following_siblings<'a>(
632        self,
633        node_hierarchy: &'a NodeHierarchyRef<'a>,
634    ) -> FollowingSiblings<'a> {
635        FollowingSiblings {
636            node_hierarchy,
637            node: Some(self),
638        }
639    }
640
641    /// Return an iterator of references to this node’s children.
642    #[inline]
643    pub fn children<'a>(self, node_hierarchy: &'a NodeHierarchyRef<'a>) -> Children<'a> {
644        Children {
645            node_hierarchy,
646            node: node_hierarchy[self].get_first_child(self),
647        }
648    }
649
650    /// Return an iterator of references to this node’s children, in reverse order.
651    #[inline]
652    pub fn reverse_children<'a>(
653        self,
654        node_hierarchy: &'a NodeHierarchyRef<'a>,
655    ) -> ReverseChildren<'a> {
656        ReverseChildren {
657            node_hierarchy,
658            node: node_hierarchy[self].last_child,
659        }
660    }
661
662    /// Return an iterator of references to this node and its descendants, in tree order.
663    ///
664    /// Parent nodes appear before the descendants.
665    /// Call `.next().unwrap()` once on the iterator to skip the node itself.
666    #[inline]
667    pub const fn descendants<'a>(
668        self,
669        node_hierarchy: &'a NodeHierarchyRef<'a>,
670    ) -> Descendants<'a> {
671        Descendants(self.traverse(node_hierarchy))
672    }
673
674    /// Return an iterator of references to this node and its descendants, in tree order.
675    #[inline]
676    pub const fn traverse<'a>(self, node_hierarchy: &'a NodeHierarchyRef<'a>) -> Traverse<'a> {
677        Traverse {
678            node_hierarchy,
679            root: self,
680            next: Some(NodeEdge::Start(self)),
681        }
682    }
683
684    /// Return an iterator of references to this node and its descendants, in tree order.
685    #[inline]
686    pub const fn reverse_traverse<'a>(
687        self,
688        node_hierarchy: &'a NodeHierarchyRef<'a>,
689    ) -> ReverseTraverse<'a> {
690        ReverseTraverse {
691            node_hierarchy,
692            root: self,
693            next: Some(NodeEdge::End(self)),
694        }
695    }
696}
697
698macro_rules! impl_node_iterator {
699    ($name:ident, $next:expr) => {
700        impl<'a> Iterator for $name<'a> {
701            type Item = NodeId;
702
703            fn next(&mut self) -> Option<NodeId> {
704                match self.node.take() {
705                    Some(node) => {
706                        self.node = $next(&self.node_hierarchy[node]);
707                        Some(node)
708                    }
709                    None => None,
710                }
711            }
712        }
713    };
714}
715
716/// An linear iterator, does not respect the DOM in any way,
717/// it just iterates over the nodes like a Vec
718#[derive(Debug, Copy, Clone)]
719pub struct LinearIterator {
720    arena_len: usize,
721    position: usize,
722}
723
724impl Iterator for LinearIterator {
725    type Item = NodeId;
726
727    fn next(&mut self) -> Option<NodeId> {
728        if self.arena_len < 1 || self.position > (self.arena_len - 1) {
729            None
730        } else {
731            let new_id = Some(NodeId::new(self.position));
732            self.position += 1;
733            new_id
734        }
735    }
736}
737
738/// An iterator of references to the ancestors a given node.
739pub struct Ancestors<'a> {
740    node_hierarchy: &'a NodeHierarchyRef<'a>,
741    node: Option<NodeId>,
742}
743
744impl_node_iterator!(Ancestors, |node: &Node| node.parent);
745
746/// An iterator of references to the siblings before a given node.
747pub struct PrecedingSiblings<'a> {
748    node_hierarchy: &'a NodeHierarchyRef<'a>,
749    node: Option<NodeId>,
750}
751
752impl_node_iterator!(PrecedingSiblings, |node: &Node| node.previous_sibling);
753
754/// An iterator of references to the siblings after a given node.
755pub struct FollowingSiblings<'a> {
756    node_hierarchy: &'a NodeHierarchyRef<'a>,
757    node: Option<NodeId>,
758}
759
760impl_node_iterator!(FollowingSiblings, |node: &Node| node.next_sibling);
761
762/// Special iterator for using NodeDataContainerRef<AzNode> instead of NodeHierarchy
763pub struct AzChildren<'a> {
764    node_hierarchy: &'a NodeDataContainerRef<'a, NodeHierarchyItem>,
765    node: Option<NodeId>,
766}
767
768impl<'a> Iterator for AzChildren<'a> {
769    type Item = NodeId;
770
771    fn next(&mut self) -> Option<NodeId> {
772        match self.node.take() {
773            Some(node) => {
774                self.node = self.node_hierarchy[node].next_sibling_id();
775                Some(node)
776            }
777            None => None,
778        }
779    }
780}
781
782/// Special iterator for using NodeDataContainerRef<AzNode> instead of NodeHierarchy
783pub struct AzReverseChildren<'a> {
784    node_hierarchy: &'a NodeDataContainerRef<'a, NodeHierarchyItem>,
785    node: Option<NodeId>,
786}
787
788impl<'a> Iterator for AzReverseChildren<'a> {
789    type Item = NodeId;
790
791    fn next(&mut self) -> Option<NodeId> {
792        match self.node.take() {
793            Some(node) => {
794                self.node = self.node_hierarchy[node].previous_sibling_id();
795                Some(node)
796            }
797            None => None,
798        }
799    }
800}
801
802impl NodeId {
803    // Traverse up through the hierarchy a node matching the predicate is found
804    //
805    // Necessary to resolve the last positioned (= relative)
806    // element of an absolute ndoe
807    pub fn get_nearest_matching_parent<'a, F>(
808        self,
809        node_hierarchy: &'a NodeDataContainerRef<'a, NodeHierarchyItem>,
810        predicate: F,
811    ) -> Option<NodeId>
812    where
813        F: Fn(NodeId) -> bool,
814    {
815        let mut current_node = node_hierarchy[self].parent_id()?;
816        loop {
817            match predicate(current_node) {
818                true => {
819                    return Some(current_node);
820                }
821                false => {
822                    current_node = node_hierarchy[current_node].parent_id()?;
823                }
824            }
825        }
826    }
827
828    /// Return the children of this node (necessary for parallel iteration over children)
829    #[inline]
830    pub fn az_children_collect<'a>(
831        self,
832        node_hierarchy: &'a NodeDataContainerRef<'a, NodeHierarchyItem>,
833    ) -> Vec<NodeId> {
834        self.az_children(node_hierarchy).collect()
835    }
836
837    /// Return an iterator of references to this node’s children.
838    #[inline]
839    pub fn az_children<'a>(
840        self,
841        node_hierarchy: &'a NodeDataContainerRef<'a, NodeHierarchyItem>,
842    ) -> AzChildren<'a> {
843        AzChildren {
844            node_hierarchy,
845            node: node_hierarchy[self].first_child_id(self),
846        }
847    }
848
849    /// Return an iterator of references to this node’s children.
850    #[inline]
851    pub fn az_reverse_children<'a>(
852        self,
853        node_hierarchy: &'a NodeDataContainerRef<'a, NodeHierarchyItem>,
854    ) -> AzReverseChildren<'a> {
855        AzReverseChildren {
856            node_hierarchy,
857            node: node_hierarchy[self].last_child_id(),
858        }
859    }
860}
861
862/// An iterator of references to the children of a given node.
863pub struct Children<'a> {
864    node_hierarchy: &'a NodeHierarchyRef<'a>,
865    node: Option<NodeId>,
866}
867
868impl_node_iterator!(Children, |node: &Node| node.next_sibling);
869
870/// An iterator of references to the children of a given node, in reverse order.
871pub struct ReverseChildren<'a> {
872    node_hierarchy: &'a NodeHierarchyRef<'a>,
873    node: Option<NodeId>,
874}
875
876impl_node_iterator!(ReverseChildren, |node: &Node| node.previous_sibling);
877
878/// An iterator of references to a given node and its descendants, in tree order.
879pub struct Descendants<'a>(Traverse<'a>);
880
881impl<'a> Iterator for Descendants<'a> {
882    type Item = NodeId;
883
884    fn next(&mut self) -> Option<NodeId> {
885        loop {
886            match self.0.next() {
887                Some(NodeEdge::Start(node)) => return Some(node),
888                Some(NodeEdge::End(_)) => {}
889                None => return None,
890            }
891        }
892    }
893}
894
895#[derive(Debug, Clone)]
896pub enum NodeEdge<T> {
897    /// Indicates that start of a node that has children.
898    /// Yielded by `Traverse::next` before the node’s descendants.
899    /// In HTML or XML, this corresponds to an opening tag like `<div>`
900    Start(T),
901
902    /// Indicates that end of a node that has children.
903    /// Yielded by `Traverse::next` after the node’s descendants.
904    /// In HTML or XML, this corresponds to a closing tag like `</div>`
905    End(T),
906}
907
908impl<T> NodeEdge<T> {
909    pub fn inner_value(self) -> T {
910        use self::NodeEdge::*;
911        match self {
912            Start(t) => t,
913            End(t) => t,
914        }
915    }
916}
917
918/// An iterator of references to a given node and its descendants, in tree order.
919pub struct Traverse<'a> {
920    node_hierarchy: &'a NodeHierarchyRef<'a>,
921    root: NodeId,
922    next: Option<NodeEdge<NodeId>>,
923}
924
925impl<'a> Iterator for Traverse<'a> {
926    type Item = NodeEdge<NodeId>;
927
928    fn next(&mut self) -> Option<NodeEdge<NodeId>> {
929        let item = self.next.take()?;
930        self.next = self.compute_next(&item);
931        Some(item)
932    }
933}
934
935impl<'a> Traverse<'a> {
936    /// Compute the next edge in tree order
937    fn compute_next(&self, item: &NodeEdge<NodeId>) -> Option<NodeEdge<NodeId>> {
938        match *item {
939            NodeEdge::Start(node) => Some(match self.node_hierarchy[node].get_first_child(node) {
940                Some(first_child) => NodeEdge::Start(first_child),
941                None => NodeEdge::End(node),
942            }),
943            NodeEdge::End(node) if node == self.root => None,
944            NodeEdge::End(node) => self.next_from_end(node),
945        }
946    }
947
948    /// From an End edge, find the next edge (next sibling's Start, or parent's End)
949    fn next_from_end(&self, node: NodeId) -> Option<NodeEdge<NodeId>> {
950        let h = &self.node_hierarchy[node];
951        h.next_sibling
952            .map(NodeEdge::Start)
953            .or_else(|| h.parent.map(NodeEdge::End))
954    }
955}
956
957/// An iterator of references to a given node and its descendants, in reverse tree order.
958pub struct ReverseTraverse<'a> {
959    node_hierarchy: &'a NodeHierarchyRef<'a>,
960    root: NodeId,
961    next: Option<NodeEdge<NodeId>>,
962}
963
964impl<'a> Iterator for ReverseTraverse<'a> {
965    type Item = NodeEdge<NodeId>;
966
967    fn next(&mut self) -> Option<NodeEdge<NodeId>> {
968        let item = self.next.take()?;
969        self.next = self.compute_next(&item);
970        Some(item)
971    }
972}
973
974impl<'a> ReverseTraverse<'a> {
975    /// Compute the next edge in reverse tree order
976    fn compute_next(&self, item: &NodeEdge<NodeId>) -> Option<NodeEdge<NodeId>> {
977        match *item {
978            NodeEdge::End(node) => Some(match self.node_hierarchy[node].last_child {
979                Some(last_child) => NodeEdge::End(last_child),
980                None => NodeEdge::Start(node),
981            }),
982            NodeEdge::Start(node) if node == self.root => None,
983            NodeEdge::Start(node) => self.next_from_start(node),
984        }
985    }
986
987    /// From a Start edge, find the next edge (previous sibling's End, or parent's Start)
988    fn next_from_start(&self, node: NodeId) -> Option<NodeEdge<NodeId>> {
989        let h = &self.node_hierarchy[node];
990        h.previous_sibling
991            .map(NodeEdge::End)
992            .or_else(|| h.parent.map(NodeEdge::Start))
993    }
994}