cranelift_bforest/path.rs
1//! A path from the root of a B+-tree to a leaf node.
2
3use super::node::Removed;
4use super::{slice_insert, slice_shift, Comparator, Forest, Node, NodeData, NodePool, MAX_PATH};
5use core::borrow::Borrow;
6use core::marker::PhantomData;
7
8#[cfg(test)]
9use core::fmt;
10
11pub(super) struct Path<F: Forest> {
12 /// Number of path entries including the root and leaf nodes.
13 size: usize,
14
15 /// Path of node references from the root to a leaf node.
16 node: [Node; MAX_PATH],
17
18 /// Entry number in each node.
19 entry: [u8; MAX_PATH],
20
21 unused: PhantomData<F>,
22}
23
24impl<F: Forest> Default for Path<F> {
25 fn default() -> Self {
26 Self {
27 size: 0,
28 node: [Node(0); MAX_PATH],
29 entry: [0; MAX_PATH],
30 unused: PhantomData,
31 }
32 }
33}
34
35impl<F: Forest> Path<F> {
36 /// Reset path by searching for `key` starting from `root`.
37 ///
38 /// If `key` is in the tree, returns the corresponding value and leaved the path pointing at
39 /// the entry. Otherwise returns `None` and:
40 ///
41 /// - A key smaller than all stored keys returns a path to the first entry of the first leaf.
42 /// - A key larger than all stored keys returns a path to one beyond the last element of the
43 /// last leaf.
44 /// - A key between the stored keys of adjacent leaf nodes returns a path to one beyond the
45 /// last entry of the first of the leaf nodes.
46 ///
47 pub fn find(
48 &mut self,
49 key: F::Key,
50 root: Node,
51 pool: &NodePool<F>,
52 comp: &dyn Comparator<F::Key>,
53 ) -> Option<F::Value> {
54 let mut node = root;
55 for level in 0.. {
56 self.size = level + 1;
57 self.node[level] = node;
58 match pool[node] {
59 NodeData::Inner { size, keys, tree } => {
60 // Invariant: `tree[i]` contains keys smaller than
61 // `keys[i]`, greater or equal to `keys[i-1]`.
62 let i = match comp.search(key, &keys[0..size.into()]) {
63 // We hit an existing key, so follow the >= branch.
64 Ok(i) => i + 1,
65 // Key is less than `keys[i]`, so follow the < branch.
66 Err(i) => i,
67 };
68 self.entry[level] = i as u8;
69 node = tree[i];
70 }
71 NodeData::Leaf { size, keys, vals } => {
72 // For a leaf we want either the found key or an insert position.
73 return match comp.search(key, &keys.borrow()[0..size.into()]) {
74 Ok(i) => {
75 self.entry[level] = i as u8;
76 Some(vals.borrow()[i])
77 }
78 Err(i) => {
79 self.entry[level] = i as u8;
80 None
81 }
82 };
83 }
84 NodeData::Free { .. } => panic!("Free {} reached from {}", node, root),
85 }
86 }
87 unreachable!();
88 }
89
90 /// Move path to the first entry of the tree starting at `root` and return it.
91 pub fn first(&mut self, root: Node, pool: &NodePool<F>) -> (F::Key, F::Value) {
92 let mut node = root;
93 for level in 0.. {
94 self.size = level + 1;
95 self.node[level] = node;
96 self.entry[level] = 0;
97 match pool[node] {
98 NodeData::Inner { tree, .. } => node = tree[0],
99 NodeData::Leaf { keys, vals, .. } => return (keys.borrow()[0], vals.borrow()[0]),
100 NodeData::Free { .. } => panic!("Free {} reached from {}", node, root),
101 }
102 }
103 unreachable!();
104 }
105
106 /// Move this path to the next key-value pair and return it.
107 pub fn next(&mut self, pool: &NodePool<F>) -> Option<(F::Key, F::Value)> {
108 match self.leaf_pos() {
109 None => return None,
110 Some((node, entry)) => {
111 let (keys, vals) = pool[node].unwrap_leaf();
112 if entry + 1 < keys.len() {
113 self.entry[self.size - 1] += 1;
114 return Some((keys[entry + 1], vals[entry + 1]));
115 }
116 }
117 }
118
119 // The current leaf node is exhausted. Move to the next one.
120 let leaf_level = self.size - 1;
121 self.next_node(leaf_level, pool).map(|node| {
122 let (keys, vals) = pool[node].unwrap_leaf();
123 (keys[0], vals[0])
124 })
125 }
126
127 /// Move this path to the previous key-value pair and return it.
128 ///
129 /// If the path is at the off-the-end position, go to the last key-value pair.
130 ///
131 /// If the path is already at the first key-value pair, leave it there and return `None`.
132 pub fn prev(&mut self, root: Node, pool: &NodePool<F>) -> Option<(F::Key, F::Value)> {
133 // We use `size == 0` as a generic off-the-end position.
134 if self.size == 0 {
135 self.goto_subtree_last(0, root, pool);
136 let (node, entry) = self.leaf_pos().unwrap();
137 let (keys, vals) = pool[node].unwrap_leaf();
138 return Some((keys[entry], vals[entry]));
139 }
140
141 match self.leaf_pos() {
142 None => return None,
143 Some((node, entry)) => {
144 if entry > 0 {
145 self.entry[self.size - 1] -= 1;
146 let (keys, vals) = pool[node].unwrap_leaf();
147 return Some((keys[entry - 1], vals[entry - 1]));
148 }
149 }
150 }
151
152 // The current leaf node is exhausted. Move to the previous one.
153 self.prev_leaf(pool).map(|node| {
154 let (keys, vals) = pool[node].unwrap_leaf();
155 let e = self.leaf_entry();
156 (keys[e], vals[e])
157 })
158 }
159
160 /// Move path to the first entry of the next node at level, if one exists.
161 ///
162 /// Returns the new node if it exists.
163 ///
164 /// Reset the path to `size = 0` and return `None` if there is no next node.
165 fn next_node(&mut self, level: usize, pool: &NodePool<F>) -> Option<Node> {
166 match self.right_sibling_branch_level(level, pool) {
167 None => {
168 self.size = 0;
169 None
170 }
171 Some(bl) => {
172 let (_, bnodes) = pool[self.node[bl]].unwrap_inner();
173 self.entry[bl] += 1;
174 let mut node = bnodes[usize::from(self.entry[bl])];
175
176 for l in bl + 1..level {
177 self.node[l] = node;
178 self.entry[l] = 0;
179 node = pool[node].unwrap_inner().1[0];
180 }
181
182 self.node[level] = node;
183 self.entry[level] = 0;
184 Some(node)
185 }
186 }
187 }
188
189 /// Move the path to the last entry of the previous leaf node, if one exists.
190 ///
191 /// Returns the new leaf node if it exists.
192 ///
193 /// Leave the path unchanged and returns `None` if we are already at the first leaf node.
194 fn prev_leaf(&mut self, pool: &NodePool<F>) -> Option<Node> {
195 self.left_sibling_branch_level(self.size - 1).map(|bl| {
196 let entry = self.entry[bl] - 1;
197 self.entry[bl] = entry;
198 let (_, bnodes) = pool[self.node[bl]].unwrap_inner();
199 self.goto_subtree_last(bl + 1, bnodes[usize::from(entry)], pool)
200 })
201 }
202
203 /// Move this path to the last position for the sub-tree at `level, root`.
204 fn goto_subtree_last(&mut self, level: usize, root: Node, pool: &NodePool<F>) -> Node {
205 let mut node = root;
206 for l in level.. {
207 self.node[l] = node;
208 match pool[node] {
209 NodeData::Inner { size, ref tree, .. } => {
210 self.entry[l] = size;
211 node = tree[usize::from(size)];
212 }
213 NodeData::Leaf { size, .. } => {
214 self.entry[l] = size - 1;
215 self.size = l + 1;
216 break;
217 }
218 NodeData::Free { .. } => panic!("Free {} reached from {}", node, root),
219 }
220 }
221 node
222 }
223
224 /// Set the root node and point the path at the first entry of the node.
225 pub fn set_root_node(&mut self, root: Node) {
226 self.size = 1;
227 self.node[0] = root;
228 self.entry[0] = 0;
229 }
230
231 /// Get the current leaf node and entry, if any.
232 pub fn leaf_pos(&self) -> Option<(Node, usize)> {
233 let i = self.size.wrapping_sub(1);
234 self.node.get(i).map(|&n| (n, self.entry[i].into()))
235 }
236
237 /// Get the current leaf node.
238 fn leaf_node(&self) -> Node {
239 self.node[self.size - 1]
240 }
241
242 /// Get the current entry in the leaf node.
243 fn leaf_entry(&self) -> usize {
244 self.entry[self.size - 1].into()
245 }
246
247 /// Is this path pointing to the first entry in the tree?
248 /// This corresponds to the smallest key.
249 fn at_first_entry(&self) -> bool {
250 self.entry[0..self.size].iter().all(|&i| i == 0)
251 }
252
253 /// Get a mutable reference to the current value.
254 /// This assumes that there is a current value.
255 pub fn value_mut<'a>(&self, pool: &'a mut NodePool<F>) -> &'a mut F::Value {
256 &mut pool[self.leaf_node()].unwrap_leaf_mut().1[self.leaf_entry()]
257 }
258
259 /// Insert the key-value pair at the current position.
260 /// The current position must be the correct insertion location for the key.
261 /// This function does not check for duplicate keys. Use `find` or similar for that.
262 /// Returns the new root node.
263 pub fn insert(&mut self, key: F::Key, value: F::Value, pool: &mut NodePool<F>) -> Node {
264 if !self.try_leaf_insert(key, value, pool) {
265 self.split_and_insert(key, value, pool);
266 }
267 self.node[0]
268 }
269
270 /// Try to insert `key, value` at the current position, but fail and return false if the leaf
271 /// node is full.
272 fn try_leaf_insert(&self, key: F::Key, value: F::Value, pool: &mut NodePool<F>) -> bool {
273 let index = self.leaf_entry();
274
275 // The case `index == 0` should only ever happen when there are no earlier leaf nodes,
276 // otherwise we should have appended to the previous leaf node instead. This invariant
277 // means that we don't need to update keys stored in inner nodes here.
278 debug_assert!(index > 0 || self.at_first_entry());
279
280 pool[self.leaf_node()].try_leaf_insert(index, key, value)
281 }
282
283 /// Split the current leaf node and then insert `key, value`.
284 /// This should only be used if `try_leaf_insert()` fails.
285 fn split_and_insert(&mut self, mut key: F::Key, value: F::Value, pool: &mut NodePool<F>) {
286 let orig_root = self.node[0];
287
288 // Loop invariant: We need to split the node at `level` and then retry a failed insertion.
289 // The items to insert are either `(key, ins_node)` or `(key, value)`.
290 let mut ins_node = None;
291 let mut split;
292 for level in (0..self.size).rev() {
293 // Split the current node.
294 let mut node = self.node[level];
295 let mut entry = self.entry[level].into();
296 split = pool[node].split(entry);
297 let rhs_node = pool.alloc_node(split.rhs_data);
298
299 // Should the path be moved to the new RHS node?
300 // Prefer the smaller node if we're right in the middle.
301 // Prefer to append to LHS all other things being equal.
302 //
303 // When inserting into an inner node (`ins_node.is_some()`), we must point to a valid
304 // entry in the current node since the new entry is inserted *after* the insert
305 // location.
306 if entry > split.lhs_entries
307 || (entry == split.lhs_entries
308 && (split.lhs_entries > split.rhs_entries || ins_node.is_some()))
309 {
310 node = rhs_node;
311 entry -= split.lhs_entries;
312 self.node[level] = node;
313 self.entry[level] = entry as u8;
314 }
315
316 // Now that we have a not-full node, it must be possible to insert.
317 match ins_node {
318 None => {
319 let inserted = pool[node].try_leaf_insert(entry, key, value);
320 debug_assert!(inserted);
321 // If we inserted at the front of the new rhs_node leaf, we need to propagate
322 // the inserted key as the critical key instead of the previous front key.
323 if entry == 0 && node == rhs_node {
324 split.crit_key = key;
325 }
326 }
327 Some(n) => {
328 let inserted = pool[node].try_inner_insert(entry, key, n);
329 debug_assert!(inserted);
330 // The lower level was moved to the new RHS node, so make sure that is
331 // reflected here.
332 if n == self.node[level + 1] {
333 self.entry[level] += 1;
334 }
335 }
336 }
337
338 // We are now done with the current level, but `rhs_node` must be inserted in the inner
339 // node above us. If we're already at level 0, the root node needs to be split.
340 key = split.crit_key;
341 ins_node = Some(rhs_node);
342 if level > 0 {
343 let pnode = &mut pool[self.node[level - 1]];
344 let pentry = self.entry[level - 1].into();
345 if pnode.try_inner_insert(pentry, key, rhs_node) {
346 // If this level level was moved to the new RHS node, update parent entry.
347 if node == rhs_node {
348 self.entry[level - 1] += 1;
349 }
350 return;
351 }
352 }
353 }
354
355 // If we get here we have split the original root node and need to add an extra level.
356 let rhs_node = ins_node.expect("empty path");
357 let root = pool.alloc_node(NodeData::inner(orig_root, key, rhs_node));
358 let entry = if self.node[0] == rhs_node { 1 } else { 0 };
359 self.size += 1;
360 slice_insert(&mut self.node[0..self.size], 0, root);
361 slice_insert(&mut self.entry[0..self.size], 0, entry);
362 }
363
364 /// Remove the key-value pair at the current position and advance the path to the next
365 /// key-value pair, leaving the path in a normalized state.
366 ///
367 /// Return the new root node.
368 pub fn remove(&mut self, pool: &mut NodePool<F>) -> Option<Node> {
369 let e = self.leaf_entry();
370 match pool[self.leaf_node()].leaf_remove(e) {
371 Removed::Healthy => {
372 if e == 0 {
373 self.update_crit_key(pool)
374 }
375 Some(self.node[0])
376 }
377 status => self.balance_nodes(status, pool),
378 }
379 }
380
381 /// Get the critical key for the current node at `level`.
382 ///
383 /// The critical key is less than or equal to all keys in the sub-tree at `level` and greater
384 /// than all keys to the left of the current node at `level`.
385 ///
386 /// The left-most node at any level does not have a critical key.
387 fn current_crit_key(&self, level: usize, pool: &NodePool<F>) -> Option<F::Key> {
388 // Find the level containing the critical key for the current node.
389 self.left_sibling_branch_level(level).map(|bl| {
390 let (keys, _) = pool[self.node[bl]].unwrap_inner();
391 keys[usize::from(self.entry[bl]) - 1]
392 })
393 }
394
395 /// Update the critical key after removing the front entry of the leaf node.
396 fn update_crit_key(&mut self, pool: &mut NodePool<F>) {
397 // Find the inner level containing the critical key for the current leaf node.
398 let crit_level = match self.left_sibling_branch_level(self.size - 1) {
399 None => return,
400 Some(l) => l,
401 };
402 let crit_kidx = self.entry[crit_level] - 1;
403
404 // Extract the new critical key from the leaf node.
405 let crit_key = pool[self.leaf_node()].leaf_crit_key();
406 let crit_node = self.node[crit_level];
407
408 match pool[crit_node] {
409 NodeData::Inner {
410 size, ref mut keys, ..
411 } => {
412 debug_assert!(crit_kidx < size);
413 keys[usize::from(crit_kidx)] = crit_key;
414 }
415 _ => panic!("Expected inner node"),
416 }
417 }
418
419 /// Given that the current leaf node is in an unhealthy (underflowed or even empty) status,
420 /// balance it with sibling nodes.
421 ///
422 /// Return the new root node.
423 fn balance_nodes(&mut self, status: Removed, pool: &mut NodePool<F>) -> Option<Node> {
424 // The current leaf node is not in a healthy state, and its critical key may have changed
425 // too.
426 //
427 // Start by dealing with a changed critical key for the leaf level.
428 if status != Removed::Empty && self.leaf_entry() == 0 {
429 self.update_crit_key(pool);
430 }
431
432 let leaf_level = self.size - 1;
433 if self.heal_level(status, leaf_level, pool) {
434 // Tree has become empty.
435 self.size = 0;
436 return None;
437 }
438
439 // Discard the root node if it has shrunk to a single sub-tree.
440 let mut ns = 0;
441 while let NodeData::Inner {
442 size: 0, ref tree, ..
443 } = pool[self.node[ns]]
444 {
445 ns += 1;
446 self.node[ns] = tree[0];
447 }
448
449 if ns > 0 {
450 for l in 0..ns {
451 pool.free_node(self.node[l]);
452 }
453
454 // Shift the whole array instead of just 0..size because `self.size` may be cleared
455 // here if the path is pointing off-the-end.
456 slice_shift(&mut self.node, ns);
457 slice_shift(&mut self.entry, ns);
458
459 if self.size > 0 {
460 self.size -= ns;
461 }
462 }
463
464 // Return the root node, even when `size=0` indicating that we're at the off-the-end
465 // position.
466 Some(self.node[0])
467 }
468
469 /// After removing an entry from the node at `level`, check its health and rebalance as needed.
470 ///
471 /// Leave the path up to and including `level` in a normalized state where all entries are in
472 /// bounds.
473 ///
474 /// Returns true if the tree becomes empty.
475 fn heal_level(&mut self, status: Removed, level: usize, pool: &mut NodePool<F>) -> bool {
476 match status {
477 Removed::Healthy => {}
478 Removed::Rightmost => {
479 // The rightmost entry was removed from the current node, so move the path so it
480 // points at the first entry of the next node at this level.
481 debug_assert_eq!(
482 usize::from(self.entry[level]),
483 pool[self.node[level]].entries()
484 );
485 self.next_node(level, pool);
486 }
487 Removed::Underflow => self.underflowed_node(level, pool),
488 Removed::Empty => return self.empty_node(level, pool),
489 }
490 false
491 }
492
493 /// The current node at `level` has underflowed, meaning that it is below half capacity but
494 /// not completely empty.
495 ///
496 /// Handle this by balancing entries with the right sibling node.
497 ///
498 /// Leave the path up to and including `level` in a valid state that points to the same entry.
499 fn underflowed_node(&mut self, level: usize, pool: &mut NodePool<F>) {
500 // Look for a right sibling node at this level. If none exists, we allow the underflowed
501 // node to persist as the right-most node at its level.
502 if let Some((crit_key, rhs_node)) = self.right_sibling(level, pool) {
503 // New critical key for the updated right sibling node.
504 let new_ck: Option<F::Key>;
505 let empty;
506 // Make a COPY of the sibling node to avoid fighting the borrow checker.
507 let mut rhs = pool[rhs_node];
508 match pool[self.node[level]].balance(crit_key, &mut rhs) {
509 None => {
510 // Everything got moved to the RHS node.
511 new_ck = self.current_crit_key(level, pool);
512 empty = true;
513 }
514 Some(key) => {
515 // Entries moved from RHS node.
516 new_ck = Some(key);
517 empty = false;
518 }
519 }
520 // Put back the updated RHS node data.
521 pool[rhs_node] = rhs;
522 // Update the critical key for the RHS node unless it has become a left-most
523 // node.
524 if let Some(ck) = new_ck {
525 self.update_right_crit_key(level, ck, pool);
526 }
527 if empty {
528 let empty_tree = self.empty_node(level, pool);
529 debug_assert!(!empty_tree);
530 }
531
532 // Any Removed::Rightmost state must have been cleared above by merging nodes. If the
533 // current entry[level] was one off the end of the node, it will now point at a proper
534 // entry.
535 debug_assert!(usize::from(self.entry[level]) < pool[self.node[level]].entries());
536 } else if usize::from(self.entry[level]) >= pool[self.node[level]].entries() {
537 // There's no right sibling at this level, so the node can't be rebalanced.
538 // Check if we are in an off-the-end position.
539 self.size = 0;
540 }
541 }
542
543 /// The current node at `level` has become empty.
544 ///
545 /// Remove the node from its parent node and leave the path in a normalized state. This means
546 /// that the path at this level will go through the right sibling of this node.
547 ///
548 /// If the current node has no right sibling, set `self.size = 0`.
549 ///
550 /// Returns true if the tree becomes empty.
551 fn empty_node(&mut self, level: usize, pool: &mut NodePool<F>) -> bool {
552 pool.free_node(self.node[level]);
553 if level == 0 {
554 // We just deleted the root node, so the tree is now empty.
555 return true;
556 }
557
558 // Get the right sibling node before recursively removing nodes.
559 let rhs_node = self.right_sibling(level, pool).map(|(_, n)| n);
560
561 // Remove the current sub-tree from the parent node.
562 let pl = level - 1;
563 let pe = self.entry[pl].into();
564 let status = pool[self.node[pl]].inner_remove(pe);
565 self.heal_level(status, pl, pool);
566
567 // Finally update the path at this level.
568 match rhs_node {
569 // We'll leave `self.entry[level]` unchanged. It can be non-zero after moving node
570 // entries to the right sibling node.
571 Some(rhs) => self.node[level] = rhs,
572 // We have no right sibling, so we must have deleted the right-most
573 // entry. The path should be moved to the "off-the-end" position.
574 None => self.size = 0,
575 }
576 false
577 }
578
579 /// Find the level where the right sibling to the current node at `level` branches off.
580 ///
581 /// This will be an inner node with two adjacent sub-trees: In one the current node at level is
582 /// a right-most node, in the other, the right sibling is a left-most node.
583 ///
584 /// Returns `None` if the current node is a right-most node so no right sibling exists.
585 fn right_sibling_branch_level(&self, level: usize, pool: &NodePool<F>) -> Option<usize> {
586 (0..level).rposition(|l| match pool[self.node[l]] {
587 NodeData::Inner { size, .. } => self.entry[l] < size,
588 _ => panic!("Expected inner node"),
589 })
590 }
591
592 /// Find the level where the left sibling to the current node at `level` branches off.
593 fn left_sibling_branch_level(&self, level: usize) -> Option<usize> {
594 self.entry[0..level].iter().rposition(|&e| e != 0)
595 }
596
597 /// Get the right sibling node to the current node at `level`.
598 /// Also return the critical key between the current node and the right sibling.
599 fn right_sibling(&self, level: usize, pool: &NodePool<F>) -> Option<(F::Key, Node)> {
600 // Find the critical level: The deepest level where two sibling subtrees contain the
601 // current node and its right sibling.
602 self.right_sibling_branch_level(level, pool).map(|bl| {
603 // Extract the critical key and the `bl+1` node.
604 let be = usize::from(self.entry[bl]);
605 let crit_key;
606 let mut node;
607 {
608 let (keys, tree) = pool[self.node[bl]].unwrap_inner();
609 crit_key = keys[be];
610 node = tree[be + 1];
611 }
612
613 // Follow left-most links back down to `level`.
614 for _ in bl + 1..level {
615 node = pool[node].unwrap_inner().1[0];
616 }
617
618 (crit_key, node)
619 })
620 }
621
622 /// Update the critical key for the right sibling node at `level`.
623 fn update_right_crit_key(&self, level: usize, crit_key: F::Key, pool: &mut NodePool<F>) {
624 let bl = self
625 .right_sibling_branch_level(level, pool)
626 .expect("No right sibling exists");
627 match pool[self.node[bl]] {
628 NodeData::Inner { ref mut keys, .. } => {
629 keys[usize::from(self.entry[bl])] = crit_key;
630 }
631 _ => panic!("Expected inner node"),
632 }
633 }
634
635 /// Normalize the path position such that it is either pointing at a real entry or `size=0`
636 /// indicating "off-the-end".
637 pub fn normalize(&mut self, pool: &mut NodePool<F>) {
638 if let Some((leaf, entry)) = self.leaf_pos() {
639 if entry >= pool[leaf].entries() {
640 let leaf_level = self.size - 1;
641 self.next_node(leaf_level, pool);
642 }
643 }
644 }
645}
646
647#[cfg(test)]
648impl<F: Forest> Path<F> {
649 /// Check the internal consistency of this path.
650 pub fn verify(&self, pool: &NodePool<F>) {
651 for level in 0..self.size {
652 match pool[self.node[level]] {
653 NodeData::Inner { size, tree, .. } => {
654 assert!(
655 level < self.size - 1,
656 "Expected leaf node at level {}",
657 level
658 );
659 assert!(
660 self.entry[level] <= size,
661 "OOB inner entry {}/{} at level {}",
662 self.entry[level],
663 size,
664 level
665 );
666 assert_eq!(
667 self.node[level + 1],
668 tree[usize::from(self.entry[level])],
669 "Node mismatch at level {}",
670 level
671 );
672 }
673 NodeData::Leaf { size, .. } => {
674 assert_eq!(level, self.size - 1, "Expected inner node");
675 assert!(
676 self.entry[level] <= size,
677 "OOB leaf entry {}/{}",
678 self.entry[level],
679 size,
680 );
681 }
682 NodeData::Free { .. } => {
683 panic!("Free {} in path", self.node[level]);
684 }
685 }
686 }
687 }
688}
689
690#[cfg(test)]
691impl<F: Forest> fmt::Display for Path<F> {
692 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
693 if self.size == 0 {
694 write!(f, "<empty path>")
695 } else {
696 write!(f, "{}[{}]", self.node[0], self.entry[0])?;
697 for i in 1..self.size {
698 write!(f, "--{}[{}]", self.node[i], self.entry[i])?;
699 }
700 Ok(())
701 }
702 }
703}
704
705#[cfg(test)]
706mod tests {
707 use super::super::{Forest, NodeData, NodePool};
708 use super::*;
709 use core::cmp::Ordering;
710
711 struct TC();
712
713 impl Comparator<i32> for TC {
714 fn cmp(&self, a: i32, b: i32) -> Ordering {
715 a.cmp(&b)
716 }
717 }
718
719 struct TF();
720
721 impl Forest for TF {
722 type Key = i32;
723 type Value = char;
724 type LeafKeys = [i32; 7];
725 type LeafValues = [char; 7];
726
727 fn splat_key(key: Self::Key) -> Self::LeafKeys {
728 [key; 7]
729 }
730
731 fn splat_value(value: Self::Value) -> Self::LeafValues {
732 [value; 7]
733 }
734 }
735
736 #[test]
737 fn search_single_leaf() {
738 // Testing Path::new() for trees with a single leaf node.
739 let mut pool = NodePool::<TF>::new();
740 let root = pool.alloc_node(NodeData::leaf(10, 'a'));
741 let mut p = Path::default();
742 let comp = TC();
743
744 // Search for key less than stored key.
745 assert_eq!(p.find(5, root, &pool, &comp), None);
746 assert_eq!(p.size, 1);
747 assert_eq!(p.node[0], root);
748 assert_eq!(p.entry[0], 0);
749
750 // Search for stored key.
751 assert_eq!(p.find(10, root, &pool, &comp), Some('a'));
752 assert_eq!(p.size, 1);
753 assert_eq!(p.node[0], root);
754 assert_eq!(p.entry[0], 0);
755
756 // Search for key greater than stored key.
757 assert_eq!(p.find(15, root, &pool, &comp), None);
758 assert_eq!(p.size, 1);
759 assert_eq!(p.node[0], root);
760 assert_eq!(p.entry[0], 1);
761
762 // Modify leaf node to contain two values.
763 match pool[root] {
764 NodeData::Leaf {
765 ref mut size,
766 ref mut keys,
767 ref mut vals,
768 } => {
769 *size = 2;
770 keys[1] = 20;
771 vals[1] = 'b';
772 }
773 _ => unreachable!(),
774 }
775
776 // Search for key between stored keys.
777 assert_eq!(p.find(15, root, &pool, &comp), None);
778 assert_eq!(p.size, 1);
779 assert_eq!(p.node[0], root);
780 assert_eq!(p.entry[0], 1);
781
782 // Search for key greater than stored keys.
783 assert_eq!(p.find(25, root, &pool, &comp), None);
784 assert_eq!(p.size, 1);
785 assert_eq!(p.node[0], root);
786 assert_eq!(p.entry[0], 2);
787 }
788
789 #[test]
790 fn search_single_inner() {
791 // Testing Path::new() for trees with a single inner node and two leaves.
792 let mut pool = NodePool::<TF>::new();
793 let leaf1 = pool.alloc_node(NodeData::leaf(10, 'a'));
794 let leaf2 = pool.alloc_node(NodeData::leaf(20, 'b'));
795 let root = pool.alloc_node(NodeData::inner(leaf1, 20, leaf2));
796 let mut p = Path::default();
797 let comp = TC();
798
799 // Search for key less than stored keys.
800 assert_eq!(p.find(5, root, &pool, &comp), None);
801 assert_eq!(p.size, 2);
802 assert_eq!(p.node[0], root);
803 assert_eq!(p.entry[0], 0);
804 assert_eq!(p.node[1], leaf1);
805 assert_eq!(p.entry[1], 0);
806
807 assert_eq!(p.find(10, root, &pool, &comp), Some('a'));
808 assert_eq!(p.size, 2);
809 assert_eq!(p.node[0], root);
810 assert_eq!(p.entry[0], 0);
811 assert_eq!(p.node[1], leaf1);
812 assert_eq!(p.entry[1], 0);
813
814 // Midway between the two leaf nodes.
815 assert_eq!(p.find(15, root, &pool, &comp), None);
816 assert_eq!(p.size, 2);
817 assert_eq!(p.node[0], root);
818 assert_eq!(p.entry[0], 0);
819 assert_eq!(p.node[1], leaf1);
820 assert_eq!(p.entry[1], 1);
821
822 assert_eq!(p.find(20, root, &pool, &comp), Some('b'));
823 assert_eq!(p.size, 2);
824 assert_eq!(p.node[0], root);
825 assert_eq!(p.entry[0], 1);
826 assert_eq!(p.node[1], leaf2);
827 assert_eq!(p.entry[1], 0);
828
829 assert_eq!(p.find(25, root, &pool, &comp), None);
830 assert_eq!(p.size, 2);
831 assert_eq!(p.node[0], root);
832 assert_eq!(p.entry[0], 1);
833 assert_eq!(p.node[1], leaf2);
834 assert_eq!(p.entry[1], 1);
835 }
836}