From a2ff2a6836119167217f65ee220bdf45d0e3960b Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Mon, 20 Nov 2017 12:31:51 -0800 Subject: [PATCH] Add goto_first() methods to SetCursor and MapCursor. --- lib/cretonne/src/bforest/map.rs | 15 ++++++++++++++- lib/cretonne/src/bforest/path.rs | 16 ++++++++++++++++ lib/cretonne/src/bforest/set.rs | 12 ++++++++++-- 3 files changed, 40 insertions(+), 3 deletions(-) diff --git a/lib/cretonne/src/bforest/map.rs b/lib/cretonne/src/bforest/map.rs index 45ff290ccd..0cc1364c47 100644 --- a/lib/cretonne/src/bforest/map.rs +++ b/lib/cretonne/src/bforest/map.rs @@ -254,6 +254,11 @@ where }) } + /// Move this cursor to the first element. + pub fn goto_first(&mut self) -> Option { + self.root.map(|root| self.path.first(root, self.pool).1) + } + /// Insert `(key, value))` into the map and leave the cursor at the inserted pair. /// /// If the map did not contain `key`, return `None`. @@ -341,6 +346,8 @@ mod test { assert_eq!(c.prev(), None); c.verify(); assert_eq!(c.tpath(), ""); + assert_eq!(c.goto_first(), None); + assert_eq!(c.tpath(), ""); } #[test] @@ -407,7 +414,7 @@ mod test { { let mut c = m.cursor(f, &()); - assert_eq!(c.goto(0), None); + assert_eq!(c.goto_first(), Some(4.0)); assert_eq!(c.key(), Some(40)); assert_eq!(c.value(), Some(4.0)); assert_eq!(c.next(), Some((50, 5.5))); @@ -516,6 +523,12 @@ mod test { assert_eq!(m.tpath(810, f, &()), "node2[7]--node8[0]"); assert_eq!(m.tpath(870, f, &()), "node2[7]--node8[6]"); + { + let mut c = m.cursor(f, &()); + assert_eq!(c.goto_first(), Some(1.1)); + assert_eq!(c.key(), Some(110)); + } + // Front of first leaf. m.insert(0, 4.2, f, &()); m.verify(f, &()); diff --git a/lib/cretonne/src/bforest/path.rs b/lib/cretonne/src/bforest/path.rs index aa42e2ecc8..3393014fee 100644 --- a/lib/cretonne/src/bforest/path.rs +++ b/lib/cretonne/src/bforest/path.rs @@ -87,6 +87,22 @@ impl Path { unreachable!(); } + /// Move path to the first entry of the tree starting at `root` and return it. + pub fn first(&mut self, root: Node, pool: &NodePool) -> (F::Key, F::Value) { + let mut node = root; + for level in 0.. { + self.size = level + 1; + self.node[level] = node; + self.entry[level] = 0; + match &pool[node] { + &NodeData::Inner { tree, .. } => node = tree[0], + &NodeData::Leaf { keys, vals, .. } => return (keys.borrow()[0], vals.borrow()[0]), + &NodeData::Free { .. } => panic!("Free {} reached from {}", node, root), + } + } + unreachable!(); + } + /// Move this path to the next key-value pair and return it. pub fn next(&mut self, pool: &NodePool) -> Option<(F::Key, F::Value)> { match self.leaf_pos() { diff --git a/lib/cretonne/src/bforest/set.rs b/lib/cretonne/src/bforest/set.rs index b716cb2e33..ce809ac648 100644 --- a/lib/cretonne/src/bforest/set.rs +++ b/lib/cretonne/src/bforest/set.rs @@ -216,6 +216,11 @@ where } } + /// Move this cursor to the first element. + pub fn goto_first(&mut self) -> Option { + self.root.map(|root| self.path.first(root, self.pool).0) + } + /// Try to insert `elem` into the set and leave the cursor at the inserted element. /// /// If the set did not contain `elem`, insert it and return true. @@ -293,9 +298,12 @@ mod test { s.clear(&mut f); assert!(!s.contains(7, &f, &())); - let c = SetCursor::new(&mut s, &mut f, &()); + let mut c = SetCursor::new(&mut s, &mut f, &()); c.verify(); assert_eq!(c.elem(), None); + + assert_eq!(c.goto_first(), None); + assert_eq!(c.tpath(), ""); } #[test] @@ -355,7 +363,7 @@ mod test { } assert!(!c.is_empty()); - assert!(c.goto(0)); + assert_eq!(c.goto_first(), Some(0)); assert_eq!(c.tpath(), "node2[0]--node0[0]"); assert_eq!(c.prev(), None);