diff --git a/aptos-move/framework/supra-framework/doc/automation_registry_state.md b/aptos-move/framework/supra-framework/doc/automation_registry_state.md
index c2ac0ed343077..e5556baaa7fba 100644
--- a/aptos-move/framework/supra-framework/doc/automation_registry_state.md
+++ b/aptos-move/framework/supra-framework/doc/automation_registry_state.md
@@ -461,7 +461,7 @@ The lenght of the transaction hash.
// Tasks that are active during next epoch and are not cancled
// current_time shows the start time of the current new epoch.
- if (task.state != CANCELLED && task.expiry_time > (current_time + epoch_interval_secs) ) {
+ if (task.state != CANCELLED && task.expiry_time > (current_time + epoch_interval_secs)) {
gas_committed_for_next_epoch = gas_committed_for_next_epoch + task.max_gas_amount;
};
@@ -564,7 +564,7 @@ Committed gas-limit is updated by reducing it with the max-gas-amount of the can
public (friend) fun cancel_task(owner: &signer, id: u64): AutomationTaskMetaData acquires AutomationRegistryState {
+public(friend) fun cancel_task(owner: &signer, id: u64): AutomationTaskMetaData acquires AutomationRegistryState {
let state = borrow_global_mut<AutomationRegistryState>(@supra_framework);
assert!(enumerable_map::contains(&state.tasks, id), EAUTOMATION_TASK_NOT_FOUND);
@@ -607,7 +607,7 @@ If the committed gas amount for the next epoch is greater then the new gas limit
Implementation
-public (friend) fun update_automation_gas_limit(
+public(friend) fun update_automation_gas_limit(
supra_framework: &signer,
automation_gas_limit: u64
) acquires AutomationRegistryState {
@@ -647,16 +647,11 @@ as cancellation takes effect in the next epoch only.
public(friend) fun get_active_task_ids(): vector<u64> acquires AutomationRegistryState {
let state = borrow_global<AutomationRegistryState>(@supra_framework);
- let active_task_ids = vector[];
- let ids = enumerable_map::get_map_list(&state.tasks);
-
- vector::for_each(ids, |id| {
- let task = enumerable_map::get_value_ref(&state.tasks, id);
- if (task.state != PENDING) {
- vector::push_back(&mut active_task_ids, id);
- };
- });
- return active_task_ids
+ enumerable_map::filter_map(&state.tasks, |task| {
+ let task: AutomationTaskMetaData = task; // we need to define task type here to avoid compiler error
+ if (task.state != PENDING) (true, task.id)
+ else (false, task.id)
+ })
}
@@ -681,7 +676,7 @@ Error will be returned if entry with specified ID does not exist.
Implementation
-public (friend) fun get_task_details(id: u64): AutomationTaskMetaData acquires AutomationRegistryState {
+public(friend) fun get_task_details(id: u64): AutomationTaskMetaData acquires AutomationRegistryState {
let automation_task_metadata = borrow_global<AutomationRegistryState>(@supra_framework);
assert!(enumerable_map::contains(&automation_task_metadata.tasks, id), EAUTOMATION_TASK_NOT_FOUND);
enumerable_map::get_value(&automation_task_metadata.tasks, id)
@@ -713,7 +708,7 @@ Checks whether there is an active task in registry with specified input task id.
if (enumerable_map::contains(&automation_task_metadata.tasks, id)) {
let value = enumerable_map::get_value_ref(&automation_task_metadata.tasks, id);
value.state != PENDING
- } else {
+ } else {
false
}
}
@@ -739,7 +734,7 @@ Returns next task index in registry
Implementation
-public (friend) fun get_next_task_index(): u64 acquires AutomationRegistryState {
+public(friend) fun get_next_task_index(): u64 acquires AutomationRegistryState {
let state = borrow_global<AutomationRegistryState>(@supra_framework);
state.current_index
}
diff --git a/aptos-move/framework/supra-framework/sources/automation_registry_state.move b/aptos-move/framework/supra-framework/sources/automation_registry_state.move
index 4e1f0d926fd2b..1a86c6bf38c21 100644
--- a/aptos-move/framework/supra-framework/sources/automation_registry_state.move
+++ b/aptos-move/framework/supra-framework/sources/automation_registry_state.move
@@ -5,12 +5,13 @@ module supra_framework::automation_registry_state {
use std::signer;
use std::vector;
- use supra_framework::event;
use supra_std::enumerable_map::{Self, EnumerableMap};
+ use supra_framework::event;
use supra_framework::system_addresses;
use supra_framework::timestamp;
+
#[test_only]
use supra_framework::account;
@@ -126,7 +127,7 @@ module supra_framework::automation_registry_state {
// Tasks that are active during next epoch and are not cancled
// current_time shows the start time of the current new epoch.
- if (task.state != CANCELLED && task.expiry_time > (current_time + epoch_interval_secs) ) {
+ if (task.state != CANCELLED && task.expiry_time > (current_time + epoch_interval_secs)) {
gas_committed_for_next_epoch = gas_committed_for_next_epoch + task.max_gas_amount;
};
@@ -189,7 +190,7 @@ module supra_framework::automation_registry_state {
/// - pending, it is removed form the list.
/// - cancelled, an error is reported
/// Committed gas-limit is updated by reducing it with the max-gas-amount of the cancelled task.
- public (friend) fun cancel_task(owner: &signer, id: u64): AutomationTaskMetaData acquires AutomationRegistryState {
+ public(friend) fun cancel_task(owner: &signer, id: u64): AutomationTaskMetaData acquires AutomationRegistryState {
let state = borrow_global_mut(@supra_framework);
assert!(enumerable_map::contains(&state.tasks, id), EAUTOMATION_TASK_NOT_FOUND);
@@ -212,7 +213,7 @@ module supra_framework::automation_registry_state {
/// Update Automation gas limit.
/// If the committed gas amount for the next epoch is greater then the new gas limit, then error is reported.
- public (friend) fun update_automation_gas_limit(
+ public(friend) fun update_automation_gas_limit(
supra_framework: &signer,
automation_gas_limit: u64
) acquires AutomationRegistryState {
@@ -232,21 +233,16 @@ module supra_framework::automation_registry_state {
public(friend) fun get_active_task_ids(): vector acquires AutomationRegistryState {
let state = borrow_global(@supra_framework);
- let active_task_ids = vector[];
- let ids = enumerable_map::get_map_list(&state.tasks);
-
- vector::for_each(ids, |id| {
- let task = enumerable_map::get_value_ref(&state.tasks, id);
- if (task.state != PENDING) {
- vector::push_back(&mut active_task_ids, id);
- };
- });
- return active_task_ids
+ enumerable_map::filter_map(&state.tasks, |task| {
+ let task: AutomationTaskMetaData = task; // we need to define task type here to avoid compiler error
+ if (task.state != PENDING) (true, task.id)
+ else (false, task.id)
+ })
}
/// Retrieves the details of a automation task entry by its ID.
/// Error will be returned if entry with specified ID does not exist.
- public (friend) fun get_task_details(id: u64): AutomationTaskMetaData acquires AutomationRegistryState {
+ public(friend) fun get_task_details(id: u64): AutomationTaskMetaData acquires AutomationRegistryState {
let automation_task_metadata = borrow_global(@supra_framework);
assert!(enumerable_map::contains(&automation_task_metadata.tasks, id), EAUTOMATION_TASK_NOT_FOUND);
enumerable_map::get_value(&automation_task_metadata.tasks, id)
@@ -258,10 +254,11 @@ module supra_framework::automation_registry_state {
if (enumerable_map::contains(&automation_task_metadata.tasks, id)) {
let value = enumerable_map::get_value_ref(&automation_task_metadata.tasks, id);
value.state != PENDING
- } else {
+ } else {
false
}
}
+
#[test_only]
fun has_task_with_id(id: u64): bool acquires AutomationRegistryState {
let automation_task_metadata = borrow_global(@supra_framework);
@@ -269,7 +266,7 @@ module supra_framework::automation_registry_state {
}
/// Returns next task index in registry
- public (friend) fun get_next_task_index(): u64 acquires AutomationRegistryState {
+ public(friend) fun get_next_task_index(): u64 acquires AutomationRegistryState {
let state = borrow_global(@supra_framework);
state.current_index
}
@@ -335,11 +332,11 @@ module supra_framework::automation_registry_state {
let account = account::create_account_for_test(@0x123456);
register(&account,
PAYLOAD,
- 100,
- 10,
- 20,
- 1,
- PARENT_HASH,
+ 100,
+ 10,
+ 20,
+ 1,
+ PARENT_HASH,
);
assert!(1 == get_next_task_index(), 1);
assert!(10 == get_gas_committed_for_next_epoch(), 1)
diff --git a/aptos-move/framework/supra-stdlib/doc/enumerable_map.md b/aptos-move/framework/supra-stdlib/doc/enumerable_map.md
index dedf74812516f..87b8d8e8cc037 100644
--- a/aptos-move/framework/supra-stdlib/doc/enumerable_map.md
+++ b/aptos-move/framework/supra-stdlib/doc/enumerable_map.md
@@ -22,10 +22,19 @@ The module includes error handling and a suite of test functions for validation.
- [Function `clear`](#0x1_enumerable_map_clear)
- [Function `get_value`](#0x1_enumerable_map_get_value)
- [Function `get_value_ref`](#0x1_enumerable_map_get_value_ref)
+- [Function `get_key_by_index`](#0x1_enumerable_map_get_key_by_index)
- [Function `get_value_mut`](#0x1_enumerable_map_get_value_mut)
- [Function `get_map_list`](#0x1_enumerable_map_get_map_list)
- [Function `contains`](#0x1_enumerable_map_contains)
- [Function `length`](#0x1_enumerable_map_length)
+- [Function `for_each_value`](#0x1_enumerable_map_for_each_value)
+- [Function `for_each_value_ref`](#0x1_enumerable_map_for_each_value_ref)
+- [Function `for_each_value_mut`](#0x1_enumerable_map_for_each_value_mut)
+- [Function `for_each_keyval`](#0x1_enumerable_map_for_each_keyval)
+- [Function `filter`](#0x1_enumerable_map_filter)
+- [Function `map`](#0x1_enumerable_map_map)
+- [Function `map_ref`](#0x1_enumerable_map_map_ref)
+- [Function `filter_map`](#0x1_enumerable_map_filter_map)
use 0x1::error;
@@ -188,7 +197,7 @@ To create an empty enum map
Implementation
-public fun new_map<K : copy + drop, V : store+drop+copy>(): EnumerableMap<K, V> {
+public fun new_map<K: copy + drop, V: store+drop+copy>(): EnumerableMap<K, V> {
return EnumerableMap<K, V> { list: vector::empty<K>(), map: table::new<K, Tuple<V>>() }
}
@@ -213,7 +222,7 @@ Add Single Key in the Enumerable Map
Implementation
-public fun add_value<K : copy+drop, V : store+drop+copy>(map: &mut EnumerableMap<K, V>, key: K, value: V) {
+public fun add_value<K: copy+drop, V: store+drop+copy>(map: &mut EnumerableMap<K, V>, key: K, value: V) {
assert!(!contains(map, key), error::already_exists(EKEY_ALREADY_ADDED));
table::add(&mut map.map, key, Tuple<V> { position: vector::length(&map.list), value });
vector::push_back(&mut map.list, key);
@@ -240,7 +249,7 @@ Add Multiple Keys in the Enumerable Map
Implementation
-public fun add_value_bulk<K: copy+drop, V : store+drop+copy>(
+public fun add_value_bulk<K: copy+drop, V: store+drop+copy>(
map: &mut EnumerableMap<K, V>,
keys: vector<K>,
values: vector<V>
@@ -271,10 +280,10 @@ Add Multiple Keys in the Enumerable Map
## Function `update_value`
-Update the value of a key thats already present in the Enumerable Map
+Update the value of a key thats already present in the Enumerable Map and return old value
-public fun update_value<K: copy, drop, V: copy, drop, store>(map: &mut enumerable_map::EnumerableMap<K, V>, key: K, new_value: V): enumerable_map::KeyValue<K, V>
+public fun update_value<K: copy, drop, V: copy, drop, store>(map: &mut enumerable_map::EnumerableMap<K, V>, key: K, new_value: V): V
@@ -283,14 +292,15 @@ Update the value of a key thats already present in the Enumerable Map
Implementation
-public fun update_value<K: copy+drop, V : store+drop+copy>(
+public fun update_value<K: copy+drop, V: store+drop+copy>(
map: &mut EnumerableMap<K, V>,
key: K,
new_value: V
-): KeyValue<K, V> {
+): V {
assert!(contains(map, key), error::not_found(EKEY_ABSENT));
+ let old_value = table::borrow(&mut map.map, key).value;
table::borrow_mut(&mut map.map, key).value = new_value;
- KeyValue { key, value: new_value }
+ old_value
}
@@ -305,7 +315,7 @@ Update the value of a key thats already present in the Enumerable Map
Remove single Key from the Enumerable Map
-public fun remove_value<K: copy, drop, V: copy, drop, store>(map: &mut enumerable_map::EnumerableMap<K, V>, key: K)
+public fun remove_value<K: copy, drop, V: copy, drop, store>(map: &mut enumerable_map::EnumerableMap<K, V>, key: K): V
@@ -314,7 +324,7 @@ Remove single Key from the Enumerable Map
Implementation
-public fun remove_value<K : copy+drop, V : store+drop+copy>(map: &mut EnumerableMap<K, V>, key: K) {
+public fun remove_value<K: copy+drop, V: store+drop+copy>(map: &mut EnumerableMap<K, V>, key: K): V {
assert!(contains(map, key), error::not_found(EKEY_ABSENT));
let map_last_index = vector::length(&map.list) - 1;
@@ -324,7 +334,7 @@ Remove single Key from the Enumerable Map
vector::swap(&mut map.list, index_of_element, map_last_index);
tuple_to_modify.position = index_of_element;
vector::pop_back(&mut map.list);
- table::remove(&mut map.map, key);
+ table::remove(&mut map.map, key).value
}
@@ -348,7 +358,7 @@ Remove Multiple Keys from the Enumerable Map
Implementation
-public fun remove_value_bulk<K : copy+drop, V : store+drop+copy>(
+public fun remove_value_bulk<K: copy+drop, V: store+drop+copy>(
map: &mut EnumerableMap<K, V>,
keys: vector<K>
): vector<K> {
@@ -395,7 +405,7 @@ Will clear the entire data from the Enumerable Map
Implementation
-public fun clear<K : copy+drop, V : store+drop+copy>(map: &mut EnumerableMap<K, V>) {
+public fun clear<K: copy+drop, V: store+drop+copy>(map: &mut EnumerableMap<K, V>) {
let list = get_map_list(map);
remove_value_bulk(map, list);
}
@@ -421,7 +431,7 @@ Returns the value of a key that is present in Enumerable Map
Implementation
-public fun get_value<K : copy+drop, V : store+drop+copy>(map: & EnumerableMap<K, V>, key: K): V {
+public fun get_value<K: copy+drop, V: store+drop+copy>(map: & EnumerableMap<K, V>, key: K): V {
table::borrow(&map.map, key).value
}
@@ -446,13 +456,38 @@ Returns reference to the value of a key that is present in Enumerable Map
Implementation
-public fun get_value_ref<K : copy+drop, V : store+drop+copy>(map: & EnumerableMap<K, V>, key: K): &V {
+public fun get_value_ref<K: copy+drop, V: store+drop+copy>(map: & EnumerableMap<K, V>, key: K): &V {
&table::borrow(&map.map, key).value
}
+
+
+
+
+## Function `get_key_by_index`
+
+Retrieves the key at the specified index from the EnumerableMap's key list.
+
+
+public fun get_key_by_index<K: copy, drop, V: copy, drop, store>(set: &enumerable_map::EnumerableMap<K, V>, index: u64): K
+
+
+
+
+
+Implementation
+
+
+public fun get_key_by_index<K: copy+drop, V: store+drop+copy>(set: &EnumerableMap<K, V>, index: u64): K {
+ *vector::borrow(&set.list, index)
+}
+
+
+
+
@@ -471,7 +506,7 @@ Returns the value of a key that is present in Enumerable Map
Implementation
-public fun get_value_mut<K : copy+drop, V : store+drop+copy>(map: &mut EnumerableMap<K, V>, key: K): &mut V {
+public fun get_value_mut<K: copy+drop, V: store+drop+copy>(map: &mut EnumerableMap<K, V>, key: K): &mut V {
&mut table::borrow_mut(&mut map.map, key).value
}
@@ -496,7 +531,7 @@ Returns the list of keys that the Enumerable Map contains
Implementation
-public fun get_map_list<K : copy+drop, V : store+drop+copy>(map: &EnumerableMap<K, V>): vector<K> {
+public fun get_map_list<K: copy+drop, V: store+drop+copy>(map: &EnumerableMap<K, V>): vector<K> {
return map.list
}
@@ -521,7 +556,7 @@ Check whether Key is present into the Enumerable map or not
Implementation
-public fun contains<K: copy+drop, V : store+drop+copy>(map: &EnumerableMap<K, V>, key: K): bool {
+public fun contains<K: copy+drop, V: store+drop+copy>(map: &EnumerableMap<K, V>, key: K): bool {
table::contains(&map.map, key)
}
@@ -546,13 +581,255 @@ Return current length of the EnumerableSetRing
Implementation
-public fun length<K : copy+drop, V : store+drop+copy>(set: &EnumerableMap<K, V>): u64 {
+public fun length<K: copy+drop, V: store+drop+copy>(set: &EnumerableMap<K, V>): u64 {
return vector::length(&set.list)
}
+
+
+
+
+## Function `for_each_value`
+
+Apply the function to each element in the EnumerableMap.
+
+
+public fun for_each_value<K: copy, drop, V: copy, drop, store>(set: &enumerable_map::EnumerableMap<K, V>, f: |V|)
+
+
+
+
+
+Implementation
+
+
+public inline fun for_each_value<K: copy+drop, V: store+drop+copy>(set: &EnumerableMap<K, V>, f: |V|) {
+ let i = 0;
+ let len = length(set);
+ while (i < len) {
+ let key = get_key_by_index(set, i);
+ f(*get_value_ref(set, key));
+ i = i + 1
+ }
+}
+
+
+
+
+
+
+
+
+## Function `for_each_value_ref`
+
+Apply the function to a reference of each element in the EnumerableMap.
+
+
+public fun for_each_value_ref<K: copy, drop, V: copy, drop, store>(set: &enumerable_map::EnumerableMap<K, V>, f: |&V|)
+
+
+
+
+
+Implementation
+
+
+public inline fun for_each_value_ref<K: copy+drop, V: store+drop+copy>(set: &EnumerableMap<K, V>, f: |&V|) {
+ let i = 0;
+ let len = length(set);
+ while (i < len) {
+ let key = get_key_by_index(set, i);
+ f(get_value_ref(set, key));
+ i = i + 1
+ }
+}
+
+
+
+
+
+
+
+
+## Function `for_each_value_mut`
+
+Apply the function to a mutable reference in the EnumerableMap.
+
+
+public fun for_each_value_mut<K: copy, drop, V: copy, drop, store>(set: &mut enumerable_map::EnumerableMap<K, V>, f: |&mut V|)
+
+
+
+
+
+Implementation
+
+
+public inline fun for_each_value_mut<K: copy+drop, V: store+drop+copy>(set: &mut EnumerableMap<K, V>, f: |&mut V|) {
+ let i = 0;
+ let len = length(set);
+ while (i < len) {
+ let key = get_key_by_index(set, i);
+ f(get_value_mut(set, key));
+ i = i + 1
+ }
+}
+
+
+
+
+
+
+
+
+## Function `for_each_keyval`
+
+Iterates over each key-value pair in an EnumerableMap and applies the provided function
+
+
+public fun for_each_keyval<K: copy, drop, V: copy, drop, store>(set: &enumerable_map::EnumerableMap<K, V>, f: |(K, V)|)
+
+
+
+
+
+Implementation
+
+
+public inline fun for_each_keyval<K: copy+drop, V: store+drop+copy>(set: &EnumerableMap<K, V>, f: |K, V|) {
+ let i = 0;
+ let len = length(set);
+ while (i < len) {
+ let key = get_key_by_index(set, i);
+ f(key, *get_value_ref(set, key));
+ i = i + 1
+ }
+}
+
+
+
+
+
+
+
+
+## Function `filter`
+
+Filter the enumerableMap using the boolean function, removing all elements for which p(v)
is not true.
+
+
+public fun filter<K: copy, drop, V: copy, drop, store>(set: &enumerable_map::EnumerableMap<K, V>, p: |&V|bool): vector<V>
+
+
+
+
+
+Implementation
+
+
+public inline fun filter<K: copy+drop, V: store+drop+copy>(set: &EnumerableMap<K, V>, p: |&V|bool): vector<V> {
+ let result = vector<V>[];
+ for_each_value_ref(set, |v| {
+ if (p(v)) vector::push_back(&mut result, *v);
+ });
+ result
+}
+
+
+
+
+
+
+
+
+## Function `map`
+
+Transforms values in an EnumerableMap using the provided function and returns a vector of results.
+
+
+public fun map<K: copy, drop, V: copy, drop, store, T>(set: &enumerable_map::EnumerableMap<K, V>, f: |V|T): vector<T>
+
+
+
+
+
+Implementation
+
+
+public inline fun map<K: copy+drop, V: store+drop+copy, T>(set: &EnumerableMap<K, V>, f: |V|T): vector<T> {
+ let result = vector<T>[];
+ for_each_value(set, |elem| vector::push_back(&mut result, f(elem)));
+ result
+}
+
+
+
+
+
+
+
+
+## Function `map_ref`
+
+Transforms values in an EnumerableMap by reference using the provided function and returns a vector of results.
+
+
+public fun map_ref<K: copy, drop, V: copy, drop, store, T>(set: &enumerable_map::EnumerableMap<K, V>, f: |&V|T): vector<T>
+
+
+
+
+
+Implementation
+
+
+public inline fun map_ref<K: copy+drop, V: store+drop+copy, T>(set: &EnumerableMap<K, V>, f: |&V|T): vector<T> {
+ let result = vector<T>[];
+ for_each_value_ref(set, |elem| vector::push_back(&mut result, f(elem)));
+ result
+}
+
+
+
+
+
+
+
+
+## Function `filter_map`
+
+Applies a filter and transformation function to values in an EnumerableMap, returning a vector of results.
+
+
+public fun filter_map<K: copy, drop, V: copy, drop, store, T>(set: &enumerable_map::EnumerableMap<K, V>, f: |V|(bool, T)): vector<T>
+
+
+
+
+
+Implementation
+
+
+public inline fun filter_map<K: copy+drop, V: store+drop+copy, T>(
+ set: &EnumerableMap<K, V>,
+ f: |V| (bool, T)
+): vector<T> {
+ let result = vector<T>[];
+ for_each_value(set, |v| {
+ let (should_include, transformed_value) = f(v);
+ if (should_include) {
+ vector::push_back(&mut result, transformed_value);
+ }
+ });
+ result
+}
+
+
+
+
diff --git a/aptos-move/framework/supra-stdlib/sources/enumerable_map.move b/aptos-move/framework/supra-stdlib/sources/enumerable_map.move
index dfc4c22d0895a..df2b6a67b2e4f 100644
--- a/aptos-move/framework/supra-stdlib/sources/enumerable_map.move
+++ b/aptos-move/framework/supra-stdlib/sources/enumerable_map.move
@@ -15,7 +15,7 @@ module supra_std::enumerable_map {
const EVECTOR_EMPTY: u64 = 3;
/// Enumerable Map to store the key value pairs
- struct EnumerableMap has store {
+ struct EnumerableMap has store {
/// List of all keys
list: vector,
/// Key mapped to a tuple containing the (position of key in list and value corresponding to the key)
@@ -23,31 +23,31 @@ module supra_std::enumerable_map {
}
/// Tuple to store the position of key in list and value corresponding to the key
- struct Tuple has store, copy, drop {
+ struct Tuple has store, copy, drop {
position: u64,
value: V,
}
/// Return type
- struct KeyValue has store, copy, drop {
+ struct KeyValue has store, copy, drop {
key: K,
value: V,
}
/// To create an empty enum map
- public fun new_map(): EnumerableMap {
+ public fun new_map(): EnumerableMap {
return EnumerableMap { list: vector::empty(), map: table::new>() }
}
/// Add Single Key in the Enumerable Map
- public fun add_value(map: &mut EnumerableMap, key: K, value: V) {
+ public fun add_value(map: &mut EnumerableMap, key: K, value: V) {
assert!(!contains(map, key), error::already_exists(EKEY_ALREADY_ADDED));
table::add(&mut map.map, key, Tuple { position: vector::length(&map.list), value });
vector::push_back(&mut map.list, key);
}
/// Add Multiple Keys in the Enumerable Map
- public fun add_value_bulk(
+ public fun add_value_bulk(
map: &mut EnumerableMap,
keys: vector,
values: vector
@@ -69,19 +69,20 @@ module supra_std::enumerable_map {
return updated_keys
}
- /// Update the value of a key thats already present in the Enumerable Map
- public fun update_value(
+ /// Update the value of a key thats already present in the Enumerable Map and return old value
+ public fun update_value(
map: &mut EnumerableMap,
key: K,
new_value: V
- ): KeyValue {
+ ): V {
assert!(contains(map, key), error::not_found(EKEY_ABSENT));
+ let old_value = table::borrow(&mut map.map, key).value;
table::borrow_mut(&mut map.map, key).value = new_value;
- KeyValue { key, value: new_value }
+ old_value
}
/// Remove single Key from the Enumerable Map
- public fun remove_value(map: &mut EnumerableMap, key: K) {
+ public fun remove_value(map: &mut EnumerableMap, key: K): V {
assert!(contains(map, key), error::not_found(EKEY_ABSENT));
let map_last_index = vector::length(&map.list) - 1;
@@ -91,11 +92,11 @@ module supra_std::enumerable_map {
vector::swap(&mut map.list, index_of_element, map_last_index);
tuple_to_modify.position = index_of_element;
vector::pop_back(&mut map.list);
- table::remove(&mut map.map, key);
+ table::remove(&mut map.map, key).value
}
/// Remove Multiple Keys from the Enumerable Map
- public fun remove_value_bulk(
+ public fun remove_value_bulk(
map: &mut EnumerableMap,
keys: vector
): vector {
@@ -122,57 +123,148 @@ module supra_std::enumerable_map {
}
/// Will clear the entire data from the Enumerable Map
- public fun clear(map: &mut EnumerableMap) {
+ public fun clear(map: &mut EnumerableMap) {
let list = get_map_list(map);
remove_value_bulk(map, list);
}
/// Returns the value of a key that is present in Enumerable Map
- public fun get_value(map: & EnumerableMap, key: K): V {
+ public fun get_value(map: & EnumerableMap, key: K): V {
table::borrow(&map.map, key).value
}
/// Returns reference to the value of a key that is present in Enumerable Map
- public fun get_value_ref(map: & EnumerableMap, key: K): &V {
+ public fun get_value_ref(map: & EnumerableMap, key: K): &V {
&table::borrow(&map.map, key).value
}
+ /// Retrieves the key at the specified index from the EnumerableMap's key list.
+ public fun get_key_by_index(set: &EnumerableMap, index: u64): K {
+ *vector::borrow(&set.list, index)
+ }
/// Returns the value of a key that is present in Enumerable Map
- public fun get_value_mut(map: &mut EnumerableMap, key: K): &mut V {
+ public fun get_value_mut(map: &mut EnumerableMap, key: K): &mut V {
&mut table::borrow_mut(&mut map.map, key).value
}
/// Returns the list of keys that the Enumerable Map contains
- public fun get_map_list(map: &EnumerableMap): vector {
+ public fun get_map_list(map: &EnumerableMap): vector {
return map.list
}
/// Check whether Key is present into the Enumerable map or not
- public fun contains(map: &EnumerableMap, key: K): bool {
+ public fun contains(map: &EnumerableMap, key: K): bool {
table::contains(&map.map, key)
}
/// Return current length of the EnumerableSetRing
- public fun length(set: &EnumerableMap): u64 {
+ public fun length(set: &EnumerableMap): u64 {
return vector::length(&set.list)
}
+ /// Apply the function to each element in the EnumerableMap.
+ public inline fun for_each_value(set: &EnumerableMap, f: |V|) {
+ let i = 0;
+ let len = length(set);
+ while (i < len) {
+ let key = get_key_by_index(set, i);
+ f(*get_value_ref(set, key));
+ i = i + 1
+ }
+ }
+
+ /// Apply the function to a reference of each element in the EnumerableMap.
+ public inline fun for_each_value_ref(set: &EnumerableMap, f: |&V|) {
+ let i = 0;
+ let len = length(set);
+ while (i < len) {
+ let key = get_key_by_index(set, i);
+ f(get_value_ref(set, key));
+ i = i + 1
+ }
+ }
+
+ /// Apply the function to a mutable reference in the EnumerableMap.
+ public inline fun for_each_value_mut(set: &mut EnumerableMap, f: |&mut V|) {
+ let i = 0;
+ let len = length(set);
+ while (i < len) {
+ let key = get_key_by_index(set, i);
+ f(get_value_mut(set, key));
+ i = i + 1
+ }
+ }
+
+ /// Iterates over each key-value pair in an EnumerableMap and applies the provided function
+ public inline fun for_each_keyval(set: &EnumerableMap, f: |K, V|) {
+ let i = 0;
+ let len = length(set);
+ while (i < len) {
+ let key = get_key_by_index(set, i);
+ f(key, *get_value_ref(set, key));
+ i = i + 1
+ }
+ }
+
+ /// Filter the enumerableMap using the boolean function, removing all elements for which `p(v)` is not true.
+ public inline fun filter(set: &EnumerableMap, p: |&V|bool): vector {
+ let result = vector[];
+ for_each_value_ref(set, |v| {
+ if (p(v)) vector::push_back(&mut result, *v);
+ });
+ result
+ }
+
+ /// Transforms values in an EnumerableMap using the provided function and returns a vector of results.
+ public inline fun map(set: &EnumerableMap, f: |V|T): vector {
+ let result = vector[];
+ for_each_value(set, |elem| vector::push_back(&mut result, f(elem)));
+ result
+ }
+
+ /// Transforms values in an EnumerableMap by reference using the provided function and returns a vector of results.
+ public inline fun map_ref(set: &EnumerableMap, f: |&V|T): vector {
+ let result = vector[];
+ for_each_value_ref(set, |elem| vector::push_back(&mut result, f(elem)));
+ result
+ }
+
+ /// Applies a filter and transformation function to values in an EnumerableMap, returning a vector of results.
+ public inline fun filter_map(
+ set: &EnumerableMap,
+ f: |V| (bool, T)
+ ): vector {
+ let result = vector[];
+ for_each_value(set, |v| {
+ let (should_include, transformed_value) = f(v);
+ if (should_include) {
+ vector::push_back(&mut result, transformed_value);
+ }
+ });
+ result
+ }
+
#[test_only]
- struct EnumerableMapTest has key {
+ struct EnumerableMapTest has key {
e: EnumerableMap
}
- #[test(owner= @0x1111)]
- public fun test_add_value(owner: &signer) {
+ #[test_only]
+ fun get_enum_map(): EnumerableMap {
let enum_map = new_map();
-
add_value(&mut enum_map, 1, 1);
add_value(&mut enum_map, 2, 2);
add_value(&mut enum_map, 3, 3);
add_value(&mut enum_map, 4, 4);
add_value(&mut enum_map, 5, 5);
add_value(&mut enum_map, 6, 6);
+ enum_map
+ }
+
+ #[test(owner= @0x1111)]
+ public fun test_add_value(owner: &signer) {
+ let enum_map = get_enum_map();
assert!(contains(&enum_map, 3), 1);
assert!(length(&enum_map) == 6, 2);
@@ -182,14 +274,7 @@ module supra_std::enumerable_map {
#[test(owner= @0x1111)]
public fun test_add_value_bulk(owner: &signer) {
- let enum_map = new_map();
-
- add_value(&mut enum_map, 1, 1);
- add_value(&mut enum_map, 2, 2);
- add_value(&mut enum_map, 3, 3);
- add_value(&mut enum_map, 4, 4);
- add_value(&mut enum_map, 5, 5);
- add_value(&mut enum_map, 6, 6);
+ let enum_map = get_enum_map();
add_value_bulk(&mut enum_map, vector[7, 8, 9], vector[7, 8, 9]);
@@ -202,14 +287,7 @@ module supra_std::enumerable_map {
#[test(owner= @0x1111)]
#[expected_failure(abort_code = 1, location = Self)]
public fun test_remove_value(owner: &signer) {
- let enum_map = new_map();
-
- add_value(&mut enum_map, 1, 1);
- add_value(&mut enum_map, 2, 2);
- add_value(&mut enum_map, 3, 3);
- add_value(&mut enum_map, 4, 4);
- add_value(&mut enum_map, 5, 5);
- add_value(&mut enum_map, 6, 6);
+ let enum_map = get_enum_map();
remove_value(&mut enum_map, 1);
remove_value(&mut enum_map, 2);
@@ -224,14 +302,7 @@ module supra_std::enumerable_map {
#[test(owner= @0x1111)]
#[expected_failure(abort_code = 2, location = Self)]
public fun test_remove_bulk_value(owner: &signer) {
- let enum_map = new_map();
-
- add_value(&mut enum_map, 1, 1);
- add_value(&mut enum_map, 2, 2);
- add_value(&mut enum_map, 3, 3);
- add_value(&mut enum_map, 4, 4);
- add_value(&mut enum_map, 5, 5);
- add_value(&mut enum_map, 6, 6);
+ let enum_map = get_enum_map();
remove_value_bulk(&mut enum_map, vector[1, 2, 3]);
@@ -244,14 +315,7 @@ module supra_std::enumerable_map {
#[test(owner= @0x1111)]
#[expected_failure(abort_code = 3, location = Self)]
public fun test_update_value(owner: &signer) {
- let enum_map = new_map();
-
- add_value(&mut enum_map, 1, 1);
- add_value(&mut enum_map, 2, 2);
- add_value(&mut enum_map, 3, 3);
- add_value(&mut enum_map, 4, 4);
- add_value(&mut enum_map, 5, 5);
- add_value(&mut enum_map, 6, 6);
+ let enum_map = get_enum_map();
update_value(&mut enum_map, 1, 7);
@@ -264,14 +328,7 @@ module supra_std::enumerable_map {
#[test(owner= @0x1111)]
public fun test_clear(owner: &signer) {
- let enum_map = new_map();
-
- add_value(&mut enum_map, 1, 1);
- add_value(&mut enum_map, 2, 2);
- add_value(&mut enum_map, 3, 3);
- add_value(&mut enum_map, 4, 4);
- add_value(&mut enum_map, 5, 5);
- add_value(&mut enum_map, 6, 6);
+ let enum_map = get_enum_map();
clear(&mut enum_map);
@@ -279,4 +336,69 @@ module supra_std::enumerable_map {
move_to(owner, EnumerableMapTest { e: enum_map })
}
+
+ #[test(owner= @0x1111)]
+ public fun test_for_each_value_and_ref(owner: &signer) {
+ let enum_map = get_enum_map();
+
+ let i = 1;
+ for_each_value_ref(&enum_map, |v| {
+ assert!(v == &i, 100);
+ i = i + 1;
+ });
+
+ let j = 1;
+ for_each_value_mut(&mut enum_map, |v| {
+ *v = j + 1; // update value with 1 increament
+ j = j + 1;
+ });
+
+ let k = 1;
+ for_each_value(&enum_map, |v| {
+ assert!(v == k + 1, 300);
+ k = k + 1;
+ });
+
+ move_to(owner, EnumerableMapTest { e: enum_map })
+ }
+
+ #[test(owner= @0x1111)]
+ public fun test_filter(owner: &signer) {
+ let enum_map = get_enum_map();
+
+ let result = filter(&enum_map, |v| *v > 3);
+
+ assert!(result == vector[4, 5, 6], 300);
+
+ move_to(owner, EnumerableMapTest { e: enum_map })
+ }
+
+ #[test(owner= @0x1111)]
+ public fun test_map_and_ref(owner: &signer) {
+ let enum_map = get_enum_map();
+
+ let result = map(&enum_map, |v| v * 3);
+
+ assert!(result == vector[3, 6, 9, 12, 15, 18], 400);
+
+ let result = map_ref(&enum_map, |v| *v * 2);
+
+ assert!(result == vector[2, 4, 6, 8, 10, 12], 500);
+
+ move_to(owner, EnumerableMapTest { e: enum_map })
+ }
+
+ #[test(owner= @0x1111)]
+ public fun test_filter_map_and_ref(owner: &signer) {
+ let enum_map = get_enum_map();
+
+ let result = filter_map(&enum_map, |v|
+ if (v % 2 == 0) (true, v)
+ else (false, 0)
+ );
+
+ assert!(result == vector[2, 4, 6], 600);
+
+ move_to(owner, EnumerableMapTest { e: enum_map })
+ }
}