Skip to content

Commit

Permalink
storage mapper from addr - add attribute, impl StorageMapperFromAddre…
Browse files Browse the repository at this point in the history
… for VecMapper
  • Loading branch information
BiancaIalangi committed Jun 13, 2024
1 parent f27462e commit 8ea2637
Show file tree
Hide file tree
Showing 12 changed files with 714 additions and 8 deletions.
621 changes: 621 additions & 0 deletions contracts/examples/adder/file.rs

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions contracts/examples/adder/src/adder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ pub trait Adder {
#[storage_mapper("sum")]
fn sum(&self) -> SingleValueMapper<BigUint>;

#[storage_mapper_from_address("sum")]
fn sum_with_address(&self, address: &ManagedAddress) -> SingleValueMapper<BigUint>;

#[init]
fn init(&self, initial_value: BigUint) {
self.sum().set(initial_value);
Expand Down
2 changes: 1 addition & 1 deletion framework/base/src/storage/mappers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ mod bi_di_mapper;
mod linked_list_mapper;
mod map_mapper;
mod map_storage_mapper;
mod mapper;
pub mod mapper;
mod ordered_binary_tree_mapper;
mod queue_mapper;
mod set_mapper;
Expand Down
9 changes: 8 additions & 1 deletion framework/base/src/storage/mappers/mapper.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{api::StorageMapperApi, storage::StorageKey};
use crate::{api::StorageMapperApi, storage::StorageKey, types::ManagedAddress};

pub trait StorageMapper<SA>: 'static
where
Expand All @@ -8,6 +8,13 @@ where
fn new(base_key: StorageKey<SA>) -> Self;
}

pub trait StorageMapperFromAddress<SA>: StorageMapper<SA>
where
SA: StorageMapperApi,
{
fn new_from_address(address: ManagedAddress<SA>, base_key: StorageKey<SA>) -> Self;
}

pub trait StorageClearable {
/// Clears all the entries owned by the storage.
fn clear(&mut self);
Expand Down
24 changes: 22 additions & 2 deletions framework/base/src/storage/mappers/vec_mapper.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use super::{
mapper::StorageMapperFromAddress,
set_mapper::{CurrentStorage, StorageAddress},
StorageClearable, StorageMapper,
};
Expand Down Expand Up @@ -56,12 +57,31 @@ where
}
}

impl<SA, T> VecMapper<SA, T, ManagedAddress<SA>>
impl<SA, T> StorageMapper<SA> for VecMapper<SA, T, ManagedAddress<SA>>
where
SA: StorageMapperApi,
T: TopEncode + TopDecode,
{
pub fn new_from_address(address: ManagedAddress<SA>, base_key: StorageKey<SA>) -> Self {
fn new(base_key: StorageKey<SA>) -> Self {
let mut len_key = base_key.clone();
len_key.append_bytes(LEN_SUFFIX);

VecMapper {
_phantom_api: PhantomData,
address: ManagedAddress::default(),
base_key,
len_key,
_phantom_item: PhantomData,
}
}
}

impl<SA, T> StorageMapperFromAddress<SA> for VecMapper<SA, T, ManagedAddress<SA>>
where
SA: StorageMapperApi,
T: TopEncode + TopDecode,
{
fn new_from_address(address: ManagedAddress<SA>, base_key: StorageKey<SA>) -> Self {
let mut len_key = base_key.clone();
len_key.append_bytes(LEN_SUFFIX);

Expand Down
7 changes: 5 additions & 2 deletions framework/derive/src/generate/auto_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ use super::{
auto_impl_event::generate_event_impl,
auto_impl_proxy::generate_proxy_getter_impl,
auto_impl_storage::{
generate_clear_impl, generate_getter_impl, generate_is_empty_impl, generate_mapper_impl,
generate_setter_impl,
generate_clear_impl, generate_getter_impl, generate_is_empty_impl,
generate_mapper_from_address_impl, generate_mapper_impl, generate_setter_impl,
},
};

Expand Down Expand Up @@ -33,6 +33,9 @@ fn generate_auto_impl(m: &Method, auto_impl: &AutoImpl) -> proc_macro2::TokenStr
AutoImpl::StorageGetter { identifier } => generate_getter_impl(m, identifier),
AutoImpl::StorageSetter { identifier } => generate_setter_impl(m, identifier),
AutoImpl::StorageMapper { identifier } => generate_mapper_impl(m, identifier),
AutoImpl::StorageMapperFromAddress { identifier } => {
generate_mapper_from_address_impl(m, identifier)
},
AutoImpl::StorageIsEmpty { identifier } => generate_is_empty_impl(m, identifier),
AutoImpl::StorageClear { identifier } => generate_clear_impl(m, identifier),
AutoImpl::ProxyGetter => generate_proxy_getter_impl(m),
Expand Down
19 changes: 19 additions & 0 deletions framework/derive/src/generate/auto_impl_storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,25 @@ pub fn generate_mapper_impl(m: &Method, identifier: &str) -> proc_macro2::TokenS
}
}

pub fn generate_mapper_from_address_impl(m: &Method, identifier: &str) -> proc_macro2::TokenStream {
let msig = method_gen::generate_sig_with_attributes(m);
let key_snippet = generate_key_snippet(&m.method_args[1..], identifier);

match m.return_type.clone() {
syn::ReturnType::Default => panic!("getter from address should return some value"),
syn::ReturnType::Type(_, ty) => {
quote! {
#msig {
#key_snippet
<#ty as multiversx_sc::storage::mappers::StorageMapper<Self::Api>>::new(
___key___
)
}
}
},
}
}

