@@ -290,37 +290,71 @@ impl<BorrowType: marker::BorrowType, K, V>
290290 }
291291}
292292
293- macro_rules! def_next_kv_uncheched_dealloc {
294- { unsafe fn $name: ident : $adjacent_kv: ident } => {
295- /// Given a leaf edge handle into an owned tree, returns a handle to the next KV,
296- /// while deallocating any node left behind yet leaving the corresponding edge
297- /// in its parent node dangling.
298- ///
299- /// # Safety
300- /// - The leaf edge must not be the last one in the direction travelled.
301- /// - The node carrying the next KV returned must not have been deallocated by a
302- /// previous call on any handle obtained for this tree.
303- unsafe fn $name <K , V >(
304- leaf_edge: Handle <NodeRef <marker:: Dying , K , V , marker:: Leaf >, marker:: Edge >,
305- ) -> Handle <NodeRef <marker:: Dying , K , V , marker:: LeafOrInternal >, marker:: KV > {
306- let mut edge = leaf_edge. forget_node_type( ) ;
307- loop {
308- edge = match edge. $adjacent_kv( ) {
309- Ok ( internal_kv) => return internal_kv,
310- Err ( last_edge) => {
311- unsafe {
312- let parent_edge = last_edge. into_node( ) . deallocate_and_ascend( ) ;
313- unwrap_unchecked( parent_edge) . forget_node_type( )
314- }
315- }
293+ impl < K , V > Handle < NodeRef < marker:: Dying , K , V , marker:: Leaf > , marker:: Edge > {
294+ /// Given a leaf edge handle into a dying tree, returns the next leaf edge
295+ /// on the right side, and the key-value pair in between, which is either
296+ /// in the same leaf node, in an ancestor node, or non-existent.
297+ ///
298+ /// This method also deallocates any node(s) it reaches the end of. This
299+ /// implies that if no more key-value pair exists, the entire remainder of
300+ /// the tree will have been deallocated and there is nothing left to return.
301+ ///
302+ /// # Safety
303+ /// The next KV must not have been previously returned by counterpart `deallocating_next_back`.
304+ unsafe fn deallocating_next ( self ) -> Option < ( Self , ( K , V ) ) > {
305+ let mut edge = self . forget_node_type ( ) ;
306+ loop {
307+ edge = match edge. right_kv ( ) {
308+ Ok ( kv) => {
309+ let k = unsafe { ptr:: read ( kv. reborrow ( ) . into_kv ( ) . 0 ) } ;
310+ let v = unsafe { ptr:: read ( kv. reborrow ( ) . into_kv ( ) . 1 ) } ;
311+ return Some ( ( kv. next_leaf_edge ( ) , ( k, v) ) ) ;
316312 }
313+ Err ( last_edge) => match unsafe { last_edge. into_node ( ) . deallocate_and_ascend ( ) } {
314+ Some ( parent_edge) => parent_edge. forget_node_type ( ) ,
315+ None => return None ,
316+ } ,
317317 }
318318 }
319- } ;
320- }
319+ }
321320
322- def_next_kv_uncheched_dealloc ! { unsafe fn next_kv_unchecked_dealloc: right_kv}
323- def_next_kv_uncheched_dealloc ! { unsafe fn next_back_kv_unchecked_dealloc: left_kv}
321+ /// Given a leaf edge handle into a dying tree, returns the next leaf edge
322+ /// on the left side, and the key-value pair in between, which is either
323+ /// in the same leaf node, in an ancestor node, or non-existent.
324+ ///
325+ /// This method also deallocates any node(s) it reaches the end of. This
326+ /// implies that if no more key-value pair exists, the entire remainder of
327+ /// the tree will have been deallocated and there is nothing left to return.
328+ ///
329+ /// # Safety
330+ /// The next KV must not have been previously returned by counterpart `deallocating_next`.
331+ unsafe fn deallocating_next_back ( self ) -> Option < ( Self , ( K , V ) ) > {
332+ let mut edge = self . forget_node_type ( ) ;
333+ loop {
334+ edge = match edge. left_kv ( ) {
335+ Ok ( kv) => {
336+ let k = unsafe { ptr:: read ( kv. reborrow ( ) . into_kv ( ) . 0 ) } ;
337+ let v = unsafe { ptr:: read ( kv. reborrow ( ) . into_kv ( ) . 1 ) } ;
338+ return Some ( ( kv. next_back_leaf_edge ( ) , ( k, v) ) ) ;
339+ }
340+ Err ( last_edge) => match unsafe { last_edge. into_node ( ) . deallocate_and_ascend ( ) } {
341+ Some ( parent_edge) => parent_edge. forget_node_type ( ) ,
342+ None => return None ,
343+ } ,
344+ }
345+ }
346+ }
347+
348+ /// Deallocates a pile of nodes from the leaf up to the root.
349+ /// This is useful when `deallocating_next` and `deallocating_next_back`
350+ /// have been nibbling at both sides of the same tree.
351+ pub fn deallocating_end ( self ) {
352+ let mut edge = self . forget_node_type ( ) ;
353+ while let Some ( parent_edge) = unsafe { edge. into_node ( ) . deallocate_and_ascend ( ) } {
354+ edge = parent_edge. forget_node_type ( ) ;
355+ }
356+ }
357+ }
324358
325359impl < ' a , K , V > Handle < NodeRef < marker:: Immut < ' a > , K , V , marker:: Leaf > , marker:: Edge > {
326360 /// Moves the leaf edge handle to the next leaf edge and returns references to the
@@ -396,11 +430,8 @@ impl<K, V> Handle<NodeRef<marker::Dying, K, V, marker::Leaf>, marker::Edge> {
396430 /// call this method again subject to its safety conditions, or call counterpart
397431 /// `next_back_unchecked` subject to its safety conditions.
398432 pub unsafe fn next_unchecked ( & mut self ) -> ( K , V ) {
399- super :: mem:: replace ( self , |leaf_edge| {
400- let kv = unsafe { next_kv_unchecked_dealloc ( leaf_edge) } ;
401- let k = unsafe { ptr:: read ( kv. reborrow ( ) . into_kv ( ) . 0 ) } ;
402- let v = unsafe { ptr:: read ( kv. reborrow ( ) . into_kv ( ) . 1 ) } ;
403- ( kv. next_leaf_edge ( ) , ( k, v) )
433+ super :: mem:: replace ( self , |leaf_edge| unsafe {
434+ unwrap_unchecked ( leaf_edge. deallocating_next ( ) )
404435 } )
405436 }
406437
@@ -417,11 +448,8 @@ impl<K, V> Handle<NodeRef<marker::Dying, K, V, marker::Leaf>, marker::Edge> {
417448 /// call this method again subject to its safety conditions, or call counterpart
418449 /// `next_unchecked` subject to its safety conditions.
419450 pub unsafe fn next_back_unchecked ( & mut self ) -> ( K , V ) {
420- super :: mem:: replace ( self , |leaf_edge| {
421- let kv = unsafe { next_back_kv_unchecked_dealloc ( leaf_edge) } ;
422- let k = unsafe { ptr:: read ( kv. reborrow ( ) . into_kv ( ) . 0 ) } ;
423- let v = unsafe { ptr:: read ( kv. reborrow ( ) . into_kv ( ) . 1 ) } ;
424- ( kv. next_back_leaf_edge ( ) , ( k, v) )
451+ super :: mem:: replace ( self , |leaf_edge| unsafe {
452+ unwrap_unchecked ( leaf_edge. deallocating_next_back ( ) )
425453 } )
426454 }
427455}
0 commit comments