diff --git a/src/btreemap.rs b/src/btreemap.rs index 1ccb2700..e72567e4 100644 --- a/src/btreemap.rs +++ b/src/btreemap.rs @@ -216,7 +216,7 @@ where _phantom: PhantomData, }; - btree.save(); + btree.save_header(); btree } @@ -243,7 +243,7 @@ where _phantom: PhantomData, }; - btree.save(); + btree.save_header(); btree } @@ -252,7 +252,7 @@ where Self::load_helper(memory, true) } - // Loads the map from memory, potentially migrating the map from V1 to V2. + /// Loads the map from memory, potentially migrating the map from V1 to V2. fn load_helper(memory: M, migrate_to_v2: bool) -> Self { // Read the header from memory. let header = Self::read_header(&memory); @@ -359,7 +359,7 @@ where // No root present. Allocate one. let node = self.allocate_node(NodeType::Leaf); self.root_addr = node.address(); - self.save(); + self.save_header(); node } else { // Load the root from memory. @@ -369,7 +369,7 @@ where if let Ok(idx) = root.search(&key) { // The key exists. Overwrite it and return the previous value. let (_, previous_value) = root.swap_entry(idx, (key, value), self.memory()); - root.save(self.allocator_mut()); + self.save_node(&mut root); return Some(V::from_bytes(Cow::Owned(previous_value))); } @@ -387,7 +387,7 @@ where // Update the root address. self.root_addr = new_root.address(); - self.save(); + self.save_header(); // Split the old (full) root. self.split_child(&mut new_root, 0); @@ -403,7 +403,7 @@ where .map(V::from_bytes) } - // Inserts an entry into a node that is *not full*. + /// Inserts an entry into a node that is *not full*. fn insert_nonfull(&mut self, mut node: Node, key: K, value: Vec) -> Option> { // We're guaranteed by the caller that the provided node is not full. assert!(!node.is_full()); @@ -415,7 +415,7 @@ where // Overwrite it and return the previous value. let (_, previous_value) = node.swap_entry(idx, (key, value), self.memory()); - node.save(self.allocator_mut()); + self.save_node(&mut node); Some(previous_value) } Err(idx) => { @@ -426,11 +426,11 @@ where // The node is a non-full leaf. // Insert the entry at the proper location. node.insert_entry(idx, (key, value)); - node.save(self.allocator_mut()); + self.save_node(&mut node); // Update the length. self.length += 1; - self.save(); + self.save_header(); // No previous value to return. None @@ -446,7 +446,7 @@ where // The key exists. Overwrite it and return the previous value. let (_, previous_value) = child.swap_entry(idx, (key, value), self.memory()); - child.save(self.allocator_mut()); + self.save_node(&mut child); return Some(previous_value); } @@ -469,22 +469,23 @@ where } } - // Takes as input a nonfull internal `node` and index to its full child, then - // splits this child into two, adding an additional child to `node`. - // - // Example: - // - // [ ... M Y ... ] - // | - // [ N O P Q R S T U V W X ] - // - // - // After splitting becomes: - // - // [ ... M S Y ... ] - // / \ - // [ N O P Q R ] [ T U V W X ] - // + /// Takes as input a nonfull internal `node` and index to its full child, then + /// splits this child into two, adding an additional child to `node`. + /// + /// Example: + /// ```ignore + /// [ ... M Y ... ] + /// | + /// [ N O P Q R S T U V W X ] + /// ``` + /// + /// After splitting becomes: + /// ```ignore + /// [ ... M S Y ... ] + /// / \ + /// [ N O P Q R ] [ T U V W X ] + /// ``` + /// fn split_child(&mut self, node: &mut Node, full_child_idx: usize) { // The node must not be full. assert!(!node.is_full()); @@ -504,9 +505,9 @@ where node.insert_entry(full_child_idx, (median_key, median_value)); - sibling.save(self.allocator_mut()); - full_child.save(self.allocator_mut()); - node.save(self.allocator_mut()); + self.save_node(&mut sibling); + self.save_node(&mut full_child); + self.save_node(node); } /// Returns the value for the given key, if it exists. @@ -570,7 +571,7 @@ where self.root_addr = NULL; self.length = 0; self.allocator.clear(); - self.save(); + self.save_header(); } /// Returns the first key-value pair in the map. The key in this @@ -639,7 +640,7 @@ where .map(|v| (min_key, V::from_bytes(Cow::Owned(v)))) } - // A helper method for recursively removing a key from the B-tree. + /// A helper method for recursively removing a key from the B-tree. fn remove_helper(&mut self, mut node: Node, key: &K) -> Option> { if node.address() != self.root_addr { // We're guaranteed that whenever this method is called an entry can be @@ -665,13 +666,13 @@ where ); // Deallocate the empty node. - node.deallocate(&mut self.allocator); + self.deallocate_node(node); self.root_addr = NULL; } else { - node.save(self.allocator_mut()); + self.save_node(&mut node); } - self.save(); + self.save_header(); Some(value) } _ => None, // Key not found. @@ -713,7 +714,7 @@ where let (_, old_value) = node.swap_entry(idx, predecessor, self.memory()); // Save the parent node. - node.save(self.allocator_mut()); + self.save_node(&mut node); return Some(old_value); } @@ -748,7 +749,7 @@ where let (_, old_value) = node.swap_entry(idx, successor, self.memory()); // Save the parent node. - node.save(self.allocator_mut()); + self.save_node(&mut node); return Some(old_value); } @@ -793,13 +794,13 @@ where self.root_addr = new_child.address(); // Deallocate the root node. - node.deallocate(&mut self.allocator); - self.save(); + self.deallocate_node(node); + self.save_header(); } else { - node.save(self.allocator_mut()); + self.save_node(&mut node); } - new_child.save(self.allocator_mut()); + self.save_node(&mut new_child); // Recursively delete the key. self.remove_helper(new_child, key) @@ -879,9 +880,9 @@ where assert_eq!(child.node_type(), NodeType::Leaf); } - left_sibling.save(self.allocator_mut()); - child.save(self.allocator_mut()); - node.save(self.allocator_mut()); + self.save_node(left_sibling); + self.save_node(&mut child); + self.save_node(&mut node); return self.remove_helper(child, key); } } @@ -934,9 +935,9 @@ where } } - right_sibling.save(self.allocator_mut()); - child.save(self.allocator_mut()); - node.save(self.allocator_mut()); + self.save_node(right_sibling); + self.save_node(&mut child); + self.save_node(&mut node); return self.remove_helper(child, key); } } @@ -957,15 +958,15 @@ where if node.entries_len() == 0 { let node_address = node.address(); - node.deallocate(&mut self.allocator); + self.deallocate_node(node); if node_address == self.root_addr { // Update the root. self.root_addr = left_sibling.address(); - self.save(); + self.save_header(); } } else { - node.save(self.allocator_mut()); + self.save_node(&mut node); } return self.remove_helper(left_sibling, key); @@ -986,15 +987,15 @@ where if node.entries_len() == 0 { let node_address = node.address(); - node.deallocate(&mut self.allocator); + self.deallocate_node(node); if node_address == self.root_addr { // Update the root. self.root_addr = right_sibling.address(); - self.save(); + self.save_header(); } } else { - node.save(self.allocator_mut()); + self.save_node(&mut node); } return self.remove_helper(right_sibling, key); @@ -1067,23 +1068,24 @@ where IterInternal::new_in_range(self, range) } - // Merges one node (`source`) into another (`into`), along with a median entry. - // - // Example (values are not included for brevity): - // - // Input: - // Source: [1, 2, 3] - // Into: [5, 6, 7] - // Median: 4 - // - // Output: - // [1, 2, 3, 4, 5, 6, 7] (stored in the `into` node) - // `source` is deallocated. + /// Merges one node (`source`) into another (`into`), along with a median entry. + /// + /// Example (values are not included for brevity): + /// + /// Input: + /// Source: [1, 2, 3] + /// Into: [5, 6, 7] + /// Median: 4 + /// + /// Output: + /// [1, 2, 3, 4, 5, 6, 7] (stored in the `into` node) + /// `source` is deallocated. fn merge(&mut self, source: Node, mut into: Node, median: Entry) -> Node { into.merge(source, median, &mut self.allocator); into } + /// Allocates a new node of the given type. fn allocate_node(&mut self, node_type: NodeType) -> Node { match self.version { Version::V1(page_size) => Node::new_v1(self.allocator.allocate(), node_type, page_size), @@ -1091,12 +1093,26 @@ where } } + /// Deallocates a node. + #[inline] + fn deallocate_node(&mut self, node: Node) { + node.deallocate(self.allocator_mut()); + } + + /// Loads a node from memory. + #[inline] fn load_node(&self, address: Address) -> Node { Node::load(address, self.version.page_size(), self.memory()) } - // Saves the map to memory. - fn save(&self) { + /// Saves the node to memory. + #[inline] + fn save_node(&mut self, node: &mut Node) { + node.save(self.allocator_mut()); + } + + /// Saves the map to memory. + fn save_header(&self) { let header = BTreeHeader { version: self.version, root_addr: self.root_addr, @@ -1151,16 +1167,17 @@ mod test { Rc::new(RefCell::new(Vec::new())) } - // A helper method to succinctly create an entry. + /// A helper method to succinctly create an entry. fn e(x: u8) -> (Blob<10>, Vec) { (b(&[x]), vec![]) } + /// A helper method to succinctly create a blob. pub(crate) fn b(x: &[u8]) -> Blob<10> { Blob::<10>::try_from(x).unwrap() } - // A test runner that runs the test using both V1 and V2 btrees. + /// A test runner that runs the test using both V1 and V2 btrees. pub fn btree_test(f: F) where K: Storable + Ord + Clone, @@ -2087,14 +2104,14 @@ mod test { fn len() { btree_test(|mut btree| { for i in 0..1000u32 { - assert_eq!(btree.insert(b(i.to_le_bytes().as_slice()), b(&[])), None); + assert_eq!(btree.insert(b(&i.to_le_bytes()), b(&[])), None); } assert_eq!(btree.len(), 1000); assert!(!btree.is_empty()); for i in 0..1000u32 { - assert_eq!(btree.remove(&b(i.to_le_bytes().as_slice())), Some(b(&[]))); + assert_eq!(btree.remove(&b(&i.to_le_bytes())), Some(b(&[]))); } assert_eq!(btree.len(), 0); @@ -2145,16 +2162,13 @@ mod test { btree_test(|mut btree| { // Insert even numbers from 0 to 1000. for i in (0..1000u32).step_by(2) { - assert_eq!(btree.insert(b(i.to_le_bytes().as_slice()), b(&[])), None); + assert_eq!(btree.insert(b(&i.to_le_bytes()), b(&[])), None); } // Contains key should return true on all the even numbers and false on all the odd // numbers. for i in 0..1000u32 { - assert_eq!( - btree.contains_key(&b(i.to_le_bytes().as_slice())), - i % 2 == 0 - ); + assert_eq!(btree.contains_key(&b(&i.to_le_bytes())), i % 2 == 0); } }); } @@ -2907,7 +2921,7 @@ mod test { // Migrate to v2 and the unbounded type. let btree: BTreeMap = BTreeMap::init(btree.into_memory()); - btree.save(); + btree.save_header(); // Reload the BTree again and try to read the value. let btree: BTreeMap = BTreeMap::init(btree.into_memory()); diff --git a/src/btreemap/node.rs b/src/btreemap/node.rs index 98288f64..50af80e0 100644 --- a/src/btreemap/node.rs +++ b/src/btreemap/node.rs @@ -330,16 +330,16 @@ impl Node { source.deallocate(allocator); } - // Appends the entries and children of node `b` into `a`, along with the median entry. - // - // PRECONDITION: - // * `a` is not empty. - // * `b` is not empty. - // * `a` and `b` are of the same node type. - // * keys of `a` < median < keys of `b` - // - // POSTCONDITION: - // * `b` is empty. + /// Appends the entries and children of node `b` into `a`, along with the median entry. + /// + /// PRECONDITION: + /// * `a` is not empty. + /// * `b` is not empty. + /// * `a` and `b` are of the same node type. + /// * keys of `a` < median < keys of `b` + /// + /// POSTCONDITION: + /// * `b` is empty. fn append(a: &mut Node, b: &mut Node, median: Entry) { // Assert preconditions. let a_len = a.entries_len(); @@ -562,7 +562,7 @@ pub struct DerivedPageSize { } impl DerivedPageSize { - // Returns the page size derived from the max key/value sizes. + /// Returns the page size derived from the max key/value sizes. fn get(&self) -> u32 { v1::size_v1(self.max_key_size, self.max_value_size).get() as u32 }