Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bytecodealliance
GitHub Repository: bytecodealliance/wasmtime
Path: blob/main/cranelift/bforest/src/path.rs
1692 views
1
//! A path from the root of a B+-tree to a leaf node.
2
3
use super::node::Removed;
4
use super::{Comparator, Forest, MAX_PATH, Node, NodeData, NodePool, slice_insert, slice_shift};
5
use core::borrow::Borrow;
6
use core::marker::PhantomData;
7
8
#[cfg(test)]
9
use core::fmt;
10
11
pub(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
24
impl<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
35
impl<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)]
648
impl<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!(level < self.size - 1, "Expected leaf node at level {level}");
655
assert!(
656
self.entry[level] <= size,
657
"OOB inner entry {}/{} at level {}",
658
self.entry[level],
659
size,
660
level
661
);
662
assert_eq!(
663
self.node[level + 1],
664
tree[usize::from(self.entry[level])],
665
"Node mismatch at level {level}"
666
);
667
}
668
NodeData::Leaf { size, .. } => {
669
assert_eq!(level, self.size - 1, "Expected inner node");
670
assert!(
671
self.entry[level] <= size,
672
"OOB leaf entry {}/{}",
673
self.entry[level],
674
size,
675
);
676
}
677
NodeData::Free { .. } => {
678
panic!("Free {} in path", self.node[level]);
679
}
680
}
681
}
682
}
683
}
684
685
#[cfg(test)]
686
impl<F: Forest> fmt::Display for Path<F> {
687
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
688
if self.size == 0 {
689
write!(f, "<empty path>")
690
} else {
691
write!(f, "{}[{}]", self.node[0], self.entry[0])?;
692
for i in 1..self.size {
693
write!(f, "--{}[{}]", self.node[i], self.entry[i])?;
694
}
695
Ok(())
696
}
697
}
698
}
699
700
#[cfg(test)]
701
mod tests {
702
use super::*;
703
use core::cmp::Ordering;
704
705
struct TC();
706
707
impl Comparator<i32> for TC {
708
fn cmp(&self, a: i32, b: i32) -> Ordering {
709
a.cmp(&b)
710
}
711
}
712
713
struct TF();
714
715
impl Forest for TF {
716
type Key = i32;
717
type Value = char;
718
type LeafKeys = [i32; 7];
719
type LeafValues = [char; 7];
720
721
fn splat_key(key: Self::Key) -> Self::LeafKeys {
722
[key; 7]
723
}
724
725
fn splat_value(value: Self::Value) -> Self::LeafValues {
726
[value; 7]
727
}
728
}
729
730
#[test]
731
fn search_single_leaf() {
732
// Testing Path::new() for trees with a single leaf node.
733
let mut pool = NodePool::<TF>::new();
734
let root = pool.alloc_node(NodeData::leaf(10, 'a'));
735
let mut p = Path::default();
736
let comp = TC();
737
738
// Search for key less than stored key.
739
assert_eq!(p.find(5, root, &pool, &comp), None);
740
assert_eq!(p.size, 1);
741
assert_eq!(p.node[0], root);
742
assert_eq!(p.entry[0], 0);
743
744
// Search for stored key.
745
assert_eq!(p.find(10, root, &pool, &comp), Some('a'));
746
assert_eq!(p.size, 1);
747
assert_eq!(p.node[0], root);
748
assert_eq!(p.entry[0], 0);
749
750
// Search for key greater than stored key.
751
assert_eq!(p.find(15, root, &pool, &comp), None);
752
assert_eq!(p.size, 1);
753
assert_eq!(p.node[0], root);
754
assert_eq!(p.entry[0], 1);
755
756
// Modify leaf node to contain two values.
757
match pool[root] {
758
NodeData::Leaf {
759
ref mut size,
760
ref mut keys,
761
ref mut vals,
762
} => {
763
*size = 2;
764
keys[1] = 20;
765
vals[1] = 'b';
766
}
767
_ => unreachable!(),
768
}
769
770
// Search for key between stored keys.
771
assert_eq!(p.find(15, root, &pool, &comp), None);
772
assert_eq!(p.size, 1);
773
assert_eq!(p.node[0], root);
774
assert_eq!(p.entry[0], 1);
775
776
// Search for key greater than stored keys.
777
assert_eq!(p.find(25, root, &pool, &comp), None);
778
assert_eq!(p.size, 1);
779
assert_eq!(p.node[0], root);
780
assert_eq!(p.entry[0], 2);
781
}
782
783
#[test]
784
fn search_single_inner() {
785
// Testing Path::new() for trees with a single inner node and two leaves.
786
let mut pool = NodePool::<TF>::new();
787
let leaf1 = pool.alloc_node(NodeData::leaf(10, 'a'));
788
let leaf2 = pool.alloc_node(NodeData::leaf(20, 'b'));
789
let root = pool.alloc_node(NodeData::inner(leaf1, 20, leaf2));
790
let mut p = Path::default();
791
let comp = TC();
792
793
// Search for key less than stored keys.
794
assert_eq!(p.find(5, root, &pool, &comp), None);
795
assert_eq!(p.size, 2);
796
assert_eq!(p.node[0], root);
797
assert_eq!(p.entry[0], 0);
798
assert_eq!(p.node[1], leaf1);
799
assert_eq!(p.entry[1], 0);
800
801
assert_eq!(p.find(10, root, &pool, &comp), Some('a'));
802
assert_eq!(p.size, 2);
803
assert_eq!(p.node[0], root);
804
assert_eq!(p.entry[0], 0);
805
assert_eq!(p.node[1], leaf1);
806
assert_eq!(p.entry[1], 0);
807
808
// Midway between the two leaf nodes.
809
assert_eq!(p.find(15, root, &pool, &comp), None);
810
assert_eq!(p.size, 2);
811
assert_eq!(p.node[0], root);
812
assert_eq!(p.entry[0], 0);
813
assert_eq!(p.node[1], leaf1);
814
assert_eq!(p.entry[1], 1);
815
816
assert_eq!(p.find(20, root, &pool, &comp), Some('b'));
817
assert_eq!(p.size, 2);
818
assert_eq!(p.node[0], root);
819
assert_eq!(p.entry[0], 1);
820
assert_eq!(p.node[1], leaf2);
821
assert_eq!(p.entry[1], 0);
822
823
assert_eq!(p.find(25, root, &pool, &comp), None);
824
assert_eq!(p.size, 2);
825
assert_eq!(p.node[0], root);
826
assert_eq!(p.entry[0], 1);
827
assert_eq!(p.node[1], leaf2);
828
assert_eq!(p.entry[1], 1);
829
}
830
}
831
832