bitstring_trees/tree/
walk.rs

1use alloc::vec::Vec;
2use bitstring::BitString;
3
4use crate::walk_mut::NodeOrTree;
5
6use super::{
7	goto::{
8		GotoStepResult,
9		NodeRef,
10	},
11	InsertPosition,
12	Node,
13	Tree,
14	TreeProperties,
15	WalkedDirection,
16};
17
18/// Walk tree
19///
20/// Some algorithms need to remember how they reached the current node via [`WalkedDirection`] as `D`.
21///
22/// When walking manually it might be useful to be able to store additional data via `A`; look for functions with the suffix `_with`.
23pub struct Walk<'r, TP: TreeProperties, D = (), A = ()> {
24	tree: Option<&'r Node<TP>>,
25	stack: Vec<(&'r Node<TP>, (D, A))>,
26}
27
28impl<'r, TP: TreeProperties, D, A> Walk<'r, TP, D, A> {
29	pub(in crate::tree) fn new(tree: &'r Tree<TP>) -> Self {
30		Self {
31			tree: tree.node.as_ref(),
32			stack: Vec::new(),
33		}
34	}
35
36	/// Walk up to parent node or tree if not at tree
37	pub fn up(&mut self) -> Option<D> {
38		Some(self.stack.pop()?.1 .0)
39	}
40
41	/// Walk up to parent node or tree if not at tree
42	pub fn up_with(&mut self) -> Option<(D, A)> {
43		Some(self.stack.pop()?.1)
44	}
45
46	/// Current node or tree
47	pub fn current(&self) -> NodeOrTree<Option<&'r Node<TP>>, &'r Node<TP>> {
48		match self.stack.last() {
49			Some(&(node, _)) => NodeOrTree::Node(node),
50			None => NodeOrTree::Tree(self.tree),
51		}
52	}
53}
54
55impl<'r, TP: TreeProperties, D, A> Walk<'r, TP, D, A>
56where
57	D: From<WalkedDirection>,
58{
59	/// Walk down from tree to root node (if present)
60	pub fn down_root_with(&mut self, add: A) -> bool {
61		if self.stack.is_empty() {
62			if let Some(root) = self.tree {
63				self.stack.push((root, (WalkedDirection::Down.into(), add)));
64				return true;
65			}
66		}
67		false
68	}
69
70	/// Walk down to left node if present and not currently at tree
71	pub fn down_left_with(&mut self, add: A) -> bool {
72		self.down_with(false, add)
73	}
74
75	/// Walk down to right node if present and not currently at tree
76	pub fn down_right_with(&mut self, add: A) -> bool {
77		self.down_with(true, add)
78	}
79
80	/// Walk down to specified node if present and not currently at tree
81	///
82	/// `false` picks left and `true` picks right.
83	pub fn down_with(&mut self, side: bool, add: A) -> bool {
84		if let Some(&(node, _)) = self.stack.last() {
85			if let Some(child) = node.get_child(side) {
86				self.stack
87					.push((child, (WalkedDirection::from_side(side).into(), add)));
88				return true;
89			}
90		}
91		false
92	}
93}
94
95impl<'r, TP: TreeProperties, D> Walk<'r, TP, D, ()>
96where
97	D: From<WalkedDirection>,
98{
99	/// Walk down from tree to root node (if at tree and not empty)
100	pub fn down_root(&mut self) -> bool {
101		self.down_root_with(())
102	}
103
104	/// Walk down to left node if present and not currently at tree
105	pub fn down_left(&mut self) -> bool {
106		self.down_left_with(())
107	}
108
109	/// Walk down to right node if present and not currently at tree
110	pub fn down_right(&mut self) -> bool {
111		self.down_right_with(())
112	}
113
114	/// Walk down to specified node if present and not currently at tree
115	///
116	/// `false` picks left and `true` picks right.
117	pub fn down(&mut self, side: bool) -> bool {
118		self.down_with(side, ())
119	}
120}
121
122impl<'r, TP: TreeProperties, D> Walk<'r, TP, D>
123where
124	D: From<WalkedDirection>,
125{
126	// first need go up until current_node.key is a prefix of key (or we are at the root)
127	fn goto_clean(&mut self, key: &TP::Key) {
128		let key_len = key.len();
129		while let Some(&(node, _)) = self.stack.last() {
130			if node._is_prefix_of(key, key_len) {
131				return;
132			}
133			self.stack.pop();
134		}
135	}
136
137	// if not in the correct subtree call goto_clean first.
138	fn goto_insert_step(
139		&mut self,
140		key: &TP::Key,
141		key_len: usize,
142	) -> Result<(), Option<InsertPosition>> {
143		if let Some(&(node, _)) = self.stack.last() {
144			match node.goto_insert_step(key, key_len) {
145				GotoStepResult::Final(r) => Err(Some(r.into())),
146				GotoStepResult::Continue(node, dir) => {
147					self.stack.push((node, (dir.into(), ())));
148					Ok(())
149				},
150			}
151		} else if let Some(root) = self.tree {
152			self.stack.push((root, (WalkedDirection::Down.into(), ())));
153			Ok(())
154		} else {
155			Err(None)
156		}
157	}
158
159	// if not in the correct subtree call goto_clean first.
160	fn goto_insert_down(&mut self, key: &TP::Key) -> Option<InsertPosition> {
161		let key_len = key.len();
162		loop {
163			match self.goto_insert_step(key, key_len) {
164				Ok(()) => (),       // continue
165				Err(r) => return r, // reached target
166			}
167		}
168	}
169
170	/// Walk to node where we'd have to insert key at
171	///
172	/// This can either be:
173	/// - root if and only if the tree is empty
174	/// - node with exactly matching key
175	/// - node where the key is between the parent node (possibly root) and the node
176	///   * to insert the key here we might have to create a new inner node and move the existing node down
177	pub fn goto_insert(&mut self, key: &TP::Key) -> Option<InsertPosition> {
178		self.goto_clean(key);
179		self.goto_insert_down(key)
180	}
181}
182
183impl<'r, TP: TreeProperties> Walk<'r, TP, WalkedDirection> {
184	/// Tree traversal: depth-first pre-order
185	pub fn next_pre_order(&mut self) -> Option<&'r Node<TP>> {
186		match self.current() {
187			NodeOrTree::Tree(_) => {
188				self.down_root();
189			},
190			NodeOrTree::Node(node) => {
191				if node.is_leaf() {
192					loop {
193						match self.up()? {
194							WalkedDirection::Down => {
195								return None;
196							}, // back up at tree
197							WalkedDirection::Left => {
198								self.down_right();
199								break;
200							},
201							WalkedDirection::Right => (), // continue further up
202						}
203					}
204				} else {
205					self.down_left();
206				}
207			},
208		}
209		return self.current().node();
210	}
211
212	/// Tree traversal: depth-first in-order
213	pub fn next_in_order(&mut self) -> Option<&'r Node<TP>> {
214		match self.current() {
215			NodeOrTree::Tree(_) => {
216				self.down_root();
217				while self.down_left() {}
218			},
219			NodeOrTree::Node(node) => {
220				if node.is_leaf() {
221					loop {
222						match self.up()? {
223							WalkedDirection::Down => {
224								return None;
225							}, // back up at tree
226							WalkedDirection::Left => {
227								break;
228							},
229							WalkedDirection::Right => (), // continue further up
230						}
231					}
232				} else {
233					self.down_right();
234					while self.down_left() {}
235				}
236			},
237		}
238		return self.current().node();
239	}
240
241	/// Tree traversal: depth-first in-order leaf nodes only
242	pub fn next_leaf(&mut self) -> Option<&'r Node<TP>> {
243		match self.current() {
244			NodeOrTree::Tree(_) => {
245				self.down_root();
246				while self.down_left() {}
247			},
248			NodeOrTree::Node(_) => {
249				loop {
250					match self.up()? {
251						WalkedDirection::Down => {
252							return None; // back up at tree
253						},
254						WalkedDirection::Left => {
255							self.down_right();
256							while self.down_left() {}
257							break;
258						},
259						WalkedDirection::Right => (), // continue further up
260					}
261				}
262			},
263		}
264		return self.current().node();
265	}
266
267	/// Tree traversal: depth-first post-order
268	pub fn next_post_order(&mut self) -> Option<&'r Node<TP>> {
269		match self.current() {
270			NodeOrTree::Tree(_) => {
271				self.down_root();
272				while self.down_left() {}
273			},
274			NodeOrTree::Node(_) => {
275				match self.up()? {
276					WalkedDirection::Down => {
277						return None;
278					}, // back up at tree
279					WalkedDirection::Left => {
280						self.down_right();
281						while self.down_left() {}
282					},
283					WalkedDirection::Right => (),
284				}
285			},
286		}
287		return self.current().node();
288	}
289}