@@ -1276,25 +1276,25 @@ impl<'a, K, V> BalancingContext<'a, K, V> {
12761276 self.right_child
12771277 }
12781278
1279- /// Returns `true` if it is valid to call `.merge()` in the balancing context,
1280- /// i.e., whether there is enough room in a node to hold the combination of
1281- /// both adjacent child nodes, along with the key-value pair in the parent.
1279+ /// Returns whether merging is possible, i.e., whether there is enough room
1280+ /// in a node to combine the central KV with both adjacent child nodes.
12821281 pub fn can_merge(&self) -> bool {
12831282 self.left_child.len() + 1 + self.right_child.len() <= CAPACITY
12841283 }
12851284}
12861285
12871286impl<'a, K: 'a, V: 'a> BalancingContext<'a, K, V> {
1288- /// Merges the parent's key-value pair and both adjacent child nodes into
1289- /// the left node and returns an edge handle in that expanded left node.
1290- /// If `track_edge_idx` is given some value, the returned edge corresponds
1291- /// to where the edge in that child node ended up,
1292- ///
1293- /// Panics unless we `.can_merge()`.
1294- pub fn merge(
1287+ /// Performs a merge and lets a closure decide what to return.
1288+ fn do_merge<
1289+ F: FnOnce(
1290+ NodeRef<marker::Mut<'a>, K, V, marker::Internal>,
1291+ NodeRef<marker::Mut<'a>, K, V, marker::LeafOrInternal>,
1292+ ) -> R,
1293+ R,
1294+ >(
12951295 self,
1296- track_edge_idx: Option<LeftOrRight<usize>> ,
1297- ) -> Handle<NodeRef<marker::Mut<'a>, K, V, marker::LeafOrInternal>, marker::Edge> {
1296+ result: F ,
1297+ ) -> R {
12981298 let Handle { node: mut parent_node, idx: parent_idx, _marker } = self.parent;
12991299 let old_parent_len = parent_node.len();
13001300 let mut left_node = self.left_child;
@@ -1304,11 +1304,6 @@ impl<'a, K: 'a, V: 'a> BalancingContext<'a, K, V> {
13041304 let new_left_len = old_left_len + 1 + right_len;
13051305
13061306 assert!(new_left_len <= CAPACITY);
1307- assert!(match track_edge_idx {
1308- None => true,
1309- Some(LeftOrRight::Left(idx)) => idx <= old_left_len,
1310- Some(LeftOrRight::Right(idx)) => idx <= right_len,
1311- });
13121307
13131308 unsafe {
13141309 *left_node.len_mut() = new_left_len as u16;
@@ -1347,14 +1342,47 @@ impl<'a, K: 'a, V: 'a> BalancingContext<'a, K, V> {
13471342 } else {
13481343 Global.deallocate(right_node.node.cast(), Layout::new::<LeafNode<K, V>>());
13491344 }
1350-
1351- let new_idx = match track_edge_idx {
1352- None => 0,
1353- Some(LeftOrRight::Left(idx)) => idx,
1354- Some(LeftOrRight::Right(idx)) => old_left_len + 1 + idx,
1355- };
1356- Handle::new_edge(left_node, new_idx)
13571345 }
1346+ result(parent_node, left_node)
1347+ }
1348+
1349+ /// Merges the parent's key-value pair and both adjacent child nodes into
1350+ /// the left child node and returns the shrunk parent node.
1351+ ///
1352+ /// Panics unless we `.can_merge()`.
1353+ pub fn merge_tracking_parent(self) -> NodeRef<marker::Mut<'a>, K, V, marker::Internal> {
1354+ self.do_merge(|parent, _child| parent)
1355+ }
1356+
1357+ /// Merges the parent's key-value pair and both adjacent child nodes into
1358+ /// the left child node and returns that child node.
1359+ ///
1360+ /// Panics unless we `.can_merge()`.
1361+ pub fn merge_tracking_child(self) -> NodeRef<marker::Mut<'a>, K, V, marker::LeafOrInternal> {
1362+ self.do_merge(|_parent, child| child)
1363+ }
1364+
1365+ /// Merges the parent's key-value pair and both adjacent child nodes into
1366+ /// the left child node and returns the edge handle in that child node
1367+ /// where the tracked child edge ended up,
1368+ ///
1369+ /// Panics unless we `.can_merge()`.
1370+ pub fn merge_tracking_child_edge(
1371+ self,
1372+ track_edge_idx: LeftOrRight<usize>,
1373+ ) -> Handle<NodeRef<marker::Mut<'a>, K, V, marker::LeafOrInternal>, marker::Edge> {
1374+ let old_left_len = self.left_child.len();
1375+ let right_len = self.right_child.len();
1376+ assert!(match track_edge_idx {
1377+ LeftOrRight::Left(idx) => idx <= old_left_len,
1378+ LeftOrRight::Right(idx) => idx <= right_len,
1379+ });
1380+ let child = self.merge_tracking_child();
1381+ let new_idx = match track_edge_idx {
1382+ LeftOrRight::Left(idx) => idx,
1383+ LeftOrRight::Right(idx) => old_left_len + 1 + idx,
1384+ };
1385+ unsafe { Handle::new_edge(child, new_idx) }
13581386 }
13591387
13601388 /// Removes a key-value pair from the left child and places it in the key-value storage
0 commit comments