Skip to content

Commit 3b2e292

Browse files
committed
Revert getIndex() and use getExpectedIndex() to handle cases where the key is not in the tree
1 parent de2db30 commit 3b2e292

File tree

3 files changed

+44
-3
lines changed

3 files changed

+44
-3
lines changed

src/MemoryBTree/Base.mo

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import Blob "mo:base/Blob";
1111

1212
import MemoryRegion "mo:memory-region/MemoryRegion";
1313
import RevIter "mo:itertools/RevIter";
14+
import Find "mo:map/Map/modules/find";
1415

1516
import MemoryCmp "../TypeUtils/MemoryCmp";
1617
import Blobify "../TypeUtils/Blobify";
@@ -900,9 +901,35 @@ module {
900901
};
901902

902903
if (int_index < 0) {
903-
index_pos + Int.abs(int_index + 1);
904+
Debug.trap("getIndex(): Key not found. Use getExpectedIndex() instead to get keys that might not be in the tree");
905+
};
906+
907+
index_pos + Int.abs(int_index);
908+
};
909+
910+
/// Returns the index of the given key in the tree.
911+
/// Used to indicate whether the key is in the tree or not.
912+
public type ExpectedIndex = {
913+
#Found : Nat;
914+
#NotFound : Nat;
915+
};
916+
917+
public func getExpectedIndex<K, V>(btree : MemoryBTree, btree_utils : BTreeUtils<K, V>, key : K) : ExpectedIndex {
918+
let key_blob = btree_utils.key.blobify.to_blob(key);
919+
let (leaf_address, index_pos) = Methods.get_leaf_node_and_index(btree, btree_utils, key_blob);
920+
921+
let count = Leaf.get_count(btree, leaf_address);
922+
let int_index = switch (btree_utils.key.cmp) {
923+
case (#GenCmp(cmp)) Leaf.binary_search<K, V>(btree, btree_utils, leaf_address, cmp, key, count);
924+
case (#BlobCmp(cmp)) {
925+
Leaf.binary_search_blob_seq(btree, leaf_address, cmp, key_blob, count);
926+
};
927+
};
928+
929+
if (int_index < 0) {
930+
#NotFound(index_pos + Int.abs(int_index + 1));
904931
} else {
905-
index_pos + Int.abs(int_index);
932+
#Found(index_pos + Int.abs(int_index));
906933
};
907934

908935
};

src/MemoryBTree/Stable.mo

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,13 @@ module StableMemoryBTree {
106106
MemoryBTree.getIndex(state, btree_utils, key);
107107
};
108108

109+
public type ExpectedIndex = MemoryBTree.ExpectedIndex;
110+
111+
public func getExpectedIndex<K, V>(btree : StableMemoryBTree, btree_utils : BTreeUtils<K, V>, key : K) : ExpectedIndex {
112+
let state = Migrations.getCurrentVersion(btree);
113+
MemoryBTree.getExpectedIndex(state, btree_utils, key);
114+
};
115+
109116
public func clear(btree : StableMemoryBTree) {
110117
let state = Migrations.getCurrentVersion(btree);
111118
MemoryBTree.clear(state);

src/MemoryBTree/lib.mo

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ module {
2121
public type ValueUtils<V> = T.ValueUtils<V>;
2222
public type MemoryBTreeStats = BaseMemoryBTree.MemoryBTreeStats;
2323

24+
public type ExpectedIndex = BaseMemoryBTree.ExpectedIndex;
25+
2426
/// Create a new stable store
2527
public func newStableStore(order : ?Nat) : StableStore = StableMemoryBTree.new(order);
2628

@@ -90,9 +92,14 @@ module {
9092
public func getFromIndex(i : Nat) : (K, V) = BaseMemoryBTree.getFromIndex<K, V>(state, btree_utils, i);
9193

9294
/// Get the index (sorted position) of the given key in the btree
93-
/// If the key is not in the BTree, the expected index is returned
95+
/// > Throws an error if the key is not found.
96+
/// > Use `getExpectedIndex()` if you want to get the index without throwing an error.
9497
public func getIndex(key : K) : Nat = BaseMemoryBTree.getIndex<K, V>(state, btree_utils, key);
9598

99+
/// Get the index (sorted position) of the given key in the btree
100+
/// Returns a `ExpectedIndex` variant that returns `#Found(index)` if the key exists or `#NotFound(index)` if it does not.
101+
public func getExpectedIndex(key : K) : BaseMemoryBTree.ExpectedIndex = BaseMemoryBTree.getExpectedIndex<K, V>(state, btree_utils, key);
102+
96103
/// Insert a new key-value pair into the BTree
97104
public func insert(key : K, val : V) : ?V = BaseMemoryBTree.insert<K, V>(state, btree_utils, key, val);
98105

0 commit comments

Comments
 (0)