im_pathtree/
node.rs

1// SPDX-FileCopyrightText: The im-pathtree authors
2// SPDX-License-Identifier: MPL-2.0
3
4use std::borrow::Borrow as _;
5
6use crate::{HalfEdge, HashMap, PathTree, PathTreeTypes};
7
8const DESCENDANTS_ITER_STACK_CAPACITY: usize = 1024;
9
10#[derive(Debug, Clone)]
11pub enum NodeValue<T: PathTreeTypes> {
12    Inner(T::InnerValue),
13    Leaf(T::LeafValue),
14}
15
16#[derive(Debug, Clone)]
17pub enum Node<T>
18where
19    T: PathTreeTypes,
20{
21    Inner(InnerNode<T>),
22    Leaf(LeafNode<T::LeafValue>),
23}
24
25impl<T> Node<T>
26where
27    T: PathTreeTypes,
28{
29    pub(crate) fn from_value_without_children(value: NodeValue<T>) -> Self {
30        let node = match value {
31            NodeValue::Inner(value) => Self::Inner(InnerNode::new(value)),
32            NodeValue::Leaf(value) => Self::Leaf(LeafNode::new(value)),
33        };
34        debug_assert_eq!(node.children_count(), 0);
35        node
36    }
37
38    pub const fn inner_value(&self) -> Option<&T::InnerValue> {
39        match self {
40            Self::Inner(InnerNode { value, .. }) => Some(value),
41            Self::Leaf(LeafNode { .. }) => None,
42        }
43    }
44
45    pub const fn leaf_value(&self) -> Option<&T::LeafValue> {
46        match self {
47            Self::Leaf(LeafNode { value, .. }) => Some(value),
48            Self::Inner(InnerNode { .. }) => None,
49        }
50    }
51}
52
53impl<T> From<InnerNode<T>> for Node<T>
54where
55    T: PathTreeTypes,
56{
57    fn from(inner: InnerNode<T>) -> Self {
58        Self::Inner(inner)
59    }
60}
61
62impl<T> From<LeafNode<T::LeafValue>> for Node<T>
63where
64    T: PathTreeTypes,
65{
66    fn from(leaf: LeafNode<T::LeafValue>) -> Self {
67        Self::Leaf(leaf)
68    }
69}
70
71impl<T> Node<T>
72where
73    T: PathTreeTypes,
74{
75    /// Returns an iterator over all children of this node
76    ///
77    /// Only includes direct children, not grandchildren or other descendants.
78    pub fn children(&self) -> impl ExactSizeIterator<Item = HalfEdge<'_, T>> + '_ {
79        match self {
80            Self::Inner(inner) => itertools::Either::Left(inner.children()),
81            Self::Leaf(_) => itertools::Either::Right(std::iter::empty()),
82        }
83    }
84
85    /// Returns the number of children.
86    ///
87    /// Only includes direct children, not grandchildren or other descendants.
88    ///
89    /// In constant time, i.e. O(1).
90    pub fn children_count(&self) -> usize {
91        match self {
92            Self::Inner(inner) => inner.children_count(),
93            Self::Leaf(_) => 0,
94        }
95    }
96
97    /// Find a child node by its path segment.
98    ///
99    /// Returns the id of the child node or `None` if not found.
100    pub fn find_child(&self, child_path_segment: &T::PathSegment) -> Option<T::NodeId> {
101        match self {
102            Self::Inner(inner) => inner.find_child(child_path_segment),
103            Self::Leaf(_) => None,
104        }
105    }
106
107    pub(crate) fn descendants<'a>(
108        &'a self,
109        tree: &'a PathTree<T>,
110    ) -> DepthFirstDescendantsIter<'a, T> {
111        match self {
112            Self::Inner(inner) => inner.descendants(tree),
113            Self::Leaf(_) => DepthFirstDescendantsIter::empty(tree),
114        }
115    }
116
117    pub(crate) fn descendants_count<'a>(&'a self, tree: &'a PathTree<T>) -> usize {
118        match self {
119            Self::Inner(inner) => inner.descendants_count(tree),
120            Self::Leaf(_) => 0,
121        }
122    }
123}
124
125/// Intrinsic data of an inner node.
126#[derive(Debug, Clone)]
127pub struct InnerNode<T>
128where
129    T: PathTreeTypes,
130{
131    pub(crate) children: HashMap<T::PathSegmentOwned, T::NodeId>,
132    pub value: T::InnerValue,
133}
134
135impl<T> InnerNode<T>
136where
137    T: PathTreeTypes,
138{
139    /// Create an empty inner node with no children
140    pub(crate) fn new(value: T::InnerValue) -> Self {
141        Self {
142            children: HashMap::new(),
143            value,
144        }
145    }
146
147    /// Edges to children of this node
148    ///
149    /// In arbitrary but stable ordering.
150    pub fn children(&self) -> impl ExactSizeIterator<Item = HalfEdge<'_, T>> + '_ {
151        self.children
152            .iter()
153            .map(|(path_segment, node_id)| HalfEdge {
154                path_segment: path_segment.borrow(),
155                node_id: *node_id,
156            })
157    }
158
159    /// Returns the number of children.
160    ///
161    /// Only includes direct children, not grandchildren or other descendants.
162    ///
163    /// In constant time, i.e. O(1).
164    pub fn children_count(&self) -> usize {
165        self.children.len()
166    }
167
168    /// Find a child node by its path segment.
169    ///
170    /// Returns the id of the child node or `None` if not found.
171    pub fn find_child(&self, child_path_segment: &T::PathSegment) -> Option<T::NodeId> {
172        self.children.get(child_path_segment).copied()
173    }
174
175    fn descendants<'a>(&'a self, tree: &'a PathTree<T>) -> DepthFirstDescendantsIter<'a, T> {
176        let mut iter = DepthFirstDescendantsIter::new(tree, DESCENDANTS_ITER_STACK_CAPACITY);
177        iter.push_parent(self);
178        iter
179    }
180
181    /// Number of descendants of this node
182    ///
183    /// Recursively counts all descendants of this node.
184    ///
185    /// More efficient than `descendants().count()`.
186    pub fn descendants_count<'a>(&'a self, tree: &'a PathTree<T>) -> usize {
187        // This recursive implementation is probably faster than `descendants().count()`.
188        // TODO: Replace by a non-recursive version.
189        self.children().fold(
190            0,
191            |count,
192             HalfEdge {
193                 path_segment: _,
194                 node_id,
195             }| {
196                count
197                    + 1
198                    + tree
199                        .lookup_node(node_id)
200                        .map_or(0, |node| node.node.descendants_count(tree))
201            },
202        )
203    }
204}
205
206/// Iterator over descendants of a node
207///
208/// Returned by [`PathTree::descendant_nodes()`].
209#[derive(Debug)]
210pub struct DepthFirstDescendantsIter<'a, T>
211where
212    T: PathTreeTypes,
213{
214    tree: &'a PathTree<T>,
215    children_stack: Vec<HalfEdge<'a, T>>,
216}
217
218impl<'a, T> DepthFirstDescendantsIter<'a, T>
219where
220    T: PathTreeTypes,
221{
222    fn new(tree: &'a PathTree<T>, stack_capacity: usize) -> Self {
223        let children_stack = Vec::with_capacity(stack_capacity);
224        Self {
225            tree,
226            children_stack,
227        }
228    }
229
230    fn empty(tree: &'a PathTree<T>) -> Self {
231        Self::new(tree, 0)
232    }
233
234    fn push_parent(&mut self, parent: &'a InnerNode<T>) {
235        let len_before = self.children_stack.len();
236        self.children_stack.extend(parent.children());
237        debug_assert!(self.children_stack.len() >= len_before);
238        // Reverse the order of children so that the first child ends up at the top of the stack.
239        self.children_stack[len_before..].reverse();
240    }
241}
242
243impl<'a, T> Iterator for DepthFirstDescendantsIter<'a, T>
244where
245    T: PathTreeTypes,
246{
247    type Item = HalfEdge<'a, T>;
248
249    fn next(&mut self) -> Option<Self::Item> {
250        let child = self.children_stack.pop()?;
251        let Some(node) = self.tree.lookup_node(child.node_id) else {
252            unreachable!("child node not found: {node_id}", node_id = child.node_id);
253        };
254        match &node.node {
255            Node::Inner(inner) => {
256                self.push_parent(inner);
257            }
258            Node::Leaf(_) => (),
259        }
260        Some(child)
261    }
262}
263
264/// Intrinsic data of a leaf node.
265#[derive(Debug, Clone)]
266pub struct LeafNode<V> {
267    pub value: V,
268}
269
270impl<V> LeafNode<V> {
271    /// Create a leaf node
272    pub(crate) const fn new(value: V) -> Self {
273        Self { value }
274    }
275}