1use 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 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 pub fn children_count(&self) -> usize {
91 match self {
92 Self::Inner(inner) => inner.children_count(),
93 Self::Leaf(_) => 0,
94 }
95 }
96
97 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#[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 pub(crate) fn new(value: T::InnerValue) -> Self {
141 Self {
142 children: HashMap::new(),
143 value,
144 }
145 }
146
147 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 pub fn children_count(&self) -> usize {
165 self.children.len()
166 }
167
168 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 pub fn descendants_count<'a>(&'a self, tree: &'a PathTree<T>) -> usize {
187 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#[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 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#[derive(Debug, Clone)]
266pub struct LeafNode<V> {
267 pub value: V,
268}
269
270impl<V> LeafNode<V> {
271 pub(crate) const fn new(value: V) -> Self {
273 Self { value }
274 }
275}