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 1f97dcba8e4c5..13403c6710107 100644
--- a/aptos-move/framework/aptos-framework/doc/big_ordered_map.md
+++ b/aptos-move/framework/aptos-framework/doc/big_ordered_map.md
@@ -56,6 +56,11 @@ A set of inline utility methods is provided instead, to provide guaranteed valid
- [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 `modify`](#0x1_big_ordered_map_modify)
+- [Function `modify_and_return`](#0x1_big_ordered_map_modify_and_return)
+- [Function `modify_or_add`](#0x1_big_ordered_map_modify_or_add)
+- [Function `modify_if_present`](#0x1_big_ordered_map_modify_if_present)
+- [Function `modify_if_present_and_return`](#0x1_big_ordered_map_modify_if_present_and_return)
- [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)
@@ -66,6 +71,7 @@ A set of inline utility methods is provided instead, to provide guaranteed valid
- [Function `contains`](#0x1_big_ordered_map_contains)
- [Function `borrow`](#0x1_big_ordered_map_borrow)
- [Function `get`](#0x1_big_ordered_map_get)
+- [Function `get_and_map`](#0x1_big_ordered_map_get_and_map)
- [Function `borrow_mut`](#0x1_big_ordered_map_borrow_mut)
- [Function `borrow_front`](#0x1_big_ordered_map_borrow_front)
- [Function `borrow_back`](#0x1_big_ordered_map_borrow_back)
@@ -85,6 +91,7 @@ A set of inline utility methods is provided instead, to provide guaranteed valid
- [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_modify`](#0x1_big_ordered_map_iter_modify)
- [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)
@@ -130,6 +137,7 @@ A set of inline utility methods is provided instead, to provide guaranteed valid
- [Function `internal_find`](#@Specification_1_internal_find)
- [Function `contains`](#@Specification_1_contains)
- [Function `borrow`](#@Specification_1_borrow)
+ - [Function `get_and_map`](#@Specification_1_get_and_map)
- [Function `borrow_mut`](#@Specification_1_borrow_mut)
- [Function `borrow_front`](#@Specification_1_borrow_front)
- [Function `borrow_back`](#@Specification_1_borrow_back)
@@ -143,6 +151,7 @@ A set of inline utility methods is provided instead, to provide guaranteed valid
- [Function `iter_borrow_key`](#@Specification_1_iter_borrow_key)
- [Function `iter_borrow`](#@Specification_1_iter_borrow)
- [Function `iter_borrow_mut`](#@Specification_1_iter_borrow_mut)
+ - [Function `iter_modify`](#@Specification_1_iter_modify)
- [Function `iter_next`](#@Specification_1_iter_next)
- [Function `iter_prev`](#@Specification_1_iter_prev)
- [Function `validate_dynamic_size_and_init_max_degrees`](#@Specification_1_validate_dynamic_size_and_init_max_degrees)
@@ -1140,6 +1149,151 @@ Returns none if there is no entry for key
.
+
+
+
+
+## Function `modify`
+
+Modifies the element in the map via calling f.
+Aborts if element doesn't exist
+
+
+
public fun modify<K: copy, drop, store, V: store>(self: &mut big_ordered_map::BigOrderedMap<K, V>, key: &K, f: |&mut V|)
+
+
+
+
+public inline fun modify<K: drop + copy + store, V: store>(self: &mut BigOrderedMap<K, V>, key: &K, f: |&mut V|) {
+ self.modify_and_return(key, |v| { f(v); true});
+}
+
+
+
+
+public fun modify_and_return<K: copy, drop, store, V: store, R>(self: &mut big_ordered_map::BigOrderedMap<K, V>, key: &K, f: |&mut V|R): R
+
+
+
+
+public inline fun modify_and_return<K: drop + copy + store, V: store, R>(self: &mut BigOrderedMap<K, V>, key: &K, f: |&mut V|R): R {
+ let iter = self.internal_find(key);
+ assert!(!iter.iter_is_end(self), error::invalid_argument(EKEY_NOT_FOUND));
+ iter.iter_modify(self, |v| f(v))
+}
+
+
+
+
+public fun modify_or_add<K: copy, drop, store, V: store>(self: &mut big_ordered_map::BigOrderedMap<K, V>, key: &K, modify_f: |&mut V| has drop, add_f: ||V has drop): bool
+
+
+
+
+public inline fun modify_or_add<K: drop + copy + store, V: store>(self: &mut BigOrderedMap<K, V>, key: &K, modify_f: |&mut V| has drop, add_f: ||V has drop): bool {
+ let exists = self.modify_if_present_and_return(key, |v| { modify_f(v); true }).is_some();
+ if (!exists) {
+ self.add(*key, add_f());
+ };
+ exists
+}
+
+
+
+
+public fun modify_if_present<K: copy, drop, store, V: store>(self: &mut big_ordered_map::BigOrderedMap<K, V>, key: &K, modify_f: |&mut V| has drop): bool
+
+
+
+
+public inline fun modify_if_present<K: drop + copy + store, V: store>(self: &mut BigOrderedMap<K, V>, key: &K, modify_f: |&mut V| has drop): bool {
+ self.modify_if_present_and_return(key, |v| { modify_f(v); true }).is_some()
+}
+
+
+
+
+public fun modify_if_present_and_return<K: copy, drop, store, V: store, R>(self: &mut big_ordered_map::BigOrderedMap<K, V>, key: &K, modify_f: |&mut V|R has drop): option::Option<R>
+
+
+
+
+public inline fun modify_if_present_and_return<K: drop + copy + store, V: store, R>(self: &mut BigOrderedMap<K, V>, key: &K, modify_f: |&mut V|R has drop): Option<R> {
+ let iter = self.internal_find(key);
+ if (iter.iter_is_end(self)) {
+ option::none()
+ } else {
+ option::some(iter.iter_modify(self, |v| modify_f(v)))
+ }
+}
+
+
+
+
public fun get_and_map<K: copy, drop, store, V: copy, store, R>(self: &big_ordered_map::BigOrderedMap<K, V>, key: &K, f: |&V|R has drop): option::Option<R>
+
+
+
+
+public fun get_and_map<K: drop + copy + store, V: copy + store, R>(self: &BigOrderedMap<K, V>, key: &K, f: |&V|R has drop): Option<R> {
+ let iter = self.internal_find(key);
+ if (iter.iter_is_end(self)) {
+ option::none()
+ } else {
+ option::some(f(iter.iter_borrow(self)))
+ }
+}
+
+
+
+
public fun iter_modify<K: drop, store, V: store, R>(self: big_ordered_map::IteratorPtr<K>, map: &mut big_ordered_map::BigOrderedMap<K, V>, f: |&mut V|R): R
+
+
+
+
+public fun iter_modify<K: drop + store, V: store, R>(self: IteratorPtr<K>, map: &mut BigOrderedMap<K, V>, f: |&mut V|R): R {
+ assert!(!self.iter_is_end(map), error::invalid_argument(EITER_OUT_OF_BOUNDS));
+ let IteratorPtr::Some { node_index, child_iter, key } = self;
+ let children = &mut map.borrow_node_mut(node_index).children;
+ let value_mut = &mut child_iter.iter_borrow_mut(children).value;
+ let result = f(value_mut);
+
+ if (map.constant_kv_size) {
+ return result;
+ };
+
+ // validate that after modifications size invariants hold
+ let key_size = bcs::serialized_size(&key);
+ let value_size = bcs::serialized_size(value_mut);
+ map.validate_size_and_init_max_degrees(key_size, value_size);
+ result
+}
+
+
+
+
public fun get_and_map<K: copy, drop, store, V: copy, store, R>(self: &big_ordered_map::BigOrderedMap<K, V>, key: &K, f: |&V|R has drop): option::Option<R>
+
+
+
+
+
+pragma opaque;
+pragma verify = false;
+
+
+
+
### Function `borrow_mut`
@@ -3965,6 +4203,23 @@ std::cmp::compare(key, k) == std::cmp::Ordering::Greater);
+pragma opaque;
+pragma verify = false;
+
+
+
+
+
+
+### Function `iter_modify`
+
+
+public fun iter_modify<K: drop, store, V: store, R>(self: big_ordered_map::IteratorPtr<K>, map: &mut big_ordered_map::BigOrderedMap<K, V>, f: |&mut V|R): R
+
+
+
+
+
pragma opaque;
pragma verify = false;
diff --git a/aptos-move/framework/aptos-framework/doc/ordered_map.md b/aptos-move/framework/aptos-framework/doc/ordered_map.md
index 6158b381b9dd1..54d6e950974b8 100644
--- a/aptos-move/framework/aptos-framework/doc/ordered_map.md
+++ b/aptos-move/framework/aptos-framework/doc/ordered_map.md
@@ -45,9 +45,13 @@ A set of inline utility methods is provided instead, to provide guaranteed valid
- [Function `upsert`](#0x1_ordered_map_upsert)
- [Function `remove`](#0x1_ordered_map_remove)
- [Function `remove_or_none`](#0x1_ordered_map_remove_or_none)
+- [Function `modify_or_add`](#0x1_ordered_map_modify_or_add)
+- [Function `modify_if_present`](#0x1_ordered_map_modify_if_present)
- [Function `contains`](#0x1_ordered_map_contains)
- [Function `borrow`](#0x1_ordered_map_borrow)
- [Function `borrow_mut`](#0x1_ordered_map_borrow_mut)
+- [Function `get`](#0x1_ordered_map_get)
+- [Function `get_and_map`](#0x1_ordered_map_get_and_map)
- [Function `replace_key_inplace`](#0x1_ordered_map_replace_key_inplace)
- [Function `add_all`](#0x1_ordered_map_add_all)
- [Function `upsert_all`](#0x1_ordered_map_upsert_all)
@@ -99,6 +103,8 @@ A set of inline utility methods is provided instead, to provide guaranteed valid
- [Function `contains`](#@Specification_1_contains)
- [Function `borrow`](#@Specification_1_borrow)
- [Function `borrow_mut`](#@Specification_1_borrow_mut)
+ - [Function `get`](#@Specification_1_get)
+ - [Function `get_and_map`](#@Specification_1_get_and_map)
- [Function `replace_key_inplace`](#@Specification_1_replace_key_inplace)
- [Function `add_all`](#@Specification_1_add_all)
- [Function `upsert_all`](#@Specification_1_upsert_all)
@@ -554,6 +560,68 @@ Returns none if key
doesn't exist.
+
+
+
+
+## Function `modify_or_add`
+
+Modifies element by calling modify_f if it exists, or calling add_f to add if it doesn't.
+Returns true if element already existed.
+
+
+public fun modify_or_add<K: copy, drop, store, V: store>(self: &mut ordered_map::OrderedMap<K, V>, key: &K, modify_f: |&mut V| has drop, add_f: ||V has drop): bool
+
+
+
+
+public inline fun modify_or_add<K: drop + copy + store, V: store>(self: &mut OrderedMap<K, V>, key: &K, modify_f: |&mut V| has drop, add_f: ||V has drop): bool {
+ let exists = self.modify_if_present(key, |v| modify_f(v));
+ if (!exists) {
+ self.add(*key, add_f());
+ };
+ exists
+}
+
+
+
+
+public fun modify_if_present<K: copy, drop, store, V: store>(self: &mut ordered_map::OrderedMap<K, V>, key: &K, modify_f: |&mut V| has drop): bool
+
+
+
+
+public inline fun modify_if_present<K: drop + copy + store, V: store>(self: &mut OrderedMap<K, V>, key: &K, modify_f: |&mut V| has drop): bool {
+ let iter = self.internal_find(key);
+ if (iter.iter_is_end(self)) {
+ false
+ } else {
+ modify_f(iter.iter_borrow_mut(self));
+ true
+ }
+}
+
+
+
+
public fun get<K: copy, drop, store, V: copy, store>(self: &ordered_map::OrderedMap<K, V>, key: &K): option::Option<V>
+
+
+
+
+public fun get<K: drop + copy + store, V: copy + store>(self: &OrderedMap<K, V>, key: &K): Option<V> {
+ let iter = self.internal_find(key);
+ if (iter.iter_is_end(self)) {
+ option::none()
+ } else {
+ option::some(*iter.iter_borrow(self))
+ }
+}
+
+
+
+
+public fun get_and_map<K: copy, drop, store, V: copy, store, R>(self: &ordered_map::OrderedMap<K, V>, key: &K, f: |&V|R has drop): option::Option<R>
+
+
+
+
+public fun get_and_map<K: drop + copy + store, V: copy + store, R>(self: &OrderedMap<K, V>, key: &K, f: |&V|R has drop): Option<R> {
+ let iter = self.internal_find(key);
+ if (iter.iter_is_end(self)) {
+ option::none()
+ } else {
+ option::some(f(iter.iter_borrow(self)))
+ }
+}
+
+
+
+
public fun get<K: copy, drop, store, V: copy, store>(self: &ordered_map::OrderedMap<K, V>, key: &K): option::Option<V>
+
+
+
+
+
+pragma opaque;
+pragma verify = false;
+
+
+
+
+
+
+### Function `get_and_map`
+
+
+public fun get_and_map<K: copy, drop, store, V: copy, store, R>(self: &ordered_map::OrderedMap<K, V>, key: &K, f: |&V|R has drop): option::Option<R>
+
+
+
+
+
+pragma opaque;
+pragma verify = false;
+
+
+
+
### Function `replace_key_inplace`
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 ae79022d5b200..7fbd1feac6f60 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
@@ -399,6 +399,68 @@ module aptos_std::big_ordered_map {
}
}
+ /// Modifies the element in the map via calling f.
+ /// Aborts if element doesn't exist
+ public inline fun modify