blob: d166205f27a73a54eb9087e13ec2b3c97d924e0f [file] [log] [blame]
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,
}