im_pathtree/
tree.rs

1// SPDX-FileCopyrightText: The im-pathtree authors
2// SPDX-License-Identifier: MPL-2.0
3
4use std::{borrow::Borrow, fmt, hash::Hash, marker::PhantomData, num::NonZeroUsize, sync::Arc};
5
6use derive_more::{Display, Error};
7
8use crate::{
9    HalfEdge, HalfEdgeOwned, HalfEdgeTreeNode, HashMap, InnerNode, LeafNode, Node, NodeValue,
10    PathSegment, RootPath, SegmentedPath as _,
11};
12
13pub trait NewNodeId<T> {
14    fn new_node_id(&mut self) -> T;
15}
16
17/// Type system for [`PathTree`].
18pub trait PathTreeTypes: Clone + Default + fmt::Debug {
19    type NodeId: Clone + Copy + Eq + Hash + fmt::Debug + fmt::Display;
20    type NewNodeId: NewNodeId<Self::NodeId> + Clone + fmt::Debug;
21    type InnerValue: Clone + fmt::Debug;
22    type LeafValue: Clone + fmt::Debug;
23    type PathSegmentOwned: Clone + Eq + Hash + fmt::Debug + Borrow<Self::PathSegment>;
24    type PathSegment: PathSegment + ?Sized;
25    type RootPath: RootPath<Self::PathSegment> + ?Sized;
26
27    fn path_segment_to_owned(path_segment: &Self::PathSegment) -> Self::PathSegmentOwned;
28}
29
30/// A conflicting path from a parent to a child node.
31#[derive(Debug)]
32pub struct TreeNodeParentChildPathConflict<T>
33where
34    T: PathTreeTypes,
35{
36    pub parent_node: Arc<TreeNode<T>>,
37    pub child_path_segment: T::PathSegmentOwned,
38}
39
40#[derive(Debug, Display, Error)]
41pub enum InsertOrUpdateNodeValueError<T>
42where
43    T: PathTreeTypes,
44{
45    #[display("path conflict")]
46    PathConflict {
47        conflict: TreeNodeParentChildPathConflict<T>,
48        value: NodeValue<T>,
49    },
50    #[display("value type mismatch")]
51    ValueTypeMismatch { value: NodeValue<T> },
52}
53
54#[derive(Debug, Display, Error)]
55pub enum UpdateNodeValueError<T>
56where
57    T: PathTreeTypes,
58{
59    #[display("value type mismatch")]
60    ValueTypeMismatch { value: NodeValue<T> },
61}
62
63impl<T> From<UpdateNodeValueError<T>> for InsertOrUpdateNodeValueError<T>
64where
65    T: PathTreeTypes,
66{
67    fn from(from: UpdateNodeValueError<T>) -> Self {
68        let UpdateNodeValueError::ValueTypeMismatch { value } = from;
69        Self::ValueTypeMismatch { value }
70    }
71}
72
73#[derive(Debug, Clone)]
74pub struct NodeInsertedOrUpdated<T>
75where
76    T: PathTreeTypes,
77{
78    /// The new child node.
79    ///
80    /// The inserted or updated child node.
81    pub node: Arc<TreeNode<T>>,
82
83    /// The changes of the parent node.
84    ///
85    /// `None` if the node has no parent (i.e. is the root node of the tree)
86    /// or if the parent node has not been updated.
87    pub parent: Option<ParentNodeUpdated<T>>,
88}
89
90#[derive(Debug, Clone)]
91pub struct ParentNodeUpdated<T>
92where
93    T: PathTreeTypes,
94{
95    /// The new parent node.
96    pub node: Arc<TreeNode<T>>,
97
98    /// The removed subtree.
99    pub removed_subtree: Option<PathTree<T>>,
100}
101
102/// Return type when removing a node from the tree.
103#[derive(Debug, Clone)]
104pub struct SubtreeRemoved<T>
105where
106    T: PathTreeTypes,
107{
108    /// New parent node.
109    ///
110    /// Updated parent node of the removed node that remains in the tree.
111    pub parent_node: Arc<TreeNode<T>>,
112
113    /// Child path segment.
114    ///
115    /// Path segment between the parent node and its former child node,
116    /// which has become the root node of the removed subtree.
117    pub child_path_segment: T::PathSegmentOwned,
118
119    /// Removed subtree.
120    ///
121    /// A new tree built from the removed node and all its descendants.
122    pub removed_subtree: PathTree<T>,
123}
124
125/// Return type when inserting or replacing a subtree.
126#[derive(Debug, Clone)]
127pub struct SubtreeInsertedOrReplaced<T>
128where
129    T: PathTreeTypes,
130{
131    /// The root node of the inserted subtree.
132    pub child_node_id: T::NodeId,
133
134    /// New parent node.
135    ///
136    /// Updated parent node that contains the subtree as child.
137    pub parent: ParentNodeUpdated<T>,
138}
139
140impl<T> InsertOrUpdateNodeValueError<T>
141where
142    T: PathTreeTypes,
143{
144    pub fn into_value(self) -> NodeValue<T> {
145        match self {
146            Self::PathConflict { value, .. } | Self::ValueTypeMismatch { value } => value,
147        }
148    }
149}
150
151/// Cheaply clonable path tree structure.
152///
153/// Could be shared safely between multiple threads.
154#[derive(Debug, Clone)]
155pub struct PathTree<T>
156where
157    T: PathTreeTypes,
158{
159    root_node_id: T::NodeId,
160    nodes: HashMap<T::NodeId, Arc<TreeNode<T>>>,
161    new_node_id: T::NewNodeId,
162    _types: PhantomData<T>,
163}
164
165#[derive(Debug, Default)]
166struct TreeNodeParentChildContext<'a, T>
167where
168    T: PathTreeTypes,
169{
170    parent_node: Option<Arc<TreeNode<T>>>,
171    child_path_segment: Option<&'a T::PathSegment>,
172}
173
174#[derive(Debug, Clone, Copy, PartialEq, Eq)]
175pub enum MatchNodePath {
176    Full,
177    PartialOrFull,
178}
179
180#[derive(Debug, Clone, Copy, PartialEq, Eq)]
181pub enum NodePathMatched {
182    Full {
183        /// Number of path segments.
184        ///
185        /// Both the total and matched number of path segments are equals.
186        number_of_segments: usize,
187    },
188    Partial {
189        /// Number of matched path segments.
190        ///
191        /// Strictly less than the total number of path segments.
192        number_of_matched_segments: NonZeroUsize,
193    },
194}
195
196#[derive(Debug, Clone)]
197pub struct NodePathResolved<'a, T>
198where
199    T: PathTreeTypes,
200{
201    pub node: &'a Arc<TreeNode<T>>,
202    pub matched_path: NodePathMatched,
203}
204
205impl<T: PathTreeTypes> PathTree<T> {
206    /// Create a new path tree with the given root node.
207    #[must_use]
208    pub fn new(mut new_node_id: T::NewNodeId, root_node_value: NodeValue<T>) -> Self {
209        let root_node_id = new_node_id.new_node_id();
210        let root_node = TreeNode {
211            id: root_node_id,
212            parent: None,
213            node: Node::from_value_without_children(root_node_value),
214        };
215        let mut nodes = HashMap::new();
216        nodes.insert(root_node_id, Arc::new(root_node));
217        Self {
218            root_node_id,
219            new_node_id,
220            nodes,
221            _types: PhantomData,
222        }
223    }
224
225    fn new_node_id(&mut self) -> T::NodeId {
226        self.new_node_id.new_node_id()
227    }
228
229    #[must_use]
230    pub const fn root_node_id(&self) -> T::NodeId {
231        self.root_node_id
232    }
233
234    #[must_use]
235    pub fn root_node(&self) -> &Arc<TreeNode<T>> {
236        self.get_node(self.root_node_id)
237    }
238
239    #[must_use]
240    pub fn lookup_node(&self, id: T::NodeId) -> Option<&Arc<TreeNode<T>>> {
241        self.nodes.get(&id)
242    }
243
244    /// Get an existing node by its id.
245    ///
246    /// Only used internally for node ids that must exist. If the node does not exist
247    /// the tree is probably in an inconsistent state!
248    ///
249    /// # Panics
250    ///
251    /// Panics if the node does not exist.
252    #[must_use]
253    fn get_node(&self, id: T::NodeId) -> &Arc<TreeNode<T>> {
254        self.nodes.get(&id).expect("node exists")
255    }
256
257    /// Find a node by its path.
258    #[must_use]
259    pub fn find_node(&self, path: &T::RootPath) -> Option<&Arc<TreeNode<T>>> {
260        self.resolve_node_path(path, MatchNodePath::Full).map(
261            |NodePathResolved { node, matched_path }| {
262                debug_assert_eq!(
263                    matched_path,
264                    NodePathMatched::Full {
265                        number_of_segments: path.segments().count()
266                    }
267                );
268                node
269            },
270        )
271    }
272
273    #[must_use]
274    pub fn contains_node(&self, node: &Arc<TreeNode<T>>) -> bool {
275        self.lookup_node(node.id)
276            .map_or(false, |tree_node| Arc::ptr_eq(tree_node, node))
277    }
278
279    /// Find a node by its path.
280    ///
281    /// Returns the found node and the number of resolved path segments.
282    #[must_use]
283    #[cfg_attr(debug_assertions, allow(clippy::missing_panics_doc))] // Never panics
284    pub fn resolve_node_path<'a>(
285        &'a self,
286        path: &T::RootPath,
287        match_path: MatchNodePath,
288    ) -> Option<NodePathResolved<'a, T>> {
289        // TODO: Use a trie data structure and Aho-Corasick algo for faster lookup?
290        let root_node = self.get_node(self.root_node_id);
291        let mut last_visited_node = root_node;
292        let mut number_of_matched_path_segments = 0;
293        let mut partial_path_match = false;
294        for path_segment in path.segments() {
295            debug_assert!(!path_segment.is_empty());
296            match &last_visited_node.node {
297                Node::Leaf(_) => {
298                    // Path is too long, i.e. the remaining path segments could not be resolved.
299                    match match_path {
300                        MatchNodePath::Full => {
301                            return None;
302                        }
303                        MatchNodePath::PartialOrFull => {
304                            partial_path_match = true;
305                            break;
306                        }
307                    }
308                }
309                Node::Inner(inner_node) => {
310                    let child_node = inner_node
311                        .children
312                        .get(path_segment)
313                        .map(|node_id| self.get_node(*node_id));
314                    if let Some(child_node) = child_node {
315                        last_visited_node = child_node;
316                        number_of_matched_path_segments += 1;
317                    } else {
318                        // Path segment mismatch.
319                        match match_path {
320                            MatchNodePath::Full => {
321                                return None;
322                            }
323                            MatchNodePath::PartialOrFull => {
324                                partial_path_match = true;
325                                break;
326                            }
327                        }
328                    }
329                }
330            }
331            debug_assert_eq!(
332                path_segment,
333                last_visited_node
334                    .parent
335                    .as_ref()
336                    .expect("has parent")
337                    .path_segment
338                    .borrow()
339            );
340        }
341        let matched_path = if partial_path_match {
342            // At least 1 segment must match for a partial match.
343            let number_of_matched_segments = NonZeroUsize::new(number_of_matched_path_segments)?;
344            debug_assert!(number_of_matched_segments.get() < path.segments().count());
345            NodePathMatched::Partial {
346                number_of_matched_segments,
347            }
348        } else {
349            debug_assert_eq!(number_of_matched_path_segments, path.segments().count());
350            NodePathMatched::Full {
351                number_of_segments: number_of_matched_path_segments,
352            }
353        };
354        Some(NodePathResolved {
355            node: last_visited_node,
356            matched_path,
357        })
358    }
359
360    #[allow(clippy::too_many_lines)] // TODO
361    fn create_missing_ancestor_nodes<'a>(
362        &mut self,
363        child_path: &'a T::RootPath,
364        mut new_inner_value: impl FnMut() -> T::InnerValue,
365        try_clone_leaf_into_inner_value: impl FnOnce(&T::LeafValue) -> Option<T::InnerValue>,
366    ) -> Result<TreeNodeParentChildContext<'a, T>, TreeNodeParentChildPathConflict<T>> {
367        if child_path.is_root() {
368            return Ok(TreeNodeParentChildContext {
369                parent_node: None,
370                child_path_segment: None,
371            });
372        }
373        let mut try_clone_leaf_into_inner_value = Some(try_clone_leaf_into_inner_value);
374        let mut next_parent_node = Arc::clone(self.root_node());
375        let (parent_path_segments, child_path_segment) = child_path.parent_child_segments();
376        debug_assert!(child_path_segment.is_some());
377        for path_segment in parent_path_segments {
378            next_parent_node = match try_replace_leaf_with_inner_node(
379                &mut self.nodes,
380                next_parent_node,
381                &mut try_clone_leaf_into_inner_value,
382            ) {
383                Ok(next_parent_node) => next_parent_node,
384                Err(parent_node) => {
385                    return Err(TreeNodeParentChildPathConflict {
386                        parent_node,
387                        child_path_segment: T::path_segment_to_owned(path_segment),
388                    });
389                }
390            };
391            let Node::Inner(inner_node) = &next_parent_node.node else {
392                break;
393            };
394            let child_node = inner_node
395                .children
396                .get(path_segment)
397                .map(|node_id| self.get_node(*node_id));
398            if let Some(child_node) = child_node {
399                log::debug!("Found child node {child_node:?} for path segment {path_segment:?}");
400                next_parent_node = Arc::clone(child_node);
401            } else {
402                // Add new, empty inner node
403                let child_node_id = self.new_node_id();
404                debug_assert_ne!(child_node_id, next_parent_node.id);
405                let child_node = TreeNode {
406                    id: child_node_id,
407                    parent: Some(HalfEdgeOwned {
408                        path_segment: T::path_segment_to_owned(path_segment),
409                        node_id: next_parent_node.id,
410                    }),
411                    node: Node::Inner(InnerNode::new(new_inner_value())),
412                };
413                log::debug!(
414                    "Inserting new child node {child_node:?} for path segment {path_segment:?}"
415                );
416                let child_node = Arc::new(child_node);
417                let new_next_parent_node = Arc::clone(&child_node);
418                let old_child_node = self.nodes.insert(child_node.id, child_node);
419                debug_assert!(old_child_node.is_none());
420                let mut inner_node = inner_node.clone();
421                let old_child_node_id = inner_node
422                    .children
423                    .insert(T::path_segment_to_owned(path_segment), child_node_id);
424                debug_assert!(old_child_node_id.is_none());
425                // Replace the parent node with the modified one.
426                update_parent_node(
427                    &mut self.nodes,
428                    TreeNode {
429                        id: next_parent_node.id,
430                        parent: next_parent_node.parent.clone(),
431                        node: inner_node.into(),
432                    },
433                );
434                next_parent_node = new_next_parent_node;
435            }
436            debug_assert_eq!(
437                path_segment,
438                next_parent_node
439                    .parent
440                    .as_ref()
441                    .expect("has parent")
442                    .path_segment
443                    .borrow()
444            );
445        }
446        let next_parent_node = match try_replace_leaf_with_inner_node(
447            &mut self.nodes,
448            next_parent_node,
449            &mut try_clone_leaf_into_inner_value,
450        ) {
451            Ok(next_parent_node) => next_parent_node,
452            Err(parent_node) => {
453                return Err(TreeNodeParentChildPathConflict {
454                    parent_node,
455                    child_path_segment: child_path_segment
456                        .map(T::path_segment_to_owned)
457                        .expect("child path segment should exist"),
458                });
459            }
460        };
461        let parent_node = match next_parent_node.node {
462            Node::Inner(_) => Some(next_parent_node),
463            Node::Leaf(_) => None,
464        };
465        Ok(TreeNodeParentChildContext {
466            parent_node,
467            child_path_segment,
468        })
469    }
470
471    /// Insert or update a node in the tree.
472    ///
473    /// All missing parent nodes are created recursively and initialized
474    /// with the value returned by `new_inner_value`.
475    ///
476    /// If the parent node exists and is a leaf node then it is replaced
477    /// with an inner node by calling `try_clone_leaf_into_inner_value`.
478    ///
479    /// Returns the updated parent node and the inserted/updated child node.
480    /// The parent node is `None` if the root node has been updated.
481    ///
482    /// In case of an error, the new value is returned back to the caller.
483    #[allow(clippy::missing_panics_doc)] // Never panics
484    pub fn insert_or_update_node_value(
485        &mut self,
486        path: &T::RootPath,
487        new_value: NodeValue<T>,
488        new_inner_value: &mut impl FnMut() -> T::InnerValue,
489        try_clone_leaf_into_inner_value: impl FnOnce(&T::LeafValue) -> Option<T::InnerValue>,
490    ) -> Result<NodeInsertedOrUpdated<T>, InsertOrUpdateNodeValueError<T>> {
491        let TreeNodeParentChildContext {
492            parent_node,
493            child_path_segment,
494        } = match self.create_missing_ancestor_nodes(
495            path,
496            new_inner_value,
497            try_clone_leaf_into_inner_value,
498        ) {
499            Ok(context) => context,
500            Err(conflict) => {
501                return Err(InsertOrUpdateNodeValueError::PathConflict {
502                    conflict,
503                    value: new_value,
504                });
505            }
506        };
507        let Some(parent_node) = parent_node else {
508            // Update the root node.
509            let old_root_node = Arc::clone(self.root_node());
510            let new_root_node = self.update_node_value(&old_root_node, new_value)?;
511            return Ok(NodeInsertedOrUpdated {
512                node: new_root_node,
513                parent: None,
514            });
515        };
516        debug_assert!(matches!(parent_node.node, Node::Inner(_)));
517        let child_path_segment = child_path_segment.expect("should never be empty");
518        self.insert_or_update_child_node_value(&parent_node, child_path_segment, None, new_value)
519    }
520
521    /// Insert or update a child node in the tree.
522    ///
523    /// The parent node must exist and it must be an inner node.
524    ///
525    /// By providing `old_child_path_segment` an existing node could
526    /// be renamed and updated. This will retain its `NodeId`.
527    ///
528    /// Returns the updated parent node and the inserted/updated child node.
529    ///
530    /// In case of an error, the new value is returned back to the caller.
531    #[allow(clippy::missing_panics_doc)] // Never panics
532    #[allow(clippy::too_many_lines)] // TODO
533    pub fn insert_or_update_child_node_value(
534        &mut self,
535        parent_node: &Arc<TreeNode<T>>,
536        child_path_segment: &T::PathSegment,
537        old_child_path_segment: Option<&T::PathSegment>,
538        new_value: NodeValue<T>,
539    ) -> Result<NodeInsertedOrUpdated<T>, InsertOrUpdateNodeValueError<T>> {
540        debug_assert!(self.contains_node(parent_node));
541        debug_assert!(matches!(parent_node.node, Node::Inner(_)));
542        let Node::Inner(inner_node) = &parent_node.node else {
543            return Err(InsertOrUpdateNodeValueError::PathConflict {
544                conflict: TreeNodeParentChildPathConflict {
545                    parent_node: Arc::clone(parent_node),
546                    child_path_segment: T::path_segment_to_owned(child_path_segment),
547                },
548                value: new_value,
549            });
550        };
551        let old_child_path_segment = old_child_path_segment.unwrap_or(child_path_segment);
552        let (child_node, inner_node_and_removed_subtree) = if let Some(child_node) = inner_node
553            .children
554            .get(old_child_path_segment)
555            .map(|node_id| self.get_node(*node_id))
556        {
557            let child_node_id = child_node.id;
558            log::debug!("Updating value of existing child node {child_node_id}");
559            let old_child_node = Arc::clone(child_node);
560            if old_child_path_segment == child_path_segment {
561                // No renaming.
562                let new_child_node = self.update_node_value(&old_child_node, new_value)?;
563                (new_child_node, None)
564            } else {
565                let new_parent = HalfEdgeOwned {
566                    path_segment: T::path_segment_to_owned(child_path_segment),
567                    node_id: parent_node.id,
568                };
569                let updated_child_node =
570                    old_child_node.try_clone_with_parent_and_value(Some(new_parent), new_value)?;
571                let (mut inner_node, removed_subtree) = if let Some(subtree_root_node_id) =
572                    parent_node.node.find_child(child_path_segment)
573                {
574                    log::debug!("Removing child node {child_node_id} with subtree from {child_path_segment:?}");
575                    let removed_subtree = self.remove_subtree_by_id(subtree_root_node_id);
576                    debug_assert!(removed_subtree.is_some());
577                    let SubtreeRemoved {
578                        parent_node,
579                        child_path_segment: removed_child_path_segment,
580                        removed_subtree,
581                    } = removed_subtree.expect("subtree has been removed");
582                    debug_assert_eq!(removed_child_path_segment.borrow(), child_path_segment);
583                    let Node::Inner(inner_node) = &parent_node.node else {
584                        unreachable!();
585                    };
586                    (inner_node.clone(), Some(removed_subtree))
587                } else {
588                    // The (new) child path segment is not occupied by a node/subtree.
589                    (inner_node.clone(), None)
590                };
591                // Move the updated node to the new, empty location.
592                log::debug!("Moving child node {child_node_id} from {old_child_path_segment:?} to {child_path_segment:?}");
593                let removed_child_node_id = inner_node.children.remove(old_child_path_segment);
594                debug_assert_eq!(removed_child_node_id, Some(child_node_id));
595                debug_assert!(self.nodes.contains_key(&child_node_id));
596                let child_node_id = updated_child_node.id;
597                let new_child_node = Arc::new(updated_child_node);
598                let replaced_child_node = self
599                    .nodes
600                    .insert(child_node_id, Arc::clone(&new_child_node));
601                debug_assert!(replaced_child_node.is_some());
602                debug_assert!(Arc::ptr_eq(
603                    replaced_child_node.as_ref().unwrap(),
604                    &old_child_node
605                ));
606                debug_assert!(!inner_node.children.contains_key(child_path_segment));
607                inner_node
608                    .children
609                    .insert(T::path_segment_to_owned(child_path_segment), child_node_id);
610                (new_child_node, Some((inner_node, removed_subtree)))
611            }
612        } else {
613            let child_node_id = self.new_node_id();
614            log::debug!("Adding new child node {child_node_id}");
615            debug_assert!(!self.nodes.contains_key(&child_node_id));
616            let new_child_node = TreeNode {
617                id: child_node_id,
618                parent: Some(HalfEdgeOwned {
619                    path_segment: T::path_segment_to_owned(child_path_segment),
620                    node_id: parent_node.id,
621                }),
622                node: Node::from_value_without_children(new_value),
623            };
624            let child_node_id = new_child_node.id;
625            let new_child_node = Arc::new(new_child_node);
626            let old_child_node = self
627                .nodes
628                .insert(child_node_id, Arc::clone(&new_child_node));
629            debug_assert!(old_child_node.is_none());
630            log::debug!(
631                "Inserted new child node {new_child_node:?}",
632                new_child_node = *new_child_node,
633            );
634            let mut inner_node = inner_node.clone();
635            if let Some(child_node_id_mut) = inner_node.children.get_mut(child_path_segment) {
636                *child_node_id_mut = child_node_id;
637            } else {
638                inner_node
639                    .children
640                    .insert(T::path_segment_to_owned(child_path_segment), child_node_id);
641            }
642            (new_child_node, Some((inner_node, None)))
643        };
644        let parent = inner_node_and_removed_subtree.map(|(inner_node, removed_subtree)| {
645            let new_parent_node = update_parent_node(
646                &mut self.nodes,
647                TreeNode {
648                    id: parent_node.id,
649                    parent: parent_node.parent.clone(),
650                    node: Node::Inner(inner_node),
651                },
652            );
653            ParentNodeUpdated {
654                node: new_parent_node,
655                removed_subtree,
656            }
657        });
658        Ok(NodeInsertedOrUpdated {
659            node: child_node,
660            parent,
661        })
662    }
663
664    /// Update a node value in the tree.
665    ///
666    /// Inner nodes with children could only be updated with an inner value.
667    ///
668    /// Returns the updated node with the new value.
669    ///
670    /// In case of an error, the new value is returned back to the caller.
671    ///
672    /// Undefined behavior if the given node does not belong to the tree.
673    /// This precondition is only checked by debug assertions.
674    #[allow(clippy::missing_panics_doc)] // Never panics
675    pub fn update_node_value(
676        &mut self,
677        node: &Arc<TreeNode<T>>,
678        new_value: NodeValue<T>,
679    ) -> Result<Arc<TreeNode<T>>, UpdateNodeValueError<T>> {
680        debug_assert!(self.contains_node(node));
681        let new_node = Arc::new(node.try_clone_with_value(new_value)?);
682        let old_node = self.nodes.insert(node.id, Arc::clone(&new_node));
683        debug_assert!(old_node.is_some());
684        debug_assert!(old_node.map_or(false, |old_node| Arc::ptr_eq(&old_node, node)));
685        log::debug!("Updated node value: {node:?} -> {new_node:?}");
686        Ok(new_node)
687    }
688
689    /// Remove a node and its children from the tree.
690    ///
691    /// Removes and returns the entire subtree rooted at the given node.
692    ///
693    /// The root node cannot be removed and the tree remains unchanged.
694    ///
695    /// Returns the removed subtree or `None` if unchanged.
696    /// The node ids in the removed subtree remain unchanged.
697    #[allow(clippy::missing_panics_doc)] // Never panics
698    pub fn remove_subtree_by_id(&mut self, node_id: T::NodeId) -> Option<SubtreeRemoved<T>> {
699        if node_id == self.root_node_id {
700            // Cannot remove the root node.
701            return None;
702        }
703        let nodes_count_before = self.nodes_count();
704        let node = self.nodes.remove(&node_id)?;
705        // The descendants of the removed node could still be collected,
706        // even though the tree is already incomplete.
707        let descendant_node_ids = node
708            .node
709            .descendants(self)
710            .map(
711                |HalfEdge {
712                     path_segment: _,
713                     node_id,
714                 }| node_id,
715            )
716            .collect::<Vec<_>>();
717        // Split off the nodes of the subtree from the remaining nodes.
718        #[cfg(feature = "im")]
719        let mut subtree_nodes: HashMap<_, _> = descendant_node_ids
720            .into_iter()
721            .filter_map(|node_id| self.nodes.remove_with_key(&node_id))
722            .collect();
723        #[cfg(not(feature = "im"))]
724        let mut subtree_nodes: HashMap<_, _> = descendant_node_ids
725            .into_iter()
726            .filter_map(|node_id| self.nodes.remove_entry(&node_id))
727            .collect();
728        // Disconnect the subtree from the parent node. The old parent node
729        // still references the root node of the removed subtree as a child.
730        let new_parent_node = {
731            debug_assert!(node.parent.is_some());
732            let HalfEdgeOwned {
733                path_segment: parent_path_segment,
734                node_id: parent_node_id,
735            } = node.parent.as_ref().expect("has parent");
736            let parent_node = self.nodes.get(parent_node_id).expect("has a parent");
737            debug_assert!(matches!(parent_node.node, Node::Inner(_)));
738            let Node::Inner(inner_node) = &parent_node.node else {
739                unreachable!();
740            };
741            let mut inner_node = inner_node.clone();
742            let removed_id = inner_node.children.remove(parent_path_segment.borrow());
743            debug_assert_eq!(removed_id, Some(node_id));
744            TreeNode {
745                id: parent_node.id,
746                parent: parent_node.parent.clone(),
747                node: Node::Inner(inner_node),
748            }
749        };
750        let new_parent_node = update_parent_node(&mut self.nodes, new_parent_node);
751        // The tree is now back in a consistent state and we can use the public API again.
752        let nodes_count_after = self.nodes_count();
753        debug_assert!(nodes_count_before >= nodes_count_after);
754        let removed_nodes_count = nodes_count_before.get() - nodes_count_after.get();
755        let TreeNode { id, parent, node } = Arc::unwrap_or_clone(node);
756        let parent = parent.expect("has a parent");
757        debug_assert_eq!(parent.node_id, new_parent_node.id);
758        let child_path_segment = parent.path_segment;
759        let subtree_root_node = Arc::new(TreeNode {
760            id,
761            parent: None,
762            node,
763        });
764        subtree_nodes.insert(node_id, subtree_root_node);
765        let removed_subtree = Self {
766            root_node_id: node_id,
767            nodes: subtree_nodes,
768            new_node_id: self.new_node_id.clone(),
769            _types: PhantomData,
770        };
771        debug_assert_eq!(removed_nodes_count, removed_subtree.nodes_count().get());
772        Some(SubtreeRemoved {
773            parent_node: new_parent_node,
774            child_path_segment,
775            removed_subtree,
776        })
777    }
778
779    /// Insert a subtree.
780    ///
781    /// The root node of the subtree will replace an existing node.
782    /// The existing node must node have any children, otherwise the
783    /// insertion will fail.
784    ///
785    /// The inserted nodes from the subtree will be assigned new ids
786    /// that are generated by this tree.
787    ///
788    /// By providing `old_child_path_segment` an existing node could
789    /// be renamed and replaced by the subtree. This will retain its
790    /// `NodeId`.
791    #[allow(clippy::missing_panics_doc)] // Never panics
792    pub fn insert_or_replace_subtree(
793        &mut self,
794        parent_node: &Arc<TreeNode<T>>,
795        child_path_segment: &T::PathSegment,
796        old_child_path_segment: Option<&T::PathSegment>,
797        mut subtree: Self,
798    ) -> Result<SubtreeInsertedOrReplaced<T>, InsertOrUpdateNodeValueError<T>> {
799        debug_assert!(self.contains_node(parent_node));
800        // Initialized with the old node id, which will be replaced with the new node id
801        // after the root node of the subtree has been inserted/replaced.
802        let mut subtree_root_node_id = subtree.root_node_id();
803        let mut subtree_root_parent_updated = None;
804        {
805            let subtree_node_ids = std::iter::once(subtree.root_node_id())
806                .chain(subtree.root_node().node.descendants(&subtree).map(
807                    |HalfEdge {
808                         path_segment: _,
809                         node_id,
810                     }| node_id,
811                ))
812                .collect::<Vec<_>>();
813            let mut old_to_new_node_id =
814                std::collections::HashMap::<T::NodeId, T::NodeId>::with_capacity(
815                    subtree_node_ids.len(),
816                );
817            for old_node_id in subtree_node_ids {
818                let old_node = subtree.nodes.remove(&old_node_id).expect("node exists");
819                // Ideally, the nodes in the subtree are not referenced in the outer
820                // context to avoid cloning them. For most use cases this assumption
821                // should be valid.
822                let TreeNode {
823                    id: _,
824                    parent,
825                    node,
826                } = Arc::unwrap_or_clone(old_node);
827                // TODO: This could be optimized when not reusing insert_or_update_child_node_value()
828                // and instead inserting or replacing the node directly.
829                let (parent_node, child_path_segment, old_child_path_segment) =
830                    if let Some(parent) = parent {
831                        debug_assert!(old_to_new_node_id.contains_key(&parent.node_id));
832                        let parent_node_id = old_to_new_node_id
833                            .get(&parent.node_id)
834                            .copied()
835                            .expect("parent node has already been inserted");
836                        let parent_node = self
837                            .nodes
838                            .get(&parent_node_id)
839                            .expect("parent node has already been inserted");
840                        (parent_node, parent.path_segment, None)
841                    } else {
842                        // Root node.
843                        debug_assert_eq!(old_node_id, subtree.root_node_id());
844                        (
845                            parent_node,
846                            T::path_segment_to_owned(child_path_segment),
847                            old_child_path_segment,
848                        )
849                    };
850                let node_value = match node {
851                    Node::Inner(inner) => NodeValue::Inner(inner.value),
852                    Node::Leaf(leaf) => NodeValue::Leaf(leaf.value),
853                };
854                let NodeInsertedOrUpdated {
855                    node: child_node,
856                    parent,
857                } = self
858                    .insert_or_update_child_node_value(
859                        &Arc::clone(parent_node),
860                        child_path_segment.borrow(),
861                        old_child_path_segment,
862                        node_value,
863                    )
864                    .inspect_err(|_| {
865                        // Insertion could only fail for the first node,
866                        // which is the root node of the subtree. This ensures
867                        // that `self` remains unchanged on error.
868                        debug_assert_eq!(old_node_id, subtree.root_node_id());
869                    })?;
870                let child_node_id = child_node.id;
871                if old_node_id == subtree.root_node_id() {
872                    // Subtree root node inserted/updated.
873                    subtree_root_node_id = child_node_id;
874                    subtree_root_parent_updated = parent;
875                }
876                debug_assert!(!old_to_new_node_id.contains_key(&old_node_id));
877                old_to_new_node_id.insert(old_node_id, child_node_id);
878            }
879        }
880        Ok(SubtreeInsertedOrReplaced {
881            child_node_id: subtree_root_node_id,
882            parent: subtree_root_parent_updated.expect("parent node has been updated"),
883        })
884    }
885
886    /// Retain only the nodes that match the given predicate.
887    ///
888    /// The root node is always retained and cannot be removed.
889    ///
890    /// Returns the number of nodes that have been removed.
891    #[allow(clippy::missing_panics_doc)] // Never panics
892    pub fn retain_nodes(&mut self, mut predicate: impl FnMut(&TreeNode<T>) -> bool) {
893        // TODO: Optimize by traversing the tree structure instead of iterating over
894        // all nodes in no particular order. If a subtree is removed then all its
895        // children don't need to be visited.
896        let mut node_ids_to_remove = Vec::new();
897        for node in self.nodes() {
898            if !predicate(node) && node.id != self.root_node_id() {
899                node_ids_to_remove.push(node.id);
900            }
901        }
902        // Remove the subtrees in reverse order of the depth of their root node.
903        node_ids_to_remove.sort_by(|lhs_id, rhs_id| {
904            let lhs_node = self.get_node(*lhs_id);
905            let rhs_node = self.get_node(*rhs_id);
906            let lhs_depth = self.ancestor_nodes_count(lhs_node);
907            let rhs_depth = self.ancestor_nodes_count(rhs_node);
908            lhs_depth.cmp(&rhs_depth)
909        });
910        for node_id in node_ids_to_remove {
911            self.remove_subtree_by_id(node_id);
912        }
913    }
914
915    /// All nodes in no particular order.
916    pub fn nodes(&self) -> impl ExactSizeIterator<Item = &Arc<TreeNode<T>>> {
917        self.nodes.values()
918    }
919
920    /// Total number of nodes in the tree.
921    ///
922    /// Executed in constant time, i.e. O(1). But only if not both
923    /// debug assertions and the feature "expensive-debug-assertions"
924    /// are enabled.
925    #[must_use]
926    pub fn nodes_count(&self) -> NonZeroUsize {
927        debug_assert!(!self.nodes.is_empty());
928        let nodes_count = self.nodes.len();
929        #[cfg(feature = "expensive-debug-assertions")]
930        {
931            // Verify invariants
932            debug_assert_eq!(
933                nodes_count,
934                1 + self.root_node().node.descendants_count(self)
935            );
936            debug_assert_eq!(nodes_count, self.nodes().count());
937        }
938        // SAFETY: A tree always contains at least a root node.
939        debug_assert!(nodes_count > 0);
940        #[allow(unsafe_code)]
941        unsafe {
942            NonZeroUsize::new_unchecked(nodes_count)
943        }
944    }
945
946    /// Iterator over all ancestor nodes of the given node.
947    ///
948    /// Returns the parent node and the respective path segment from the child node
949    /// in bottom-up order.
950    pub fn ancestor_nodes<'a>(
951        &'a self,
952        node: &'a Arc<TreeNode<T>>,
953    ) -> impl Iterator<Item = HalfEdgeTreeNode<'_, T>> + Clone {
954        AncestorTreeNodeIter::new(self, node)
955    }
956
957    /// The number of parent nodes of the given node up to the root node.
958    #[must_use]
959    pub fn ancestor_nodes_count(&self, node: &Arc<TreeNode<T>>) -> usize {
960        self.ancestor_nodes(node).count()
961    }
962
963    /// Returns an iterator over all descendants of this node
964    ///
965    /// Recursively traverses the subtree.
966    ///
967    /// The ordering of nodes is undefined and an implementation detail. Only parent
968    /// nodes are guaranteed to be visited before their children.
969    pub fn descendant_nodes<'a>(
970        &'a self,
971        node: &'a Arc<TreeNode<T>>,
972    ) -> impl Iterator<Item = HalfEdge<'a, T>> {
973        debug_assert!(self.contains_node(node));
974        node.node.descendants(self)
975    }
976
977    /// Number of child nodes of the given node (recursively).
978    #[must_use]
979    pub fn descendant_nodes_count(&self, node: &Arc<TreeNode<T>>) -> usize {
980        debug_assert!(self.contains_node(node));
981        node.node.descendants_count(self)
982    }
983}
984
985/// Immutable node in the tree.
986#[derive(Debug, Clone)]
987pub struct TreeNode<T: PathTreeTypes> {
988    /// Identifier for direct lookup.
989    pub id: T::NodeId,
990
991    /// Link to the parent node.
992    ///
993    /// Must be `None` for the root node and `Some` for all other nodes.
994    pub parent: Option<HalfEdgeOwned<T>>,
995
996    /// The actual content of this node.
997    pub node: Node<T>,
998}
999
1000impl<T: PathTreeTypes> TreeNode<T> {
1001    fn try_clone_with_value(
1002        &self,
1003        new_value: NodeValue<T>,
1004    ) -> Result<Self, UpdateNodeValueError<T>> {
1005        self.try_clone_with_parent_and_value(None, new_value)
1006    }
1007
1008    /// Clones the node with a new parent and value.
1009    ///
1010    /// Leaf values could be replaced by both leaf and inner values.
1011    /// An inner value could only be replaced by a leaf value, if the
1012    /// node does not have any children.
1013    ///
1014    /// Fails if the type of the new value is incompatible with the
1015    /// current value type of the node, depending on its children.
1016    fn try_clone_with_parent_and_value(
1017        &self,
1018        new_parent: Option<HalfEdgeOwned<T>>,
1019        new_value: NodeValue<T>,
1020    ) -> Result<Self, UpdateNodeValueError<T>> {
1021        let new_node = match &self.node {
1022            Node::Inner(InnerNode { children, .. }) => {
1023                match new_value {
1024                    NodeValue::Inner(new_value) => {
1025                        // Remains an inner node with the current children and the new value.
1026                        Self {
1027                            id: self.id,
1028                            parent: new_parent.or_else(|| self.parent.clone()),
1029                            node: Node::Inner(InnerNode {
1030                                children: children.clone(),
1031                                value: new_value,
1032                            }),
1033                        }
1034                    }
1035                    new_value @ NodeValue::Leaf(_) => {
1036                        if !children.is_empty() {
1037                            return Err(UpdateNodeValueError::ValueTypeMismatch {
1038                                value: new_value,
1039                            });
1040                        }
1041                        Self {
1042                            id: self.id,
1043                            parent: new_parent.or_else(|| self.parent.clone()),
1044                            node: Node::from_value_without_children(new_value),
1045                        }
1046                    }
1047                }
1048            }
1049            Node::Leaf(_) => {
1050                // Leaf node values could be replaced by both leaf and inner node values.
1051                Self {
1052                    id: self.id,
1053                    parent: new_parent.or_else(|| self.parent.clone()),
1054                    node: Node::from_value_without_children(new_value),
1055                }
1056            }
1057        };
1058        debug_assert_eq!(self.id, new_node.id);
1059        debug_assert_eq!(self.node.children_count(), new_node.node.children_count());
1060        debug_assert!(self
1061            .node
1062            .children()
1063            .zip(new_node.node.children())
1064            .all(|(old, new)| old == new));
1065        Ok(new_node)
1066    }
1067}
1068
1069fn try_replace_leaf_with_inner_node<T: PathTreeTypes>(
1070    nodes: &mut HashMap<T::NodeId, Arc<TreeNode<T>>>,
1071    node: Arc<TreeNode<T>>,
1072    try_clone_leaf_into_inner_value: &mut Option<
1073        impl FnOnce(&T::LeafValue) -> Option<T::InnerValue>,
1074    >,
1075) -> Result<Arc<TreeNode<T>>, Arc<TreeNode<T>>> {
1076    let TreeNode {
1077        id,
1078        parent,
1079        node: Node::Leaf(LeafNode { value: leaf_value }),
1080    } = &*node
1081    else {
1082        return Ok(node);
1083    };
1084    let try_clone_leaf_into_inner_value = try_clone_leaf_into_inner_value
1085        .take()
1086        .expect("consumed at most once");
1087    let Some(inner_value) = try_clone_leaf_into_inner_value(leaf_value) else {
1088        // Keep this leaf node
1089        return Err(node);
1090    };
1091    // Replace leaf node with empty inner node
1092    let inner_node = TreeNode {
1093        id: *id,
1094        parent: parent.clone(),
1095        node: InnerNode::new(inner_value).into(),
1096    };
1097    log::debug!(
1098        "Replacing leaf node {leaf_node:?} with inner node {inner_node:?}",
1099        leaf_node = *node
1100    );
1101    let inner_node = Arc::new(inner_node);
1102    let replaced_leaf_node = nodes.insert(inner_node.id, Arc::clone(&inner_node));
1103    debug_assert!(replaced_leaf_node.is_some());
1104    Ok(inner_node)
1105}
1106
1107/// Iterator over all ancestor nodes of the given node.
1108///
1109/// Returns the node and the respective path segment from the child node.
1110#[derive(Debug, Clone)]
1111pub struct AncestorTreeNodeIter<'a, T: PathTreeTypes> {
1112    tree: &'a PathTree<T>,
1113    next_node: Option<&'a Arc<TreeNode<T>>>,
1114}
1115
1116impl<'a, T: PathTreeTypes> AncestorTreeNodeIter<'a, T> {
1117    /// Create a new iterator over all ancestor nodes of the given node.
1118    ///
1119    /// The given node must exist in the tree. This is only checked in
1120    /// debug builds. Otherwise the iterator will be empty.
1121    #[must_use]
1122    pub fn new(tree: &'a PathTree<T>, node: &'a Arc<TreeNode<T>>) -> Self {
1123        debug_assert!(tree.contains_node(node));
1124        Self {
1125            tree,
1126            next_node: Some(node),
1127        }
1128    }
1129}
1130
1131impl<'a, T: PathTreeTypes> Iterator for AncestorTreeNodeIter<'a, T> {
1132    type Item = HalfEdgeTreeNode<'a, T>;
1133
1134    fn next(&mut self) -> Option<Self::Item> {
1135        let parent = self.next_node.as_ref()?.parent.as_ref()?;
1136        self.next_node = self.tree.lookup_node(parent.node_id);
1137        self.next_node.map(|node| HalfEdgeTreeNode {
1138            path_segment: parent.path_segment.borrow(),
1139            node,
1140        })
1141    }
1142}
1143
1144fn update_parent_node<T: PathTreeTypes>(
1145    nodes: &mut HashMap<T::NodeId, Arc<TreeNode<T>>>,
1146    parent_node: TreeNode<T>,
1147) -> Arc<TreeNode<T>> {
1148    debug_assert!(matches!(parent_node.node, Node::Inner(_)));
1149    let parent_node_id = parent_node.id;
1150    let new_parent_node = Arc::new(parent_node);
1151    debug_assert!(nodes.contains_key(&parent_node_id));
1152    let old_parent_node = nodes.insert(parent_node_id, Arc::clone(&new_parent_node));
1153    debug_assert!(old_parent_node.is_some());
1154    log::debug!(
1155        "Updated parent node {old_parent_node:?} to {new_parent_node:?}",
1156        old_parent_node = old_parent_node.expect("old parent exists"),
1157        new_parent_node = *new_parent_node,
1158    );
1159    new_parent_node
1160}