diff --git a/src/libcollections/btree/map.rs b/src/libcollections/btree/map.rs index f0a4902bb9235..1ab0a61208b68 100644 --- a/src/libcollections/btree/map.rs +++ b/src/libcollections/btree/map.rs @@ -20,7 +20,10 @@ pub use self::Entry::*; use core::prelude::*; use self::StackOp::*; -use super::node::*; +use super::node::{mod, Node, Found, GoDown}; +use super::node::{Traversal, MutTraversal, MoveTraversal}; +use super::node::TraversalItem::{mod, Elem, Edge}; +use super::node::ForceResult::{Leaf, Internal}; use core::borrow::BorrowFrom; use std::hash::{Writer, Hash}; use core::default::Default; @@ -123,12 +126,12 @@ pub enum Entry<'a, K:'a, V:'a> { /// A vacant Entry. pub struct VacantEntry<'a, K:'a, V:'a> { key: K, - stack: stack::VacantSearchStack<'a, K, V>, + stack: stack::SearchStack<'a, K, V, node::Edge, node::Leaf>, } /// An occupied Entry. pub struct OccupiedEntry<'a, K:'a, V:'a> { - stack: stack::OccupiedSearchStack<'a, K, V>, + stack: stack::SearchStack<'a, K, V, node::KV, node::LeafOrInternal>, } impl BTreeMap { @@ -206,10 +209,10 @@ impl BTreeMap { loop { match Node::search(cur_node, key) { Found(handle) => return Some(handle.into_kv().1), - GoDown(handle) => match handle.into_edge() { - None => return None, - Some(next_node) => { - cur_node = next_node; + GoDown(handle) => match handle.force() { + Leaf(_) => return None, + Internal(internal_handle) => { + cur_node = internal_handle.into_edge(); continue; } } @@ -270,10 +273,10 @@ impl BTreeMap { let cur_node = temp_node; match Node::search(cur_node, key) { Found(handle) => return Some(handle.into_kv_mut().1), - GoDown(handle) => match handle.into_edge_mut() { - None => return None, - Some(next_node) => { - temp_node = next_node; + GoDown(handle) => match handle.force() { + Leaf(_) => return None, + Internal(internal_handle) => { + temp_node = internal_handle.into_edge_mut(); continue; } } @@ -352,27 +355,27 @@ impl BTreeMap { let result = stack.with(move |pusher, node| { // Same basic logic as found in `find`, but with PartialSearchStack mediating the // actual nodes for us - match Node::search(node, &key) { + return match Node::search(node, &key) { Found(mut handle) => { // Perfect match, swap the values and return the old one mem::swap(handle.val_mut(), &mut value); - return Finished(Some(value)); + Finished(Some(value)) }, GoDown(handle) => { // We need to keep searching, try to get the search stack // to go down further - match pusher.push(handle) { - stack::Done(new_stack) => { + match handle.force() { + Leaf(leaf_handle) => { // We've reached a leaf, perform the insertion here - new_stack.insert(key, value); - return Finished(None); + pusher.seal(leaf_handle).insert(key, value); + Finished(None) } - stack::Grew(new_stack) => { + Internal(internal_handle) => { // We've found the subtree to insert this key/value pair in, // keep searching - return Continue((new_stack, key, value)); + Continue((pusher.push(internal_handle), key, value)) } - }; + } } } }); @@ -450,18 +453,18 @@ impl BTreeMap { let mut stack = stack::PartialSearchStack::new(self); loop { let result = stack.with(move |pusher, node| { - match Node::search(node, key) { + return match Node::search(node, key) { Found(handle) => { // Perfect match. Terminate the stack here, and remove the entry - return Finished(Some(pusher.seal(handle).remove())); + Finished(Some(pusher.seal(handle).remove())) }, GoDown(handle) => { // We need to keep searching, try to go down the next edge - match pusher.push(handle) { + match handle.force() { // We're at a leaf; the key isn't in here - stack::Done(_) => return Finished(None), - stack::Grew(new_stack) => return Continue(new_stack) - }; + Leaf(_) => Finished(None), + Internal(internal_handle) => Continue(pusher.push(internal_handle)) + } } } }); @@ -484,12 +487,11 @@ enum Continuation { /// to nodes. By using this module much better safety guarantees can be made, and more search /// boilerplate gets cut out. mod stack { - pub use self::PushResult::*; use core::prelude::*; use core::kinds::marker; use core::mem; use super::BTreeMap; - use super::super::node::*; + use super::super::node::{mod, Node, Fit, Split, KV, Edge, Internal, Leaf, LeafOrInternal}; use vec::Vec; /// A generic mutable reference, identical to `&mut` except for the fact that its lifetime @@ -513,30 +515,23 @@ mod stack { } } - type StackItem = EdgeNodeHandle<*mut Node>; + type StackItem = node::Handle<*mut Node, Edge, Internal>; type Stack = Vec>; - /// A PartialSearchStack handles the construction of a search stack. + /// A `PartialSearchStack` handles the construction of a search stack. pub struct PartialSearchStack<'a, K:'a, V:'a> { map: &'a mut BTreeMap, stack: Stack, next: *mut Node, } - /// An OccupiedSearchStack represents a full path to an element of interest. It provides methods - /// for manipulating the element at the top of its stack. - pub struct OccupiedSearchStack<'a, K:'a, V:'a> { + /// A `SearchStack` represents a full path to an element or an edge of interest. It provides + /// methods depending on the type of what the path points to for removing an element, inserting + /// a new element, and manipulating to element at the top of the stack. + pub struct SearchStack<'a, K:'a, V:'a, Type, NodeType> { map: &'a mut BTreeMap, stack: Stack, - top: KVNodeHandle<*mut Node>, - } - - /// A VacantSearchStack represents a full path to a spot for a new element of interest. It - /// provides a method inserting an element at the top of its stack. - pub struct VacantSearchStack<'a, K:'a, V:'a> { - map: &'a mut BTreeMap, - stack: Stack, - top: EdgeNodeHandle<*mut Node>, + top: node::Handle<*mut Node, Type, NodeType>, } /// A `PartialSearchStack` that doesn't hold a a reference to the next node, and is just @@ -548,14 +543,6 @@ mod stack { marker: marker::InvariantLifetime<'id> } - /// The result of asking a PartialSearchStack to push another node onto itself. Either it - /// Grew, in which case it's still Partial, or it found its last node was actually a leaf, in - /// which case it seals itself and yields a complete SearchStack. - pub enum PushResult<'a, K:'a, V:'a> { - Grew(PartialSearchStack<'a, K, V>), - Done(VacantSearchStack<'a, K, V>), - } - impl<'a, K, V> PartialSearchStack<'a, K, V> { /// Creates a new PartialSearchStack from a BTreeMap by initializing the stack with the /// root of the tree. @@ -603,40 +590,29 @@ mod stack { /// Pushes the requested child of the stack's current top on top of the stack. If the child /// exists, then a new PartialSearchStack is yielded. Otherwise, a VacantSearchStack is /// yielded. - pub fn push(mut self, mut edge: EdgeNodeHandle>>) - -> PushResult<'a, K, V> { - let to_insert = edge.as_raw(); - match edge.edge_mut() { - None => { - Done(VacantSearchStack { - map: self.map, - stack: self.stack, - top: to_insert, - }) - }, - Some(node) => { - self.stack.push(to_insert); - Grew(PartialSearchStack { - map: self.map, - stack: self.stack, - next: node as *mut _, - }) - }, + pub fn push(mut self, mut edge: node::Handle>, Edge, Internal>) + -> PartialSearchStack<'a, K, V> { + self.stack.push(edge.as_raw()); + PartialSearchStack { + map: self.map, + stack: self.stack, + next: edge.edge_mut() as *mut _, } } - /// Converts the PartialSearchStack into an OccupiedSearchStack. - pub fn seal(self, mut node: KVNodeHandle>>) - -> OccupiedSearchStack<'a, K, V> { - OccupiedSearchStack { + /// Converts the PartialSearchStack into a SearchStack. + pub fn seal + (self, mut handle: node::Handle>, Type, NodeType>) + -> SearchStack<'a, K, V, Type, NodeType> { + SearchStack { map: self.map, stack: self.stack, - top: node.as_raw(), + top: handle.as_raw(), } } } - impl<'a, K, V> OccupiedSearchStack<'a, K, V> { + impl<'a, K, V, NodeType> SearchStack<'a, K, V, KV, NodeType> { /// Gets a reference to the value the stack points to. pub fn peek(&self) -> &V { unsafe { self.top.from_raw().into_kv().1 } @@ -657,20 +633,13 @@ mod stack { ) } } + } + impl<'a, K, V> SearchStack<'a, K, V, KV, Leaf> { /// Removes the key and value in the top element of the stack, then handles underflows as /// described in BTree's pop function. - pub fn remove(mut self) -> V { - // Ensure that the search stack goes to a leaf. This is necessary to perform deletion - // in a BTree. Note that this may put the tree in an inconsistent state (further - // described in leafify's comments), but this is immediately fixed by the - // removing the value we want to remove - self.leafify(); - - let map = self.map; - map.length -= 1; - - let mut stack = self.stack; + fn remove_leaf(mut self) -> V { + self.map.length -= 1; // Remove the key-value pair from the leaf that this search stack points to. // Then, note if the leaf is underfull, and promptly forget the leaf and its ptr @@ -682,16 +651,16 @@ mod stack { }; loop { - match stack.pop() { + match self.stack.pop() { None => { // We've reached the root, so no matter what, we're done. We manually // access the root via the tree itself to avoid creating any dangling // pointers. - if map.root.len() == 0 && !map.root.is_leaf() { + if self.map.root.len() == 0 && !self.map.root.is_leaf() { // We've emptied out the root, so make its only child the new root. // If it's a leaf, we just let it become empty. - map.depth -= 1; - map.root.into_edge(); + self.map.depth -= 1; + self.map.root.hoist_lone_child(); } return value; } @@ -710,6 +679,18 @@ mod stack { } } } + } + + impl<'a, K, V> SearchStack<'a, K, V, KV, LeafOrInternal> { + /// Removes the key and value in the top element of the stack, then handles underflows as + /// described in BTree's pop function. + pub fn remove(self) -> V { + // Ensure that the search stack goes to a leaf. This is necessary to perform deletion + // in a BTree. Note that this may put the tree in an inconsistent state (further + // described in into_leaf's comments), but this is immediately fixed by the + // removing the value we want to remove + self.into_leaf().remove_leaf() + } /// Subroutine for removal. Takes a search stack for a key that might terminate at an /// internal node, and mutates the tree and search stack to *make* it a search stack @@ -717,7 +698,7 @@ mod stack { /// leaves the tree in an inconsistent state that must be repaired by the caller by /// removing the entry in question. Specifically the key-value pair and its successor will /// become swapped. - fn leafify(&mut self) { + fn into_leaf(mut self) -> SearchStack<'a, K, V, KV, Leaf> { unsafe { let mut top_raw = self.top; let mut top = top_raw.from_raw_mut(); @@ -726,31 +707,43 @@ mod stack { let val_ptr = top.val_mut() as *mut _; // Try to go into the right subtree of the found key to find its successor - let mut right_edge = top.right_edge(); - let right_edge_raw = right_edge.as_raw(); - match right_edge.edge_mut() { - None => { + match top.force() { + Leaf(mut leaf_handle) => { // We're a proper leaf stack, nothing to do + return SearchStack { + map: self.map, + stack: self.stack, + top: leaf_handle.as_raw() + } } - Some(mut temp_node) => { + Internal(mut internal_handle) => { + let mut right_handle = internal_handle.right_edge(); + //We're not a proper leaf stack, let's get to work. - self.stack.push(right_edge_raw); + self.stack.push(right_handle.as_raw()); + + let mut temp_node = right_handle.edge_mut(); loop { // Walk into the smallest subtree of this node let node = temp_node; - if node.is_leaf() { - // This node is a leaf, do the swap and return - let mut handle = node.kv_handle(0); - self.top = handle.as_raw(); - mem::swap(handle.key_mut(), &mut *key_ptr); - mem::swap(handle.val_mut(), &mut *val_ptr); - break; - } else { - // This node is internal, go deeper - let mut handle = node.edge_handle(0); - self.stack.push(handle.as_raw()); - temp_node = handle.into_edge_mut().unwrap(); + match node.kv_handle(0).force() { + Leaf(mut handle) => { + // This node is a leaf, do the swap and return + mem::swap(handle.key_mut(), &mut *key_ptr); + mem::swap(handle.val_mut(), &mut *val_ptr); + return SearchStack { + map: self.map, + stack: self.stack, + top: handle.as_raw() + } + }, + Internal(kv_handle) => { + // This node is internal, go deeper + let mut handle = kv_handle.into_left_edge(); + self.stack.push(handle.as_raw()); + temp_node = handle.into_edge_mut(); + } } } } @@ -759,7 +752,7 @@ mod stack { } } - impl<'a, K, V> VacantSearchStack<'a, K, V> { + impl<'a, K, V> SearchStack<'a, K, V, Edge, Leaf> { /// Inserts the key and value into the top element in the stack, and if that node has to /// split recursively inserts the split contents into the next element stack until /// splits stop. @@ -1234,27 +1227,28 @@ impl BTreeMap { let mut stack = stack::PartialSearchStack::new(self); loop { let result = stack.with(move |pusher, node| { - match Node::search(node, &key) { + return match Node::search(node, &key) { Found(handle) => { // Perfect match - return Finished(Occupied(OccupiedEntry { + Finished(Occupied(OccupiedEntry { stack: pusher.seal(handle) - })); + })) }, GoDown(handle) => { - match pusher.push(handle) { - stack::Done(new_stack) => { - // Not in the tree, but we've found where it goes - return Finished(Vacant(VacantEntry { - stack: new_stack, + match handle.force() { + Leaf(leaf_handle) => { + Finished(Vacant(VacantEntry { + stack: pusher.seal(leaf_handle), key: key, - })); + })) + }, + Internal(internal_handle) => { + Continue(( + pusher.push(internal_handle), + key + )) } - stack::Grew(new_stack) => { - // We've found the subtree this key must go in - return Continue((new_stack, key)); - } - }; + } } } }); diff --git a/src/libcollections/btree/node.rs b/src/libcollections/btree/node.rs index ae23f38c92913..3718dd516b21a 100644 --- a/src/libcollections/btree/node.rs +++ b/src/libcollections/btree/node.rs @@ -13,6 +13,7 @@ pub use self::InsertionResult::*; pub use self::SearchResult::*; +pub use self::ForceResult::*; pub use self::TraversalItem::*; use core::prelude::*; @@ -34,9 +35,9 @@ pub enum InsertionResult { /// Represents the result of a search for a key in a single node pub enum SearchResult { /// The element was found at the given index - Found(KVNodeHandle), + Found(Handle), /// The element wasn't found, but if it's anywhere, it must be beyond this edge - GoDown(EdgeNodeHandle), + GoDown(Handle), } /// A B-Tree Node. We keep keys/edges/values separate to optimize searching for keys. @@ -428,8 +429,10 @@ impl Clone for Node { } } -/// A reference to a key/value pair in the middle of a `Node`. Methods are provided for removing -/// the pair and accessing the pair and the adjacent edges. +/// A reference to something in the middle of a `Node`. There are two `Type`s of `Handle`s, +/// namely `KV` handles, which point to key/value pairs, and `Edge` handles, which point to edges +/// before or after key/value pairs. Methods are provided for removing pairs, inserting into edges, +/// accessing the stored values, and moving around the `Node`. /// /// This handle is generic, and can take any sort of reference to a `Node`. The reason for this is /// two-fold. First of all, it reduces the amount of repetitive code, implementing functions that @@ -490,20 +493,17 @@ impl Clone for Node { /// } /// ``` #[deriving(Copy)] -pub struct KVNodeHandle { +pub struct Handle { node: NodeRef, index: uint } -/// A reference to an edge in the middle of a `Node`. Methods are provided for inserting stuff into -/// the space, handling underflow, and accessing the pointed-to edge. -/// -/// Please see the notes on `KVNodeHandle` about the generic parameter and safety concerns. -#[deriving(Copy)] -pub struct EdgeNodeHandle { - node: NodeRef, - index: uint -} +pub enum KV {} +pub enum Edge {} + +pub enum LeafOrInternal {} +pub enum Leaf {} +pub enum Internal {} impl Node { /// Searches for the given key in the node. If it finds an exact match, @@ -516,12 +516,12 @@ impl Node { // worse for uints. let (found, index) = node.search_linear(key); if found { - Found(KVNodeHandle { + Found(Handle { node: node, index: index }) } else { - GoDown(EdgeNodeHandle { + GoDown(Handle { node: node, index: index }) @@ -586,70 +586,104 @@ impl Node { } } -impl<'a, K: 'a, V: 'a> EdgeNodeHandle<&'a Node> { +impl>, Type, NodeType> Handle { + /// Returns a reference to the node that contains the pointed-to edge or key/value pair. This + /// is very different from `edge` and `edge_mut` because those return children of the node + /// returned by `node`. + pub fn node(&self) -> &Node { + &*self.node + } +} + +impl>, Type, NodeType> Handle { + /// Converts a handle into one that stores the same information using a raw pointer. This can + /// be useful in conjunction with `from_raw` when the type system is insufficient for + /// determining the lifetimes of the nodes. + pub fn as_raw(&mut self) -> Handle<*mut Node, Type, NodeType> { + Handle { + node: &mut *self.node as *mut _, + index: self.index + } + } +} + +impl Handle<*mut Node, Type, NodeType> { + /// Converts from a handle stored with a raw pointer, which isn't directly usable, to a handle + /// stored with a reference. This is an unsafe inverse of `as_raw`, and together they allow + /// unsafely extending the lifetime of the reference to the `Node`. + pub unsafe fn from_raw<'a>(&'a self) -> Handle<&'a Node, Type, NodeType> { + Handle { + node: &*self.node, + index: self.index + } + } + + /// Converts from a handle stored with a raw pointer, which isn't directly usable, to a handle + /// stored with a mutable reference. This is an unsafe inverse of `as_raw`, and together they + /// allow unsafely extending the lifetime of the reference to the `Node`. + pub unsafe fn from_raw_mut<'a>(&'a mut self) -> Handle<&'a mut Node, Type, NodeType> { + Handle { + node: &mut *self.node, + index: self.index + } + } +} + +impl<'a, K: 'a, V: 'a> Handle<&'a Node, Edge, Internal> { /// Turns the handle into a reference to the edge it points at. This is necessary because the /// returned pointer has a larger lifetime than what would be returned by `edge` or `edge_mut`, /// making it more suitable for moving down a chain of nodes. - /// - /// Returns `None` if called on an edge in a leaf node. - pub fn into_edge(self) -> Option<&'a Node> { - if self.node.is_leaf() { - None - } else { - unsafe { - Some(self.node.edges().unsafe_get(self.index)) - } + pub fn into_edge(self) -> &'a Node { + unsafe { + self.node.edges().unsafe_get(self.index) } } } -impl<'a, K: 'a, V: 'a> EdgeNodeHandle<&'a mut Node> { +impl<'a, K: 'a, V: 'a> Handle<&'a mut Node, Edge, Internal> { /// Turns the handle into a mutable reference to the edge it points at. This is necessary /// because the returned pointer has a larger lifetime than what would be returned by /// `edge_mut`, making it more suitable for moving down a chain of nodes. - /// - /// Returns `None` if called on an edge in a leaf node. - pub fn into_edge_mut(self) -> Option<&'a mut Node> { - if self.node.is_leaf() { - None - } else { - unsafe { - Some(self.node.edges_mut().unsafe_mut(self.index)) - } + pub fn into_edge_mut(self) -> &'a mut Node { + unsafe { + self.node.edges_mut().unsafe_mut(self.index) } } } -impl>> EdgeNodeHandle { - /// Returns a reference to the node that contains the pointed-to edge. This is very different - /// from `edge` and `edge_mut` because those return children of the node returned by `node`. - pub fn node(&self) -> &Node { - &*self.node - } - +impl>> Handle { // This doesn't exist because there are no uses for it, // but is fine to add, analagous to edge_mut. // // /// Returns a reference to the edge pointed-to by this handle. This should not be // /// confused with `node`, which references the parent node of what is returned here. - // /// - // /// Returns `None` when called on an edge in a leaf node. - // pub fn edge(&self) -> Option<&Node> + // pub fn edge(&self) -> &Node } -impl>> EdgeNodeHandle { - /// Returns a mutable reference to the edge pointed-to by this handle. This should not be - /// confused with `node`, which references the parent node of what is returned here. - /// - /// Returns `None` when called on an edge in a leaf node. - pub fn edge_mut(&mut self) -> Option<&mut Node> { +pub enum ForceResult { + Leaf(Handle), + Internal(Handle) +} + +impl>, Type> Handle { + /// Figure out whether this handle is pointing to something in a leaf node or to something in + /// an internal node, clarifying the type according to the result. + pub fn force(self) -> ForceResult { if self.node.is_leaf() { - None + Leaf(Handle { + node: self.node, + index: self.index + }) } else { - unsafe { Some(self.node.edges_mut().unsafe_mut(self.index)) } + Internal(Handle { + node: self.node, + index: self.index + }) } } +} +impl>> Handle { /// Tries to insert this key-value pair at the given index in this leaf node /// If the node is full, we have to split it. /// @@ -657,10 +691,6 @@ impl>> EdgeNodeHandle { /// they're done mutating the tree, but we don't want to borrow anything for now. pub fn insert_as_leaf(mut self, key: K, value: V) -> (InsertionResult, *mut V) { - // Necessary for correctness, but in a private module - debug_assert!(self.node.is_leaf(), - "insert_as_leaf must only be called on leaf nodes"); - if !self.node.is_full() { // The element can fit, just insert it (Fit, unsafe { self.node.insert_kv(self.index, key, value) as *mut _ }) @@ -683,15 +713,21 @@ impl>> EdgeNodeHandle { (Split(new_key, new_val, new_right), ptr) } } +} + +impl>> Handle { + /// Returns a mutable reference to the edge pointed-to by this handle. This should not be + /// confused with `node`, which references the parent node of what is returned here. + pub fn edge_mut(&mut self) -> &mut Node { + unsafe { + self.node.edges_mut().unsafe_mut(self.index) + } + } /// Tries to insert this key-value pair at the given index in this internal node /// If the node is full, we have to split it. pub fn insert_as_internal(mut self, key: K, value: V, right: Node) -> InsertionResult { - // Necessary for correctness, but in a private module - debug_assert!(!self.node.is_leaf(), - "insert_as_internal must only be called on internal nodes"); - if !self.node.is_full() { // The element can fit, just insert it unsafe { @@ -739,26 +775,6 @@ impl>> EdgeNodeHandle { } } - /// Gets the handle pointing to the key/value pair just to the left of the pointed-to edge. - /// This is unsafe because the handle might point to the first edge in the node, which has no - /// pair to its left. - unsafe fn left_kv<'a>(&'a mut self) -> KVNodeHandle<&'a mut Node> { - KVNodeHandle { - node: &mut *self.node, - index: self.index - 1 - } - } - - /// Gets the handle pointing to the key/value pair just to the right of the pointed-to edge. - /// This is unsafe because the handle might point to the last edge in the node, which has no - /// pair to its right. - unsafe fn right_kv<'a>(&'a mut self) -> KVNodeHandle<&'a mut Node> { - KVNodeHandle { - node: &mut *self.node, - index: self.index - } - } - /// Right is underflowed. Tries to steal from left, /// but merges left and right if left is low too. unsafe fn handle_underflow_to_left(&mut self) { @@ -780,41 +796,31 @@ impl>> EdgeNodeHandle { self.right_kv().merge_children(); } } - - /// Converts a handle into one that stores the same information using a raw pointer. This can - /// be useful in conjunction with `from_raw` in the cases in which the type system is - /// insufficient for determining the lifetimes of the nodes. - pub fn as_raw(&mut self) -> EdgeNodeHandle<*mut Node> { - EdgeNodeHandle { - node: &mut *self.node as *mut _, - index: self.index - } - } } -impl EdgeNodeHandle<*mut Node> { - /// Converts from a handle stored with a raw pointer, which isn't directly usable, to a handle - /// stored with a reference. This is an unsafe inverse of `as_raw`, and together they allow - /// unsafely extending the lifetime of the reference to the `Node`. - pub unsafe fn from_raw<'a>(&'a self) -> EdgeNodeHandle<&'a Node> { - EdgeNodeHandle { - node: &*self.node, - index: self.index +impl>, NodeType> Handle { + /// Gets the handle pointing to the key/value pair just to the left of the pointed-to edge. + /// This is unsafe because the handle might point to the first edge in the node, which has no + /// pair to its left. + unsafe fn left_kv<'a>(&'a mut self) -> Handle<&'a mut Node, KV, NodeType> { + Handle { + node: &mut *self.node, + index: self.index - 1 } } - /// Converts from a handle stored with a raw pointer, which isn't directly usable, to a handle - /// stored with a mutable reference. This is an unsafe inverse of `as_raw`, and together they - /// allow unsafely extending the lifetime of the reference to the `Node`. - pub unsafe fn from_raw_mut<'a>(&'a mut self) -> EdgeNodeHandle<&'a mut Node> { - EdgeNodeHandle { + /// Gets the handle pointing to the key/value pair just to the right of the pointed-to edge. + /// This is unsafe because the handle might point to the last edge in the node, which has no + /// pair to its right. + unsafe fn right_kv<'a>(&'a mut self) -> Handle<&'a mut Node, KV, NodeType> { + Handle { node: &mut *self.node, index: self.index } } } -impl<'a, K: 'a, V: 'a> KVNodeHandle<&'a Node> { +impl<'a, K: 'a, V: 'a, NodeType> Handle<&'a Node, KV, NodeType> { /// Turns the handle into references to the key and value it points at. This is necessary /// because the returned pointers have larger lifetimes than what would be returned by `key` /// or `val`. @@ -829,7 +835,7 @@ impl<'a, K: 'a, V: 'a> KVNodeHandle<&'a Node> { } } -impl<'a, K: 'a, V: 'a> KVNodeHandle<&'a mut Node> { +impl<'a, K: 'a, V: 'a, NodeType> Handle<&'a mut Node, KV, NodeType> { /// Turns the handle into mutable references to the key and value it points at. This is /// necessary because the returned pointers have larger lifetimes than what would be returned /// by `key_mut` or `val_mut`. @@ -842,14 +848,19 @@ impl<'a, K: 'a, V: 'a> KVNodeHandle<&'a mut Node> { ) } } -} -impl<'a, K: 'a, V: 'a, NodeRef: Deref> + 'a> KVNodeHandle { - /// Returns a reference to the node that contains the pointed-to key/value pair. - pub fn node(&'a self) -> &'a Node { - &*self.node + /// Convert this handle into one pointing at the edge immediately to the left of the key/value + /// pair pointed-to by this handle. This is useful because it returns a reference with larger + /// lifetime than `left_edge`. + pub fn into_left_edge(self) -> Handle<&'a mut Node, Edge, NodeType> { + Handle { + node: &mut *self.node, + index: self.index + } } +} +impl<'a, K: 'a, V: 'a, NodeRef: Deref> + 'a, NodeType> Handle { // These are fine to include, but are currently unneeded. // // /// Returns a reference to the key pointed-to by this handle. This doesn't return a @@ -867,7 +878,7 @@ impl<'a, K: 'a, V: 'a, NodeRef: Deref> + 'a> KVNodeHandle { // } } -impl<'a, K: 'a, V: 'a, NodeRef: DerefMut> + 'a> KVNodeHandle { +impl<'a, K: 'a, V: 'a, NodeRef: DerefMut> + 'a, NodeType> Handle { /// Returns a mutable reference to the key pointed-to by this handle. This doesn't return a /// reference with a lifetime as large as `into_kv_mut`, but it also does not consume the /// handle. @@ -883,11 +894,11 @@ impl<'a, K: 'a, V: 'a, NodeRef: DerefMut> + 'a> KVNodeHandle } } -impl>> KVNodeHandle { +impl>, NodeType> Handle { /// Gets the handle pointing to the edge immediately to the left of the key/value pair pointed /// to by this handle. - pub fn left_edge<'a>(&'a mut self) -> EdgeNodeHandle<&'a mut Node> { - EdgeNodeHandle { + pub fn left_edge<'a>(&'a mut self) -> Handle<&'a mut Node, Edge, NodeType> { + Handle { node: &mut *self.node, index: self.index } @@ -895,41 +906,33 @@ impl>> KVNodeHandle { /// Gets the handle pointing to the edge immediately to the right of the key/value pair pointed /// to by this handle. - pub fn right_edge<'a>(&'a mut self) -> EdgeNodeHandle<&'a mut Node> { - EdgeNodeHandle { + pub fn right_edge<'a>(&'a mut self) -> Handle<&'a mut Node, Edge, NodeType> { + Handle { node: &mut *self.node, index: self.index + 1 } } +} +impl>> Handle { /// Removes the key/value pair at the handle's location. /// /// # Panics (in debug build) /// /// Panics if the node containing the pair is not a leaf node. pub fn remove_as_leaf(mut self) -> (K, V) { - // Necessary for correctness, but in a private module - debug_assert!(self.node.is_leaf(), "remove_as_leaf must only be called on leaf nodes"); unsafe { self.node.remove_kv(self.index) } } +} - /// Converts a handle into one that stores the same information using a raw pointer. This can - /// be useful in conjunction with `from_raw` in the cases in which the type system is - /// insufficient for determining the lifetimes of the nodes. - pub fn as_raw(&mut self) -> KVNodeHandle<*mut Node> { - KVNodeHandle { - node: &mut *self.node as *mut _, - index: self.index - } - } - +impl>> Handle { /// Steal! Stealing is roughly analogous to a binary tree rotation. /// In this case, we're "rotating" right. unsafe fn steal_rightward(&mut self) { // Take the biggest stuff off left let (mut key, mut val, edge) = { let mut left_handle = self.left_edge(); - let left = left_handle.edge_mut().unwrap(); + let left = left_handle.edge_mut(); let (key, val) = left.pop_kv(); let edge = if left.is_leaf() { None @@ -946,7 +949,7 @@ impl>> KVNodeHandle { // Put them at the start of right let mut right_handle = self.right_edge(); - let right = right_handle.edge_mut().unwrap(); + let right = right_handle.edge_mut(); right.insert_kv(0, key, val); match edge { Some(edge) => right.insert_edge(0, edge), @@ -960,7 +963,7 @@ impl>> KVNodeHandle { // Take the smallest stuff off right let (mut key, mut val, edge) = { let mut right_handle = self.right_edge(); - let right = right_handle.edge_mut().unwrap(); + let right = right_handle.edge_mut(); let (key, val) = right.remove_kv(0); let edge = if right.is_leaf() { None @@ -977,7 +980,7 @@ impl>> KVNodeHandle { // Put them at the end of left let mut left_handle = self.left_edge(); - let left = left_handle.edge_mut().unwrap(); + let left = left_handle.edge_mut(); left.push_kv(key, val); match edge { Some(edge) => left.push_edge(edge), @@ -994,57 +997,21 @@ impl>> KVNodeHandle { let right = self.node.remove_edge(self.index + 1); // Give left right's stuff. - self.left_edge().edge_mut().unwrap() + self.left_edge().edge_mut() .absorb(key, val, right); } } -impl KVNodeHandle<*mut Node> { - /// Converts from a handle stored with a raw pointer, which isn't directly usable, to a handle - /// stored with a reference. This is an unsafe inverse of `as_raw`, and together they allow - /// unsafely extending the lifetime of the reference to the `Node`. - pub unsafe fn from_raw<'a>(&'a self) -> KVNodeHandle<&'a Node> { - KVNodeHandle { - node: &*self.node, - index: self.index - } - } - - /// Converts from a handle stored with a raw pointer, which isn't directly usable, to a handle - /// stored with a mutable reference. This is an unsafe inverse of `as_raw`, and together they - /// allow unsafely extending the lifetime of the reference to the `Node`. - pub unsafe fn from_raw_mut<'a>(&'a mut self) -> KVNodeHandle<&'a mut Node> { - KVNodeHandle { - node: &mut *self.node, - index: self.index - } - } -} - impl Node { /// Returns the mutable handle pointing to the key/value pair at a given index. /// /// # Panics (in debug build) /// /// Panics if the given index is out of bounds. - pub fn kv_handle(&mut self, index: uint) -> KVNodeHandle<&mut Node> { + pub fn kv_handle(&mut self, index: uint) -> Handle<&mut Node, KV, LeafOrInternal> { // Necessary for correctness, but in a private module debug_assert!(index < self.len(), "kv_handle index out of bounds"); - KVNodeHandle { - node: self, - index: index - } - } - - /// Returns the mutable handle pointing to the edge at a given index. - /// - /// # Panics (in debug build) - /// - /// Panics if the given index is out of bounds. - pub fn edge_handle(&mut self, index: uint) -> EdgeNodeHandle<&mut Node> { - // Necessary for correctness, but in a private module - debug_assert!(index <= self.len(), "edge_handle index out of bounds"); - EdgeNodeHandle { + Handle { node: self, index: index } @@ -1100,7 +1067,7 @@ impl Node { } /// When a node has no keys or values and only a single edge, extract that edge. - pub fn into_edge(&mut self) { + pub fn hoist_lone_child(&mut self) { // Necessary for correctness, but in a private module debug_assert!(self.len() == 0); debug_assert!(!self.is_leaf());