id_tree/behaviors.rs
1use NodeId;
2
3///
4/// Describes the possible behaviors of the `Tree::remove_node` method.
5///
6pub enum RemoveBehavior {
7 ///
8 /// All children will be dropped recursively. In other words, the entire sub-tree of the `Node`
9 /// being removed will be dropped from the tree. Those `Node`s will no longer exist and
10 /// cannot be accessed even if you have the `NodeId` the previously pointed to them.
11 ///
12 /// This means even without using `Clone` you might end up with copies of invalid `NodeId`s.
13 /// Use this behavior with caution.
14 ///
15 /// ```
16 /// use id_tree::*;
17 /// use id_tree::InsertBehavior::*;
18 /// use id_tree::RemoveBehavior::*;
19 ///
20 /// let mut tree: Tree<i32> = Tree::new();
21 ///
22 /// let root_id = tree.insert(Node::new(0), AsRoot).unwrap();
23 /// let child_id = tree.insert(Node::new(1), UnderNode(&root_id)).unwrap();
24 /// let grandchild_id = tree.insert(Node::new(2), UnderNode(&child_id)).unwrap();
25 ///
26 /// let child = tree.remove_node(child_id, DropChildren).ok().unwrap();
27 ///
28 /// assert!(tree.get(&grandchild_id).is_err());
29 /// assert_eq!(tree.get(&root_id).unwrap().children().len(), 0);
30 /// assert_eq!(child.children().len(), 0);
31 /// assert_eq!(child.parent(), None);
32 /// ```
33 ///
34 DropChildren,
35
36 ///
37 /// If the removed `Node` (let's call it `A`) has a parent, `A`'s parent will become the
38 /// parent of `A`'s children. This effectively just shifts them up one level in the `Tree`.
39 ///
40 /// If `A` doesn't have a parent, then this behaves exactly like
41 /// `RemoveBehavior::OrphanChildren`.
42 ///
43 /// ```
44 /// use id_tree::*;
45 /// use id_tree::InsertBehavior::*;
46 /// use id_tree::RemoveBehavior::*;
47 ///
48 /// let mut tree: Tree<i32> = Tree::new();
49 ///
50 /// let root_id = tree.insert(Node::new(0), AsRoot).unwrap();
51 /// let child_id = tree.insert(Node::new(1), UnderNode(&root_id)).unwrap();
52 /// let grandchild_id = tree.insert(Node::new(2), UnderNode(&child_id)).unwrap();
53 ///
54 /// let child = tree.remove_node(child_id, LiftChildren).ok().unwrap();
55 ///
56 /// assert!(tree.get(&grandchild_id).is_ok());
57 /// assert!(tree.get(&root_id).unwrap().children().contains(&grandchild_id));
58 /// assert_eq!(child.children().len(), 0);
59 /// assert_eq!(child.parent(), None);
60 /// ```
61 ///
62 LiftChildren,
63
64 ///
65 /// All children will have their parent references cleared. This means nothing will point to
66 /// them, but they will still exist in the tree. Those `Node`s can still be accessed provided
67 /// that you have the `NodeId` that points to them.
68 ///
69 /// ```
70 /// use id_tree::*;
71 /// use id_tree::InsertBehavior::*;
72 /// use id_tree::RemoveBehavior::*;
73 ///
74 /// let mut tree: Tree<i32> = Tree::new();
75 ///
76 /// let root_id = tree.insert(Node::new(0), AsRoot).unwrap();
77 /// let child_id = tree.insert(Node::new(1), UnderNode(&root_id)).unwrap();
78 /// let grandchild_id = tree.insert(Node::new(2), UnderNode(&child_id)).unwrap();
79 ///
80 /// let child = tree.remove_node(child_id, OrphanChildren).ok().unwrap();
81 ///
82 /// assert!(tree.get(&grandchild_id).is_ok());
83 /// assert_eq!(tree.get(&root_id).unwrap().children().len(), 0);
84 /// assert_eq!(child.children().len(), 0);
85 /// assert_eq!(child.parent(), None);
86 /// ```
87 ///
88 OrphanChildren,
89}
90
91///
92/// Describes the possible behaviors of the `Tree::move_node` method.
93///
94pub enum MoveBehavior<'a> {
95 ///
96 /// Sets the `Node` in question as the new root `Node`, leaving all children in their place (in
97 /// other words, they will travel with the `Node` being moved).
98 ///
99 /// If there is already a root `Node` in place, it will be attached as the last child of the new
100 /// root.
101 ///
102 /// ```
103 /// use id_tree::*;
104 /// use id_tree::InsertBehavior::*;
105 /// use id_tree::MoveBehavior::*;
106 ///
107 /// let mut tree: Tree<i32> = Tree::new();
108 ///
109 /// let root_id = tree.insert(Node::new(1), AsRoot).unwrap();
110 /// let child_id = tree.insert(Node::new(2), UnderNode(&root_id)).unwrap();
111 /// let grandchild_id = tree.insert(Node::new(3), UnderNode(&child_id)).unwrap();
112 ///
113 /// tree.move_node(&grandchild_id, ToRoot).unwrap();
114 ///
115 /// assert_eq!(tree.root_node_id(), Some(&grandchild_id));
116 /// assert!(tree.get(&grandchild_id).unwrap().children().contains(&root_id));
117 /// assert!(!tree.get(&child_id).unwrap().children().contains(&grandchild_id));
118 /// ```
119 ///
120 ToRoot,
121
122 ///
123 /// Moves a `Node` inside the `Tree` to a new parent leaving all children in their place.
124 ///
125 /// If the new parent (let's call it `B`) is a descendant of the `Node` being moved (`A`), then
126 /// the direct child of `A` on the path from `A` to `B` will be shifted upwards to take the
127 /// place of its parent (`A`). All other children of `A` will be left alone, meaning they will
128 /// travel with it down the `Tree`.
129 ///
130 /// Please note that during the "shift-up" part of the above scenario, the `Node` being shifted
131 /// up will always be added as the last child of its new parent.
132 ///
133 /// ```
134 /// use id_tree::*;
135 /// use id_tree::InsertBehavior::*;
136 /// use id_tree::MoveBehavior::*;
137 ///
138 /// let mut tree: Tree<i32> = Tree::new();
139 ///
140 /// let root_id = tree.insert(Node::new(1), AsRoot).ok().unwrap();
141 /// let first_child_id = tree.insert(Node::new(2), UnderNode(&root_id)).unwrap();
142 /// let second_child_id = tree.insert(Node::new(3), UnderNode(&root_id)).unwrap();
143 /// let grandchild_id = tree.insert(Node::new(4), UnderNode(&first_child_id)).unwrap();
144 ///
145 /// tree.move_node(&grandchild_id, ToParent(&second_child_id)).unwrap();
146 ///
147 /// assert!(!tree.get(&first_child_id).unwrap().children().contains(&grandchild_id));
148 /// assert!(tree.get(&second_child_id).unwrap().children().contains(&grandchild_id));
149 /// ```
150 ///
151 ToParent(&'a NodeId),
152}
153
154///
155/// Describes the possible behaviors of the `Tree::insert` method.
156///
157pub enum InsertBehavior<'a> {
158 ///
159 /// Sets the root of the `Tree`.
160 ///
161 /// If there is already a root `Node` present in the tree, that `Node` is set as the first child
162 /// of the new root.
163 ///
164 /// ```
165 /// use id_tree::*;
166 /// use id_tree::InsertBehavior::*;
167 ///
168 /// let mut tree: Tree<i32> = Tree::new();
169 ///
170 /// tree.insert(Node::new(5), AsRoot).unwrap();
171 /// ```
172 AsRoot,
173
174 ///
175 /// Returns a `Result` containing the `NodeId` of the child that was added or a `NodeIdError` if
176 /// one occurred.
177 ///
178 /// Note: Adds the new Node to the end of its children.
179 ///
180 /// ```
181 /// use id_tree::*;
182 /// use id_tree::InsertBehavior::*;
183 ///
184 /// let root_node = Node::new(1);
185 /// let child_node = Node::new(2);
186 ///
187 /// let mut tree: Tree<i32> = Tree::new();
188 /// let root_id = tree.insert(root_node, AsRoot).unwrap();
189 ///
190 /// tree.insert(child_node, UnderNode(&root_id)).unwrap();
191 /// ```
192 UnderNode(&'a NodeId),
193}
194
195///
196/// Describes the possible behaviors of the `Tree::swap_nodes` method.
197///
198pub enum SwapBehavior {
199 ///
200 /// Take the children of the `Node`s being swapped with them. In other words, this swaps the
201 /// `Node`s in question along with their entire sub-tree. This *does not* affect the
202 /// relationship between the `Node`s being swapped and their children.
203 ///
204 /// If one `Node` is a descendant of the other getting swapped, the former *upper* `Node` is
205 /// attached as the last child of the former *lower* `Node` after the swap. (The *lower* will
206 /// take the *uppers* original position as usual.) The subtree of the former *upper* node is not
207 /// touched except that the *lower* `Node` is moved including all its children.
208 ///
209 /// ```
210 /// use id_tree::*;
211 /// use id_tree::InsertBehavior::*;
212 /// use id_tree::SwapBehavior::*;
213 ///
214 /// let mut tree: Tree<i32> = Tree::new();
215 ///
216 /// let root_id = tree.insert(Node::new(1), AsRoot).unwrap();
217 /// let first_child_id = tree.insert(Node::new(2), UnderNode(&root_id)).unwrap();
218 /// let second_child_id = tree.insert(Node::new(3), UnderNode(&root_id)).unwrap();
219 /// let grandchild_id = tree.insert(Node::new(4), UnderNode(&second_child_id)).unwrap();
220 ///
221 /// tree.swap_nodes(&first_child_id, &grandchild_id, TakeChildren).unwrap();
222 ///
223 /// assert!(tree.get(&second_child_id).unwrap().children().contains(&first_child_id));
224 /// assert!(tree.get(&root_id).unwrap().children().contains(&grandchild_id));
225 /// ```
226 ///
227 TakeChildren,
228
229 ///
230 /// Leave the children of the `Node`s being swapped where they are. In other words, this only
231 /// swaps the `Node`s themselves. This *does* affect the relationship between the `Node`s
232 /// being swapped and their children.
233 ///
234 /// Please Note: Because this behavior alters the relationship between the `Node`s being
235 /// swapped and their children, any calls to `children()` that have been cloned will no longer
236 /// point to the children of the `Node` that you might think they do.
237 ///
238 /// ```
239 /// use id_tree::*;
240 /// use id_tree::InsertBehavior::*;
241 /// use id_tree::SwapBehavior::*;
242 ///
243 /// let mut tree: Tree<i32> = Tree::new();
244 ///
245 /// let root_id = tree.insert(Node::new(1), AsRoot).unwrap();
246 /// let first_child_id = tree.insert(Node::new(2), UnderNode(&root_id)).unwrap();
247 /// let second_child_id = tree.insert(Node::new(3), UnderNode(&root_id)).unwrap();
248 /// let grandchild_id = tree.insert(Node::new(4), UnderNode(&second_child_id)).unwrap();
249 ///
250 /// tree.swap_nodes(&first_child_id, &second_child_id, LeaveChildren).unwrap();
251 ///
252 /// assert!(tree.get(&first_child_id).unwrap().children().contains(&grandchild_id));
253 /// assert_eq!(tree.get(&second_child_id).unwrap().children().len(), 0);
254 /// ```
255 ///
256 LeaveChildren,
257
258 ///
259 /// Swap the children of the `Node`s in question only. This does not swap the `Node`s that are
260 /// specified when calling this method. This *does* affect the relationship between the
261 /// `Node`s that are specified and their children.
262 ///
263 /// If one `Node` is a descendant of the other getting swapped, the child swapping step will
264 /// take place and then the *lower* `Node` in the swap will be added as the last child of the
265 /// *upper* `Node` in the swap.
266 ///
267 /// Please Note: Because this behavior alters the relationship between the `Node`s being
268 /// swapped and their children, any calls to `children()` that have been cloned will no longer
269 /// point to the children of the `Node` that you think they do.
270 ///
271 /// ```
272 /// use id_tree::*;
273 /// use id_tree::InsertBehavior::*;
274 /// use id_tree::SwapBehavior::*;
275 ///
276 /// let mut tree: Tree<i32> = Tree::new();
277 ///
278 /// let root_id = tree.insert(Node::new(1), AsRoot).unwrap();
279 /// let first_child_id = tree.insert(Node::new(2), UnderNode(&root_id)).unwrap();
280 /// let second_child_id = tree.insert(Node::new(3), UnderNode(&root_id)).unwrap();
281 /// let grandchild_id = tree.insert(Node::new(4), UnderNode(&second_child_id)).unwrap();
282 /// let grandchild_id_2 = tree.insert(Node::new(5), UnderNode(&first_child_id)).unwrap();
283 ///
284 /// tree.swap_nodes(&first_child_id, &second_child_id, ChildrenOnly).unwrap();
285 ///
286 /// assert!(tree.get(&first_child_id).unwrap().children().contains(&grandchild_id));
287 /// assert!(tree.get(&second_child_id).unwrap().children().contains(&grandchild_id_2));
288 /// ```
289 ///
290 ChildrenOnly,
291}