property_map - [mainnet]
PropertyMap is a specialization of SimpleMap for Tokens.
It maps a String key to a PropertyValue that consists of type (string) and value (vector
use 0x1::bcs;
use 0x1::from_bcs;
use 0x1::simple_map;
use 0x1::string;
use 0x1::type_info;
Constants
The property key already exists
const EKEY_AREADY_EXIST_IN_PROPERTY_MAP: u64 = 1;
Property key and type count don’t match
const EKEY_COUNT_NOT_MATCH_TYPE_COUNT: u64 = 5;
Property key and value count don’t match
const EKEY_COUNT_NOT_MATCH_VALUE_COUNT: u64 = 4;
The name (key) of the property is too long
const EPROPERTY_MAP_NAME_TOO_LONG: u64 = 7;
The property doesn’t exist
const EPROPERTY_NOT_EXIST: u64 = 3;
The number of property exceeds the limit
const EPROPERTY_NUMBER_EXCEED_LIMIT: u64 = 2;
Property type doesn’t match
const ETYPE_NOT_MATCH: u64 = 6;
The maximal number of property that can be stored in property map
const MAX_PROPERTY_MAP_SIZE: u64 = 1000;
const MAX_PROPERTY_NAME_LENGTH: u64 = 128;
Structs
PropertyMap
struct PropertyMap has copy, drop, store
Fields
PropertyValue
struct PropertyValue has copy, drop, store
Fields
-
value: vector<u8> -
type: string::String
Functions
new
public fun new(keys: vector<string::String>, values: vector<vector<u8>>, types: vector<string::String>): property_map::PropertyMap
Implementation
public fun new(
keys: vector<String>,
values: vector<vector<u8>>,
types: vector<String>
): PropertyMap {
let length = keys.length();
assert!(length <= MAX_PROPERTY_MAP_SIZE, error::invalid_argument(EPROPERTY_NUMBER_EXCEED_LIMIT));
assert!(length == values.length(), error::invalid_argument(EKEY_COUNT_NOT_MATCH_VALUE_COUNT));
assert!(length == types.length(), error::invalid_argument(EKEY_COUNT_NOT_MATCH_TYPE_COUNT));
let properties = empty();
for (i in 0..length) {
let key = keys[i];
assert!(key.length() <= MAX_PROPERTY_NAME_LENGTH, error::invalid_argument(EPROPERTY_MAP_NAME_TOO_LONG));
properties.map.add(
key,
PropertyValue { value: values[i], type: types[i] }
);
};
properties
}
new_with_key_and_property_value
Create property map directly from key and property value
public fun new_with_key_and_property_value(keys: vector<string::String>, values: vector<property_map::PropertyValue>): property_map::PropertyMap
Implementation
public fun new_with_key_and_property_value(
keys: vector<String>,
values: vector<PropertyValue>
): PropertyMap {
let length = keys.length();
assert!(length <= MAX_PROPERTY_MAP_SIZE, error::invalid_argument(EPROPERTY_NUMBER_EXCEED_LIMIT));
assert!(length == values.length(), error::invalid_argument(EKEY_COUNT_NOT_MATCH_VALUE_COUNT));
let properties = empty();
for (i in 0..length) {
let key = keys[i];
let val = values[i];
assert!(key.length() <= MAX_PROPERTY_NAME_LENGTH, error::invalid_argument(EPROPERTY_MAP_NAME_TOO_LONG));
properties.add(key, val);
};
properties
}
empty
public fun empty(): property_map::PropertyMap
Implementation
public fun empty(): PropertyMap {
PropertyMap {
map: simple_map::create<String, PropertyValue>(),
}
}
contains_key
public fun contains_key(self: &property_map::PropertyMap, key: &string::String): bool
Implementation
public fun contains_key(self: &PropertyMap, key: &String): bool {
self.map.contains_key(key)
}
add
public fun add(self: &mut property_map::PropertyMap, key: string::String, value: property_map::PropertyValue)
Implementation
public fun add(self: &mut PropertyMap, key: String, value: PropertyValue) {
assert!(key.length() <= MAX_PROPERTY_NAME_LENGTH, error::invalid_argument(EPROPERTY_MAP_NAME_TOO_LONG));
assert!(self.map.length() < MAX_PROPERTY_MAP_SIZE, error::invalid_state(EPROPERTY_NUMBER_EXCEED_LIMIT));
self.map.add(key, value);
}
length
public fun length(self: &property_map::PropertyMap): u64
Implementation
public fun length(self: &PropertyMap): u64 {
self.map.length()
}
borrow
public fun borrow(self: &property_map::PropertyMap, key: &string::String): &property_map::PropertyValue
Implementation
public fun borrow(self: &PropertyMap, key: &String): &PropertyValue {
let found = self.contains_key(key);
assert!(found, EPROPERTY_NOT_EXIST);
self.map.borrow(key)
}
keys
Return all the keys in the property map in the order they are added.
public fun keys(self: &property_map::PropertyMap): vector<string::String>
Implementation
public fun keys(self: &PropertyMap): vector<String> {
self.map.keys()
}
types
Return the types of all properties in the property map in the order they are added.
public fun types(self: &property_map::PropertyMap): vector<string::String>
Implementation
public fun types(self: &PropertyMap): vector<String> {
self.map.values().map_ref(|v| {
v.type
})
}
values
Return the values of all properties in the property map in the order they are added.
public fun values(self: &property_map::PropertyMap): vector<vector<u8>>
Implementation
public fun values(self: &PropertyMap): vector<vector<u8>> {
self.map.values().map_ref(|v| {
v.value
})
}
read_string
public fun read_string(self: &property_map::PropertyMap, key: &string::String): string::String
Implementation
public fun read_string(self: &PropertyMap, key: &String): String {
let prop = self.borrow(key);
assert!(prop.type == string::utf8(b"0x1::string::String"), error::invalid_state(ETYPE_NOT_MATCH));
from_bcs::to_string(prop.value)
}
read_u8
public fun read_u8(self: &property_map::PropertyMap, key: &string::String): u8
Implementation
public fun read_u8(self: &PropertyMap, key: &String): u8 {
let prop = self.borrow(key);
assert!(prop.type == string::utf8(b"u8"), error::invalid_state(ETYPE_NOT_MATCH));
from_bcs::to_u8(prop.value)
}
read_u64
public fun read_u64(self: &property_map::PropertyMap, key: &string::String): u64
Implementation
public fun read_u64(self: &PropertyMap, key: &String): u64 {
let prop = self.borrow(key);
assert!(prop.type == string::utf8(b"u64"), error::invalid_state(ETYPE_NOT_MATCH));
from_bcs::to_u64(prop.value)
}
read_address
public fun read_address(self: &property_map::PropertyMap, key: &string::String): address
Implementation
public fun read_address(self: &PropertyMap, key: &String): address {
let prop = self.borrow(key);
assert!(prop.type == string::utf8(b"address"), error::invalid_state(ETYPE_NOT_MATCH));
from_bcs::to_address(prop.value)
}
read_u128
public fun read_u128(self: &property_map::PropertyMap, key: &string::String): u128
Implementation
public fun read_u128(self: &PropertyMap, key: &String): u128 {
let prop = self.borrow(key);
assert!(prop.type == string::utf8(b"u128"), error::invalid_state(ETYPE_NOT_MATCH));
from_bcs::to_u128(prop.value)
}
read_bool
public fun read_bool(self: &property_map::PropertyMap, key: &string::String): bool
Implementation
public fun read_bool(self: &PropertyMap, key: &String): bool {
let prop = self.borrow(key);
assert!(prop.type == string::utf8(b"bool"), error::invalid_state(ETYPE_NOT_MATCH));
from_bcs::to_bool(prop.value)
}
borrow_value
public fun borrow_value(self: &property_map::PropertyValue): vector<u8>
Implementation
public fun borrow_value(self: &PropertyValue): vector<u8> {
self.value
}
borrow_type
public fun borrow_type(self: &property_map::PropertyValue): string::String
Implementation
public fun borrow_type(self: &PropertyValue): String {
self.type
}
remove
public fun remove(self: &mut property_map::PropertyMap, key: &string::String): (string::String, property_map::PropertyValue)
Implementation
public fun remove(
self: &mut PropertyMap,
key: &String
): (String, PropertyValue) {
let found = self.contains_key(key);
assert!(found, error::not_found(EPROPERTY_NOT_EXIST));
self.map.remove(key)
}
update_property_map
Update the property in the existing property map Allow updating existing keys’ value and add new key-value pairs
public fun update_property_map(self: &mut property_map::PropertyMap, keys: vector<string::String>, values: vector<vector<u8>>, types: vector<string::String>)
Implementation
public fun update_property_map(
self: &mut PropertyMap,
keys: vector<String>,
values: vector<vector<u8>>,
types: vector<String>,
) {
let key_len = keys.length();
let val_len = values.length();
let typ_len = types.length();
assert!(key_len == val_len, error::invalid_state(EKEY_COUNT_NOT_MATCH_VALUE_COUNT));
assert!(key_len == typ_len, error::invalid_state(EKEY_COUNT_NOT_MATCH_TYPE_COUNT));
for (i in 0..key_len) {
let key = &keys[i];
let prop_val = PropertyValue {
value: values[i],
type: types[i],
};
if (self.contains_key(key)) {
self.update_property_value(key, prop_val);
} else {
self.add(*key, prop_val);
};
}
}
update_property_value
public fun update_property_value(self: &mut property_map::PropertyMap, key: &string::String, value: property_map::PropertyValue)
Implementation
public fun update_property_value(
self: &mut PropertyMap,
key: &String,
value: PropertyValue
) {
let property_val = self.map.borrow_mut(key);
*property_val = value;
}
create_property_value_raw
public fun create_property_value_raw(value: vector<u8>, type: string::String): property_map::PropertyValue
Implementation
public fun create_property_value_raw(
value: vector<u8>,
type: String
): PropertyValue {
PropertyValue {
value,
type,
}
}
create_property_value
create a property value from generic type data
public fun create_property_value<T: copy>(data: &T): property_map::PropertyValue
Implementation
public fun create_property_value<T: copy>(data: &T): PropertyValue {
let name = type_name<T>();
if (
name == string::utf8(b"bool") ||
name == string::utf8(b"u8") ||
name == string::utf8(b"u64") ||
name == string::utf8(b"u128") ||
name == string::utf8(b"address") ||
name == string::utf8(b"0x1::string::String")
) {
create_property_value_raw(bcs::to_bytes<T>(data), name)
} else {
create_property_value_raw(bcs::to_bytes<T>(data), string::utf8(b"vector<u8>"))
}
}
Specification
pragma verify = true;
pragma aborts_if_is_strict;
let MAX_PROPERTY_MAP_SIZE = 1000;
let MAX_PROPERTY_NAME_LENGTH = 128;
new
public fun new(keys: vector<string::String>, values: vector<vector<u8>>, types: vector<string::String>): property_map::PropertyMap
pragma aborts_if_is_partial;
let length = len(keys);
aborts_if !(length <= MAX_PROPERTY_MAP_SIZE);
aborts_if !(length == len(values));
aborts_if !(length == len(types));
new_with_key_and_property_value
public fun new_with_key_and_property_value(keys: vector<string::String>, values: vector<property_map::PropertyValue>): property_map::PropertyMap
pragma aborts_if_is_partial;
let length = len(keys);
aborts_if !(length <= MAX_PROPERTY_MAP_SIZE);
aborts_if !(length == len(values));
empty
public fun empty(): property_map::PropertyMap
aborts_if false;
contains_key
public fun contains_key(self: &property_map::PropertyMap, key: &string::String): bool
aborts_if false;
add
public fun add(self: &mut property_map::PropertyMap, key: string::String, value: property_map::PropertyValue)
aborts_if !(key.length() <= MAX_PROPERTY_NAME_LENGTH);
aborts_if !(!simple_map::spec_contains_key(self.map, key));
aborts_if !(simple_map::spec_len(self.map) < MAX_PROPERTY_MAP_SIZE);
length
public fun length(self: &property_map::PropertyMap): u64
aborts_if false;
borrow
public fun borrow(self: &property_map::PropertyMap, key: &string::String): &property_map::PropertyValue
aborts_if !simple_map::spec_contains_key(self.map, key);
keys
public fun keys(self: &property_map::PropertyMap): vector<string::String>
pragma verify = false;
types
public fun types(self: &property_map::PropertyMap): vector<string::String>
pragma verify = false;
values
public fun values(self: &property_map::PropertyMap): vector<vector<u8>>
pragma verify = false;
read_string
public fun read_string(self: &property_map::PropertyMap, key: &string::String): string::String
Check utf8 for correctness and whether equal
to prop.type
pragma aborts_if_is_partial;
aborts_if !simple_map::spec_contains_key(self.map, key);
aborts_if !string::spec_internal_check_utf8(b"0x1::string::String");
let prop = simple_map::spec_get(self.map, key);
aborts_if prop.type != spec_utf8(b"0x1::string::String");
aborts_if !aptos_std::from_bcs::deserializable<String>(prop.value);
fun spec_utf8(bytes: vector<u8>): String {
String { bytes }
}
read_u8
public fun read_u8(self: &property_map::PropertyMap, key: &string::String): u8
let str = b"u8";
aborts_if !simple_map::spec_contains_key(self.map, key);
aborts_if !string::spec_internal_check_utf8(str);
let prop = simple_map::spec_get(self.map, key);
aborts_if prop.type != spec_utf8(str);
aborts_if !aptos_std::from_bcs::deserializable<u8>(prop.value);
read_u64
public fun read_u64(self: &property_map::PropertyMap, key: &string::String): u64
let str = b"u64";
aborts_if !simple_map::spec_contains_key(self.map, key);
aborts_if !string::spec_internal_check_utf8(str);
let prop = simple_map::spec_get(self.map, key);
aborts_if prop.type != spec_utf8(str);
aborts_if !aptos_std::from_bcs::deserializable<u64>(prop.value);
read_address
public fun read_address(self: &property_map::PropertyMap, key: &string::String): address
let str = b"address";
aborts_if !simple_map::spec_contains_key(self.map, key);
aborts_if !string::spec_internal_check_utf8(str);
let prop = simple_map::spec_get(self.map, key);
aborts_if prop.type != spec_utf8(str);
aborts_if !aptos_std::from_bcs::deserializable<address>(prop.value);
read_u128
public fun read_u128(self: &property_map::PropertyMap, key: &string::String): u128
let str = b"u128";
aborts_if !simple_map::spec_contains_key(self.map, key);
aborts_if !string::spec_internal_check_utf8(str);
let prop = simple_map::spec_get(self.map, key);
aborts_if prop.type != spec_utf8(str);
aborts_if !aptos_std::from_bcs::deserializable<u128>(prop.value);
read_bool
public fun read_bool(self: &property_map::PropertyMap, key: &string::String): bool
let str = b"bool";
aborts_if !simple_map::spec_contains_key(self.map, key);
aborts_if !string::spec_internal_check_utf8(str);
let prop = simple_map::spec_get(self.map, key);
aborts_if prop.type != spec_utf8(str);
aborts_if !aptos_std::from_bcs::deserializable<bool>(prop.value);
borrow_value
public fun borrow_value(self: &property_map::PropertyValue): vector<u8>
aborts_if false;
borrow_type
public fun borrow_type(self: &property_map::PropertyValue): string::String
aborts_if false;
remove
public fun remove(self: &mut property_map::PropertyMap, key: &string::String): (string::String, property_map::PropertyValue)
aborts_if !simple_map::spec_contains_key(self.map, key);
update_property_map
public fun update_property_map(self: &mut property_map::PropertyMap, keys: vector<string::String>, values: vector<vector<u8>>, types: vector<string::String>)
pragma aborts_if_is_partial;
let key_len = len(keys);
let val_len = len(values);
let typ_len = len(types);
aborts_if !(key_len == val_len);
aborts_if !(key_len == typ_len);
update_property_value
public fun update_property_value(self: &mut property_map::PropertyMap, key: &string::String, value: property_map::PropertyValue)
aborts_if !simple_map::spec_contains_key(self.map, key);
create_property_value_raw
public fun create_property_value_raw(value: vector<u8>, type: string::String): property_map::PropertyValue
aborts_if false;
create_property_value
public fun create_property_value<T: copy>(data: &T): property_map::PropertyValue
Abort according to the code
let name = type_name<T>();
aborts_if !string::spec_internal_check_utf8(b"bool");
aborts_if name != spec_utf8(b"bool") &&
!string::spec_internal_check_utf8(b"u8");
aborts_if name != spec_utf8(b"bool") &&
name != spec_utf8(b"u8") &&
!string::spec_internal_check_utf8(b"u64");
aborts_if name != spec_utf8(b"bool") &&
name != spec_utf8(b"u8") &&
name != spec_utf8(b"u64") &&
!string::spec_internal_check_utf8(b"u128");
aborts_if name != spec_utf8(b"bool") &&
name != spec_utf8(b"u8") &&
name != spec_utf8(b"u64") &&
name != spec_utf8(b"u128") &&
!string::spec_internal_check_utf8(b"address");
aborts_if name != spec_utf8(b"bool") &&
name != spec_utf8(b"u8") &&
name != spec_utf8(b"u64") &&
name != spec_utf8(b"u128") &&
name != spec_utf8(b"address") &&
!string::spec_internal_check_utf8(b"0x1::string::String");
aborts_if name != spec_utf8(b"bool") &&
name != spec_utf8(b"u8") &&
name != spec_utf8(b"u64") &&
name != spec_utf8(b"u128") &&
name != spec_utf8(b"address") &&
name != spec_utf8(b"0x1::string::String") &&
!string::spec_internal_check_utf8(b"vector<u8>");