pub fn generate_is_empty_impl(m: &Method, identifier: &str) -> proc_macro2::TokenStream {
let msig = method_gen::generate_sig_with_attributes(m);
let key_snippet = generate_key_snippet(m.method_args.as_slice(), identifier);
Expand Down
1 change: 1 addition & 0 deletions framework/derive/src/model/method.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ pub enum AutoImpl {
StorageGetter { identifier: String },
StorageSetter { identifier: String },
StorageMapper { identifier: String },
StorageMapperFromAddress { identifier: String },
StorageIsEmpty { identifier: String },
StorageClear { identifier: String },
ProxyGetter,
Expand Down
1 change: 1 addition & 0 deletions framework/derive/src/parse/attributes/attr_names.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ pub(super) static ATTR_CALLBACK_CALL_RESULT: &str = "call_result";
pub(super) static ATTR_STORAGE_GET: &str = "storage_get";
pub(super) static ATTR_STORAGE_SET: &str = "storage_set";
pub(super) static ATTR_STORAGE_MAPPER: &str = "storage_mapper";
pub(super) static ATTR_STORAGE_MAPPER_FROM_ADDRESS: &str = "storage_mapper_from_address";
pub(super) static ATTR_STORAGE_IS_EMPTY: &str = "storage_is_empty";
pub(super) static ATTR_STORAGE_CLEAR: &str = "storage_clear";
pub(super) static ATTR_PROXY: &str = "proxy";
Expand Down
14 changes: 14 additions & 0 deletions framework/derive/src/parse/attributes/storage_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,20 @@ impl StorageMapperAttribute {
}
}

pub struct StorageMapperFromAddressAttribute {
pub identifier: String,
}

impl StorageMapperFromAddressAttribute {
pub fn parse(attr: &syn::Attribute) -> Option<Self> {
is_attr_one_string_arg(attr, ATTR_STORAGE_MAPPER_FROM_ADDRESS).map(|arg_str| {
StorageMapperFromAddressAttribute {
identifier: arg_str,
}
})
}
}

pub struct StorageIsEmptyAttribute {
pub identifier: String,
}
Expand Down
17 changes: 16 additions & 1 deletion framework/derive/src/parse/auto_impl_parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@ use super::attributes::*;
fn assert_no_other_auto_impl(method: &Method) {
assert!(
method.implementation.is_no_implementation(),
"Only one auto-implementation can be specified at one time. Auto-implementations are: {}{}{}{}{}{}{}{}",
"Only one auto-implementation can be specified at one time. Auto-implementations are: {}{}{}{}{}{}{}{}{}",
"`#[storage_get]`, ",
"`#[storage_set]`, ",
"`#[storage_mapper]`, ",
"`#[storage_mapper_from_address]`, ",
"`#[storage_is_empty]`, ",
"`#[storage_clear]`, ",
"`#[proxy]`, ",
Expand Down Expand Up @@ -72,6 +73,20 @@ pub fn process_storage_mapper_attribute(attr: &syn::Attribute, method: &mut Meth
.is_some()
}

pub fn process_storage_mapper_from_address_attribute(
attr: &syn::Attribute,
method: &mut Method,
) -> bool {
StorageMapperFromAddressAttribute::parse(attr)
.map(|storage_mapper_from_address| {
assert_no_other_auto_impl(&*method);
method.implementation = MethodImpl::Generated(AutoImpl::StorageMapperFromAddress {
identifier: storage_mapper_from_address.identifier,
});
})
.is_some()
}

pub fn process_storage_is_empty_attribute(attr: &syn::Attribute, method: &mut Method) -> bool {
StorageIsEmptyAttribute::parse(attr)
.map(|storage_is_empty| {
Expand Down
4 changes: 3 additions & 1 deletion framework/derive/src/parse/method_parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ use super::{
auto_impl_parse::{
process_event_attribute, process_proxy_attribute, process_storage_clear_attribute,
process_storage_get_attribute, process_storage_is_empty_attribute,
process_storage_mapper_attribute, process_storage_set_attribute,
process_storage_mapper_attribute, process_storage_mapper_from_address_attribute,
process_storage_set_attribute,
},
extract_method_args, process_allow_multiple_var_args_attribute, process_callback_attribute,
process_callback_raw_attribute, process_endpoint_attribute, process_external_view_attribute,
Expand Down Expand Up @@ -127,6 +128,7 @@ fn process_attribute_second_pass(
|| process_storage_get_attribute(attr, method)
|| process_storage_set_attribute(attr, method)
|| process_storage_mapper_attribute(attr, method)
|| process_storage_mapper_from_address_attribute(attr, method)
|| process_storage_is_empty_attribute(attr, method)
|| process_storage_clear_attribute(attr, method)
|| process_output_names_attribute(attr, method)
Expand Down

0 comments on commit 8ea2637

Please sign in to comment.