navigate.rs.html -- source
Description: Source to the Rust file `src\liballoc\collections\btree\navigate.rs`.
Keywords: rust, rustlang, rust-lang

      1
      2
      3
      4
      5
      6
      7
      8
      9
     10
     11
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
     25
     26
     27
     28
     29
     30
     31
     32
     33
     34
     35
     36
     37
     38
     39
     40
     41
     42
     43
     44
     45
     46
     47
     48
     49
     50
     51
     52
     53
     54
     55
     56
     57
     58
     59
     60
     61
     62
     63
     64
     65
     66
     67
     68
     69
     70
     71
     72
     73
     74
     75
     76
     77
     78
     79
     80
     81
     82
     83
     84
     85
     86
     87
     88
     89
     90
     91
     92
     93
     94
     95
     96
     97
     98
     99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259

    use core::ptr;

    use super::node::{marker, ForceResult::*, Handle, NodeRef};
    use super::unwrap_unchecked;

    impl<BorrowType, K, V> Handle<NodeRef<BorrowType, K, V, marker::Leaf>, marker::Edge> {
        /// Given a leaf edge handle, returns [`Result::Ok`] with a handle to the neighboring KV
        /// on the right side, which is either in the same leaf node or in an ancestor node.
        /// If the leaf edge is the last one in the tree, returns [`Result::Err`] with the root node.
        pub fn next_kv(
            self,
        ) -> Result<
            Handle<NodeRef<BorrowType, K, V, marker::LeafOrInternal>, marker::KV>,
            NodeRef<BorrowType, K, V, marker::LeafOrInternal>,
        > {
            let mut edge = self.forget_node_type();
            loop {
                edge = match edge.right_kv() {
                    Ok(internal_kv) => return Ok(internal_kv),
                    Err(last_edge) => match last_edge.into_node().ascend() {
                        Ok(parent_edge) => parent_edge.forget_node_type(),
                        Err(root) => return Err(root.forget_type()),
                    },
                }
            }
        }

        /// Given a leaf edge handle, returns [`Result::Ok`] with a handle to the neighboring KV
        /// on the left side, which is either in the same leaf node or in an ancestor node.
        /// If the leaf edge is the first one in the tree, returns [`Result::Err`] with the root node.
        pub fn next_back_kv(
            self,
        ) -> Result<
            Handle<NodeRef<BorrowType, K, V, marker::LeafOrInternal>, marker::KV>,
            NodeRef<BorrowType, K, V, marker::LeafOrInternal>,
        > {
            let mut edge = self.forget_node_type();
            loop {
                edge = match edge.left_kv() {
                    Ok(internal_kv) => return Ok(internal_kv),
                    Err(last_edge) => match last_edge.into_node().ascend() {
                        Ok(parent_edge) => parent_edge.forget_node_type(),
                        Err(root) => return Err(root.forget_type()),
                    },
                }
            }
        }
    }

    macro_rules! def_next_kv_uncheched_dealloc {
        { unsafe fn $name:ident : $adjacent_kv:ident } => {
            /// Given a leaf edge handle into an owned tree, returns a handle to the next KV,
            /// while deallocating any node left behind.
            /// Unsafe for two reasons:
            /// - The caller must ensure that the leaf edge is not the last one in the tree.
            /// - The node pointed at by the given handle, and its ancestors, may be deallocated,
            ///   while the reference to those nodes in the surviving ancestors is left dangling;
            ///   thus using the returned handle to navigate further is dangerous.
            unsafe fn $name <K, V>(
                leaf_edge: Handle<NodeRef<marker::Owned, K, V, marker::Leaf>, marker::Edge>,
            ) -> Handle<NodeRef<marker::Owned, K, V, marker::LeafOrInternal>, marker::KV> {
                let mut edge = leaf_edge.forget_node_type();
                loop {
                    edge = match edge.$adjacent_kv() {
                        Ok(internal_kv) => return internal_kv,
                        Err(last_edge) => {
                            unsafe {
                                let parent_edge = last_edge.into_node().deallocate_and_ascend();
                                unwrap_unchecked(parent_edge).forget_node_type()
                            }
                        }
                    }
                }
            }
        };
    }

    def_next_kv_uncheched_dealloc! {unsafe fn next_kv_unchecked_dealloc: right_kv}
    def_next_kv_uncheched_dealloc! {unsafe fn next_back_kv_unchecked_dealloc: left_kv}

    /// This replaces the value behind the `v` unique reference by calling the
    /// relevant function.
    ///
    /// Safety: The change closure must not panic.
    #[inline]
    unsafe fn replace<T, R>(v: &mut T, change: impl FnOnce(T) -> (T, R)) -> R {
        let value = unsafe { ptr::read(v) };
        let (new_value, ret) = change(value);
        unsafe {
            ptr::write(v, new_value);
        }
        ret
    }

    impl<'a, K, V> Handle<NodeRef<marker::Immut<'a>, K, V, marker::Leaf>, marker::Edge> {
        /// Moves the leaf edge handle to the next leaf edge and returns references to the
        /// key and value in between.
        /// Unsafe because the caller must ensure that the leaf edge is not the last one in the tree.
        pub unsafe fn next_unchecked(&mut self) -> (&'a K, &'a V) {
            unsafe {
                replace(self, |leaf_edge| {
                    let kv = leaf_edge.next_kv();
                    let kv = unwrap_unchecked(kv.ok());
                    (kv.next_leaf_edge(), kv.into_kv())
                })
            }
        }

        /// Moves the leaf edge handle to the previous leaf edge and returns references to the
        /// key and value in between.
        /// Unsafe because the caller must ensure that the leaf edge is not the first one in the tree.
        pub unsafe fn next_back_unchecked(&mut self) -> (&'a K, &'a V) {
            unsafe {
                replace(self, |leaf_edge| {
                    let kv = leaf_edge.next_back_kv();
                    let kv = unwrap_unchecked(kv.ok());
                    (kv.next_back_leaf_edge(), kv.into_kv())
                })
            }
        }
    }

    impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::Edge> {
        /// Moves the leaf edge handle to the next leaf edge and returns references to the
        /// key and value in between.
        /// Unsafe for two reasons:
        /// - The caller must ensure that the leaf edge is not the last one in the tree.
        /// - Using the updated handle may well invalidate the returned references.
        pub unsafe fn next_unchecked(&mut self) -> (&'a mut K, &'a mut V) {
            unsafe {
                let kv = replace(self, |leaf_edge| {
                    let kv = leaf_edge.next_kv();
                    let kv = unwrap_unchecked(kv.ok());
                    (ptr::read(&kv).next_leaf_edge(), kv)
                });
                // Doing the descend (and perhaps another move) invalidates the references
                // returned by `into_kv_mut`, so we have to do this last.
                kv.into_kv_mut()
            }
        }

        /// Moves the leaf edge handle to the previous leaf and returns references to the
        /// key and value in between.
        /// Unsafe for two reasons:
        /// - The caller must ensure that the leaf edge is not the first one in the tree.
        /// - Using the updated handle may well invalidate the returned references.
        pub unsafe fn next_back_unchecked(&mut self) -> (&'a mut K, &'a mut V) {
            unsafe {
                let kv = replace(self, |leaf_edge| {
                    let kv = leaf_edge.next_back_kv();
                    let kv = unwrap_unchecked(kv.ok());
                    (ptr::read(&kv).next_back_leaf_edge(), kv)
                });
                // Doing the descend (and perhaps another move) invalidates the references
                // returned by `into_kv_mut`, so we have to do this last.
                kv.into_kv_mut()
            }
        }
    }

    impl<K, V> Handle<NodeRef<marker::Owned, K, V, marker::Leaf>, marker::Edge> {
        /// Moves the leaf edge handle to the next leaf edge and returns the key and value
        /// in between, while deallocating any node left behind.
        /// Unsafe for three reasons:
        /// - The caller must ensure that the leaf edge is not the last one in the tree
        ///   and is not a handle previously resulting from counterpart `next_back_unchecked`.
        /// - If the leaf edge is the last edge of a node, that node and possibly ancestors
        ///   will be deallocated, while the reference to those nodes in the surviving ancestor
        ///   is left dangling; thus further use of the leaf edge handle is dangerous.
        ///   It is, however, safe to call this method again on the updated handle.
        ///   if the two preconditions above hold.
        /// - Using the updated handle may well invalidate the returned references.
        pub unsafe fn next_unchecked(&mut self) -> (K, V) {
            unsafe {
                replace(self, |leaf_edge| {
                    let kv = next_kv_unchecked_dealloc(leaf_edge);
                    let k = ptr::read(kv.reborrow().into_kv().0);
                    let v = ptr::read(kv.reborrow().into_kv().1);
                    (kv.next_leaf_edge(), (k, v))
                })
            }
        }

        /// Moves the leaf edge handle to the previous leaf edge and returns the key
        /// and value in between, while deallocating any node left behind.
        /// Unsafe for three reasons:
        /// - The caller must ensure that the leaf edge is not the first one in the tree
        ///   and is not a handle previously resulting from counterpart `next_unchecked`.
        /// - If the lead edge is the first edge of a node, that node and possibly ancestors
        ///   will be deallocated, while the reference to those nodes in the surviving ancestor
        ///   is left dangling; thus further use of the leaf edge handle is dangerous.
        ///   It is, however, safe to call this method again on the updated handle.
        ///   if the two preconditions above hold.
        /// - Using the updated handle may well invalidate the returned references.
        pub unsafe fn next_back_unchecked(&mut self) -> (K, V) {
            unsafe {
                replace(self, |leaf_edge| {
                    let kv = next_back_kv_unchecked_dealloc(leaf_edge);
                    let k = ptr::read(kv.reborrow().into_kv().0);
                    let v = ptr::read(kv.reborrow().into_kv().1);
                    (kv.next_back_leaf_edge(), (k, v))
                })
            }
        }
    }

    impl<BorrowType, K, V> NodeRef<BorrowType, K, V, marker::LeafOrInternal> {
        /// Returns the leftmost leaf edge in or underneath a node - in other words, the edge
        /// you need first when navigating forward (or last when navigating backward).
        #[inline]
        pub fn first_leaf_edge(self) -> Handle<NodeRef<BorrowType, K, V, marker::Leaf>, marker::Edge> {
            let mut node = self;
            loop {
                match node.force() {
                    Leaf(leaf) => return leaf.first_edge(),
                    Internal(internal) => node = internal.first_edge().descend(),
                }
            }
        }

        /// Returns the rightmost leaf edge in or underneath a node - in other words, the edge
        /// you need last when navigating forward (or first when navigating backward).
        #[inline]
        pub fn last_leaf_edge(self) -> Handle<NodeRef<BorrowType, K, V, marker::Leaf>, marker::Edge> {
            let mut node = self;
            loop {
                match node.force() {
                    Leaf(leaf) => return leaf.last_edge(),
                    Internal(internal) => node = internal.last_edge().descend(),
                }
            }
        }
    }

    impl<BorrowType, K, V> Handle<NodeRef<BorrowType, K, V, marker::LeafOrInternal>, marker::KV> {
        /// Returns the leaf edge closest to a KV for forward navigation.
        pub fn next_leaf_edge(self) -> Handle<NodeRef<BorrowType, K, V, marker::Leaf>, marker::Edge> {
            match self.force() {
                Leaf(leaf_kv) => leaf_kv.right_edge(),
                Internal(internal_kv) => {
                    let next_internal_edge = internal_kv.right_edge();
                    next_internal_edge.descend().first_leaf_edge()
                }
            }
        }

        /// Returns the leaf edge closest to a KV for backward navigation.
        pub fn next_back_leaf_edge(
            self,
        ) -> Handle<NodeRef<BorrowType, K, V, marker::Leaf>, marker::Edge> {
            match self.force() {
                Leaf(leaf_kv) => leaf_kv.left_edge(),
                Internal(internal_kv) => {
                    let next_internal_edge = internal_kv.left_edge();
                    next_internal_edge.descend().last_leaf_edge()
                }
            }
        }
    }