id_tree 1.8.0

A library for creating and modifying Tree structures.
Documentation
use NodeId;

///
/// Describes the possible behaviors of the `Tree::remove_node` method.
///
pub enum RemoveBehavior {
    ///
    /// All children will be dropped recursively.  In other words, the entire sub-tree of the `Node`
    /// being removed will be dropped from the tree.  Those `Node`s will no longer exist and
    /// cannot be accessed even if you have the `NodeId` the previously pointed to them.
    ///
    /// This means even without using `Clone` you might end up with copies of invalid `NodeId`s.
    /// Use this behavior with caution.
    ///
    /// ```
    /// use id_tree::*;
    /// use id_tree::InsertBehavior::*;
    /// use id_tree::RemoveBehavior::*;
    ///
    /// let mut tree: Tree<i32> = Tree::new();
    ///
    /// let root_id = tree.insert(Node::new(0), AsRoot).unwrap();
    /// let child_id = tree.insert(Node::new(1), UnderNode(&root_id)).unwrap();
    /// let grandchild_id = tree.insert(Node::new(2), UnderNode(&child_id)).unwrap();
    ///
    /// let child = tree.remove_node(child_id, DropChildren).ok().unwrap();
    ///
    /// assert!(tree.get(&grandchild_id).is_err());
    /// assert_eq!(tree.get(&root_id).unwrap().children().len(), 0);
    /// assert_eq!(child.children().len(), 0);
    /// assert_eq!(child.parent(), None);
    /// ```
    ///
    DropChildren,

    ///
    /// If the removed `Node` (let's call it `A`) has a parent, `A`'s parent will become the
    /// parent of `A`'s children.  This effectively just shifts them up one level in the `Tree`.
    ///
    /// If `A` doesn't have a parent, then this behaves exactly like
    /// `RemoveBehavior::OrphanChildren`.
    ///
    /// ```
    /// use id_tree::*;
    /// use id_tree::InsertBehavior::*;
    /// use id_tree::RemoveBehavior::*;
    ///
    /// let mut tree: Tree<i32> = Tree::new();
    ///
    /// let root_id = tree.insert(Node::new(0), AsRoot).unwrap();
    /// let child_id = tree.insert(Node::new(1), UnderNode(&root_id)).unwrap();
    /// let grandchild_id = tree.insert(Node::new(2), UnderNode(&child_id)).unwrap();
    ///
    /// let child = tree.remove_node(child_id, LiftChildren).ok().unwrap();
    ///
    /// assert!(tree.get(&grandchild_id).is_ok());
    /// assert!(tree.get(&root_id).unwrap().children().contains(&grandchild_id));
    /// assert_eq!(child.children().len(), 0);
    /// assert_eq!(child.parent(), None);
    /// ```
    ///
    LiftChildren,

    ///
    /// All children will have their parent references cleared.  This means nothing will point to
    /// them, but they will still exist in the tree.  Those `Node`s can still be accessed provided
    /// that you have the `NodeId` that points to them.
    ///
    /// ```
    /// use id_tree::*;
    /// use id_tree::InsertBehavior::*;
    /// use id_tree::RemoveBehavior::*;
    ///
    /// let mut tree: Tree<i32> = Tree::new();
    ///
    /// let root_id = tree.insert(Node::new(0), AsRoot).unwrap();
    /// let child_id = tree.insert(Node::new(1), UnderNode(&root_id)).unwrap();
    /// let grandchild_id = tree.insert(Node::new(2), UnderNode(&child_id)).unwrap();
    ///
    /// let child = tree.remove_node(child_id, OrphanChildren).ok().unwrap();
    ///
    /// assert!(tree.get(&grandchild_id).is_ok());
    /// assert_eq!(tree.get(&root_id).unwrap().children().len(), 0);
    /// assert_eq!(child.children().len(), 0);
    /// assert_eq!(child.parent(), None);
    /// ```
    ///
    OrphanChildren,
}

