1747ad3c4Slazypassion //! B+-tree nodes.
2747ad3c4Slazypassion 
3*90ac295eSAlex Crichton use super::{Forest, INNER_SIZE, Node, SetValue, slice_insert, slice_shift};
4747ad3c4Slazypassion use core::borrow::{Borrow, BorrowMut};
5747ad3c4Slazypassion use core::fmt;
6747ad3c4Slazypassion 
7747ad3c4Slazypassion /// B+-tree node.
8747ad3c4Slazypassion ///
9747ad3c4Slazypassion /// A B+-tree has different node types for inner nodes and leaf nodes. Inner nodes contain M node
10747ad3c4Slazypassion /// references and M-1 keys while leaf nodes contain N keys and values. Values for M and N are
11747ad3c4Slazypassion /// chosen such that a node is exactly 64 bytes (a cache line) when keys and values are 32 bits
12747ad3c4Slazypassion /// each.
13747ad3c4Slazypassion ///
14747ad3c4Slazypassion /// An inner node contains at least M/2 node references unless it is the right-most node at its
15747ad3c4Slazypassion /// level. A leaf node contains at least N/2 keys unless it is the right-most leaf.
16747ad3c4Slazypassion pub(super) enum NodeData<F: Forest> {
17747ad3c4Slazypassion     Inner {
18747ad3c4Slazypassion         /// The number of keys in this node.
19747ad3c4Slazypassion         /// The number of node references is always one more.
20747ad3c4Slazypassion         size: u8,
21747ad3c4Slazypassion 
22747ad3c4Slazypassion         /// Keys discriminating sub-trees.
23747ad3c4Slazypassion         ///
24747ad3c4Slazypassion         /// The key in `keys[i]` is greater than all keys in `tree[i]` and less than or equal to
25747ad3c4Slazypassion         /// all keys in `tree[i+1]`.
26747ad3c4Slazypassion         keys: [F::Key; INNER_SIZE - 1],
27747ad3c4Slazypassion 
28747ad3c4Slazypassion         /// Sub-trees.
29747ad3c4Slazypassion         tree: [Node; INNER_SIZE],
30747ad3c4Slazypassion     },
31747ad3c4Slazypassion     Leaf {
32747ad3c4Slazypassion         /// Number of key-value pairs in this node.
33747ad3c4Slazypassion         size: u8,
34747ad3c4Slazypassion 
35747ad3c4Slazypassion         // Key array.
36747ad3c4Slazypassion         keys: F::LeafKeys,
37747ad3c4Slazypassion 
38747ad3c4Slazypassion         // Value array.
39747ad3c4Slazypassion         vals: F::LeafValues,
40747ad3c4Slazypassion     },
41747ad3c4Slazypassion     /// An unused node on the free list.
42747ad3c4Slazypassion     Free { next: Option<Node> },
43747ad3c4Slazypassion }
44747ad3c4Slazypassion 
45747ad3c4Slazypassion // Implement `Clone` and `Copy` manually, because deriving them would also require `Forest` to
46747ad3c4Slazypassion // implement `Clone`.
47747ad3c4Slazypassion impl<F: Forest> Copy for NodeData<F> {}
48747ad3c4Slazypassion impl<F: Forest> Clone for NodeData<F> {
clone(&self) -> Self49747ad3c4Slazypassion     fn clone(&self) -> Self {
50747ad3c4Slazypassion         *self
51747ad3c4Slazypassion     }
52747ad3c4Slazypassion }
53747ad3c4Slazypassion 
54747ad3c4Slazypassion impl<F: Forest> NodeData<F> {
55747ad3c4Slazypassion     /// Is this a free/unused node?
is_free(&self) -> bool56747ad3c4Slazypassion     pub fn is_free(&self) -> bool {
57747ad3c4Slazypassion         match *self {
589f506692SPeter Huene             Self::Free { .. } => true,
59747ad3c4Slazypassion             _ => false,
60747ad3c4Slazypassion         }
61747ad3c4Slazypassion     }
62747ad3c4Slazypassion 
63747ad3c4Slazypassion     /// Get the number of entries in this node.
64747ad3c4Slazypassion     ///
65747ad3c4Slazypassion     /// This is the number of outgoing edges in an inner node, or the number of key-value pairs in
66747ad3c4Slazypassion     /// a leaf node.
entries(&self) -> usize67747ad3c4Slazypassion     pub fn entries(&self) -> usize {
68747ad3c4Slazypassion         match *self {
699f506692SPeter Huene             Self::Inner { size, .. } => usize::from(size) + 1,
709f506692SPeter Huene             Self::Leaf { size, .. } => usize::from(size),
719f506692SPeter Huene             Self::Free { .. } => panic!("freed node"),
72747ad3c4Slazypassion         }
73747ad3c4Slazypassion     }
74747ad3c4Slazypassion 
75747ad3c4Slazypassion     /// Create an inner node with a single key and two sub-trees.
inner(left: Node, key: F::Key, right: Node) -> Self76747ad3c4Slazypassion     pub fn inner(left: Node, key: F::Key, right: Node) -> Self {
77747ad3c4Slazypassion         // Splat the key and right node to the whole array.
78747ad3c4Slazypassion         // Saves us from inventing a default/reserved value.
79747ad3c4Slazypassion         let mut tree = [right; INNER_SIZE];
80747ad3c4Slazypassion         tree[0] = left;
819f506692SPeter Huene         Self::Inner {
82747ad3c4Slazypassion             size: 1,
83747ad3c4Slazypassion             keys: [key; INNER_SIZE - 1],
84747ad3c4Slazypassion             tree,
85747ad3c4Slazypassion         }
86747ad3c4Slazypassion     }
87747ad3c4Slazypassion 
88747ad3c4Slazypassion     /// Create a leaf node with a single key-value pair.
leaf(key: F::Key, value: F::Value) -> Self89747ad3c4Slazypassion     pub fn leaf(key: F::Key, value: F::Value) -> Self {
909f506692SPeter Huene         Self::Leaf {
91747ad3c4Slazypassion             size: 1,
92747ad3c4Slazypassion             keys: F::splat_key(key),
93747ad3c4Slazypassion             vals: F::splat_value(value),
94747ad3c4Slazypassion         }
95747ad3c4Slazypassion     }
96747ad3c4Slazypassion 
97747ad3c4Slazypassion     /// Unwrap an inner node into two slices (keys, trees).
unwrap_inner(&self) -> (&[F::Key], &[Node])98747ad3c4Slazypassion     pub fn unwrap_inner(&self) -> (&[F::Key], &[Node]) {
99747ad3c4Slazypassion         match *self {
1009f506692SPeter Huene             Self::Inner {
101747ad3c4Slazypassion                 size,
102747ad3c4Slazypassion                 ref keys,
103747ad3c4Slazypassion                 ref tree,
104747ad3c4Slazypassion             } => {
105747ad3c4Slazypassion                 let size = usize::from(size);
106747ad3c4Slazypassion                 // TODO: We could probably use `get_unchecked()` here since `size` is always in
107747ad3c4Slazypassion                 // range.
108747ad3c4Slazypassion                 (&keys[0..size], &tree[0..=size])
109747ad3c4Slazypassion             }
110747ad3c4Slazypassion             _ => panic!("Expected inner node"),
111747ad3c4Slazypassion         }
112747ad3c4Slazypassion     }
113747ad3c4Slazypassion 
114747ad3c4Slazypassion     /// Unwrap a leaf node into two slices (keys, values) of the same length.
unwrap_leaf(&self) -> (&[F::Key], &[F::Value])115747ad3c4Slazypassion     pub fn unwrap_leaf(&self) -> (&[F::Key], &[F::Value]) {
116747ad3c4Slazypassion         match *self {
1179f506692SPeter Huene             Self::Leaf {
118747ad3c4Slazypassion                 size,
119747ad3c4Slazypassion                 ref keys,
120747ad3c4Slazypassion                 ref vals,
121747ad3c4Slazypassion             } => {
122747ad3c4Slazypassion                 let size = usize::from(size);
123747ad3c4Slazypassion                 let keys = keys.borrow();
124747ad3c4Slazypassion                 let vals = vals.borrow();
125747ad3c4Slazypassion                 // TODO: We could probably use `get_unchecked()` here since `size` is always in
126747ad3c4Slazypassion                 // range.
127747ad3c4Slazypassion                 (&keys[0..size], &vals[0..size])
128747ad3c4Slazypassion             }
129747ad3c4Slazypassion             _ => panic!("Expected leaf node"),
130747ad3c4Slazypassion         }
131747ad3c4Slazypassion     }
132747ad3c4Slazypassion 
133747ad3c4Slazypassion     /// Unwrap a mutable leaf node into two slices (keys, values) of the same length.
unwrap_leaf_mut(&mut self) -> (&mut [F::Key], &mut [F::Value])134747ad3c4Slazypassion     pub fn unwrap_leaf_mut(&mut self) -> (&mut [F::Key], &mut [F::Value]) {
135747ad3c4Slazypassion         match *self {
1369f506692SPeter Huene             Self::Leaf {
137747ad3c4Slazypassion                 size,
138747ad3c4Slazypassion                 ref mut keys,
139747ad3c4Slazypassion                 ref mut vals,
140747ad3c4Slazypassion             } => {
141747ad3c4Slazypassion                 let size = usize::from(size);
142747ad3c4Slazypassion                 let keys = keys.borrow_mut();
143747ad3c4Slazypassion                 let vals = vals.borrow_mut();
144747ad3c4Slazypassion                 // TODO: We could probably use `get_unchecked_mut()` here since `size` is always in
145747ad3c4Slazypassion                 // range.
146747ad3c4Slazypassion                 (&mut keys[0..size], &mut vals[0..size])
147747ad3c4Slazypassion             }
148747ad3c4Slazypassion             _ => panic!("Expected leaf node"),
149747ad3c4Slazypassion         }
150747ad3c4Slazypassion     }
151747ad3c4Slazypassion 
152747ad3c4Slazypassion     /// Get the critical key for a leaf node.
153747ad3c4Slazypassion     /// This is simply the first key.
leaf_crit_key(&self) -> F::Key154747ad3c4Slazypassion     pub fn leaf_crit_key(&self) -> F::Key {
155747ad3c4Slazypassion         match *self {
1569f506692SPeter Huene             Self::Leaf { size, ref keys, .. } => {
157747ad3c4Slazypassion                 debug_assert!(size > 0, "Empty leaf node");
158747ad3c4Slazypassion                 keys.borrow()[0]
159747ad3c4Slazypassion             }
160747ad3c4Slazypassion             _ => panic!("Expected leaf node"),
161747ad3c4Slazypassion         }
162747ad3c4Slazypassion     }
163747ad3c4Slazypassion 
164747ad3c4Slazypassion     /// Try to insert `(key, node)` at key-position `index` in an inner node.
165747ad3c4Slazypassion     /// This means that `key` is inserted at `keys[i]` and `node` is inserted at `tree[i + 1]`.
166747ad3c4Slazypassion     /// If the node is full, this leaves the node unchanged and returns false.
try_inner_insert(&mut self, index: usize, key: F::Key, node: Node) -> bool167747ad3c4Slazypassion     pub fn try_inner_insert(&mut self, index: usize, key: F::Key, node: Node) -> bool {
168747ad3c4Slazypassion         match *self {
1699f506692SPeter Huene             Self::Inner {
170747ad3c4Slazypassion                 ref mut size,
171747ad3c4Slazypassion                 ref mut keys,
172747ad3c4Slazypassion                 ref mut tree,
173747ad3c4Slazypassion             } => {
174747ad3c4Slazypassion                 let sz = usize::from(*size);
175747ad3c4Slazypassion                 debug_assert!(sz <= keys.len());
176a0442ea0SHamir Mahal                 debug_assert!(index <= sz, "Can't insert at {index} with {sz} keys");
177747ad3c4Slazypassion 
178747ad3c4Slazypassion                 if let Some(ks) = keys.get_mut(0..=sz) {
179747ad3c4Slazypassion                     *size = (sz + 1) as u8;
180747ad3c4Slazypassion                     slice_insert(ks, index, key);
181747ad3c4Slazypassion                     slice_insert(&mut tree[1..=sz + 1], index, node);
182747ad3c4Slazypassion                     true
183747ad3c4Slazypassion                 } else {
184747ad3c4Slazypassion                     false
185747ad3c4Slazypassion                 }
186747ad3c4Slazypassion             }
187747ad3c4Slazypassion             _ => panic!("Expected inner node"),
188747ad3c4Slazypassion         }
189747ad3c4Slazypassion     }
190747ad3c4Slazypassion 
191747ad3c4Slazypassion     /// Try to insert `key, value` at `index` in a leaf node, but fail and return false if the node
192747ad3c4Slazypassion     /// is full.
try_leaf_insert(&mut self, index: usize, key: F::Key, value: F::Value) -> bool193747ad3c4Slazypassion     pub fn try_leaf_insert(&mut self, index: usize, key: F::Key, value: F::Value) -> bool {
194747ad3c4Slazypassion         match *self {
1959f506692SPeter Huene             Self::Leaf {
196747ad3c4Slazypassion                 ref mut size,
197747ad3c4Slazypassion                 ref mut keys,
198747ad3c4Slazypassion                 ref mut vals,
199747ad3c4Slazypassion             } => {
200747ad3c4Slazypassion                 let sz = usize::from(*size);
201747ad3c4Slazypassion                 let keys = keys.borrow_mut();
202747ad3c4Slazypassion                 let vals = vals.borrow_mut();
203747ad3c4Slazypassion                 debug_assert!(sz <= keys.len());
204747ad3c4Slazypassion                 debug_assert!(index <= sz);
205747ad3c4Slazypassion 
206747ad3c4Slazypassion                 if let Some(ks) = keys.get_mut(0..=sz) {
207747ad3c4Slazypassion                     *size = (sz + 1) as u8;
208747ad3c4Slazypassion                     slice_insert(ks, index, key);
209747ad3c4Slazypassion                     slice_insert(&mut vals[0..=sz], index, value);
210747ad3c4Slazypassion                     true
211747ad3c4Slazypassion                 } else {
212747ad3c4Slazypassion                     false
213747ad3c4Slazypassion                 }
214747ad3c4Slazypassion             }
215747ad3c4Slazypassion             _ => panic!("Expected leaf node"),
216747ad3c4Slazypassion         }
217747ad3c4Slazypassion     }
218747ad3c4Slazypassion 
219747ad3c4Slazypassion     /// Split off the second half of this node.
220747ad3c4Slazypassion     /// It is assumed that this a completely full inner or leaf node.
221747ad3c4Slazypassion     ///
222747ad3c4Slazypassion     /// The `insert_index` parameter is the position where an insertion was tried and failed. The
223747ad3c4Slazypassion     /// node will be split in half with a bias towards an even split after the insertion is retried.
split(&mut self, insert_index: usize) -> SplitOff<F>224747ad3c4Slazypassion     pub fn split(&mut self, insert_index: usize) -> SplitOff<F> {
225747ad3c4Slazypassion         match *self {
2269f506692SPeter Huene             Self::Inner {
227747ad3c4Slazypassion                 ref mut size,
228747ad3c4Slazypassion                 ref keys,
229747ad3c4Slazypassion                 ref tree,
230747ad3c4Slazypassion             } => {
231747ad3c4Slazypassion                 debug_assert_eq!(usize::from(*size), keys.len(), "Node not full");
232747ad3c4Slazypassion 
233747ad3c4Slazypassion                 // Number of tree entries in the lhs node.
234747ad3c4Slazypassion                 let l_ents = split_pos(tree.len(), insert_index + 1);
235747ad3c4Slazypassion                 let r_ents = tree.len() - l_ents;
236747ad3c4Slazypassion 
237747ad3c4Slazypassion                 // With INNER_SIZE=8, we get l_ents=4 and:
238747ad3c4Slazypassion                 //
239747ad3c4Slazypassion                 // self: [ n0 k0 n1 k1 n2 k2 n3 k3 n4 k4 n5 k5 n6 k6 n7 ]
240747ad3c4Slazypassion                 // lhs:  [ n0 k0 n1 k1 n2 k2 n3 ]
241747ad3c4Slazypassion                 // crit_key = k3 (not present in either node)
242747ad3c4Slazypassion                 // rhs:  [ n4 k4 n5 k5 n6 k6 n7 ]
243747ad3c4Slazypassion 
244747ad3c4Slazypassion                 // 1. Truncate the LHS.
245747ad3c4Slazypassion                 *size = (l_ents - 1) as u8;
246747ad3c4Slazypassion 
247747ad3c4Slazypassion                 // 2. Copy second half to `rhs_data`.
248747ad3c4Slazypassion                 let mut r_keys = *keys;
249747ad3c4Slazypassion                 r_keys[0..r_ents - 1].copy_from_slice(&keys[l_ents..]);
250747ad3c4Slazypassion 
251747ad3c4Slazypassion                 let mut r_tree = *tree;
252747ad3c4Slazypassion                 r_tree[0..r_ents].copy_from_slice(&tree[l_ents..]);
253747ad3c4Slazypassion 
254747ad3c4Slazypassion                 SplitOff {
255747ad3c4Slazypassion                     lhs_entries: l_ents,
256747ad3c4Slazypassion                     rhs_entries: r_ents,
257747ad3c4Slazypassion                     crit_key: keys[l_ents - 1],
2589f506692SPeter Huene                     rhs_data: Self::Inner {
259747ad3c4Slazypassion                         size: (r_ents - 1) as u8,
260747ad3c4Slazypassion                         keys: r_keys,
261747ad3c4Slazypassion                         tree: r_tree,
262747ad3c4Slazypassion                     },
263747ad3c4Slazypassion                 }
264747ad3c4Slazypassion             }
2659f506692SPeter Huene             Self::Leaf {
266747ad3c4Slazypassion                 ref mut size,
267747ad3c4Slazypassion                 ref keys,
268747ad3c4Slazypassion                 ref vals,
269747ad3c4Slazypassion             } => {
270747ad3c4Slazypassion                 let o_keys = keys.borrow();
271747ad3c4Slazypassion                 let o_vals = vals.borrow();
272747ad3c4Slazypassion                 debug_assert_eq!(usize::from(*size), o_keys.len(), "Node not full");
273747ad3c4Slazypassion 
274747ad3c4Slazypassion                 let l_size = split_pos(o_keys.len(), insert_index);
275747ad3c4Slazypassion                 let r_size = o_keys.len() - l_size;
276747ad3c4Slazypassion 
277747ad3c4Slazypassion                 // 1. Truncate the LHS node at `l_size`.
278747ad3c4Slazypassion                 *size = l_size as u8;
279747ad3c4Slazypassion 
280747ad3c4Slazypassion                 // 2. Copy second half to `rhs_data`.
281747ad3c4Slazypassion                 let mut r_keys = *keys;
282747ad3c4Slazypassion                 r_keys.borrow_mut()[0..r_size].copy_from_slice(&o_keys[l_size..]);
283747ad3c4Slazypassion 
284747ad3c4Slazypassion                 let mut r_vals = *vals;
285747ad3c4Slazypassion                 r_vals.borrow_mut()[0..r_size].copy_from_slice(&o_vals[l_size..]);
286747ad3c4Slazypassion 
287747ad3c4Slazypassion                 SplitOff {
288747ad3c4Slazypassion                     lhs_entries: l_size,
289747ad3c4Slazypassion                     rhs_entries: r_size,
290747ad3c4Slazypassion                     crit_key: o_keys[l_size],
2919f506692SPeter Huene                     rhs_data: Self::Leaf {
292747ad3c4Slazypassion                         size: r_size as u8,
293747ad3c4Slazypassion                         keys: r_keys,
294747ad3c4Slazypassion                         vals: r_vals,
295747ad3c4Slazypassion                     },
296747ad3c4Slazypassion                 }
297747ad3c4Slazypassion             }
298747ad3c4Slazypassion             _ => panic!("Expected leaf node"),
299747ad3c4Slazypassion         }
300747ad3c4Slazypassion     }
301747ad3c4Slazypassion 
302747ad3c4Slazypassion     /// Remove the sub-tree at `index` from this inner node.
303747ad3c4Slazypassion     ///
304747ad3c4Slazypassion     /// Note that `index` refers to a sub-tree entry and not a key entry as it does for
305747ad3c4Slazypassion     /// `try_inner_insert()`. It is possible to remove the first sub-tree (which can't be inserted
306747ad3c4Slazypassion     /// by `try_inner_insert()`).
307747ad3c4Slazypassion     ///
308747ad3c4Slazypassion     /// Return an indication of the node's health (i.e. below half capacity).
inner_remove(&mut self, index: usize) -> Removed309747ad3c4Slazypassion     pub fn inner_remove(&mut self, index: usize) -> Removed {
310747ad3c4Slazypassion         match *self {
3119f506692SPeter Huene             Self::Inner {
312747ad3c4Slazypassion                 ref mut size,
313747ad3c4Slazypassion                 ref mut keys,
314747ad3c4Slazypassion                 ref mut tree,
315747ad3c4Slazypassion             } => {
316747ad3c4Slazypassion                 let ents = usize::from(*size) + 1;
317747ad3c4Slazypassion                 debug_assert!(ents <= tree.len());
318747ad3c4Slazypassion                 debug_assert!(index < ents);
319747ad3c4Slazypassion                 // Leave an invalid 0xff size when node becomes empty.
320747ad3c4Slazypassion                 *size = ents.wrapping_sub(2) as u8;
321747ad3c4Slazypassion                 if ents > 1 {
322747ad3c4Slazypassion                     slice_shift(&mut keys[index.saturating_sub(1)..ents - 1], 1);
323747ad3c4Slazypassion                 }
324747ad3c4Slazypassion                 slice_shift(&mut tree[index..ents], 1);
325747ad3c4Slazypassion                 Removed::new(index, ents - 1, tree.len())
326747ad3c4Slazypassion             }
327747ad3c4Slazypassion             _ => panic!("Expected inner node"),
328747ad3c4Slazypassion         }
329747ad3c4Slazypassion     }
330747ad3c4Slazypassion 
331747ad3c4Slazypassion     /// Remove the key-value pair at `index` from this leaf node.
332747ad3c4Slazypassion     ///
333747ad3c4Slazypassion     /// Return an indication of the node's health (i.e. below half capacity).
leaf_remove(&mut self, index: usize) -> Removed334747ad3c4Slazypassion     pub fn leaf_remove(&mut self, index: usize) -> Removed {
335747ad3c4Slazypassion         match *self {
3369f506692SPeter Huene             Self::Leaf {
337747ad3c4Slazypassion                 ref mut size,
338747ad3c4Slazypassion                 ref mut keys,
339747ad3c4Slazypassion                 ref mut vals,
340747ad3c4Slazypassion             } => {
341747ad3c4Slazypassion                 let sz = usize::from(*size);
342747ad3c4Slazypassion                 let keys = keys.borrow_mut();
343747ad3c4Slazypassion                 let vals = vals.borrow_mut();
344747ad3c4Slazypassion                 *size -= 1;
345747ad3c4Slazypassion                 slice_shift(&mut keys[index..sz], 1);
346747ad3c4Slazypassion                 slice_shift(&mut vals[index..sz], 1);
347747ad3c4Slazypassion                 Removed::new(index, sz - 1, keys.len())
348747ad3c4Slazypassion             }
349747ad3c4Slazypassion             _ => panic!("Expected leaf node"),
350747ad3c4Slazypassion         }
351747ad3c4Slazypassion     }
352747ad3c4Slazypassion 
353747ad3c4Slazypassion     /// Balance this node with its right sibling.
354747ad3c4Slazypassion     ///
355747ad3c4Slazypassion     /// It is assumed that the current node has underflowed. Look at the right sibling node and do
356747ad3c4Slazypassion     /// one of two things:
357747ad3c4Slazypassion     ///
358747ad3c4Slazypassion     /// 1. Move all entries to the right node, leaving this node empty, or
359747ad3c4Slazypassion     /// 2. Distribute entries evenly between the two nodes.
360747ad3c4Slazypassion     ///
361747ad3c4Slazypassion     /// In the first case, `None` is returned. In the second case, the new critical key for the
362747ad3c4Slazypassion     /// right sibling node is returned.
balance(&mut self, crit_key: F::Key, rhs: &mut Self) -> Option<F::Key>363747ad3c4Slazypassion     pub fn balance(&mut self, crit_key: F::Key, rhs: &mut Self) -> Option<F::Key> {
364747ad3c4Slazypassion         match (self, rhs) {
365747ad3c4Slazypassion             (
3669f506692SPeter Huene                 &mut Self::Inner {
367747ad3c4Slazypassion                     size: ref mut l_size,
368747ad3c4Slazypassion                     keys: ref mut l_keys,
369747ad3c4Slazypassion                     tree: ref mut l_tree,
370747ad3c4Slazypassion                 },
3719f506692SPeter Huene                 &mut Self::Inner {
372747ad3c4Slazypassion                     size: ref mut r_size,
373747ad3c4Slazypassion                     keys: ref mut r_keys,
374747ad3c4Slazypassion                     tree: ref mut r_tree,
375747ad3c4Slazypassion                 },
376747ad3c4Slazypassion             ) => {
377747ad3c4Slazypassion                 let l_ents = usize::from(*l_size) + 1;
378747ad3c4Slazypassion                 let r_ents = usize::from(*r_size) + 1;
379747ad3c4Slazypassion                 let ents = l_ents + r_ents;
380747ad3c4Slazypassion 
381747ad3c4Slazypassion                 if ents <= r_tree.len() {
382747ad3c4Slazypassion                     // All entries will fit in the RHS node.
383747ad3c4Slazypassion                     // We'll leave the LHS node empty, but first use it as a scratch space.
384747ad3c4Slazypassion                     *l_size = 0;
385747ad3c4Slazypassion                     // Insert `crit_key` between the two nodes.
386747ad3c4Slazypassion                     l_keys[l_ents - 1] = crit_key;
387747ad3c4Slazypassion                     l_keys[l_ents..ents - 1].copy_from_slice(&r_keys[0..r_ents - 1]);
388747ad3c4Slazypassion                     r_keys[0..ents - 1].copy_from_slice(&l_keys[0..ents - 1]);
389747ad3c4Slazypassion                     l_tree[l_ents..ents].copy_from_slice(&r_tree[0..r_ents]);
390747ad3c4Slazypassion                     r_tree[0..ents].copy_from_slice(&l_tree[0..ents]);
391747ad3c4Slazypassion                     *r_size = (ents - 1) as u8;
392747ad3c4Slazypassion                     None
393747ad3c4Slazypassion                 } else {
394747ad3c4Slazypassion                     // The entries don't all fit in one node. Distribute some from RHS -> LHS.
395747ad3c4Slazypassion                     // Split evenly with a bias to putting one entry in LHS.
396747ad3c4Slazypassion                     let r_goal = ents / 2;
397747ad3c4Slazypassion                     let l_goal = ents - r_goal;
398747ad3c4Slazypassion                     debug_assert!(l_goal > l_ents, "Node must be underflowed");
399747ad3c4Slazypassion 
400747ad3c4Slazypassion                     l_keys[l_ents - 1] = crit_key;
401747ad3c4Slazypassion                     l_keys[l_ents..l_goal - 1].copy_from_slice(&r_keys[0..l_goal - 1 - l_ents]);
402747ad3c4Slazypassion                     l_tree[l_ents..l_goal].copy_from_slice(&r_tree[0..l_goal - l_ents]);
403747ad3c4Slazypassion                     *l_size = (l_goal - 1) as u8;
404747ad3c4Slazypassion 
405747ad3c4Slazypassion                     let new_crit = r_keys[r_ents - r_goal - 1];
406747ad3c4Slazypassion                     slice_shift(&mut r_keys[0..r_ents - 1], r_ents - r_goal);
407747ad3c4Slazypassion                     slice_shift(&mut r_tree[0..r_ents], r_ents - r_goal);
408747ad3c4Slazypassion                     *r_size = (r_goal - 1) as u8;
409747ad3c4Slazypassion 
410747ad3c4Slazypassion                     Some(new_crit)
411747ad3c4Slazypassion                 }
412747ad3c4Slazypassion             }
413747ad3c4Slazypassion             (
4149f506692SPeter Huene                 &mut Self::Leaf {
415747ad3c4Slazypassion                     size: ref mut l_size,
416747ad3c4Slazypassion                     keys: ref mut l_keys,
417747ad3c4Slazypassion                     vals: ref mut l_vals,
418747ad3c4Slazypassion                 },
4199f506692SPeter Huene                 &mut Self::Leaf {
420747ad3c4Slazypassion                     size: ref mut r_size,
421747ad3c4Slazypassion                     keys: ref mut r_keys,
422747ad3c4Slazypassion                     vals: ref mut r_vals,
423747ad3c4Slazypassion                 },
424747ad3c4Slazypassion             ) => {
425747ad3c4Slazypassion                 let l_ents = usize::from(*l_size);
426747ad3c4Slazypassion                 let l_keys = l_keys.borrow_mut();
427747ad3c4Slazypassion                 let l_vals = l_vals.borrow_mut();
428747ad3c4Slazypassion                 let r_ents = usize::from(*r_size);
429747ad3c4Slazypassion                 let r_keys = r_keys.borrow_mut();
430747ad3c4Slazypassion                 let r_vals = r_vals.borrow_mut();
431747ad3c4Slazypassion                 let ents = l_ents + r_ents;
432747ad3c4Slazypassion 
433747ad3c4Slazypassion                 if ents <= r_vals.len() {
434747ad3c4Slazypassion                     // We can fit all entries in the RHS node.
435747ad3c4Slazypassion                     // We'll leave the LHS node empty, but first use it as a scratch space.
436747ad3c4Slazypassion                     *l_size = 0;
437747ad3c4Slazypassion                     l_keys[l_ents..ents].copy_from_slice(&r_keys[0..r_ents]);
438747ad3c4Slazypassion                     r_keys[0..ents].copy_from_slice(&l_keys[0..ents]);
439747ad3c4Slazypassion                     l_vals[l_ents..ents].copy_from_slice(&r_vals[0..r_ents]);
440747ad3c4Slazypassion                     r_vals[0..ents].copy_from_slice(&l_vals[0..ents]);
441747ad3c4Slazypassion                     *r_size = ents as u8;
442747ad3c4Slazypassion                     None
443747ad3c4Slazypassion                 } else {
444747ad3c4Slazypassion                     // The entries don't all fit in one node. Distribute some from RHS -> LHS.
445747ad3c4Slazypassion                     // Split evenly with a bias to putting one entry in LHS.
446747ad3c4Slazypassion                     let r_goal = ents / 2;
447747ad3c4Slazypassion                     let l_goal = ents - r_goal;
448747ad3c4Slazypassion                     debug_assert!(l_goal > l_ents, "Node must be underflowed");
449747ad3c4Slazypassion 
450747ad3c4Slazypassion                     l_keys[l_ents..l_goal].copy_from_slice(&r_keys[0..l_goal - l_ents]);
451747ad3c4Slazypassion                     l_vals[l_ents..l_goal].copy_from_slice(&r_vals[0..l_goal - l_ents]);
452747ad3c4Slazypassion                     *l_size = l_goal as u8;
453747ad3c4Slazypassion 
454747ad3c4Slazypassion                     slice_shift(&mut r_keys[0..r_ents], r_ents - r_goal);
455747ad3c4Slazypassion                     slice_shift(&mut r_vals[0..r_ents], r_ents - r_goal);
456747ad3c4Slazypassion                     *r_size = r_goal as u8;
457747ad3c4Slazypassion 
458747ad3c4Slazypassion                     Some(r_keys[0])
459747ad3c4Slazypassion                 }
460747ad3c4Slazypassion             }
461747ad3c4Slazypassion             _ => panic!("Mismatched nodes"),
462747ad3c4Slazypassion         }
463747ad3c4Slazypassion     }
464747ad3c4Slazypassion }
465747ad3c4Slazypassion 
466747ad3c4Slazypassion /// Find the right split position for halving a full node with `len` entries to recover from a
467747ad3c4Slazypassion /// failed insertion at `ins`.
468747ad3c4Slazypassion ///
469747ad3c4Slazypassion /// If `len` is even, we should split straight down the middle regardless of `len`.
470747ad3c4Slazypassion ///
471747ad3c4Slazypassion /// If `len` is odd, we should split the node such that the two halves are the same size after the
472747ad3c4Slazypassion /// insertion is retried.
split_pos(len: usize, ins: usize) -> usize473747ad3c4Slazypassion fn split_pos(len: usize, ins: usize) -> usize {
474747ad3c4Slazypassion     // Anticipate `len` being a compile time constant, so this all folds away when `len` is even.
475747ad3c4Slazypassion     if ins <= len / 2 {
476747ad3c4Slazypassion         len / 2
477747ad3c4Slazypassion     } else {
478747ad3c4Slazypassion         (len + 1) / 2
479747ad3c4Slazypassion     }
480747ad3c4Slazypassion }
481747ad3c4Slazypassion 
482747ad3c4Slazypassion /// The result of splitting off the second half of a node.
483747ad3c4Slazypassion pub(super) struct SplitOff<F: Forest> {
484747ad3c4Slazypassion     /// The number of entries left in the original node which becomes the left-hand-side of the
485747ad3c4Slazypassion     /// pair. This is the number of outgoing node edges for an inner node, and the number of
486747ad3c4Slazypassion     /// key-value pairs for a leaf node.
487747ad3c4Slazypassion     pub lhs_entries: usize,
488747ad3c4Slazypassion 
489747ad3c4Slazypassion     /// The number of entries in the new RHS node.
490747ad3c4Slazypassion     pub rhs_entries: usize,
491747ad3c4Slazypassion 
492747ad3c4Slazypassion     /// The critical key separating the LHS and RHS nodes. All keys in the LHS sub-tree are less
493747ad3c4Slazypassion     /// than the critical key, and all entries in the RHS sub-tree are greater or equal to the
494747ad3c4Slazypassion     /// critical key.
495747ad3c4Slazypassion     pub crit_key: F::Key,
496747ad3c4Slazypassion 
497747ad3c4Slazypassion     /// The RHS node data containing the elements that were removed from the original node (now the
498747ad3c4Slazypassion     /// LHS).
499747ad3c4Slazypassion     pub rhs_data: NodeData<F>,
500747ad3c4Slazypassion }
501747ad3c4Slazypassion 
502747ad3c4Slazypassion /// The result of removing an entry from a node.
503747ad3c4Slazypassion #[derive(Clone, Copy, Debug, PartialEq, Eq)]
504747ad3c4Slazypassion pub(super) enum Removed {
505747ad3c4Slazypassion     /// An entry was removed, and the node is still in good shape.
506747ad3c4Slazypassion     Healthy,
507747ad3c4Slazypassion 
508747ad3c4Slazypassion     /// The node is in good shape after removing the rightmost element.
509747ad3c4Slazypassion     Rightmost,
510747ad3c4Slazypassion 
511747ad3c4Slazypassion     /// The node has too few entries now, and it should be balanced with a sibling node.
512747ad3c4Slazypassion     Underflow,
513747ad3c4Slazypassion 
514747ad3c4Slazypassion     /// The last entry was removed. For an inner node, this means that the `keys` array is empty
515747ad3c4Slazypassion     /// and there is just a single sub-tree left.
516747ad3c4Slazypassion     Empty,
517747ad3c4Slazypassion }
518747ad3c4Slazypassion 
519747ad3c4Slazypassion impl Removed {
520747ad3c4Slazypassion     /// Create a `Removed` status from a size and capacity.
new(removed: usize, new_size: usize, capacity: usize) -> Self521747ad3c4Slazypassion     fn new(removed: usize, new_size: usize, capacity: usize) -> Self {
522747ad3c4Slazypassion         if 2 * new_size >= capacity {
523747ad3c4Slazypassion             if removed == new_size {
5249f506692SPeter Huene                 Self::Rightmost
525747ad3c4Slazypassion             } else {
5269f506692SPeter Huene                 Self::Healthy
527747ad3c4Slazypassion             }
528747ad3c4Slazypassion         } else if new_size > 0 {
5299f506692SPeter Huene             Self::Underflow
530747ad3c4Slazypassion         } else {
5319f506692SPeter Huene             Self::Empty
532747ad3c4Slazypassion         }
533747ad3c4Slazypassion     }
534747ad3c4Slazypassion }
535747ad3c4Slazypassion 
536747ad3c4Slazypassion // Display ": value" or nothing at all for `()`.
537747ad3c4Slazypassion pub(super) trait ValDisp {
valfmt(&self, f: &mut fmt::Formatter) -> fmt::Result538747ad3c4Slazypassion     fn valfmt(&self, f: &mut fmt::Formatter) -> fmt::Result;
539747ad3c4Slazypassion }
540747ad3c4Slazypassion 
541747ad3c4Slazypassion impl ValDisp for SetValue {
valfmt(&self, _: &mut fmt::Formatter) -> fmt::Result542747ad3c4Slazypassion     fn valfmt(&self, _: &mut fmt::Formatter) -> fmt::Result {
543747ad3c4Slazypassion         Ok(())
544747ad3c4Slazypassion     }
545747ad3c4Slazypassion }
546747ad3c4Slazypassion 
547747ad3c4Slazypassion impl<T: fmt::Display> ValDisp for T {
valfmt(&self, f: &mut fmt::Formatter) -> fmt::Result548747ad3c4Slazypassion     fn valfmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
549a0442ea0SHamir Mahal         write!(f, ":{self}")
550747ad3c4Slazypassion     }
551747ad3c4Slazypassion }
552747ad3c4Slazypassion 
553747ad3c4Slazypassion impl<F> fmt::Display for NodeData<F>
554747ad3c4Slazypassion where
555747ad3c4Slazypassion     F: Forest,
556747ad3c4Slazypassion     F::Key: fmt::Display,
557747ad3c4Slazypassion     F::Value: ValDisp,
558747ad3c4Slazypassion {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result559747ad3c4Slazypassion     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
560747ad3c4Slazypassion         match *self {
5619f506692SPeter Huene             Self::Inner { size, keys, tree } => {
562747ad3c4Slazypassion                 write!(f, "[ {}", tree[0])?;
563747ad3c4Slazypassion                 for i in 0..usize::from(size) {
564747ad3c4Slazypassion                     write!(f, " {} {}", keys[i], tree[i + 1])?;
565747ad3c4Slazypassion                 }
566747ad3c4Slazypassion                 write!(f, " ]")
567747ad3c4Slazypassion             }
5689f506692SPeter Huene             Self::Leaf { size, keys, vals } => {
569747ad3c4Slazypassion                 let keys = keys.borrow();
570747ad3c4Slazypassion                 let vals = vals.borrow();
571747ad3c4Slazypassion                 write!(f, "[")?;
572747ad3c4Slazypassion                 for i in 0..usize::from(size) {
573747ad3c4Slazypassion                     write!(f, " {}", keys[i])?;
574747ad3c4Slazypassion                     vals[i].valfmt(f)?;
575747ad3c4Slazypassion                 }
576747ad3c4Slazypassion                 write!(f, " ]")
577747ad3c4Slazypassion             }
578a0442ea0SHamir Mahal             Self::Free { next: Some(n) } => write!(f, "[ free -> {n} ]"),
5799f506692SPeter Huene             Self::Free { next: None } => write!(f, "[ free ]"),
580747ad3c4Slazypassion         }
581747ad3c4Slazypassion     }
582747ad3c4Slazypassion }
583747ad3c4Slazypassion 
584747ad3c4Slazypassion #[cfg(test)]
585747ad3c4Slazypassion mod tests {
586747ad3c4Slazypassion     use super::*;
587d25e6119Sbjorn3     use alloc::string::ToString;
588bb8fa40eSbjorn3     use core::mem;
589747ad3c4Slazypassion 
590747ad3c4Slazypassion     // Forest impl for a set implementation.
591747ad3c4Slazypassion     struct TF();
592747ad3c4Slazypassion 
593747ad3c4Slazypassion     impl Forest for TF {
594747ad3c4Slazypassion         type Key = char;
595747ad3c4Slazypassion         type Value = SetValue;
596747ad3c4Slazypassion         type LeafKeys = [char; 15];
597747ad3c4Slazypassion         type LeafValues = [SetValue; 15];
598747ad3c4Slazypassion 
splat_key(key: Self::Key) -> Self::LeafKeys599747ad3c4Slazypassion         fn splat_key(key: Self::Key) -> Self::LeafKeys {
600747ad3c4Slazypassion             [key; 15]
601747ad3c4Slazypassion         }
602747ad3c4Slazypassion 
splat_value(value: Self::Value) -> Self::LeafValues603747ad3c4Slazypassion         fn splat_value(value: Self::Value) -> Self::LeafValues {
604747ad3c4Slazypassion             [value; 15]
605747ad3c4Slazypassion         }
606747ad3c4Slazypassion     }
607747ad3c4Slazypassion 
608747ad3c4Slazypassion     #[test]
inner()609747ad3c4Slazypassion     fn inner() {
610747ad3c4Slazypassion         let n1 = Node(1);
611747ad3c4Slazypassion         let n2 = Node(2);
612747ad3c4Slazypassion         let n3 = Node(3);
613747ad3c4Slazypassion         let n4 = Node(4);
614747ad3c4Slazypassion         let mut inner = NodeData::<TF>::inner(n1, 'c', n4);
615747ad3c4Slazypassion         assert_eq!(mem::size_of_val(&inner), 64);
616747ad3c4Slazypassion         assert_eq!(inner.to_string(), "[ node1 c node4 ]");
617747ad3c4Slazypassion 
618747ad3c4Slazypassion         assert!(inner.try_inner_insert(0, 'a', n2));
619747ad3c4Slazypassion         assert_eq!(inner.to_string(), "[ node1 a node2 c node4 ]");
620747ad3c4Slazypassion 
621747ad3c4Slazypassion         assert!(inner.try_inner_insert(1, 'b', n3));
622747ad3c4Slazypassion         assert_eq!(inner.to_string(), "[ node1 a node2 b node3 c node4 ]");
623747ad3c4Slazypassion 
624747ad3c4Slazypassion         for i in 3..7 {
625747ad3c4Slazypassion             assert!(inner.try_inner_insert(
626747ad3c4Slazypassion                 usize::from(i),
627747ad3c4Slazypassion                 ('a' as u8 + i) as char,
628747ad3c4Slazypassion                 Node(i as u32 + 2),
629747ad3c4Slazypassion             ));
630747ad3c4Slazypassion         }
631747ad3c4Slazypassion         assert_eq!(
632747ad3c4Slazypassion             inner.to_string(),
633747ad3c4Slazypassion             "[ node1 a node2 b node3 c node4 d node5 e node6 f node7 g node8 ]"
634747ad3c4Slazypassion         );
635747ad3c4Slazypassion 
636747ad3c4Slazypassion         // Now the node is full and insertion should fail anywhere.
637747ad3c4Slazypassion         assert!(!inner.try_inner_insert(0, 'x', n3));
638747ad3c4Slazypassion         assert!(!inner.try_inner_insert(4, 'x', n3));
639747ad3c4Slazypassion         assert!(!inner.try_inner_insert(7, 'x', n3));
640747ad3c4Slazypassion 
641747ad3c4Slazypassion         // Splitting should be independent of the hint because we have an even number of node
642747ad3c4Slazypassion         // references.
643a0442ea0SHamir Mahal         let saved = inner;
644747ad3c4Slazypassion         let sp = inner.split(1);
645747ad3c4Slazypassion         assert_eq!(sp.lhs_entries, 4);
646747ad3c4Slazypassion         assert_eq!(sp.rhs_entries, 4);
647747ad3c4Slazypassion         assert_eq!(sp.crit_key, 'd');
648747ad3c4Slazypassion         // The critical key is not present in either of the resulting nodes.
649747ad3c4Slazypassion         assert_eq!(inner.to_string(), "[ node1 a node2 b node3 c node4 ]");
650747ad3c4Slazypassion         assert_eq!(sp.rhs_data.to_string(), "[ node5 e node6 f node7 g node8 ]");
651747ad3c4Slazypassion 
652747ad3c4Slazypassion         assert_eq!(inner.inner_remove(0), Removed::Underflow);
653747ad3c4Slazypassion         assert_eq!(inner.to_string(), "[ node2 b node3 c node4 ]");
654747ad3c4Slazypassion 
655747ad3c4Slazypassion         assert_eq!(inner.inner_remove(1), Removed::Underflow);
656747ad3c4Slazypassion         assert_eq!(inner.to_string(), "[ node2 c node4 ]");
657747ad3c4Slazypassion 
658747ad3c4Slazypassion         assert_eq!(inner.inner_remove(1), Removed::Underflow);
659747ad3c4Slazypassion         assert_eq!(inner.to_string(), "[ node2 ]");
660747ad3c4Slazypassion 
661747ad3c4Slazypassion         assert_eq!(inner.inner_remove(0), Removed::Empty);
662747ad3c4Slazypassion 
663747ad3c4Slazypassion         inner = saved;
664747ad3c4Slazypassion         let sp = inner.split(6);
665747ad3c4Slazypassion         assert_eq!(sp.lhs_entries, 4);
666747ad3c4Slazypassion         assert_eq!(sp.rhs_entries, 4);
667747ad3c4Slazypassion         assert_eq!(sp.crit_key, 'd');
668747ad3c4Slazypassion         assert_eq!(inner.to_string(), "[ node1 a node2 b node3 c node4 ]");
669747ad3c4Slazypassion         assert_eq!(sp.rhs_data.to_string(), "[ node5 e node6 f node7 g node8 ]");
670747ad3c4Slazypassion     }
671747ad3c4Slazypassion 
672747ad3c4Slazypassion     #[test]
leaf()673747ad3c4Slazypassion     fn leaf() {
674747ad3c4Slazypassion         let mut leaf = NodeData::<TF>::leaf('d', SetValue());
675747ad3c4Slazypassion         assert_eq!(leaf.to_string(), "[ d ]");
676747ad3c4Slazypassion 
677747ad3c4Slazypassion         assert!(leaf.try_leaf_insert(0, 'a', SetValue()));
678747ad3c4Slazypassion         assert_eq!(leaf.to_string(), "[ a d ]");
679747ad3c4Slazypassion         assert!(leaf.try_leaf_insert(1, 'b', SetValue()));
680747ad3c4Slazypassion         assert!(leaf.try_leaf_insert(2, 'c', SetValue()));
681747ad3c4Slazypassion         assert_eq!(leaf.to_string(), "[ a b c d ]");
682747ad3c4Slazypassion         for i in 4..15 {
683747ad3c4Slazypassion             assert!(leaf.try_leaf_insert(usize::from(i), ('a' as u8 + i) as char, SetValue()));
684747ad3c4Slazypassion         }
685747ad3c4Slazypassion         assert_eq!(leaf.to_string(), "[ a b c d e f g h i j k l m n o ]");
686747ad3c4Slazypassion 
687747ad3c4Slazypassion         // Now the node is full and insertion should fail anywhere.
688747ad3c4Slazypassion         assert!(!leaf.try_leaf_insert(0, 'x', SetValue()));
689747ad3c4Slazypassion         assert!(!leaf.try_leaf_insert(8, 'x', SetValue()));
690747ad3c4Slazypassion         assert!(!leaf.try_leaf_insert(15, 'x', SetValue()));
691747ad3c4Slazypassion 
692747ad3c4Slazypassion         // The index given to `split` is not the split position, it's a hint for balancing the node.
693a0442ea0SHamir Mahal         let saved = leaf;
694747ad3c4Slazypassion         let sp = leaf.split(12);
695747ad3c4Slazypassion         assert_eq!(sp.lhs_entries, 8);
696747ad3c4Slazypassion         assert_eq!(sp.rhs_entries, 7);
697747ad3c4Slazypassion         assert_eq!(sp.crit_key, 'i');
698747ad3c4Slazypassion         assert_eq!(leaf.to_string(), "[ a b c d e f g h ]");
699747ad3c4Slazypassion         assert_eq!(sp.rhs_data.to_string(), "[ i j k l m n o ]");
700747ad3c4Slazypassion 
701747ad3c4Slazypassion         assert!(leaf.try_leaf_insert(8, 'i', SetValue()));
702747ad3c4Slazypassion         assert_eq!(leaf.leaf_remove(2), Removed::Healthy);
703747ad3c4Slazypassion         assert_eq!(leaf.to_string(), "[ a b d e f g h i ]");
704747ad3c4Slazypassion         assert_eq!(leaf.leaf_remove(7), Removed::Underflow);
705747ad3c4Slazypassion         assert_eq!(leaf.to_string(), "[ a b d e f g h ]");
706747ad3c4Slazypassion 
707747ad3c4Slazypassion         leaf = saved;
708747ad3c4Slazypassion         let sp = leaf.split(7);
709747ad3c4Slazypassion         assert_eq!(sp.lhs_entries, 7);
710747ad3c4Slazypassion         assert_eq!(sp.rhs_entries, 8);
711747ad3c4Slazypassion         assert_eq!(sp.crit_key, 'h');
712747ad3c4Slazypassion         assert_eq!(leaf.to_string(), "[ a b c d e f g ]");
713747ad3c4Slazypassion         assert_eq!(sp.rhs_data.to_string(), "[ h i j k l m n o ]");
714747ad3c4Slazypassion     }
715747ad3c4Slazypassion 
716747ad3c4Slazypassion     #[test]
optimal_split_pos()717747ad3c4Slazypassion     fn optimal_split_pos() {
718747ad3c4Slazypassion         // An even split is easy.
719747ad3c4Slazypassion         assert_eq!(split_pos(8, 0), 4);
720747ad3c4Slazypassion         assert_eq!(split_pos(8, 8), 4);
721747ad3c4Slazypassion 
722747ad3c4Slazypassion         // Easy cases for odd splits.
723747ad3c4Slazypassion         assert_eq!(split_pos(7, 0), 3);
724747ad3c4Slazypassion         assert_eq!(split_pos(7, 7), 4);
725747ad3c4Slazypassion 
726747ad3c4Slazypassion         // If the insertion point is the same as the split position, we
727747ad3c4Slazypassion         // will append to the lhs node.
728747ad3c4Slazypassion         assert_eq!(split_pos(7, 3), 3);
729747ad3c4Slazypassion         assert_eq!(split_pos(7, 4), 4);
730747ad3c4Slazypassion     }
731747ad3c4Slazypassion 
732747ad3c4Slazypassion     #[test]
inner_balance()733747ad3c4Slazypassion     fn inner_balance() {
734747ad3c4Slazypassion         let n1 = Node(1);
735747ad3c4Slazypassion         let n2 = Node(2);
736747ad3c4Slazypassion         let n3 = Node(3);
737747ad3c4Slazypassion         let mut lhs = NodeData::<TF>::inner(n1, 'a', n2);
738747ad3c4Slazypassion         assert!(lhs.try_inner_insert(1, 'b', n3));
739747ad3c4Slazypassion         assert_eq!(lhs.to_string(), "[ node1 a node2 b node3 ]");
740747ad3c4Slazypassion 
741747ad3c4Slazypassion         let n11 = Node(11);
742747ad3c4Slazypassion         let n12 = Node(12);
743747ad3c4Slazypassion         let mut rhs = NodeData::<TF>::inner(n11, 'p', n12);
744747ad3c4Slazypassion 
745747ad3c4Slazypassion         for i in 1..4 {
746747ad3c4Slazypassion             assert!(rhs.try_inner_insert(
747747ad3c4Slazypassion                 usize::from(i),
748747ad3c4Slazypassion                 ('p' as u8 + i) as char,
749747ad3c4Slazypassion                 Node(i as u32 + 12),
750747ad3c4Slazypassion             ));
751747ad3c4Slazypassion         }
752747ad3c4Slazypassion         assert_eq!(
753747ad3c4Slazypassion             rhs.to_string(),
754747ad3c4Slazypassion             "[ node11 p node12 q node13 r node14 s node15 ]"
755747ad3c4Slazypassion         );
756747ad3c4Slazypassion 
757747ad3c4Slazypassion         // 3+5 elements fit in RHS.
758747ad3c4Slazypassion         assert_eq!(lhs.balance('o', &mut rhs), None);
759747ad3c4Slazypassion         assert_eq!(
760747ad3c4Slazypassion             rhs.to_string(),
761747ad3c4Slazypassion             "[ node1 a node2 b node3 o node11 p node12 q node13 r node14 s node15 ]"
762747ad3c4Slazypassion         );
763747ad3c4Slazypassion 
764747ad3c4Slazypassion         // 2+8 elements are redistributed.
765747ad3c4Slazypassion         lhs = NodeData::<TF>::inner(Node(20), 'x', Node(21));
766747ad3c4Slazypassion         assert_eq!(lhs.balance('y', &mut rhs), Some('o'));
767747ad3c4Slazypassion         assert_eq!(
768747ad3c4Slazypassion             lhs.to_string(),
769747ad3c4Slazypassion             "[ node20 x node21 y node1 a node2 b node3 ]"
770747ad3c4Slazypassion         );
771747ad3c4Slazypassion         assert_eq!(
772747ad3c4Slazypassion             rhs.to_string(),
773747ad3c4Slazypassion             "[ node11 p node12 q node13 r node14 s node15 ]"
774747ad3c4Slazypassion         );
775747ad3c4Slazypassion     }
776747ad3c4Slazypassion 
777747ad3c4Slazypassion     #[test]
leaf_balance()778747ad3c4Slazypassion     fn leaf_balance() {
779747ad3c4Slazypassion         let mut lhs = NodeData::<TF>::leaf('a', SetValue());
780747ad3c4Slazypassion         for i in 1..6 {
781747ad3c4Slazypassion             assert!(lhs.try_leaf_insert(usize::from(i), ('a' as u8 + i) as char, SetValue()));
782747ad3c4Slazypassion         }
783747ad3c4Slazypassion         assert_eq!(lhs.to_string(), "[ a b c d e f ]");
784747ad3c4Slazypassion 
785747ad3c4Slazypassion         let mut rhs = NodeData::<TF>::leaf('0', SetValue());
786747ad3c4Slazypassion         for i in 1..8 {
787747ad3c4Slazypassion             assert!(rhs.try_leaf_insert(usize::from(i), ('0' as u8 + i) as char, SetValue()));
788747ad3c4Slazypassion         }
789747ad3c4Slazypassion         assert_eq!(rhs.to_string(), "[ 0 1 2 3 4 5 6 7 ]");
790747ad3c4Slazypassion 
791747ad3c4Slazypassion         // 6+8 elements all fits in rhs.
792747ad3c4Slazypassion         assert_eq!(lhs.balance('0', &mut rhs), None);
793747ad3c4Slazypassion         assert_eq!(rhs.to_string(), "[ a b c d e f 0 1 2 3 4 5 6 7 ]");
794747ad3c4Slazypassion 
795747ad3c4Slazypassion         assert!(lhs.try_leaf_insert(0, 'x', SetValue()));
796747ad3c4Slazypassion         assert!(lhs.try_leaf_insert(1, 'y', SetValue()));
797747ad3c4Slazypassion         assert!(lhs.try_leaf_insert(2, 'z', SetValue()));
798747ad3c4Slazypassion         assert_eq!(lhs.to_string(), "[ x y z ]");
799747ad3c4Slazypassion 
800747ad3c4Slazypassion         // 3+14 elements need redistribution.
801747ad3c4Slazypassion         assert_eq!(lhs.balance('a', &mut rhs), Some('0'));
802747ad3c4Slazypassion         assert_eq!(lhs.to_string(), "[ x y z a b c d e f ]");
803747ad3c4Slazypassion         assert_eq!(rhs.to_string(), "[ 0 1 2 3 4 5 6 7 ]");
804747ad3c4Slazypassion     }
805747ad3c4Slazypassion }
806