diff --git a/aptos-move/framework/aptos-framework/doc/big_ordered_map.md b/aptos-move/framework/aptos-framework/doc/big_ordered_map.md index 5b430acaf6775..1f97dcba8e4c5 100644 --- a/aptos-move/framework/aptos-framework/doc/big_ordered_map.md +++ b/aptos-move/framework/aptos-framework/doc/big_ordered_map.md @@ -26,15 +26,21 @@ If you need larger, use other constructor methods. Based on initial configuration, BigOrderedMap will always accept insertion of keys and values up to the allowed size, and will abort with EKEY_BYTES_TOO_LARGE or EARGUMENT_BYTES_TOO_LARGE. -TODO: all iterator functions are public(friend) for now, so that they can be modified in a -backward incompatible way. Type is also named IteratorPtr, so that Iterator is free to use later. -They are waiting for Move improvement that will allow references to be part of the struct, +Warning: All iterator functions need to be carefully used, because they are just pointers into the +structure, and modification of the map invalidates them (without compiler being able to catch it). +Type is also named IteratorPtr, so that Iterator is free to use later. +Better guarantees would need future Move improvements that will allow references to be part of the struct, allowing cleaner iterator APIs. +That's why all functions returning iterators are prefixed with "internal_", to clarify nuances needed to make +sure usage is correct. +A set of inline utility methods is provided instead, to provide guaranteed valid usage to iterators. + - [Enum `Node`](#0x1_big_ordered_map_Node) - [Enum `Child`](#0x1_big_ordered_map_Child) - [Enum `IteratorPtr`](#0x1_big_ordered_map_IteratorPtr) +- [Struct `IteratorPtrWithPath`](#0x1_big_ordered_map_IteratorPtrWithPath) - [Enum `BigOrderedMap`](#0x1_big_ordered_map_BigOrderedMap) - [Constants](#@Constants_0) - [Function `new`](#0x1_big_ordered_map_new) @@ -49,11 +55,14 @@ allowing cleaner iterator APIs. - [Function `add`](#0x1_big_ordered_map_add) - [Function `upsert`](#0x1_big_ordered_map_upsert) - [Function `remove`](#0x1_big_ordered_map_remove) +- [Function `remove_or_none`](#0x1_big_ordered_map_remove_or_none) - [Function `add_all`](#0x1_big_ordered_map_add_all) - [Function `pop_front`](#0x1_big_ordered_map_pop_front) - [Function `pop_back`](#0x1_big_ordered_map_pop_back) -- [Function `lower_bound`](#0x1_big_ordered_map_lower_bound) -- [Function `find`](#0x1_big_ordered_map_find) +- [Function `internal_lower_bound`](#0x1_big_ordered_map_internal_lower_bound) +- [Function `internal_find`](#0x1_big_ordered_map_internal_find) +- [Function `internal_find_with_path`](#0x1_big_ordered_map_internal_find_with_path) +- [Function `iter_with_path_get_iter`](#0x1_big_ordered_map_iter_with_path_get_iter) - [Function `contains`](#0x1_big_ordered_map_contains) - [Function `borrow`](#0x1_big_ordered_map_borrow) - [Function `get`](#0x1_big_ordered_map_get) @@ -67,16 +76,16 @@ allowing cleaner iterator APIs. - [Function `for_each_and_clear`](#0x1_big_ordered_map_for_each_and_clear) - [Function `for_each`](#0x1_big_ordered_map_for_each) - [Function `for_each_ref`](#0x1_big_ordered_map_for_each_ref) -- [Function `for_each_ref_friend`](#0x1_big_ordered_map_for_each_ref_friend) - [Function `for_each_mut`](#0x1_big_ordered_map_for_each_mut) - [Function `destroy`](#0x1_big_ordered_map_destroy) -- [Function `new_begin_iter`](#0x1_big_ordered_map_new_begin_iter) -- [Function `new_end_iter`](#0x1_big_ordered_map_new_end_iter) +- [Function `internal_new_begin_iter`](#0x1_big_ordered_map_internal_new_begin_iter) +- [Function `internal_new_end_iter`](#0x1_big_ordered_map_internal_new_end_iter) - [Function `iter_is_begin`](#0x1_big_ordered_map_iter_is_begin) - [Function `iter_is_end`](#0x1_big_ordered_map_iter_is_end) - [Function `iter_borrow_key`](#0x1_big_ordered_map_iter_borrow_key) - [Function `iter_borrow`](#0x1_big_ordered_map_iter_borrow) - [Function `iter_borrow_mut`](#0x1_big_ordered_map_iter_borrow_mut) +- [Function `iter_remove`](#0x1_big_ordered_map_iter_remove) - [Function `iter_next`](#0x1_big_ordered_map_iter_next) - [Function `iter_prev`](#0x1_big_ordered_map_iter_prev) - [Function `for_each_leaf_node_ref`](#0x1_big_ordered_map_for_each_leaf_node_ref) @@ -117,8 +126,8 @@ allowing cleaner iterator APIs. - [Function `add_all`](#@Specification_1_add_all) - [Function `pop_front`](#@Specification_1_pop_front) - [Function `pop_back`](#@Specification_1_pop_back) - - [Function `lower_bound`](#@Specification_1_lower_bound) - - [Function `find`](#@Specification_1_find) + - [Function `internal_lower_bound`](#@Specification_1_internal_lower_bound) + - [Function `internal_find`](#@Specification_1_internal_find) - [Function `contains`](#@Specification_1_contains) - [Function `borrow`](#@Specification_1_borrow) - [Function `borrow_mut`](#@Specification_1_borrow_mut) @@ -127,8 +136,8 @@ allowing cleaner iterator APIs. - [Function `prev_key`](#@Specification_1_prev_key) - [Function `next_key`](#@Specification_1_next_key) - [Function `keys`](#@Specification_1_keys) - - [Function `new_begin_iter`](#@Specification_1_new_begin_iter) - - [Function `new_end_iter`](#@Specification_1_new_end_iter) + - [Function `internal_new_begin_iter`](#@Specification_1_internal_new_begin_iter) + - [Function `internal_new_end_iter`](#@Specification_1_internal_new_end_iter) - [Function `iter_is_begin`](#@Specification_1_iter_is_begin) - [Function `iter_is_end`](#@Specification_1_iter_is_end) - [Function `iter_borrow_key`](#@Specification_1_iter_borrow_key) @@ -349,6 +358,39 @@ TODO: Once fields can be (mutable) references, this class will be deprecated. + + + + +## Struct `IteratorPtrWithPath` + + + +
struct IteratorPtrWithPath<K> has copy, drop
+
+
+
+
+iterator: big_ordered_map::IteratorPtr<K>
+path: vector<u64>
+key.
+
+
+
+
+## Function `remove_or_none`
+
+Removes the entry from BigOrderedMap and returns the value which key maps to.
+Returns none if there is no entry for key.
+
+
+public fun remove_or_none<K: copy, drop, store, V: store>(self: &mut big_ordered_map::BigOrderedMap<K, V>, key: &K): option::Option<V>
+
+
+
+
+public fun remove_or_none<K: drop + copy + store, V: store>(self: &mut BigOrderedMap<K, V>, key: &K): Option<V> {
+ // Optimize case where only root node exists
+ // (optimizes out borrowing and path creation in `find_leaf_path`)
+ if (self.root.is_leaf) {
+ let value_option = self.root.children.remove_or_none(key);
+ if (value_option.is_some()) {
+ let Child::Leaf {
+ value,
+ } = value_option.destroy_some();
+ return option::some(value);
+ } else {
+ value_option.destroy_none();
+ return option::none();
+ }
+ };
+
+ let path_to_leaf = self.find_leaf_path(key);
+
+ if (path_to_leaf.is_empty()) {
+ option::none()
+ } else {
+ let Child::Leaf {
+ value,
+ } = self.remove_at(path_to_leaf, key);
+ option::some(value)
+ }
+}
+
+
+
+
public fun pop_front<K: drop + copy + store, V: store>(self: &mut BigOrderedMap<K, V>): (K, V) {
- let it = self.new_begin_iter();
+ let it = self.internal_new_begin_iter();
let k = *it.iter_borrow_key();
let v = self.remove(&k);
(k, v)
@@ -1123,7 +1215,7 @@ Aborts with EKEY_ALREADY_EXISTS if key already exist, or duplicate keys are pass
public fun pop_back<K: drop + copy + store, V: store>(self: &mut BigOrderedMap<K, V>): (K, V) {
- let it = self.new_end_iter().iter_prev(self);
+ let it = self.internal_new_end_iter().iter_prev(self);
let k = *it.iter_borrow_key();
let v = self.remove(&k);
(k, v)
@@ -1134,15 +1226,18 @@ Aborts with EKEY_ALREADY_EXISTS if key already exist, or duplicate keys are pass
-
+
+
+## Function `internal_lower_bound`
-## Function `lower_bound`
+Warning: Marked as internal, as it is safer to utilize provided inline functions instead.
+For direct usage of this method, check Warning at the top of the file corresponding to iterators.
Returns an iterator pointing to the first element that is greater or equal to the provided
key, or an end iterator if such element doesn't exist.
-public(friend) fun lower_bound<K: copy, drop, store, V: store>(self: &big_ordered_map::BigOrderedMap<K, V>, key: &K): big_ordered_map::IteratorPtr<K>
+public fun internal_lower_bound<K: copy, drop, store, V: store>(self: &big_ordered_map::BigOrderedMap<K, V>, key: &K): big_ordered_map::IteratorPtr<K>
@@ -1151,18 +1246,18 @@ key, or an end iterator if such element doesn't exist.
Implementation
-public(friend) fun lower_bound<K: drop + copy + store, V: store>(self: &BigOrderedMap<K, V>, key: &K): IteratorPtr<K> {
+public fun internal_lower_bound<K: drop + copy + store, V: store>(self: &BigOrderedMap<K, V>, key: &K): IteratorPtr<K> {
let leaf = self.find_leaf(key);
if (leaf == NULL_INDEX) {
- return self.new_end_iter()
+ return self.internal_new_end_iter()
};
let node = self.borrow_node(leaf);
assert!(node.is_leaf, error::invalid_state(EINTERNAL_INVARIANT_BROKEN));
- let child_lower_bound = node.children.lower_bound(key);
+ let child_lower_bound = node.children.internal_lower_bound(key);
if (child_lower_bound.iter_is_end(&node.children)) {
- self.new_end_iter()
+ self.internal_new_end_iter()
} else {
let iter_key = *child_lower_bound.iter_borrow_key(&node.children);
new_iter(leaf, child_lower_bound, iter_key)
@@ -1174,15 +1269,18 @@ key, or an end iterator if such element doesn't exist.
-
+
-## Function `find`
+## Function `internal_find`
+
+Warning: Marked as internal, as it is safer to utilize provided inline functions instead.
+For direct usage of this method, check Warning at the top of the file corresponding to iterators.
Returns an iterator pointing to the element that equals to the provided key, or an end
iterator if the key is not found.
-public(friend) fun find<K: copy, drop, store, V: store>(self: &big_ordered_map::BigOrderedMap<K, V>, key: &K): big_ordered_map::IteratorPtr<K>
+public fun internal_find<K: copy, drop, store, V: store>(self: &big_ordered_map::BigOrderedMap<K, V>, key: &K): big_ordered_map::IteratorPtr<K>
@@ -1191,20 +1289,90 @@ iterator if the key is not found.
Implementation
-public(friend) fun find<K: drop + copy + store, V: store>(self: &BigOrderedMap<K, V>, key: &K): IteratorPtr<K> {
- let lower_bound = self.lower_bound(key);
- if (lower_bound.iter_is_end(self)) {
- lower_bound
- } else if (&lower_bound.key == key) {
- lower_bound
+public fun internal_find<K: drop + copy + store, V: store>(self: &BigOrderedMap<K, V>, key: &K): IteratorPtr<K> {
+ let internal_lower_bound = self.internal_lower_bound(key);
+ if (internal_lower_bound.iter_is_end(self)) {
+ internal_lower_bound
+ } else if (&internal_lower_bound.key == key) {
+ internal_lower_bound
} else {
- self.new_end_iter()
+ self.internal_new_end_iter()
}
}
+
+
+
+
+## Function `internal_find_with_path`
+
+Warning: Marked as internal, as it is safer to utilize provided inline functions instead.
+For direct usage of this method, check Warning at the top of the file corresponding to iterators.
+
+
+public fun internal_find_with_path<K: copy, drop, store, V: store>(self: &big_ordered_map::BigOrderedMap<K, V>, key: &K): big_ordered_map::IteratorPtrWithPath<K>
+
+
+
+
+
+Implementation
+
+
+public fun internal_find_with_path<K: drop + copy + store, V: store>(self: &BigOrderedMap<K, V>, key: &K): IteratorPtrWithPath<K> {
+ let leaf_path = self.find_leaf_path(key);
+ if (leaf_path.is_empty()) {
+ return IteratorPtrWithPath { iterator: self.internal_new_end_iter(), path: vector::empty() };
+ };
+
+ let leaf = leaf_path[leaf_path.length() - 1];
+ let node = self.borrow_node(leaf);
+ assert!(node.is_leaf, error::invalid_state(EINTERNAL_INVARIANT_BROKEN));
+
+ let child_lower_bound = node.children.internal_lower_bound(key);
+ if (child_lower_bound.iter_is_end(&node.children)) {
+ IteratorPtrWithPath { iterator: self.internal_new_end_iter(), path: vector::empty() }
+ } else {
+ let iter_key = *child_lower_bound.iter_borrow_key(&node.children);
+
+ if (&iter_key == key) {
+ IteratorPtrWithPath { iterator: new_iter(leaf, child_lower_bound, iter_key), path: leaf_path }
+ } else {
+ IteratorPtrWithPath { iterator: self.internal_new_end_iter(), path: vector::empty() }
+ }
+ }
+}
+
+
+
+
+
+
+
+
+## Function `iter_with_path_get_iter`
+
+
+
+public fun iter_with_path_get_iter<K: copy, drop, store>(self: &big_ordered_map::IteratorPtrWithPath<K>): big_ordered_map::IteratorPtr<K>
+
+
+
+
+
+Implementation
+
+
+public fun iter_with_path_get_iter<K: drop + copy + store>(self: &IteratorPtrWithPath<K>): IteratorPtr<K> {
+ self.iterator
+}
+
+
+
+
@@ -1224,10 +1392,10 @@ Returns true iff the key exists in the map.
public fun contains<K: drop + copy + store, V: store>(self: &BigOrderedMap<K, V>, key: &K): bool {
- let lower_bound = self.lower_bound(key);
- if (lower_bound.iter_is_end(self)) {
+ let internal_lower_bound = self.internal_lower_bound(key);
+ if (internal_lower_bound.iter_is_end(self)) {
false
- } else if (&lower_bound.key == key) {
+ } else if (&internal_lower_bound.key == key) {
true
} else {
false
@@ -1256,7 +1424,7 @@ Returns a reference to the element with its key, aborts if the key is not found.
public fun borrow<K: drop + copy + store, V: store>(self: &BigOrderedMap<K, V>, key: &K): &V {
- let iter = self.find(key);
+ let iter = self.internal_find(key);
assert!(!iter.iter_is_end(self), error::invalid_argument(EKEY_NOT_FOUND));
iter.iter_borrow(self)
@@ -1283,7 +1451,7 @@ Returns a reference to the element with its key, aborts if the key is not found.
public fun get<K: drop + copy + store, V: copy + store>(self: &BigOrderedMap<K, V>, key: &K): Option<V> {
- let iter = self.find(key);
+ let iter = self.internal_find(key);
if (iter.iter_is_end(self)) {
option::none()
} else {
@@ -1316,7 +1484,7 @@ In case of variable size, use either borrow, copypublic fun borrow_mut<K: drop + copy + store, V: store>(self: &mut BigOrderedMap<K, V>, key: &K): &mut V {
- let iter = self.find(key);
+ let iter = self.internal_find(key);
assert!(!iter.iter_is_end(self), error::invalid_argument(EKEY_NOT_FOUND));
iter.iter_borrow_mut(self)
}
@@ -1342,7 +1510,7 @@ In case of variable size, use either borrow, copypublic fun borrow_front<K: drop + copy + store, V: store>(self: &BigOrderedMap<K, V>): (K, &V) {
- let it = self.new_begin_iter();
+ let it = self.internal_new_begin_iter();
let key = *it.iter_borrow_key();
(key, it.iter_borrow(self))
}
@@ -1368,7 +1536,7 @@ In case of variable size, use either borrow, copypublic fun borrow_back<K: drop + copy + store, V: store>(self: &BigOrderedMap<K, V>): (K, &V) {
- let it = self.new_end_iter().iter_prev(self);
+ let it = self.internal_new_end_iter().iter_prev(self);
let key = *it.iter_borrow_key();
(key, it.iter_borrow(self))
}
@@ -1394,7 +1562,7 @@ In case of variable size, use either borrow, copypublic fun prev_key<K: drop + copy + store, V: store>(self: &BigOrderedMap<K, V>, key: &K): Option<K> {
- let it = self.lower_bound(key);
+ let it = self.internal_lower_bound(key);
if (it.iter_is_begin(self)) {
option::none()
} else {
@@ -1423,7 +1591,7 @@ In case of variable size, use either borrow, copypublic fun next_key<K: drop + copy + store, V: store>(self: &BigOrderedMap<K, V>, key: &K): Option<K> {
- let it = self.lower_bound(key);
+ let it = self.internal_lower_bound(key);
if (it.iter_is_end(self)) {
option::none()
} else {
@@ -1466,8 +1634,8 @@ Disclaimer: This function may be costly as the BigOrderedMap may be huge in size
public fun to_ordered_map<K: drop + copy + store, V: copy + store>(self: &BigOrderedMap<K, V>): OrderedMap<K, V> {
let result = ordered_map::new();
- self.for_each_ref_friend(|k, v| {
- result.new_end_iter().iter_add(&mut result, *k, *v);
+ self.for_each_ref(|k, v| {
+ result.internal_new_end_iter().iter_add(&mut result, *k, *v);
});
result
}
@@ -1498,7 +1666,7 @@ use iterartor or next_key/prev_key to iterate over across portion of the map.
public fun keys<K: store + copy + drop, V: store + copy>(self: &BigOrderedMap<K, V>): vector<K> {
let result = vector[];
- self.for_each_ref_friend(|k, _v| {
+ self.for_each_ref(|k, _v| {
result.push_back(*k);
});
result
@@ -1579,9 +1747,6 @@ to O(n).
Apply the function to a reference of each element in the vector.
-Current implementation is O(n * log(n)). After function values will be optimized
-to O(n).
-
public fun for_each_ref<K: copy, drop, store, V: store>(self: &big_ordered_map::BigOrderedMap<K, V>, f: |&K, &V|)
@@ -1593,58 +1758,15 @@ to O(n).
public inline fun for_each_ref<K: drop + copy + store, V: store>(self: &BigOrderedMap<K, V>, f: |&K, &V|) {
- // This implementation is innefficient: O(log(n)) for next_key / borrow lookups every time,
- // but is the only one available through the public API.
- if (!self.is_empty()) {
- let (k, v) = self.borrow_front();
- f(&k, v);
-
- let cur_k = self.next_key(&k);
- while (cur_k.is_some()) {
- let k = cur_k.destroy_some();
- f(&k, self.borrow(&k));
-
- cur_k = self.next_key(&k);
- };
- };
-
- // TODO use this more efficient implementation when function values are enabled.
- // self.for_each_leaf_node_ref(|node| {
- // node.children.for_each_ref(|k: &K, v: &Child<V>| {
- // f(k, &v.value);
- // });
- // })
-}
-
-
-
-
-
-
-
-
-## Function `for_each_ref_friend`
-
-
-
-public(friend) fun for_each_ref_friend<K: copy, drop, store, V: store>(self: &big_ordered_map::BigOrderedMap<K, V>, f: |&K, &V|)
-
-
-
-
-
-Implementation
-
-
-public(friend) inline fun for_each_ref_friend<K: drop + copy + store, V: store>(self: &BigOrderedMap<K, V>, f: |&K, &V|) {
- let iter = self.new_begin_iter();
+ let iter = self.internal_new_begin_iter();
while (!iter.iter_is_end(self)) {
f(iter.iter_borrow_key(), iter.iter_borrow(self));
iter = iter.iter_next(self);
};
+ // TODO use this more efficient implementation when function values are enabled.
// self.for_each_leaf_node_ref(|node| {
- // node.children.for_each_ref_friend(|k: &K, v: &Child<V>| {
+ // node.children.for_each_ref(|k: &K, v: &Child<V>| {
// f(k, &v.value);
// });
// })
@@ -1661,9 +1783,6 @@ to O(n).
Apply the function to a mutable reference of each key-value pair in the map.
-Current implementation is O(n * log(n)). After function values will be optimized
-to O(n).
-
public fun for_each_mut<K: copy, drop, store, V: store>(self: &mut big_ordered_map::BigOrderedMap<K, V>, f: |&K, &mut V|)
@@ -1675,31 +1794,12 @@ to O(n).
public inline fun for_each_mut<K: copy + drop + store, V: store>(self: &mut BigOrderedMap<K, V>, f: |&K, &mut V|) {
- // This implementation is innefficient: O(log(n)) for next_key / borrow lookups every time,
- // but is the only one available through the public API.
- if (!self.is_empty()) {
- let (k, _v) = self.borrow_front();
-
- let done = false;
- while (!done) {
- f(&k, self.borrow_mut(&k));
-
- let cur_k = self.next_key(&k);
- if (cur_k.is_some()) {
- k = cur_k.destroy_some();
- } else {
- done = true;
- }
- };
- };
-
- // TODO: if we make iterator api public update to:
- // let iter = self.new_begin_iter();
- // while (!iter.iter_is_end(self)) {
- // let key = *iter.iter_borrow_key(self);
- // f(key, iter.iter_borrow_mut(self));
- // iter = iter.iter_next(self);
- // }
+ let iter = self.internal_new_begin_iter();
+ while (!iter.iter_is_end(self)) {
+ let key = *iter.iter_borrow_key();
+ f(&key, iter.iter_borrow_mut(self));
+ iter = iter.iter_next(self);
+ }
}
@@ -1737,14 +1837,17 @@ to O(n).
-
+
-## Function `new_begin_iter`
+## Function `internal_new_begin_iter`
+
+Warning: Marked as internal, as it is safer to utilize provided inline functions instead.
+For direct usage of this method, check Warning at the top of the file corresponding to iterators.
Returns the begin iterator.
-public(friend) fun new_begin_iter<K: copy, store, V: store>(self: &big_ordered_map::BigOrderedMap<K, V>): big_ordered_map::IteratorPtr<K>
+public fun internal_new_begin_iter<K: copy, store, V: store>(self: &big_ordered_map::BigOrderedMap<K, V>): big_ordered_map::IteratorPtr<K>
@@ -1753,14 +1856,14 @@ Returns the begin iterator.
Implementation
-public(friend) fun new_begin_iter<K: copy + store, V: store>(self: &BigOrderedMap<K, V>): IteratorPtr<K> {
+public fun internal_new_begin_iter<K: copy + store, V: store>(self: &BigOrderedMap<K, V>): IteratorPtr<K> {
if (self.is_empty()) {
return IteratorPtr::End;
};
let node = self.borrow_node(self.min_leaf_index);
assert!(!node.children.is_empty(), error::invalid_state(EINTERNAL_INVARIANT_BROKEN));
- let begin_child_iter = node.children.new_begin_iter();
+ let begin_child_iter = node.children.internal_new_begin_iter();
let begin_child_key = *begin_child_iter.iter_borrow_key(&node.children);
new_iter(self.min_leaf_index, begin_child_iter, begin_child_key)
}
@@ -1770,14 +1873,17 @@ Returns the begin iterator.
-
+
+
+## Function `internal_new_end_iter`
-## Function `new_end_iter`
+Warning: Marked as internal, as it is safer to utilize provided inline functions instead.
+For direct usage of this method, check Warning at the top of the file corresponding to iterators.
Returns the end iterator.
-public(friend) fun new_end_iter<K: copy, store, V: store>(self: &big_ordered_map::BigOrderedMap<K, V>): big_ordered_map::IteratorPtr<K>
+public fun internal_new_end_iter<K: copy, store, V: store>(self: &big_ordered_map::BigOrderedMap<K, V>): big_ordered_map::IteratorPtr<K>
@@ -1786,7 +1892,7 @@ Returns the end iterator.
Implementation
-public(friend) fun new_end_iter<K: copy + store, V: store>(self: &BigOrderedMap<K, V>): IteratorPtr<K> {
+public fun internal_new_end_iter<K: copy + store, V: store>(self: &BigOrderedMap<K, V>): IteratorPtr<K> {
IteratorPtr::End
}
@@ -1801,7 +1907,7 @@ Returns the end iterator.
-public(friend) fun iter_is_begin<K: store, V: store>(self: &big_ordered_map::IteratorPtr<K>, map: &big_ordered_map::BigOrderedMap<K, V>): bool
+public fun iter_is_begin<K: store, V: store>(self: &big_ordered_map::IteratorPtr<K>, map: &big_ordered_map::BigOrderedMap<K, V>): bool
@@ -1810,7 +1916,7 @@ Returns the end iterator.
Implementation
-public(friend) fun iter_is_begin<K: store, V: store>(self: &IteratorPtr<K>, map: &BigOrderedMap<K, V>): bool {
+public fun iter_is_begin<K: store, V: store>(self: &IteratorPtr<K>, map: &BigOrderedMap<K, V>): bool {
if (self is IteratorPtr::End<K>) {
map.is_empty()
} else {
@@ -1829,7 +1935,7 @@ Returns the end iterator.
-public(friend) fun iter_is_end<K: store, V: store>(self: &big_ordered_map::IteratorPtr<K>, _map: &big_ordered_map::BigOrderedMap<K, V>): bool
+public fun iter_is_end<K: store, V: store>(self: &big_ordered_map::IteratorPtr<K>, _map: &big_ordered_map::BigOrderedMap<K, V>): bool
@@ -1838,7 +1944,7 @@ Returns the end iterator.
Implementation
-public(friend) fun iter_is_end<K: store, V: store>(self: &IteratorPtr<K>, _map: &BigOrderedMap<K, V>): bool {
+public fun iter_is_end<K: store, V: store>(self: &IteratorPtr<K>, _map: &BigOrderedMap<K, V>): bool {
self is IteratorPtr::End<K>
}
@@ -1856,7 +1962,7 @@ Aborts with EITER_OUT_OF_BOUNDS if iterator is pointing to the end.
Note: Requires that the map is not changed after the input iterator is generated.
-public(friend) fun iter_borrow_key<K>(self: &big_ordered_map::IteratorPtr<K>): &K
+public fun iter_borrow_key<K>(self: &big_ordered_map::IteratorPtr<K>): &K
@@ -1865,7 +1971,7 @@ Note: Requires that the map is not changed after the input iterator is generated
Implementation
-public(friend) fun iter_borrow_key<K>(self: &IteratorPtr<K>): &K {
+public fun iter_borrow_key<K>(self: &IteratorPtr<K>): &K {
assert!(!(self is IteratorPtr::End<K>), error::invalid_argument(EITER_OUT_OF_BOUNDS));
&self.key
}
@@ -1884,7 +1990,7 @@ Aborts with EITER_OUT_OF_BOUNDS if iterator is pointing to the end.
Note: Requires that the map is not changed after the input iterator is generated.
-public(friend) fun iter_borrow<K: drop, store, V: store>(self: big_ordered_map::IteratorPtr<K>, map: &big_ordered_map::BigOrderedMap<K, V>): &V
+public fun iter_borrow<K: drop, store, V: store>(self: big_ordered_map::IteratorPtr<K>, map: &big_ordered_map::BigOrderedMap<K, V>): &V
@@ -1893,7 +1999,7 @@ Note: Requires that the map is not changed after the input iterator is generated
Implementation
-public(friend) fun iter_borrow<K: drop + store, V: store>(self: IteratorPtr<K>, map: &BigOrderedMap<K, V>): &V {
+public fun iter_borrow<K: drop + store, V: store>(self: IteratorPtr<K>, map: &BigOrderedMap<K, V>): &V {
assert!(!self.iter_is_end(map), error::invalid_argument(EITER_OUT_OF_BOUNDS));
let IteratorPtr::Some { node_index, child_iter, key: _ } = self;
let children = &map.borrow_node(node_index).children;
@@ -1918,7 +2024,7 @@ In case of variable size, use either borrow, copypublic(friend) fun iter_borrow_mut<K: drop, store, V: store>(self: big_ordered_map::IteratorPtr<K>, map: &mut big_ordered_map::BigOrderedMap<K, V>): &mut V
+public fun iter_borrow_mut<K: drop, store, V: store>(self: big_ordered_map::IteratorPtr<K>, map: &mut big_ordered_map::BigOrderedMap<K, V>): &mut V
@@ -1927,7 +2033,7 @@ Note: Requires that the map is not changed after the input iterator is generated
Implementation
-public(friend) fun iter_borrow_mut<K: drop + store, V: store>(self: IteratorPtr<K>, map: &mut BigOrderedMap<K, V>): &mut V {
+public fun iter_borrow_mut<K: drop + store, V: store>(self: IteratorPtr<K>, map: &mut BigOrderedMap<K, V>): &mut V {
assert!(map.constant_kv_size || bcs::constant_serialized_size<V>().is_some(), error::invalid_argument(EBORROW_MUT_REQUIRES_CONSTANT_VALUE_SIZE));
assert!(!self.iter_is_end(map), error::invalid_argument(EITER_OUT_OF_BOUNDS));
let IteratorPtr::Some { node_index, child_iter, key: _ } = self;
@@ -1938,6 +2044,50 @@ Note: Requires that the map is not changed after the input iterator is generated
+
+
+
+
+## Function `iter_remove`
+
+Removes the entry from BigOrderedMap and returns the value which key maps to.
+Aborts if there is no entry for key.
+
+
+public fun iter_remove<K: copy, drop, store, V: store>(self: big_ordered_map::IteratorPtrWithPath<K>, map: &mut big_ordered_map::BigOrderedMap<K, V>): V
+
+
+
+
+
+Implementation
+
+
+public fun iter_remove<K: drop + copy + store, V: store>(self: IteratorPtrWithPath<K>, map: &mut BigOrderedMap<K, V>): V {
+ let IteratorPtrWithPath { iterator: iter, path: path_to_leaf } = self;
+ assert!(!iter.iter_is_end(map), error::invalid_argument(EITER_OUT_OF_BOUNDS));
+ let IteratorPtr::Some { node_index: _, child_iter, key } = iter;
+
+ // Optimize case where only root node exists
+ // (optimizes out borrowing and path creation in `find_leaf_path`)
+ if (map.root.is_leaf) {
+ let Child::Leaf {
+ value,
+ } = child_iter.iter_remove(&mut map.root.children);
+ return value;
+ };
+
+ assert!(!path_to_leaf.is_empty(), error::invalid_argument(EKEY_NOT_FOUND));
+
+ let Child::Leaf {
+ value,
+ } = map.remove_at(path_to_leaf, &key);
+ value
+}
+
+
+
+
@@ -1949,7 +2099,7 @@ Aborts with EITER_OUT_OF_BOUNDS if iterator is pointing to the end.
Requires the map is not changed after the input iterator is generated.
-public(friend) fun iter_next<K: copy, drop, store, V: store>(self: big_ordered_map::IteratorPtr<K>, map: &big_ordered_map::BigOrderedMap<K, V>): big_ordered_map::IteratorPtr<K>
+public fun iter_next<K: copy, drop, store, V: store>(self: big_ordered_map::IteratorPtr<K>, map: &big_ordered_map::BigOrderedMap<K, V>): big_ordered_map::IteratorPtr<K>
@@ -1958,7 +2108,7 @@ Requires the map is not changed after the input iterator is generated.
Implementation
-public(friend) fun iter_next<K: drop + copy + store, V: store>(self: IteratorPtr<K>, map: &BigOrderedMap<K, V>): IteratorPtr<K> {
+public fun iter_next<K: drop + copy + store, V: store>(self: IteratorPtr<K>, map: &BigOrderedMap<K, V>): IteratorPtr<K> {
assert!(!(self is IteratorPtr::End<K>), error::invalid_argument(EITER_OUT_OF_BOUNDS));
let node_index = self.node_index;
@@ -1976,13 +2126,13 @@ Requires the map is not changed after the input iterator is generated.
if (next_index != NULL_INDEX) {
let next_node = map.borrow_node(next_index);
- let child_iter = next_node.children.new_begin_iter();
+ let child_iter = next_node.children.internal_new_begin_iter();
assert!(!child_iter.iter_is_end(&next_node.children), error::invalid_state(EINTERNAL_INVARIANT_BROKEN));
let iter_key = *child_iter.iter_borrow_key(&next_node.children);
return new_iter(next_index, child_iter, iter_key);
};
- map.new_end_iter()
+ map.internal_new_end_iter()
}
@@ -1999,7 +2149,7 @@ Aborts with EITER_OUT_OF_BOUNDS if iterator is pointing to the beginning.
Requires the map is not changed after the input iterator is generated.
-public(friend) fun iter_prev<K: copy, drop, store, V: store>(self: big_ordered_map::IteratorPtr<K>, map: &big_ordered_map::BigOrderedMap<K, V>): big_ordered_map::IteratorPtr<K>
+public fun iter_prev<K: copy, drop, store, V: store>(self: big_ordered_map::IteratorPtr<K>, map: &big_ordered_map::BigOrderedMap<K, V>): big_ordered_map::IteratorPtr<K>
@@ -2008,7 +2158,7 @@ Requires the map is not changed after the input iterator is generated.
Implementation
-public(friend) fun iter_prev<K: drop + copy + store, V: store>(self: IteratorPtr<K>, map: &BigOrderedMap<K, V>): IteratorPtr<K> {
+public fun iter_prev<K: drop + copy + store, V: store>(self: IteratorPtr<K>, map: &BigOrderedMap<K, V>): IteratorPtr<K> {
let prev_index = if (self is IteratorPtr::End<K>) {
map.max_leaf_index
} else {
@@ -2030,7 +2180,7 @@ Requires the map is not changed after the input iterator is generated.
let prev_node = map.borrow_node(prev_index);
let prev_children = &prev_node.children;
- let child_iter = prev_children.new_end_iter().iter_prev(prev_children);
+ let child_iter = prev_children.internal_new_end_iter().iter_prev(prev_children);
let iter_key = *child_iter.iter_borrow_key(prev_children);
new_iter(prev_index, child_iter, iter_key)
}
@@ -2177,7 +2327,7 @@ Borrow a node mutably, given an index. Works for both root (i.e. inline) node an
if (current_node.is_leaf) {
break;
};
- let last_value = current_node.children.new_end_iter().iter_prev(¤t_node.children).iter_remove(&mut current_node.children);
+ let last_value = current_node.children.internal_new_end_iter().iter_prev(¤t_node.children).iter_remove(&mut current_node.children);
current = last_value.node_index.stored_to_index();
current_node.children.add(key, last_value);
};
@@ -2518,7 +2668,7 @@ return NULL_INDEX if key is larger than any key currently stored in
return current;
};
let children = &node.children;
- let child_iter = children.lower_bound(key);
+ let child_iter = children.internal_lower_bound(key);
if (child_iter.iter_is_end(children)) {
return NULL_INDEX;
} else {
@@ -2563,7 +2713,7 @@ Returns empty path if key is larger than any key currently stored i
return vec;
};
let children = &node.children;
- let child_iter = children.lower_bound(key);
+ let child_iter = children.internal_lower_bound(key);
if (child_iter.iter_is_end(children)) {
return vector::empty();
} else {
@@ -2709,7 +2859,7 @@ If allow_overwrite is not set, function will abort if keywith `key` already exists, we either need to replace or abort.
- let iter = children.find(&key);
+ let iter = children.internal_find(&key);
if (!iter.iter_is_end(children)) {
assert!(node.is_leaf, error::invalid_state(EINTERNAL_INVARIANT_BROKEN));
assert!(allow_overwrite, error::invalid_argument(EKEY_ALREADY_EXISTS));
@@ -2734,7 +2884,7 @@ If allow_overwrite is not set, function will abort if keylet max_key = {
let root_children = &self.root.children;
- let max_key = *root_children.new_end_iter().iter_prev(root_children).iter_borrow_key(root_children);
+ let max_key = *root_children.internal_new_end_iter().iter_prev(root_children).iter_borrow_key(root_children);
// need to check if key is largest, as invariant is that "parent's pointers" have been updated,
// but key itself can be larger than all previous ones.
if (cmp::compare(&max_key, &key).is_lt()) {
@@ -2828,7 +2978,7 @@ If allow_overwrite is not set, function will abort if keylet max_left_key = *left_children.new_end_iter().iter_prev(left_children).iter_borrow_key(left_children);
+ let max_left_key = *left_children.internal_new_end_iter().iter_prev(left_children).iter_borrow_key(left_children);
self.nodes.fill_reserved_slot(left_node_reserved_slot, left_node);
self.nodes.fill_reserved_slot(right_node_reserved_slot, right_node);
@@ -2867,7 +3017,7 @@ Given a path to node (excluding the node itself), which is currently stored unde
children.replace_key_inplace(old_key, new_key);
// If we were not updating the largest child, we don't need to continue.
- if (children.new_end_iter().iter_prev(children).iter_borrow_key(children) != &new_key) {
+ if (children.internal_new_end_iter().iter_prev(children).iter_borrow_key(children) != &new_key) {
return
};
}
@@ -2919,7 +3069,7 @@ Given a path to node (excluding the node itself), which is currently stored unde
let Child::Inner {
node_index: inner_child_index,
- } = children.new_end_iter().iter_prev(children).iter_remove(children);
+ } = children.internal_new_end_iter().iter_prev(children).iter_remove(children);
let inner_child = self.nodes.remove(inner_child_index);
if (inner_child.is_leaf) {
@@ -2943,7 +3093,7 @@ Given a path to node (excluding the node itself), which is currently stored unde
// See if the node is big enough, or we need to merge it with another node on this level.
let big_enough = degree * 2 >= max_degree;
- let new_max_key = *children.new_end_iter().iter_prev(children).iter_borrow_key(children);
+ let new_max_key = *children.internal_new_end_iter().iter_prev(children).iter_borrow_key(children);
// See if max key was updated for the current node, and if so - update it on the path.
let max_key_updated = cmp::compare(&new_max_key, key).is_lt();
@@ -2979,7 +3129,7 @@ Given a path to node (excluding the node itself), which is currently stored unde
// If we are the largest node from the parent, we merge with the `prev`
// (which is then guaranteed to have the same parent, as any node has >1 children),
// otherwise we merge with `next`.
- if (parent_children.new_end_iter().iter_prev(parent_children).iter_borrow(parent_children).node_index.stored_to_index() == node_index) {
+ if (parent_children.internal_new_end_iter().iter_prev(parent_children).iter_borrow(parent_children).node_index.stored_to_index() == node_index) {
prev
} else {
next
@@ -2996,25 +3146,25 @@ Given a path to node (excluding the node itself), which is currently stored unde
// The sibling node has enough elements, we can just borrow an element from the sibling node.
if (sibling_index == next) {
// if sibling is the node with larger keys, we remove a child from the start
- let old_max_key = *children.new_end_iter().iter_prev(children).iter_borrow_key(children);
- let sibling_begin_iter = sibling_children.new_begin_iter();
+ let old_max_key = *children.internal_new_end_iter().iter_prev(children).iter_borrow_key(children);
+ let sibling_begin_iter = sibling_children.internal_new_begin_iter();
let borrowed_max_key = *sibling_begin_iter.iter_borrow_key(sibling_children);
- let borrowed_element = sibling_begin_iter.iter_remove(sibling_children);
+ let borrowed_element = sibling_begin_iter.iter_remove(sibling_children);
- children.new_end_iter().iter_add(children, borrowed_max_key, borrowed_element);
+ children.internal_new_end_iter().iter_add(children, borrowed_max_key, borrowed_element);
// max_key of the current node changed, so update
self.update_key(path_to_node, &old_max_key, borrowed_max_key);
} else {
// if sibling is the node with smaller keys, we remove a child from the end
- let sibling_end_iter = sibling_children.new_end_iter().iter_prev(sibling_children);
+ let sibling_end_iter = sibling_children.internal_new_end_iter().iter_prev(sibling_children);
let borrowed_max_key = *sibling_end_iter.iter_borrow_key(sibling_children);
- let borrowed_element = sibling_end_iter.iter_remove(sibling_children);
+ let borrowed_element = sibling_end_iter.iter_remove(sibling_children);
children.add(borrowed_max_key, borrowed_element);
// max_key of the sibling node changed, so update
- self.update_key(path_to_node, &borrowed_max_key, *sibling_children.new_end_iter().iter_prev(sibling_children).iter_borrow_key(sibling_children));
+ self.update_key(path_to_node, &borrowed_max_key, *sibling_children.internal_new_end_iter().iter_prev(sibling_children).iter_borrow_key(sibling_children));
};
self.nodes.fill_reserved_slot(node_slot, node);
@@ -3028,7 +3178,7 @@ Given a path to node (excluding the node itself), which is currently stored unde
let (key_to_remove, reserved_slot_to_remove) = if (sibling_index == next) {
// destroying larger sibling node, keeping sibling_slot.
let Node::V1 { children: sibling_children, is_leaf: _, prev: _, next: sibling_next } = sibling_node;
- let key_to_remove = *children.new_end_iter().iter_prev(children).iter_borrow_key(children);
+ let key_to_remove = *children.internal_new_end_iter().iter_prev(children).iter_borrow_key(children);
children.append_disjoint(sibling_children);
node.next = sibling_next;
@@ -3053,7 +3203,7 @@ Given a path to node (excluding the node itself), which is currently stored unde
} else {
// destroying larger current node, keeping node_slot
let Node::V1 { children: node_children, is_leaf: _, prev: _, next: node_next } = node;
- let key_to_remove = *sibling_children.new_end_iter().iter_prev(sibling_children).iter_borrow_key(sibling_children);
+ let key_to_remove = *sibling_children.internal_new_end_iter().iter_prev(sibling_children).iter_borrow_key(sibling_children);
sibling_children.append_disjoint(node_children);
sibling_node.next = node_next;
@@ -3508,12 +3658,12 @@ Given a path to node (excluding the node itself), which is currently stored unde
-
+
-### Function `lower_bound`
+### Function `internal_lower_bound`
-public(friend) fun lower_bound<K: copy, drop, store, V: store>(self: &big_ordered_map::BigOrderedMap<K, V>, key: &K): big_ordered_map::IteratorPtr<K>
+public fun internal_lower_bound<K: copy, drop, store, V: store>(self: &big_ordered_map::BigOrderedMap<K, V>, key: &K): big_ordered_map::IteratorPtr<K>
@@ -3525,12 +3675,12 @@ Given a path to node (excluding the node itself), which is currently stored unde
-
+
-### Function `find`
+### Function `internal_find`
-public(friend) fun find<K: copy, drop, store, V: store>(self: &big_ordered_map::BigOrderedMap<K, V>, key: &K): big_ordered_map::IteratorPtr<K>
+public fun internal_find<K: copy, drop, store, V: store>(self: &big_ordered_map::BigOrderedMap<K, V>, key: &K): big_ordered_map::IteratorPtr<K>
@@ -3702,12 +3852,12 @@ std::cmp::compare(key, k) == std::cmp::Ordering::Greater);
-
+
-### Function `new_begin_iter`
+### Function `internal_new_begin_iter`
-public(friend) fun new_begin_iter<K: copy, store, V: store>(self: &big_ordered_map::BigOrderedMap<K, V>): big_ordered_map::IteratorPtr<K>
+public fun internal_new_begin_iter<K: copy, store, V: store>(self: &big_ordered_map::BigOrderedMap<K, V>): big_ordered_map::IteratorPtr<K>
@@ -3719,12 +3869,12 @@ std::cmp::compare(key, k) == std::cmp::Ordering::Greater);
-
+
-### Function `new_end_iter`
+### Function `internal_new_end_iter`
-public(friend) fun new_end_iter<K: copy, store, V: store>(self: &big_ordered_map::BigOrderedMap<K, V>): big_ordered_map::IteratorPtr<K>
+public fun internal_new_end_iter<K: copy, store, V: store>(self: &big_ordered_map::BigOrderedMap<K, V>): big_ordered_map::IteratorPtr<K>
@@ -3741,7 +3891,7 @@ std::cmp::compare(key, k) == std::cmp::Ordering::Greater);
### Function `iter_is_begin`
-public(friend) fun iter_is_begin<K: store, V: store>(self: &big_ordered_map::IteratorPtr<K>, map: &big_ordered_map::BigOrderedMap<K, V>): bool
+public fun iter_is_begin<K: store, V: store>(self: &big_ordered_map::IteratorPtr<K>, map: &big_ordered_map::BigOrderedMap<K, V>): bool
@@ -3758,7 +3908,7 @@ std::cmp::compare(key, k) == std::cmp::Ordering::Greater);
### Function `iter_is_end`
-public(friend) fun iter_is_end<K: store, V: store>(self: &big_ordered_map::IteratorPtr<K>, _map: &big_ordered_map::BigOrderedMap<K, V>): bool
+public fun iter_is_end<K: store, V: store>(self: &big_ordered_map::IteratorPtr<K>, _map: &big_ordered_map::BigOrderedMap<K, V>): bool
@@ -3775,7 +3925,7 @@ std::cmp::compare(key, k) == std::cmp::Ordering::Greater);
### Function `iter_borrow_key`
-public(friend) fun iter_borrow_key<K>(self: &big_ordered_map::IteratorPtr<K>): &K
+public fun iter_borrow_key<K>(self: &big_ordered_map::IteratorPtr<K>): &K
@@ -3792,7 +3942,7 @@ std::cmp::compare(key, k) == std::cmp::Ordering::Greater);
### Function `iter_borrow`
-public(friend) fun iter_borrow<K: drop, store, V: store>(self: big_ordered_map::IteratorPtr<K>, map: &big_ordered_map::BigOrderedMap<K, V>): &V
+public fun iter_borrow<K: drop, store, V: store>(self: big_ordered_map::IteratorPtr<K>, map: &big_ordered_map::BigOrderedMap<K, V>): &V
@@ -3809,7 +3959,7 @@ std::cmp::compare(key, k) == std::cmp::Ordering::Greater);
### Function `iter_borrow_mut`
-public(friend) fun iter_borrow_mut<K: drop, store, V: store>(self: big_ordered_map::IteratorPtr<K>, map: &mut big_ordered_map::BigOrderedMap<K, V>): &mut V
+public fun iter_borrow_mut<K: drop, store, V: store>(self: big_ordered_map::IteratorPtr<K>, map: &mut big_ordered_map::BigOrderedMap<K, V>): &mut V
@@ -3826,7 +3976,7 @@ std::cmp::compare(key, k) == std::cmp::Ordering::Greater);
### Function `iter_next`
-public(friend) fun iter_next<K: copy, drop, store, V: store>(self: big_ordered_map::IteratorPtr<K>, map: &big_ordered_map::BigOrderedMap<K, V>): big_ordered_map::IteratorPtr<K>
+public fun iter_next<K: copy, drop, store, V: store>(self: big_ordered_map::IteratorPtr<K>, map: &big_ordered_map::BigOrderedMap<K, V>): big_ordered_map::IteratorPtr<K>
@@ -3843,7 +3993,7 @@ std::cmp::compare(key, k) == std::cmp::Ordering::Greater);
### Function `iter_prev`
-public(friend) fun iter_prev<K: copy, drop, store, V: store>(self: big_ordered_map::IteratorPtr<K>, map: &big_ordered_map::BigOrderedMap<K, V>): big_ordered_map::IteratorPtr<K>
+public fun iter_prev<K: copy, drop, store, V: store>(self: big_ordered_map::IteratorPtr<K>, map: &big_ordered_map::BigOrderedMap<K, V>): big_ordered_map::IteratorPtr<K>
diff --git a/aptos-move/framework/aptos-framework/doc/ordered_map.md b/aptos-move/framework/aptos-framework/doc/ordered_map.md
index f8845f1dd9c0d..842cddd962aa1 100644
--- a/aptos-move/framework/aptos-framework/doc/ordered_map.md
+++ b/aptos-move/framework/aptos-framework/doc/ordered_map.md
@@ -22,11 +22,16 @@ All methods that start with iter_*, operate with IteratorPtr being selfkey doesn't exist.
+
+
+
+
+## Function `remove_or_none`
+
+Remove a key/value pair from the map.
+Returns none if key doesn't exist.
+
+
+public fun remove_or_none<K: drop, V>(self: &mut ordered_map::OrderedMap<K, V>, key: &K): option::Option<V>
+
+
+
+
+
+Implementation
+
+
+public fun remove_or_none<K: drop, V>(self: &mut OrderedMap<K, V>, key: &K): Option<V> {
+ let len = self.entries.length();
+ let index = binary_search(key, &self.entries, 0, len);
+ if (index < len && key == &self.entries[index].key) {
+ let Entry { key: _, value } = self.entries.remove(index);
+ option::some(value)
+ } else {
+ option::none()
+ }
+}
+
+
+
+
@@ -534,7 +573,7 @@ Returns whether map contains a given key.
public fun contains<K, V>(self: &OrderedMap<K, V>, key: &K): bool {
- !self.find(key).iter_is_end(self)
+ !self.internal_find(key).iter_is_end(self)
}
@@ -558,7 +597,7 @@ Returns whether map contains a given key.
public fun borrow<K, V>(self: &OrderedMap<K, V>, key: &K): &V {
- self.find(key).iter_borrow(self)
+ self.internal_find(key).iter_borrow(self)
}
@@ -582,7 +621,7 @@ Returns whether map contains a given key.
public fun borrow_mut<K, V>(self: &mut OrderedMap<K, V>, key: &K): &mut V {
- self.find(key).iter_borrow_mut(self)
+ self.internal_find(key).iter_borrow_mut(self)
}
@@ -985,7 +1024,7 @@ After the call, the original map will be left containing the elements [0, at).
public fun prev_key<K: copy, V>(self: &OrderedMap<K, V>, key: &K): Option<K> {
- let it = self.lower_bound(key);
+ let it = self.internal_lower_bound(key);
if (it.iter_is_begin(self)) {
option::none()
} else {
@@ -1014,7 +1053,7 @@ After the call, the original map will be left containing the elements [0, at).
public fun next_key<K: copy, V>(self: &OrderedMap<K, V>, key: &K): Option<K> {
- let it = self.lower_bound(key);
+ let it = self.internal_lower_bound(key);
if (it.iter_is_end(self)) {
option::none()
} else {
@@ -1037,15 +1076,18 @@ After the call, the original map will be left containing the elements [0, at).
-
+
+
+## Function `internal_lower_bound`
-## Function `lower_bound`
+Warning: Marked as internal, as it is safer to utilize provided inline functions instead.
+For direct usage of this method, check Warning at the top of the file corresponding to iterators.
Returns an iterator pointing to the first element that is greater or equal to the provided
key, or an end iterator if such element doesn't exist.
-public(friend) fun lower_bound<K, V>(self: &ordered_map::OrderedMap<K, V>, key: &K): ordered_map::IteratorPtr
+public fun internal_lower_bound<K, V>(self: &ordered_map::OrderedMap<K, V>, key: &K): ordered_map::IteratorPtr
@@ -1054,13 +1096,13 @@ key, or an end iterator if such element doesn't exist.
Implementation
-public(friend) fun lower_bound<K, V>(self: &OrderedMap<K, V>, key: &K): IteratorPtr {
+public fun internal_lower_bound<K, V>(self: &OrderedMap<K, V>, key: &K): IteratorPtr {
let entries = &self.entries;
let len = entries.length();
let index = binary_search(key, entries, 0, len);
if (index == len) {
- self.new_end_iter()
+ self.internal_new_end_iter()
} else {
new_iter(index)
}
@@ -1071,15 +1113,18 @@ key, or an end iterator if such element doesn't exist.
-
+
+
+## Function `internal_find`
-## Function `find`
+Warning: Marked as internal, as it is safer to utilize provided inline functions instead.
+For direct usage of this method, check Warning at the top of the file corresponding to iterators.
Returns an iterator pointing to the element that equals to the provided key, or an end
iterator if the key is not found.
-public(friend) fun find<K, V>(self: &ordered_map::OrderedMap<K, V>, key: &K): ordered_map::IteratorPtr
+public fun internal_find<K, V>(self: &ordered_map::OrderedMap<K, V>, key: &K): ordered_map::IteratorPtr
@@ -1088,14 +1133,14 @@ iterator if the key is not found.
Implementation
-public(friend) fun find<K, V>(self: &OrderedMap<K, V>, key: &K): IteratorPtr {
- let lower_bound = self.lower_bound(key);
- if (lower_bound.iter_is_end(self)) {
- lower_bound
- } else if (lower_bound.iter_borrow_key(self) == key) {
- lower_bound
+public fun internal_find<K, V>(self: &OrderedMap<K, V>, key: &K): IteratorPtr {
+ let internal_lower_bound = self.internal_lower_bound(key);
+ if (internal_lower_bound.iter_is_end(self)) {
+ internal_lower_bound
+ } else if (internal_lower_bound.iter_borrow_key(self) == key) {
+ internal_lower_bound
} else {
- self.new_end_iter()
+ self.internal_new_end_iter()
}
}
@@ -1104,14 +1149,17 @@ iterator if the key is not found.
-
+
-## Function `new_begin_iter`
+## Function `internal_new_begin_iter`
+
+Warning: Marked as internal, as it is safer to utilize provided inline functions instead.
+For direct usage of this method, check Warning at the top of the file corresponding to iterators.
Returns the begin iterator.
-public(friend) fun new_begin_iter<K, V>(self: &ordered_map::OrderedMap<K, V>): ordered_map::IteratorPtr
+public fun internal_new_begin_iter<K, V>(self: &ordered_map::OrderedMap<K, V>): ordered_map::IteratorPtr
@@ -1120,7 +1168,7 @@ Returns the begin iterator.
Implementation
-public(friend) fun new_begin_iter<K, V>(self: &OrderedMap<K, V>): IteratorPtr {
+public fun internal_new_begin_iter<K, V>(self: &OrderedMap<K, V>): IteratorPtr {
if (self.is_empty()) {
return IteratorPtr::End;
};
@@ -1133,14 +1181,17 @@ Returns the begin iterator.
-
+
+
+## Function `internal_new_end_iter`
-## Function `new_end_iter`
+Warning: Marked as internal, as it is safer to utilize provided inline functions instead.
+For direct usage of this method, check Warning at the top of the file corresponding to iterators.
Returns the end iterator.
-public(friend) fun new_end_iter<K, V>(self: &ordered_map::OrderedMap<K, V>): ordered_map::IteratorPtr
+public fun internal_new_end_iter<K, V>(self: &ordered_map::OrderedMap<K, V>): ordered_map::IteratorPtr
@@ -1149,7 +1200,7 @@ Returns the end iterator.
Implementation
-public(friend) fun new_end_iter<K, V>(self: &OrderedMap<K, V>): IteratorPtr {
+public fun internal_new_end_iter<K, V>(self: &OrderedMap<K, V>): IteratorPtr {
IteratorPtr::End
}
@@ -1166,7 +1217,7 @@ Returns the next iterator, or none if already at the end iterator.
Note: Requires that the map is not changed after the input iterator is generated.
-public(friend) fun iter_next<K, V>(self: ordered_map::IteratorPtr, map: &ordered_map::OrderedMap<K, V>): ordered_map::IteratorPtr
+public fun iter_next<K, V>(self: ordered_map::IteratorPtr, map: &ordered_map::OrderedMap<K, V>): ordered_map::IteratorPtr
@@ -1175,14 +1226,14 @@ Note: Requires that the map is not changed after the input iterator is generated
Implementation
-public(friend) fun iter_next<K, V>(self: IteratorPtr, map: &OrderedMap<K, V>): IteratorPtr {
+public fun iter_next<K, V>(self: IteratorPtr, map: &OrderedMap<K, V>): IteratorPtr {
assert!(!self.iter_is_end(map), error::invalid_argument(EITER_OUT_OF_BOUNDS));
let index = self.index + 1;
if (index < map.entries.length()) {
new_iter(index)
} else {
- map.new_end_iter()
+ map.internal_new_end_iter()
}
}
@@ -1199,7 +1250,7 @@ Returns the previous iterator, or none if already at the begin iterator.
Note: Requires that the map is not changed after the input iterator is generated.
-public(friend) fun iter_prev<K, V>(self: ordered_map::IteratorPtr, map: &ordered_map::OrderedMap<K, V>): ordered_map::IteratorPtr
+public fun iter_prev<K, V>(self: ordered_map::IteratorPtr, map: &ordered_map::OrderedMap<K, V>): ordered_map::IteratorPtr
@@ -1208,7 +1259,7 @@ Note: Requires that the map is not changed after the input iterator is generated
Implementation
-public(friend) fun iter_prev<K, V>(self: IteratorPtr, map: &OrderedMap<K, V>): IteratorPtr {
+public fun iter_prev<K, V>(self: IteratorPtr, map: &OrderedMap<K, V>): IteratorPtr {
assert!(!self.iter_is_begin(map), error::invalid_argument(EITER_OUT_OF_BOUNDS));
let index = if (self is IteratorPtr::End) {
@@ -1232,7 +1283,7 @@ Note: Requires that the map is not changed after the input iterator is generated
Returns whether the iterator is a begin iterator.
-public(friend) fun iter_is_begin<K, V>(self: &ordered_map::IteratorPtr, map: &ordered_map::OrderedMap<K, V>): bool
+public fun iter_is_begin<K, V>(self: &ordered_map::IteratorPtr, map: &ordered_map::OrderedMap<K, V>): bool
@@ -1241,7 +1292,7 @@ Returns whether the iterator is a begin iterator.
Implementation
-public(friend) fun iter_is_begin<K, V>(self: &IteratorPtr, map: &OrderedMap<K, V>): bool {
+public fun iter_is_begin<K, V>(self: &IteratorPtr, map: &OrderedMap<K, V>): bool {
if (self is IteratorPtr::End) {
map.is_empty()
} else {
@@ -1263,7 +1314,7 @@ Returns true iff the iterator is a begin iterator from a non-empty collection.
This method doesn't require having access to map, unlike iter_is_begin.
-public(friend) fun iter_is_begin_from_non_empty(self: &ordered_map::IteratorPtr): bool
+public fun iter_is_begin_from_non_empty(self: &ordered_map::IteratorPtr): bool
@@ -1272,7 +1323,7 @@ This method doesn't require having access to map, unlike iter_is_begin.
Implementation
-public(friend) fun iter_is_begin_from_non_empty(self: &IteratorPtr): bool {
+public fun iter_is_begin_from_non_empty(self: &IteratorPtr): bool {
if (self is IteratorPtr::End) {
false
} else {
@@ -1292,7 +1343,7 @@ This method doesn't require having access to map, unlike iter_is_begin.
Returns whether the iterator is an end iterator.
-public(friend) fun iter_is_end<K, V>(self: &ordered_map::IteratorPtr, _map: &ordered_map::OrderedMap<K, V>): bool
+public fun iter_is_end<K, V>(self: &ordered_map::IteratorPtr, _map: &ordered_map::OrderedMap<K, V>): bool
@@ -1301,7 +1352,7 @@ Returns whether the iterator is an end iterator.
Implementation
-public(friend) fun iter_is_end<K, V>(self: &IteratorPtr, _map: &OrderedMap<K, V>): bool {
+public fun iter_is_end<K, V>(self: &IteratorPtr, _map: &OrderedMap<K, V>): bool {
self is IteratorPtr::End
}
@@ -1319,7 +1370,7 @@ Aborts with EITER_OUT_OF_BOUNDS if iterator is pointing to the end.
Note: Requires that the map is not changed after the input iterator is generated.
-public(friend) fun iter_borrow_key<K, V>(self: &ordered_map::IteratorPtr, map: &ordered_map::OrderedMap<K, V>): &K
+public fun iter_borrow_key<K, V>(self: &ordered_map::IteratorPtr, map: &ordered_map::OrderedMap<K, V>): &K
@@ -1328,7 +1379,7 @@ Note: Requires that the map is not changed after the input iterator is generated
Implementation
-public(friend) fun iter_borrow_key<K, V>(self: &IteratorPtr, map: &OrderedMap<K, V>): &K {
+public fun iter_borrow_key<K, V>(self: &IteratorPtr, map: &OrderedMap<K, V>): &K {
assert!(!(self is IteratorPtr::End), error::invalid_argument(EITER_OUT_OF_BOUNDS));
&map.entries.borrow(self.index).key
@@ -1348,7 +1399,7 @@ Aborts with EITER_OUT_OF_BOUNDS if iterator is pointing to the end.
Note: Requires that the map is not changed after the input iterator is generated.
-public(friend) fun iter_borrow<K, V>(self: ordered_map::IteratorPtr, map: &ordered_map::OrderedMap<K, V>): &V
+public fun iter_borrow<K, V>(self: ordered_map::IteratorPtr, map: &ordered_map::OrderedMap<K, V>): &V
@@ -1357,7 +1408,7 @@ Note: Requires that the map is not changed after the input iterator is generated
Implementation
-public(friend) fun iter_borrow<K, V>(self: IteratorPtr, map: &OrderedMap<K, V>): &V {
+public fun iter_borrow<K, V>(self: IteratorPtr, map: &OrderedMap<K, V>): &V {
assert!(!(self is IteratorPtr::End), error::invalid_argument(EITER_OUT_OF_BOUNDS));
&map.entries.borrow(self.index).value
}
@@ -1376,7 +1427,7 @@ Aborts with EITER_OUT_OF_BOUNDS if iterator is pointing to the end.
Note: Requires that the map is not changed after the input iterator is generated.
-public(friend) fun iter_borrow_mut<K, V>(self: ordered_map::IteratorPtr, map: &mut ordered_map::OrderedMap<K, V>): &mut V
+public fun iter_borrow_mut<K, V>(self: ordered_map::IteratorPtr, map: &mut ordered_map::OrderedMap<K, V>): &mut V
@@ -1385,7 +1436,7 @@ Note: Requires that the map is not changed after the input iterator is generated
Implementation
-public(friend) fun iter_borrow_mut<K, V>(self: IteratorPtr, map: &mut OrderedMap<K, V>): &mut V {
+public fun iter_borrow_mut<K, V>(self: IteratorPtr, map: &mut OrderedMap<K, V>): &mut V {
assert!(!(self is IteratorPtr::End), error::invalid_argument(EITER_OUT_OF_BOUNDS));
&mut map.entries.borrow_mut(self.index).value
}
@@ -1404,7 +1455,7 @@ Aborts with EITER_OUT_OF_BOUNDS if iterator is pointing to the end.
Note: Requires that the map is not changed after the input iterator is generated.
-public(friend) fun iter_remove<K: drop, V>(self: ordered_map::IteratorPtr, map: &mut ordered_map::OrderedMap<K, V>): V
+public fun iter_remove<K: drop, V>(self: ordered_map::IteratorPtr, map: &mut ordered_map::OrderedMap<K, V>): V
@@ -1413,7 +1464,7 @@ Note: Requires that the map is not changed after the input iterator is generated
Implementation
-public(friend) fun iter_remove<K: drop, V>(self: IteratorPtr, map: &mut OrderedMap<K, V>): V {
+public fun iter_remove<K: drop, V>(self: IteratorPtr, map: &mut OrderedMap<K, V>): V {
assert!(!(self is IteratorPtr::End), error::invalid_argument(EITER_OUT_OF_BOUNDS));
let Entry { key: _, value } = map.entries.remove(self.index);
@@ -1434,7 +1485,7 @@ Aborts with EITER_OUT_OF_BOUNDS if iterator is pointing to the end.
Note: Requires that the map is not changed after the input iterator is generated.
-public(friend) fun iter_replace<K: copy, drop, V>(self: ordered_map::IteratorPtr, map: &mut ordered_map::OrderedMap<K, V>, value: V): V
+public fun iter_replace<K: copy, drop, V>(self: ordered_map::IteratorPtr, map: &mut ordered_map::OrderedMap<K, V>, value: V): V
@@ -1443,7 +1494,7 @@ Note: Requires that the map is not changed after the input iterator is generated
Implementation
-public(friend) fun iter_replace<K: copy + drop, V>(self: IteratorPtr, map: &mut OrderedMap<K, V>, value: V): V {
+public fun iter_replace<K: copy + drop, V>(self: IteratorPtr, map: &mut OrderedMap<K, V>, value: V): V {
assert!(!(self is IteratorPtr::End), error::invalid_argument(EITER_OUT_OF_BOUNDS));
// TODO once mem::replace is public/released, update to:
@@ -1471,7 +1522,7 @@ Aborts with ENEW_KEY_NOT_IN_ORDER is key is not larger than the key before the i
or smaller than the key at the iterator position.
-public(friend) fun iter_add<K, V>(self: ordered_map::IteratorPtr, map: &mut ordered_map::OrderedMap<K, V>, key: K, value: V)
+public fun iter_add<K, V>(self: ordered_map::IteratorPtr, map: &mut ordered_map::OrderedMap<K, V>, key: K, value: V)
@@ -1480,7 +1531,7 @@ or smaller than the key at the iterator position.
Implementation
-public(friend) fun iter_add<K, V>(self: IteratorPtr, map: &mut OrderedMap<K, V>, key: K, value: V) {
+public fun iter_add<K, V>(self: IteratorPtr, map: &mut OrderedMap<K, V>, key: K, value: V) {
let len = map.entries.length();
let insert_index = if (self is IteratorPtr::End) {
len
@@ -1689,9 +1740,6 @@ Apply the function to each key-value pair in the map, consuming it.
Apply the function to a reference of each key-value pair in the map.
-Current implementation is O(n * log(n)). After function values will be optimized
-to O(n).
-
public fun for_each_ref<K: copy, drop, V>(self: &ordered_map::OrderedMap<K, V>, f: |&K, &V|)
@@ -1703,29 +1751,13 @@ to O(n).
public inline fun for_each_ref<K: copy + drop, V>(self: &OrderedMap<K, V>, f: |&K, &V|) {
- // This implementation is innefficient: O(log(n)) for next_key / borrow lookups every time,
- // but is the only one available through the public API.
- if (!self.is_empty()) {
- let (k, v) = self.borrow_front();
- f(k, v);
-
- let cur_k = self.next_key(k);
- while (cur_k.is_some()) {
- let k = cur_k.destroy_some();
- f(&k, self.borrow(&k));
-
- cur_k = self.next_key(&k);
- };
- };
-
- // TODO: if we make iterator api public update to:
- // let iter = self.new_begin_iter();
- // while (!iter.iter_is_end(self)) {
- // f(iter.iter_borrow_key(self), iter.iter_borrow(self));
- // iter = iter.iter_next(self);
- // }
+ let iter = self.internal_new_begin_iter();
+ while (!iter.iter_is_end(self)) {
+ f(iter.iter_borrow_key(self), iter.iter_borrow(self));
+ iter = iter.iter_next(self);
+ }
- // TODO: once move supports private functions udpate to:
+ // TODO: once move supports private functions update to:
// vector::for_each_ref(
// &self.entries,
// |entry| {
@@ -1737,34 +1769,6 @@ to O(n).
-
-
-
-
-## Function `for_each_ref_friend`
-
-
-
-public(friend) fun for_each_ref_friend<K: copy, drop, V>(self: &ordered_map::OrderedMap<K, V>, f: |&K, &V|)
-
-
-
-
-
-Implementation
-
-
-public(friend) inline fun for_each_ref_friend<K: copy + drop, V>(self: &OrderedMap<K, V>, f: |&K, &V|) {
- let iter = self.new_begin_iter();
- while (!iter.iter_is_end(self)) {
- f(iter.iter_borrow_key(self), iter.iter_borrow(self));
- iter = iter.iter_next(self);
- }
-}
-
-
-
-
@@ -1773,9 +1777,6 @@ to O(n).
Apply the function to a mutable reference of each key-value pair in the map.
-Current implementation is O(n * log(n)). After function values will be optimized
-to O(n).
-
public fun for_each_mut<K: copy, drop, V>(self: &mut ordered_map::OrderedMap<K, V>, f: |&K, &mut V|)
@@ -1787,32 +1788,12 @@ to O(n).
public inline fun for_each_mut<K: copy + drop, V>(self: &mut OrderedMap<K, V>, f: |&K, &mut V|) {
- // This implementation is innefficient: O(log(n)) for next_key / borrow lookups every time,
- // but is the only one available through the public API.
- if (!self.is_empty()) {
- let (k, _v) = self.borrow_front();
-
- let k = *k;
- let done = false;
- while (!done) {
- f(&k, self.borrow_mut(&k));
-
- let cur_k = self.next_key(&k);
- if (cur_k.is_some()) {
- k = cur_k.destroy_some();
- } else {
- done = true;
- }
- };
- };
-
- // TODO: if we make iterator api public update to:
- // let iter = self.new_begin_iter();
- // while (!iter.iter_is_end(self)) {
- // let key = *iter.iter_borrow_key(self);
- // f(key, iter.iter_borrow_mut(self));
- // iter = iter.iter_next(self);
- // }
+ let iter = self.internal_new_begin_iter();
+ while (!iter.iter_is_end(self)) {
+ let key = *iter.iter_borrow_key(self);
+ f(&key, iter.iter_borrow_mut(self));
+ iter = iter.iter_next(self);
+ }
// TODO: once move supports private functions udpate to:
// vector::for_each_mut(
@@ -2135,6 +2116,23 @@ to O(n).
+
+
+### Function `remove_or_none`
+
+
+public fun remove_or_none<K: drop, V>(self: &mut ordered_map::OrderedMap<K, V>, key: &K): option::Option<V>
+
+
+
+
+
+pragma opaque;
+pragma verify = false;
+
+
+
+
### Function `contains`
@@ -2430,12 +2428,12 @@ std::cmp::compare(key, k) == std::cmp::Ordering::Greater);
-
+
-### Function `lower_bound`
+### Function `internal_lower_bound`
-public(friend) fun lower_bound<K, V>(self: &ordered_map::OrderedMap<K, V>, key: &K): ordered_map::IteratorPtr
+public fun internal_lower_bound<K, V>(self: &ordered_map::OrderedMap<K, V>, key: &K): ordered_map::IteratorPtr
@@ -2447,12 +2445,12 @@ std::cmp::compare(key, k) == std::cmp::Ordering::Greater);
-
+
-### Function `find`
+### Function `internal_find`
-public(friend) fun find<K, V>(self: &ordered_map::OrderedMap<K, V>, key: &K): ordered_map::IteratorPtr
+public fun internal_find<K, V>(self: &ordered_map::OrderedMap<K, V>, key: &K): ordered_map::IteratorPtr
@@ -2464,12 +2462,12 @@ std::cmp::compare(key, k) == std::cmp::Ordering::Greater);
-
+
-### Function `new_begin_iter`
+### Function `internal_new_begin_iter`
-public(friend) fun new_begin_iter<K, V>(self: &ordered_map::OrderedMap<K, V>): ordered_map::IteratorPtr
+public fun internal_new_begin_iter<K, V>(self: &ordered_map::OrderedMap<K, V>): ordered_map::IteratorPtr
@@ -2481,12 +2479,12 @@ std::cmp::compare(key, k) == std::cmp::Ordering::Greater);
-
+
-### Function `new_end_iter`
+### Function `internal_new_end_iter`
-public(friend) fun new_end_iter<K, V>(self: &ordered_map::OrderedMap<K, V>): ordered_map::IteratorPtr
+public fun internal_new_end_iter<K, V>(self: &ordered_map::OrderedMap<K, V>): ordered_map::IteratorPtr
@@ -2503,7 +2501,7 @@ std::cmp::compare(key, k) == std::cmp::Ordering::Greater);
### Function `iter_next`
-public(friend) fun iter_next<K, V>(self: ordered_map::IteratorPtr, map: &ordered_map::OrderedMap<K, V>): ordered_map::IteratorPtr
+public fun iter_next<K, V>(self: ordered_map::IteratorPtr, map: &ordered_map::OrderedMap<K, V>): ordered_map::IteratorPtr
@@ -2520,7 +2518,7 @@ std::cmp::compare(key, k) == std::cmp::Ordering::Greater);
### Function `iter_prev`
-public(friend) fun iter_prev<K, V>(self: ordered_map::IteratorPtr, map: &ordered_map::OrderedMap<K, V>): ordered_map::IteratorPtr
+public fun iter_prev<K, V>(self: ordered_map::IteratorPtr, map: &ordered_map::OrderedMap<K, V>): ordered_map::IteratorPtr
@@ -2537,7 +2535,7 @@ std::cmp::compare(key, k) == std::cmp::Ordering::Greater);
### Function `iter_is_begin`
-public(friend) fun iter_is_begin<K, V>(self: &ordered_map::IteratorPtr, map: &ordered_map::OrderedMap<K, V>): bool
+public fun iter_is_begin<K, V>(self: &ordered_map::IteratorPtr, map: &ordered_map::OrderedMap<K, V>): bool
@@ -2554,7 +2552,7 @@ std::cmp::compare(key, k) == std::cmp::Ordering::Greater);
### Function `iter_is_begin_from_non_empty`
-public(friend) fun iter_is_begin_from_non_empty(self: &ordered_map::IteratorPtr): bool
+public fun iter_is_begin_from_non_empty(self: &ordered_map::IteratorPtr): bool
@@ -2571,7 +2569,7 @@ std::cmp::compare(key, k) == std::cmp::Ordering::Greater);
### Function `iter_is_end`
-public(friend) fun iter_is_end<K, V>(self: &ordered_map::IteratorPtr, _map: &ordered_map::OrderedMap<K, V>): bool
+public fun iter_is_end<K, V>(self: &ordered_map::IteratorPtr, _map: &ordered_map::OrderedMap<K, V>): bool
@@ -2588,7 +2586,7 @@ std::cmp::compare(key, k) == std::cmp::Ordering::Greater);
### Function `iter_borrow_key`
-public(friend) fun iter_borrow_key<K, V>(self: &ordered_map::IteratorPtr, map: &ordered_map::OrderedMap<K, V>): &K
+public fun iter_borrow_key<K, V>(self: &ordered_map::IteratorPtr, map: &ordered_map::OrderedMap<K, V>): &K
@@ -2605,7 +2603,7 @@ std::cmp::compare(key, k) == std::cmp::Ordering::Greater);
### Function `iter_borrow`
-public(friend) fun iter_borrow<K, V>(self: ordered_map::IteratorPtr, map: &ordered_map::OrderedMap<K, V>): &V
+public fun iter_borrow<K, V>(self: ordered_map::IteratorPtr, map: &ordered_map::OrderedMap<K, V>): &V
@@ -2622,7 +2620,7 @@ std::cmp::compare(key, k) == std::cmp::Ordering::Greater);
### Function `iter_borrow_mut`
-public(friend) fun iter_borrow_mut<K, V>(self: ordered_map::IteratorPtr, map: &mut ordered_map::OrderedMap<K, V>): &mut V
+public fun iter_borrow_mut<K, V>(self: ordered_map::IteratorPtr, map: &mut ordered_map::OrderedMap<K, V>): &mut V
@@ -2639,7 +2637,7 @@ std::cmp::compare(key, k) == std::cmp::Ordering::Greater);
### Function `iter_remove`
-public(friend) fun iter_remove<K: drop, V>(self: ordered_map::IteratorPtr, map: &mut ordered_map::OrderedMap<K, V>): V
+public fun iter_remove<K: drop, V>(self: ordered_map::IteratorPtr, map: &mut ordered_map::OrderedMap<K, V>): V
@@ -2656,7 +2654,7 @@ std::cmp::compare(key, k) == std::cmp::Ordering::Greater);
### Function `iter_replace`
-public(friend) fun iter_replace<K: copy, drop, V>(self: ordered_map::IteratorPtr, map: &mut ordered_map::OrderedMap<K, V>, value: V): V
+public fun iter_replace<K: copy, drop, V>(self: ordered_map::IteratorPtr, map: &mut ordered_map::OrderedMap<K, V>, value: V): V
@@ -2673,7 +2671,7 @@ std::cmp::compare(key, k) == std::cmp::Ordering::Greater);
### Function `iter_add`
-public(friend) fun iter_add<K, V>(self: ordered_map::IteratorPtr, map: &mut ordered_map::OrderedMap<K, V>, key: K, value: V)
+public fun iter_add<K, V>(self: ordered_map::IteratorPtr, map: &mut ordered_map::OrderedMap<K, V>, key: K, value: V)
diff --git a/aptos-move/framework/aptos-framework/sources/datastructures/big_ordered_map.move b/aptos-move/framework/aptos-framework/sources/datastructures/big_ordered_map.move
index 789b928f6253a..ae79022d5b200 100644
--- a/aptos-move/framework/aptos-framework/sources/datastructures/big_ordered_map.move
+++ b/aptos-move/framework/aptos-framework/sources/datastructures/big_ordered_map.move
@@ -21,10 +21,15 @@
/// Based on initial configuration, BigOrderedMap will always accept insertion of keys and values
/// up to the allowed size, and will abort with EKEY_BYTES_TOO_LARGE or EARGUMENT_BYTES_TOO_LARGE.
///
-/// TODO: all iterator functions are public(friend) for now, so that they can be modified in a
-/// backward incompatible way. Type is also named IteratorPtr, so that Iterator is free to use later.
-/// They are waiting for Move improvement that will allow references to be part of the struct,
+/// Warning: All iterator functions need to be carefully used, because they are just pointers into the
+/// structure, and modification of the map invalidates them (without compiler being able to catch it).
+/// Type is also named IteratorPtr, so that Iterator is free to use later.
+/// Better guarantees would need future Move improvements that will allow references to be part of the struct,
/// allowing cleaner iterator APIs.
+///
+/// That's why all functions returning iterators are prefixed with "internal_", to clarify nuances needed to make
+/// sure usage is correct.
+/// A set of inline utility methods is provided instead, to provide guaranteed valid usage to iterators.
module aptos_std::big_ordered_map {
use std::error;
use std::vector;
@@ -157,6 +162,11 @@ module aptos_std::big_ordered_map {
},
}
+ struct IteratorPtrWithPath has copy, drop {
+ iterator: IteratorPtr,
+ path: vector,
+ }
+
/// The BigOrderedMap data structure.
enum BigOrderedMap has store {
BPlusTreeMap {
@@ -359,6 +369,36 @@ module aptos_std::big_ordered_map {
value
}
+ /// Removes the entry from BigOrderedMap and returns the value which `key` maps to.
+ /// Returns none if there is no entry for `key`.
+ public fun remove_or_none(self: &mut BigOrderedMap, key: &K): Option {
+ // Optimize case where only root node exists
+ // (optimizes out borrowing and path creation in `find_leaf_path`)
+ if (self.root.is_leaf) {
+ let value_option = self.root.children.remove_or_none(key);
+ if (value_option.is_some()) {
+ let Child::Leaf {
+ value,
+ } = value_option.destroy_some();
+ return option::some(value);
+ } else {
+ value_option.destroy_none();
+ return option::none();
+ }
+ };
+
+ let path_to_leaf = self.find_leaf_path(key);
+
+ if (path_to_leaf.is_empty()) {
+ option::none()
+ } else {
+ let Child::Leaf {
+ value,
+ } = self.remove_at(path_to_leaf, key);
+ option::some(value)
+ }
+ }
+
/// Add multiple key/value pairs to the map. The keys must not already exist.
/// Aborts with EKEY_ALREADY_EXISTS if key already exist, or duplicate keys are passed in.
public fun add_all(self: &mut BigOrderedMap, keys: vector, values: vector) {
@@ -370,14 +410,14 @@ module aptos_std::big_ordered_map {
}
public fun pop_front(self: &mut BigOrderedMap): (K, V) {
- let it = self.new_begin_iter();
+ let it = self.internal_new_begin_iter();
let k = *it.iter_borrow_key();
let v = self.remove(&k);
(k, v)
}
public fun pop_back(self: &mut BigOrderedMap): (K, V) {
- let it = self.new_end_iter().iter_prev(self);
+ let it = self.internal_new_end_iter().iter_prev(self);
let k = *it.iter_borrow_key();
let v = self.remove(&k);
(k, v)
@@ -385,45 +425,82 @@ module aptos_std::big_ordered_map {
// ============================= Accessors ================================
+ /// Warning: Marked as internal, as it is safer to utilize provided inline functions instead.
+ /// For direct usage of this method, check Warning at the top of the file corresponding to iterators.
+ ///
/// Returns an iterator pointing to the first element that is greater or equal to the provided
/// key, or an end iterator if such element doesn't exist.
- public(friend) fun lower_bound(self: &BigOrderedMap, key: &K): IteratorPtr {
+ public fun internal_lower_bound(self: &BigOrderedMap, key: &K): IteratorPtr {
let leaf = self.find_leaf(key);
if (leaf == NULL_INDEX) {
- return self.new_end_iter()
+ return self.internal_new_end_iter()
};
let node = self.borrow_node(leaf);
assert!(node.is_leaf, error::invalid_state(EINTERNAL_INVARIANT_BROKEN));
- let child_lower_bound = node.children.lower_bound(key);
+ let child_lower_bound = node.children.internal_lower_bound(key);
if (child_lower_bound.iter_is_end(&node.children)) {
- self.new_end_iter()
+ self.internal_new_end_iter()
} else {
let iter_key = *child_lower_bound.iter_borrow_key(&node.children);
new_iter(leaf, child_lower_bound, iter_key)
}
}
+ /// Warning: Marked as internal, as it is safer to utilize provided inline functions instead.
+ /// For direct usage of this method, check Warning at the top of the file corresponding to iterators.
+ ///
/// Returns an iterator pointing to the element that equals to the provided key, or an end
/// iterator if the key is not found.
- public(friend) fun find(self: &BigOrderedMap, key: &K): IteratorPtr {
- let lower_bound = self.lower_bound(key);
- if (lower_bound.iter_is_end(self)) {
- lower_bound
- } else if (&lower_bound.key == key) {
- lower_bound
+ public fun internal_find(self: &BigOrderedMap, key: &K): IteratorPtr {
+ let internal_lower_bound = self.internal_lower_bound(key);
+ if (internal_lower_bound.iter_is_end(self)) {
+ internal_lower_bound
+ } else if (&internal_lower_bound.key == key) {
+ internal_lower_bound
+ } else {
+ self.internal_new_end_iter()
+ }
+ }
+
+ /// Warning: Marked as internal, as it is safer to utilize provided inline functions instead.
+ /// For direct usage of this method, check Warning at the top of the file corresponding to iterators.
+ ///
+ public fun internal_find_with_path(self: &BigOrderedMap