///
/// Describes the possible behaviors of the `Tree::move_node` method.
///
pub enum MoveBehavior<'a> {
    ///
    /// Sets the `Node` in question as the new root `Node`, leaving all children in their place (in
    /// other words, they will travel with the `Node` being moved).
    ///
    /// If there is already a root `Node` in place, it will be attached as the last child of the new
    /// root.
    ///
    /// ```
    /// use id_tree::*;
    /// use id_tree::InsertBehavior::*;
    /// use id_tree::MoveBehavior::*;
    ///
    /// let mut tree: Tree<i32> = Tree::new();
    ///
    /// let root_id = tree.insert(Node::new(1), AsRoot).unwrap();
    /// let child_id = tree.insert(Node::new(2),  UnderNode(&root_id)).unwrap();
    /// let grandchild_id = tree.insert(Node::new(3), UnderNode(&child_id)).unwrap();
    ///
    /// tree.move_node(&grandchild_id, ToRoot).unwrap();
    ///
    /// assert_eq!(tree.root_node_id(), Some(&grandchild_id));
    /// assert!(tree.get(&grandchild_id).unwrap().children().contains(&root_id));
    /// assert!(!tree.get(&child_id).unwrap().children().contains(&grandchild_id));
    /// ```
    ///
    ToRoot,

    ///
    /// Moves a `Node` inside the `Tree` to a new parent leaving all children in their place.
    ///
    /// If the new parent (let's call it `B`) is a descendant of the `Node` being moved (`A`), then
    /// the direct child of `A` on the path from `A` to `B` will be shifted upwards to take the
    /// place of its parent (`A`).  All other children of `A` will be left alone, meaning they will
    /// travel with it down the `Tree`.
    ///
    /// Please note that during the "shift-up" part of the above scenario, the `Node` being shifted
    /// up will always be added as the last child of its new parent.
    ///
    /// ```
    /// use id_tree::*;
    /// use id_tree::InsertBehavior::*;
    /// use id_tree::MoveBehavior::*;
    ///
    /// let mut tree: Tree<i32> = Tree::new();
    ///
    /// let root_id = tree.insert(Node::new(1), AsRoot).ok().unwrap();
    /// let first_child_id = tree.insert(Node::new(2),  UnderNode(&root_id)).unwrap();
    /// let second_child_id = tree.insert(Node::new(3), UnderNode(&root_id)).unwrap();
    /// let grandchild_id = tree.insert(Node::new(4), UnderNode(&first_child_id)).unwrap();
    ///
    /// tree.move_node(&grandchild_id, ToParent(&second_child_id)).unwrap();
    ///
    /// assert!(!tree.get(&first_child_id).unwrap().children().contains(&grandchild_id));
    /// assert!(tree.get(&second_child_id).unwrap().children().contains(&grandchild_id));
    /// ```
    ///
    ToParent(&'a NodeId),
}

///
/// Describes the possible behaviors of the `Tree::insert` method.
///
pub enum InsertBehavior<'a> {
    ///
    /// Sets the root of the `Tree`.
    ///
    /// If there is already a root `Node` present in the tree, that `Node` is set as the first child
    /// of the new root.
    ///
    /// ```
    /// use id_tree::*;
    /// use id_tree::InsertBehavior::*;
    ///
    /// let mut tree: Tree<i32> = Tree::new();
    ///
    /// tree.insert(Node::new(5), AsRoot).unwrap();
    /// ```
    AsRoot,

    ///
    /// Returns a `Result` containing the `NodeId` of the child that was added or a `NodeIdError` if
    /// one occurred.
    ///
    /// Note: Adds the new Node to the end of its children.
    ///
    /// ```
    /// use id_tree::*;
    /// use id_tree::InsertBehavior::*;
    ///
    /// let root_node = Node::new(1);
    /// let child_node = Node::new(2);
    ///
    /// let mut tree: Tree<i32> = Tree::new();
    /// let root_id = tree.insert(root_node, AsRoot).unwrap();
    ///
    /// tree.insert(child_node, UnderNode(&root_id)).unwrap();
    /// ```
    UnderNode(&'a NodeId),
}

