From 3013155e2724cd1c01eafb0ce71794ffdd1e47b4 Mon Sep 17 00:00:00 2001 From: Igor Date: Fri, 9 Aug 2024 21:57:38 -0700 Subject: [PATCH] [framework] Add copyable_any_map::AnyMap --- .../framework/aptos-stdlib/doc/any_map.md | 225 ++++++++++++++++++ .../framework/aptos-stdlib/doc/overview.md | 1 + .../sources/data_structures/any_map.move | 49 ++++ .../sources/data_structures/ordered_map.move | 2 + .../aptos-stdlib/sources/from_bcs.move | 2 +- 5 files changed, 278 insertions(+), 1 deletion(-) create mode 100644 aptos-move/framework/aptos-stdlib/doc/any_map.md create mode 100644 aptos-move/framework/aptos-stdlib/sources/data_structures/any_map.move diff --git a/aptos-move/framework/aptos-stdlib/doc/any_map.md b/aptos-move/framework/aptos-stdlib/doc/any_map.md new file mode 100644 index 00000000000000..8f56bc44a7cefc --- /dev/null +++ b/aptos-move/framework/aptos-stdlib/doc/any_map.md @@ -0,0 +1,225 @@ + + + +# Module `0x1::any_map` + + + +- [Struct `AnyMap`](#0x1_any_map_AnyMap) +- [Constants](#@Constants_0) +- [Function `new`](#0x1_any_map_new) +- [Function `add`](#0x1_any_map_add) +- [Function `get_copy`](#0x1_any_map_get_copy) +- [Function `remove`](#0x1_any_map_remove) +- [Function `remove_if_present`](#0x1_any_map_remove_if_present) +- [Function `length`](#0x1_any_map_length) + + +
use 0x1::bcs;
+use 0x1::from_bcs;
+use 0x1::option;
+use 0x1::ordered_map;
+use 0x1::string;
+use 0x1::type_info;
+use 0x1::vector;
+
+ + + + + +## Struct `AnyMap` + + + +
struct AnyMap has drop, store
+
+ + + +
+Fields + + +
+
+entries: ordered_map::OrderedMap<string::String, vector<u8>> +
+
+ +
+
+ + +
+ + + +## Constants + + + + +The type provided for unpack is not the same as was given for pack. + + +
const ETYPE_MISMATCH: u64 = 1;
+
+ + + + + +## Function `new` + + + +
public fun new(): any_map::AnyMap
+
+ + + +
+Implementation + + +
public fun new(): AnyMap {
+    AnyMap {
+        entries: ordered_map::new(),
+    }
+}
+
+ + + +
+ + + +## Function `add` + + + +
public fun add<T: drop, store>(self: &mut any_map::AnyMap, x: T)
+
+ + + +
+Implementation + + +
public fun add<T: drop + store>(self: &mut AnyMap, x: T) {
+    self.entries.add(type_info::type_name<T>(), to_bytes(&x));
+}
+
+ + + +
+ + + +## Function `get_copy` + + + +
public fun get_copy<T: copy, drop, store>(self: &any_map::AnyMap): T
+
+ + + +
+Implementation + + +
public fun get_copy<T: copy + drop + store>(self: &AnyMap): T {
+    let data = self.entries.borrow(&type_info::type_name<T>());
+    from_bcs::from_bytes<T>(vector::slice(data, 0, vector::length(data)))
+}
+
+ + + +
+ + + +## Function `remove` + + + +
public fun remove<T>(self: &mut any_map::AnyMap): T
+
+ + + +
+Implementation + + +
public fun remove<T>(self: &mut AnyMap): T {
+    let data = self.entries.remove(&type_info::type_name<T>());
+    from_bcs::from_bytes<T>(data)
+}
+
+ + + +
+ + + +## Function `remove_if_present` + + + +
public fun remove_if_present<T>(self: &mut any_map::AnyMap): option::Option<T>
+
+ + + +
+Implementation + + +
public fun remove_if_present<T>(self: &mut AnyMap): option::Option<T> {
+    let iter = self.entries.find(&type_info::type_name<T>());
+    if (iter.iter_is_end(&self.entries)) {
+        option::none()
+    } else {
+        option::some(from_bcs::from_bytes<T>(iter.iter_remove(&mut self.entries)))
+    }
+}
+
+ + + +
+ + + +## Function `length` + + + +
public fun length(self: &any_map::AnyMap): u64
+
+ + + +
+Implementation + + +
public fun length(self: &AnyMap): u64 {
+    self.entries.length()
+}
+
+ + + +
+ + +[move-book]: https://aptos.dev/move/book/SUMMARY diff --git a/aptos-move/framework/aptos-stdlib/doc/overview.md b/aptos-move/framework/aptos-stdlib/doc/overview.md index fa811e7bef51de..efa85e003ee85e 100644 --- a/aptos-move/framework/aptos-stdlib/doc/overview.md +++ b/aptos-move/framework/aptos-stdlib/doc/overview.md @@ -13,6 +13,7 @@ This is the reference documentation of the Aptos standard library. - [`0x1::any`](any.md#0x1_any) +- [`0x1::any_map`](any_map.md#0x1_any_map) - [`0x1::aptos_hash`](hash.md#0x1_aptos_hash) - [`0x1::big_ordered_map`](big_ordered_map.md#0x1_big_ordered_map) - [`0x1::big_vector`](big_vector.md#0x1_big_vector) diff --git a/aptos-move/framework/aptos-stdlib/sources/data_structures/any_map.move b/aptos-move/framework/aptos-stdlib/sources/data_structures/any_map.move new file mode 100644 index 00000000000000..7fac64bce5c9ee --- /dev/null +++ b/aptos-move/framework/aptos-stdlib/sources/data_structures/any_map.move @@ -0,0 +1,49 @@ +module aptos_std::any_map { + use std::bcs::to_bytes; + use std::option; + use std::string::String; + use std::vector; + use aptos_std::from_bcs; + use aptos_std::ordered_map::{Self, OrderedMap}; + use aptos_std::type_info; + + /// The type provided for `unpack` is not the same as was given for `pack`. + const ETYPE_MISMATCH: u64 = 1; + + struct AnyMap has drop, store { + entries: OrderedMap>, + } + + public fun new(): AnyMap { + AnyMap { + entries: ordered_map::new(), + } + } + + public fun add(self: &mut AnyMap, x: T) { + self.entries.add(type_info::type_name(), to_bytes(&x)); + } + + public fun get_copy(self: &AnyMap): T { + let data = self.entries.borrow(&type_info::type_name()); + from_bcs::from_bytes(vector::slice(data, 0, vector::length(data))) + } + + public fun remove(self: &mut AnyMap): T { + let data = self.entries.remove(&type_info::type_name()); + from_bcs::from_bytes(data) + } + + public fun remove_if_present(self: &mut AnyMap): option::Option { + let iter = self.entries.find(&type_info::type_name()); + if (iter.iter_is_end(&self.entries)) { + option::none() + } else { + option::some(from_bcs::from_bytes(iter.iter_remove(&mut self.entries))) + } + } + + public fun length(self: &AnyMap): u64 { + self.entries.length() + } +} diff --git a/aptos-move/framework/aptos-stdlib/sources/data_structures/ordered_map.move b/aptos-move/framework/aptos-stdlib/sources/data_structures/ordered_map.move index 2aa56f6bb5d1cc..fd28af80cf66f2 100644 --- a/aptos-move/framework/aptos-stdlib/sources/data_structures/ordered_map.move +++ b/aptos-move/framework/aptos-stdlib/sources/data_structures/ordered_map.move @@ -24,6 +24,8 @@ /// module aptos_std::ordered_map { friend aptos_std::big_ordered_map; + // Friend until iterator API is finalized + friend aptos_std::any_map; use std::vector; diff --git a/aptos-move/framework/aptos-stdlib/sources/from_bcs.move b/aptos-move/framework/aptos-stdlib/sources/from_bcs.move index 3eb6e2177d2f42..ee962ab748ceb4 100644 --- a/aptos-move/framework/aptos-stdlib/sources/from_bcs.move +++ b/aptos-move/framework/aptos-stdlib/sources/from_bcs.move @@ -67,7 +67,7 @@ module aptos_std::from_bcs { public(friend) native fun from_bytes(bytes: vector): T; friend aptos_std::any; friend aptos_std::copyable_any; - + friend aptos_std::any_map; #[test_only] use std::bcs;