///
/// Describes the possible behaviors of the `Tree::swap_nodes` method.
///
pub enum SwapBehavior {
    ///
    /// Take the children of the `Node`s being swapped with them.  In other words, this swaps the
    /// `Node`s in question along with their entire sub-tree.  This *does not* affect the
    /// relationship between the `Node`s being swapped and their children.
    ///
    /// If one `Node` is a descendant of the other getting swapped, the former *upper* `Node` is
    /// attached as the last child of the former *lower* `Node` after the swap. (The *lower* will
    /// take the *uppers* original position as usual.) The subtree of the former *upper* node is not
    /// touched except that the *lower* `Node` is moved including all its children.
    ///
    /// ```
    /// use id_tree::*;
    /// use id_tree::InsertBehavior::*;
    /// use id_tree::SwapBehavior::*;
    ///
    /// let mut tree: Tree<i32> = Tree::new();
    ///
    /// let root_id = tree.insert(Node::new(1), AsRoot).unwrap();
    /// let first_child_id = tree.insert(Node::new(2), UnderNode(&root_id)).unwrap();
    /// let second_child_id = tree.insert(Node::new(3), UnderNode(&root_id)).unwrap();
    /// let grandchild_id = tree.insert(Node::new(4), UnderNode(&second_child_id)).unwrap();
    ///
    /// tree.swap_nodes(&first_child_id, &grandchild_id, TakeChildren).unwrap();
    ///
    /// assert!(tree.get(&second_child_id).unwrap().children().contains(&first_child_id));
    /// assert!(tree.get(&root_id).unwrap().children().contains(&grandchild_id));
    /// ```
    ///
    TakeChildren,

    ///
    /// Leave the children of the `Node`s being swapped where they are.  In other words, this only
    /// swaps the `Node`s themselves.  This *does* affect the relationship between the `Node`s
    /// being swapped and their children.
    ///
    /// Please Note: Because this behavior alters the relationship between the `Node`s being
    /// swapped and their children, any calls to `children()` that have been cloned will no longer
    /// point to the children of the `Node` that you might think they do.
    ///
    /// ```
    /// use id_tree::*;
    /// use id_tree::InsertBehavior::*;
    /// use id_tree::SwapBehavior::*;
    ///
    /// let mut tree: Tree<i32> = Tree::new();
    ///
    /// let root_id = tree.insert(Node::new(1), AsRoot).unwrap();
    /// let first_child_id = tree.insert(Node::new(2), UnderNode(&root_id)).unwrap();
    /// let second_child_id = tree.insert(Node::new(3), UnderNode(&root_id)).unwrap();
    /// let grandchild_id = tree.insert(Node::new(4), UnderNode(&second_child_id)).unwrap();
    ///
    /// tree.swap_nodes(&first_child_id, &second_child_id, LeaveChildren).unwrap();
    ///
    /// assert!(tree.get(&first_child_id).unwrap().children().contains(&grandchild_id));
    /// assert_eq!(tree.get(&second_child_id).unwrap().children().len(), 0);
    /// ```
    ///
    LeaveChildren,

    ///
    /// Swap the children of the `Node`s in question only.  This does not swap the `Node`s that are
    /// specified when calling this method.  This *does* affect the relationship between the
    /// `Node`s that are specified and their children.
    ///
    /// If one `Node` is a descendant of the other getting swapped, the child swapping step will
    /// take place and then the *lower* `Node` in the swap will be added as the last child of the
    /// *upper* `Node` in the swap.
    ///
    /// Please Note: Because this behavior alters the relationship between the `Node`s being
    /// swapped and their children, any calls to `children()` that have been cloned will no longer
    /// point to the children of the `Node` that you think they do.
    ///
    /// ```
    /// use id_tree::*;
    /// use id_tree::InsertBehavior::*;
    /// use id_tree::SwapBehavior::*;
    ///
    /// let mut tree: Tree<i32> = Tree::new();
    ///
    /// let root_id = tree.insert(Node::new(1), AsRoot).unwrap();
    /// let first_child_id = tree.insert(Node::new(2), UnderNode(&root_id)).unwrap();
    /// let second_child_id = tree.insert(Node::new(3), UnderNode(&root_id)).unwrap();
    /// let grandchild_id = tree.insert(Node::new(4), UnderNode(&second_child_id)).unwrap();
    /// let grandchild_id_2 = tree.insert(Node::new(5), UnderNode(&first_child_id)).unwrap();
    ///
    /// tree.swap_nodes(&first_child_id, &second_child_id, ChildrenOnly).unwrap();
    ///
    /// assert!(tree.get(&first_child_id).unwrap().children().contains(&grandchild_id));
    /// assert!(tree.get(&second_child_id).unwrap().children().contains(&grandchild_id_2));
    /// ```
    ///
    ChildrenOnly,
}