mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-12 21:41:12 +00:00
Implement a proper generic resolution in decl_storage! (#2913)
* Add failing test case * move storage maps to blake2_128 (#2268) * remove default hash, introduce twox_128 and blake2 * use blake2_128 & create ext_blake2_128 * refactor code * add benchmark * factorize generator * fix * parameterizable hasher * some fix * fix * fix * fix * metadata * fix * remove debug print * map -> blake2_256 * fix test * fix test * Apply suggestions from code review Co-Authored-By: thiolliere <gui.thiolliere@gmail.com> * impl twox 128 concat (#2353) * impl twox_128_concat * comment addressed * fix * impl twox_128->64_concat * fix test * Fix compilation and cleanup some docs * Lol * Remove traits from storage types that are not generic * Get instance test almost working as wanted * Make `srml-support-test` compile again :) * Fixes test of srml-support * Fix compilation * Break some lines * Remove incorrect macro match arm * Integrates review feedback * Update documentation * Fix compilation
This commit is contained in:
@@ -98,7 +98,7 @@ use proc_macro::TokenStream;
|
||||
///
|
||||
/// Storage items are accessible in multiple ways:
|
||||
///
|
||||
/// * The structure: `Foo::<T>`
|
||||
/// * The structure: `Foo` or `Foo::<T>` depending if the value type is generic or not.
|
||||
/// * The `Store` trait structure: `<Module<T> as Store>::Foo`
|
||||
/// * The getter on the module that calls get on the structure: `Module::<T>::foo()`
|
||||
///
|
||||
@@ -136,9 +136,9 @@ use proc_macro::TokenStream;
|
||||
/// trait Store for Module<T: Trait<I>, I: Instance=DefaultInstance> as Example {}
|
||||
/// ```
|
||||
///
|
||||
/// Then the genesis config is generated with two generic parameters (i.e. `GenesisConfig<T, I>`)
|
||||
/// and storage items are accessible using two generic parameters, e.g.:
|
||||
/// `<Dummy<T, I>>::get()` or `Dummy::<T, I>::get()`.
|
||||
/// Accessing the structure no requires the instance as generic parameter:
|
||||
/// * `Foo::<I>` if the value type is not generic
|
||||
/// * `Foo::<T, I>` if the value type is generic
|
||||
#[proc_macro]
|
||||
pub fn decl_storage(input: TokenStream) -> TokenStream {
|
||||
storage::transformation::decl_storage_impl(input)
|
||||
|
||||
@@ -14,11 +14,13 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use proc_macro2::TokenStream as TokenStream2;
|
||||
use syn;
|
||||
use quote::quote;
|
||||
use crate::storage::transformation::{DeclStorageTypeInfos, InstanceOpts};
|
||||
|
||||
use srml_support_procedural_tools::syn_ext as ext;
|
||||
use proc_macro2::TokenStream as TokenStream2;
|
||||
use syn::Ident;
|
||||
use quote::quote;
|
||||
|
||||
pub fn option_unwrap(is_option: bool) -> TokenStream2 {
|
||||
if !is_option {
|
||||
// raw type case
|
||||
@@ -79,7 +81,6 @@ impl<'a, I: Iterator<Item=syn::Meta>> Impls<'a, I> {
|
||||
};
|
||||
|
||||
let InstanceOpts {
|
||||
comma_instance,
|
||||
equal_default_instance,
|
||||
bound_instantiable,
|
||||
instance,
|
||||
@@ -87,20 +88,37 @@ impl<'a, I: Iterator<Item=syn::Meta>> Impls<'a, I> {
|
||||
} = instance_opts;
|
||||
|
||||
let final_prefix = if let Some(instance) = instance {
|
||||
let const_name = syn::Ident::new(&format!("{}{}", PREFIX_FOR, name.to_string()), proc_macro2::Span::call_site());
|
||||
let const_name = Ident::new(&format!("{}{}", PREFIX_FOR, name.to_string()), proc_macro2::Span::call_site());
|
||||
quote!{ #instance::#const_name.as_bytes() }
|
||||
} else {
|
||||
quote!{ #prefix.as_bytes() }
|
||||
};
|
||||
|
||||
// generator for value
|
||||
quote!{
|
||||
#( #[ #attrs ] )*
|
||||
#visibility struct #name<#traitinstance: #traittype, #instance #bound_instantiable #equal_default_instance>
|
||||
(#scrate::rstd::marker::PhantomData<(#traitinstance #comma_instance)>);
|
||||
let (struct_trait, impl_trait, trait_and_instance) = if ext::type_contains_ident(
|
||||
value_type, traitinstance
|
||||
) {
|
||||
(
|
||||
quote!(#traitinstance: #traittype, #instance #bound_instantiable #equal_default_instance),
|
||||
quote!(#traitinstance: #traittype, #instance #bound_instantiable),
|
||||
quote!(#traitinstance, #instance),
|
||||
)
|
||||
} else {
|
||||
(
|
||||
quote!(#instance #bound_instantiable #equal_default_instance),
|
||||
quote!(#instance #bound_instantiable),
|
||||
quote!(#instance)
|
||||
)
|
||||
};
|
||||
|
||||
impl<#traitinstance: #traittype, #instance #bound_instantiable>
|
||||
#scrate::storage::hashed::generator::StorageValue<#typ> for #name<#traitinstance, #instance>
|
||||
// generator for value
|
||||
quote! {
|
||||
#( #[ #attrs ] )*
|
||||
#visibility struct #name<#struct_trait>(
|
||||
#scrate::rstd::marker::PhantomData<(#trait_and_instance)>
|
||||
);
|
||||
|
||||
impl<#impl_trait> #scrate::storage::hashed::generator::StorageValue<#typ>
|
||||
for #name<#trait_and_instance>
|
||||
{
|
||||
type Query = #value_type;
|
||||
|
||||
@@ -170,7 +188,6 @@ impl<'a, I: Iterator<Item=syn::Meta>> Impls<'a, I> {
|
||||
};
|
||||
|
||||
let InstanceOpts {
|
||||
comma_instance,
|
||||
equal_default_instance,
|
||||
bound_instantiable,
|
||||
instance,
|
||||
@@ -184,14 +201,31 @@ impl<'a, I: Iterator<Item=syn::Meta>> Impls<'a, I> {
|
||||
quote!{ #prefix.as_bytes() }
|
||||
};
|
||||
|
||||
let (struct_trait, impl_trait, trait_and_instance) = if ext::type_contains_ident(value_type, traitinstance)
|
||||
|| ext::type_contains_ident(kty, traitinstance)
|
||||
{
|
||||
(
|
||||
quote!(#traitinstance: #traittype, #instance #bound_instantiable #equal_default_instance),
|
||||
quote!(#traitinstance: #traittype, #instance #bound_instantiable),
|
||||
quote!(#traitinstance, #instance),
|
||||
)
|
||||
} else {
|
||||
(
|
||||
quote!(#instance #bound_instantiable #equal_default_instance),
|
||||
quote!(#instance #bound_instantiable),
|
||||
quote!(#instance)
|
||||
)
|
||||
};
|
||||
|
||||
// generator for map
|
||||
quote!{
|
||||
#( #[ #attrs ] )*
|
||||
#visibility struct #name<#traitinstance: #traittype, #instance #bound_instantiable #equal_default_instance>
|
||||
(#scrate::rstd::marker::PhantomData<(#traitinstance #comma_instance)>);
|
||||
#visibility struct #name<#struct_trait>(
|
||||
#scrate::rstd::marker::PhantomData<(#trait_and_instance)>
|
||||
);
|
||||
|
||||
impl<#traitinstance: #traittype, #instance #bound_instantiable>
|
||||
#scrate::storage::hashed::generator::StorageMap<#kty, #typ> for #name<#traitinstance, #instance>
|
||||
impl<#impl_trait>
|
||||
#scrate::storage::hashed::generator::StorageMap<#kty, #typ> for #name<#trait_and_instance>
|
||||
{
|
||||
type Query = #value_type;
|
||||
|
||||
@@ -235,8 +269,8 @@ impl<'a, I: Iterator<Item=syn::Meta>> Impls<'a, I> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<#traitinstance: 'static + #traittype, #instance #bound_instantiable>
|
||||
#scrate::storage::hashed::generator::AppendableStorageMap<#kty, #typ> for #name<#traitinstance, #instance>
|
||||
impl<#impl_trait> #scrate::storage::hashed::generator::AppendableStorageMap<#kty, #typ>
|
||||
for #name<#trait_and_instance>
|
||||
{}
|
||||
}
|
||||
}
|
||||
@@ -257,7 +291,6 @@ impl<'a, I: Iterator<Item=syn::Meta>> Impls<'a, I> {
|
||||
} = self;
|
||||
|
||||
let InstanceOpts {
|
||||
comma_instance,
|
||||
equal_default_instance,
|
||||
bound_instantiable,
|
||||
instance,
|
||||
@@ -304,6 +337,26 @@ impl<'a, I: Iterator<Item=syn::Meta>> Impls<'a, I> {
|
||||
}
|
||||
};
|
||||
|
||||
let (struct_trait, impl_trait, trait_and_instance, trait_lifetime) = if ext::type_contains_ident(
|
||||
value_type,
|
||||
traitinstance
|
||||
) || ext::type_contains_ident(kty, traitinstance)
|
||||
{
|
||||
(
|
||||
quote!(#traitinstance: #traittype, #instance #bound_instantiable #equal_default_instance),
|
||||
quote!(#traitinstance: #traittype, #instance #bound_instantiable),
|
||||
quote!(#traitinstance, #instance),
|
||||
quote!(#traitinstance: 'static),
|
||||
)
|
||||
} else {
|
||||
(
|
||||
quote!(#instance #bound_instantiable #equal_default_instance),
|
||||
quote!(#instance #bound_instantiable),
|
||||
quote!(#instance),
|
||||
quote!()
|
||||
)
|
||||
};
|
||||
|
||||
// generator for linked map
|
||||
let helpers = quote! {
|
||||
/// Linkage data of an element (it's successor and predecessor)
|
||||
@@ -337,15 +390,14 @@ impl<'a, I: Iterator<Item=syn::Meta>> Impls<'a, I> {
|
||||
pub _data: #phantom_data<V>,
|
||||
}
|
||||
|
||||
impl<'a, S: #scrate::HashedStorage<#scrate::#hasher>, #traitinstance: #traittype, #instance #bound_instantiable>
|
||||
Iterator for Enumerator<'a, S, #kty, (#typ, #traitinstance, #instance)>
|
||||
where #traitinstance: 'a
|
||||
impl<'a, S: #scrate::HashedStorage<#scrate::#hasher>, #impl_trait>
|
||||
Iterator for Enumerator<'a, S, #kty, (#typ, #trait_and_instance)>
|
||||
{
|
||||
type Item = (#kty, #typ);
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let next = self.next.take()?;
|
||||
let key_for = <super::#name<#traitinstance, #instance>
|
||||
let key_for = <super::#name<#trait_and_instance>
|
||||
as #scrate::storage::hashed::generator::StorageMap<#kty, #typ>>::key_for(&next);
|
||||
|
||||
let (val, linkage): (#typ, Linkage<#kty>) = self.storage.get(&*key_for)
|
||||
@@ -355,7 +407,7 @@ impl<'a, I: Iterator<Item=syn::Meta>> Impls<'a, I> {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) trait Utils<#traitinstance: #traittype, #instance #bound_instantiable> {
|
||||
pub(crate) trait Utils<#struct_trait> {
|
||||
/// Update linkage when this element is removed.
|
||||
///
|
||||
/// Takes care of updating previous and next elements points
|
||||
@@ -388,9 +440,9 @@ impl<'a, I: Iterator<Item=syn::Meta>> Impls<'a, I> {
|
||||
|
||||
let structure = quote! {
|
||||
#( #[ #attrs ] )*
|
||||
#visibility struct #name<#traitinstance: #traittype, #instance #bound_instantiable #equal_default_instance>(#phantom_data<(#traitinstance #comma_instance)>);
|
||||
#visibility struct #name<#struct_trait>(#phantom_data<(#trait_and_instance)>);
|
||||
|
||||
impl<#traitinstance: #traittype, #instance #bound_instantiable> self::#inner_module::Utils<#traitinstance, #instance> for #name<#traitinstance, #instance> {
|
||||
impl<#impl_trait> self::#inner_module::Utils<#trait_and_instance> for #name<#trait_and_instance> {
|
||||
fn remove_linkage<S: #scrate::HashedStorage<#scrate::#hasher>>(
|
||||
linkage: self::#inner_module::Linkage<#kty>,
|
||||
storage: &mut S,
|
||||
@@ -477,8 +529,8 @@ impl<'a, I: Iterator<Item=syn::Meta>> Impls<'a, I> {
|
||||
|
||||
#structure
|
||||
|
||||
impl<#traitinstance: #traittype, #instance #bound_instantiable>
|
||||
#scrate::storage::hashed::generator::StorageMap<#kty, #typ> for #name<#traitinstance, #instance>
|
||||
impl<#impl_trait>
|
||||
#scrate::storage::hashed::generator::StorageMap<#kty, #typ> for #name<#trait_and_instance>
|
||||
{
|
||||
type Query = #value_type;
|
||||
|
||||
@@ -553,8 +605,10 @@ impl<'a, I: Iterator<Item=syn::Meta>> Impls<'a, I> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<#traitinstance: 'static + #traittype, #instance #bound_instantiable>
|
||||
#scrate::storage::hashed::generator::EnumerableStorageMap<#kty, #typ> for #name<#traitinstance, #instance>
|
||||
impl<#impl_trait>
|
||||
#scrate::storage::hashed::generator::EnumerableStorageMap<#kty, #typ> for #name<#trait_and_instance>
|
||||
where
|
||||
#trait_lifetime
|
||||
{
|
||||
fn head<S: #scrate::HashedStorage<#scrate::#hasher>>(storage: &S) -> Option<#kty> {
|
||||
use self::#inner_module::Utils;
|
||||
@@ -562,18 +616,20 @@ impl<'a, I: Iterator<Item=syn::Meta>> Impls<'a, I> {
|
||||
Self::read_head(storage)
|
||||
}
|
||||
|
||||
fn enumerate<'a, S>(storage: &'a S) -> #scrate::rstd::boxed::Box<dyn Iterator<Item = (#kty, #typ)> + 'a>
|
||||
where
|
||||
S: #scrate::HashedStorage<#scrate::#hasher>,
|
||||
#kty: 'a,
|
||||
#typ: 'a,
|
||||
fn enumerate<'a, S>(
|
||||
storage: &'a S
|
||||
) -> #scrate::rstd::boxed::Box<dyn Iterator<Item = (#kty, #typ)> + 'a>
|
||||
where
|
||||
S: #scrate::HashedStorage<#scrate::#hasher>,
|
||||
#kty: 'a,
|
||||
#typ: 'a,
|
||||
{
|
||||
use self::#inner_module::{Utils, Enumerator};
|
||||
|
||||
#scrate::rstd::boxed::Box::new(Enumerator {
|
||||
next: Self::read_head(storage),
|
||||
storage,
|
||||
_data: #phantom_data::<(#typ, #traitinstance, #instance)>::default(),
|
||||
_data: #phantom_data::<(#typ, #trait_and_instance)>::default(),
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -620,7 +676,6 @@ impl<'a, I: Iterator<Item=syn::Meta>> Impls<'a, I> {
|
||||
};
|
||||
|
||||
let InstanceOpts {
|
||||
comma_instance,
|
||||
equal_default_instance,
|
||||
bound_instantiable,
|
||||
instance,
|
||||
@@ -634,14 +689,31 @@ impl<'a, I: Iterator<Item=syn::Meta>> Impls<'a, I> {
|
||||
quote!{ #prefix.as_bytes() }
|
||||
};
|
||||
|
||||
let (struct_trait, impl_trait, trait_and_instance) = if ext::type_contains_ident(value_type, traitinstance)
|
||||
|| ext::type_contains_ident(k1ty, traitinstance)
|
||||
|| ext::type_contains_ident(k2ty, traitinstance)
|
||||
{
|
||||
(
|
||||
quote!(#traitinstance: #traittype, #instance #bound_instantiable #equal_default_instance),
|
||||
quote!(#traitinstance: #traittype, #instance #bound_instantiable),
|
||||
quote!(#traitinstance, #instance),
|
||||
)
|
||||
} else {
|
||||
(
|
||||
quote!(#instance #bound_instantiable #equal_default_instance),
|
||||
quote!(#instance #bound_instantiable),
|
||||
quote!(#instance)
|
||||
)
|
||||
};
|
||||
|
||||
// generator for double map
|
||||
quote!{
|
||||
#( #[ #attrs ] )*
|
||||
#visibility struct #name<#traitinstance: #traittype, #instance #bound_instantiable #equal_default_instance>
|
||||
(#scrate::rstd::marker::PhantomData<(#traitinstance #comma_instance)>);
|
||||
#visibility struct #name<#struct_trait>
|
||||
(#scrate::rstd::marker::PhantomData<(#trait_and_instance)>);
|
||||
|
||||
impl<#traitinstance: #traittype, #instance #bound_instantiable>
|
||||
#scrate::storage::unhashed::generator::StorageDoubleMap<#k1ty, #k2ty, #typ> for #name<#traitinstance, #instance>
|
||||
impl<#impl_trait>
|
||||
#scrate::storage::unhashed::generator::StorageDoubleMap<#k1ty, #k2ty, #typ> for #name<#trait_and_instance>
|
||||
{
|
||||
type Query = #value_type;
|
||||
|
||||
@@ -686,9 +758,7 @@ impl<'a, I: Iterator<Item=syn::Meta>> Impls<'a, I> {
|
||||
#mutate_impl ;
|
||||
ret
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,7 +67,6 @@ struct StorageDefinition {
|
||||
pub crate_ident: Ident,
|
||||
pub content: ext::Braces<ext::Punctuated<DeclStorageLine, Token![;]>>,
|
||||
pub extra_genesis: ext::Opt<AddExtraGenesis>,
|
||||
pub extra_genesis_skip_phantom_data_field: ext::Opt<ExtraGenesisSkipPhantomDataField>,
|
||||
}
|
||||
|
||||
#[derive(Parse, ToTokens, Debug)]
|
||||
@@ -82,12 +81,6 @@ struct AddExtraGenesis {
|
||||
pub content: ext::Braces<AddExtraGenesisContent>,
|
||||
}
|
||||
|
||||
#[derive(Parse, ToTokens, Debug)]
|
||||
struct ExtraGenesisSkipPhantomDataField {
|
||||
pub genesis_phantom_keyword: keyword::extra_genesis_skip_phantom_data_field,
|
||||
pub token: Token![;],
|
||||
}
|
||||
|
||||
#[derive(Parse, ToTokens, Debug)]
|
||||
struct AddExtraGenesisContent {
|
||||
pub lines: ext::Punctuated<AddExtraGenesisLineEnum, Token![;]>,
|
||||
|
||||
@@ -14,15 +14,15 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// tag::description[]
|
||||
//! `decl_storage` macro transformation
|
||||
// end::description[]
|
||||
|
||||
use srml_support_procedural_tools::syn_ext as ext;
|
||||
use srml_support_procedural_tools::{generate_crate_access, generate_hidden_includes, clean_type_string};
|
||||
use srml_support_procedural_tools::{
|
||||
generate_crate_access, generate_hidden_includes, clean_type_string
|
||||
};
|
||||
|
||||
use proc_macro::TokenStream;
|
||||
use proc_macro2::TokenStream as TokenStream2;
|
||||
use proc_macro2::{TokenStream as TokenStream2, Span};
|
||||
|
||||
use syn::{
|
||||
Ident,
|
||||
@@ -39,6 +39,9 @@ use quote::quote;
|
||||
use super::*;
|
||||
|
||||
const NUMBER_OF_INSTANCE: usize = 16;
|
||||
const DEFAULT_INSTANTIABLE_TRAIT_NAME: &str = "__GeneratedInstantiable";
|
||||
const DEFAULT_INSTANCE_NAME: &str = "__GeneratedInstance";
|
||||
const INHERENT_INSTANCE_NAME: &str = "__InherentHiddenInstance";
|
||||
|
||||
// try macro but returning tokenized error
|
||||
macro_rules! try_tok(( $expre : expr ) => {
|
||||
@@ -65,11 +68,14 @@ pub fn decl_storage_impl(input: TokenStream) -> TokenStream {
|
||||
crate_ident: cratename,
|
||||
content: ext::Braces { content: storage_lines, ..},
|
||||
extra_genesis,
|
||||
extra_genesis_skip_phantom_data_field,
|
||||
..
|
||||
} = def;
|
||||
|
||||
let instance_opts = match get_instance_opts(mod_instance, mod_instantiable, mod_default_instance) {
|
||||
let instance_opts = match get_instance_opts(
|
||||
mod_instance,
|
||||
mod_instantiable,
|
||||
mod_default_instance
|
||||
) {
|
||||
Ok(opts) => opts,
|
||||
Err(err) => return err.to_compile_error().into(),
|
||||
};
|
||||
@@ -104,7 +110,6 @@ pub fn decl_storage_impl(input: TokenStream) -> TokenStream {
|
||||
&instance_opts,
|
||||
&storage_lines,
|
||||
&extra_genesis.inner,
|
||||
extra_genesis_skip_phantom_data_field.inner.is_some(),
|
||||
));
|
||||
let decl_storage_items = decl_storage_items(
|
||||
&scrate,
|
||||
@@ -114,6 +119,7 @@ pub fn decl_storage_impl(input: TokenStream) -> TokenStream {
|
||||
&cratename,
|
||||
&storage_lines,
|
||||
);
|
||||
|
||||
let decl_store_items = decl_store_items(
|
||||
&storage_lines,
|
||||
);
|
||||
@@ -172,7 +178,6 @@ pub fn decl_storage_impl(input: TokenStream) -> TokenStream {
|
||||
}
|
||||
|
||||
#extra_genesis
|
||||
|
||||
};
|
||||
|
||||
expanded.into()
|
||||
@@ -185,11 +190,9 @@ fn decl_store_extra_genesis(
|
||||
instance_opts: &InstanceOpts,
|
||||
storage_lines: &ext::Punctuated<DeclStorageLine, Token![;]>,
|
||||
extra_genesis: &Option<AddExtraGenesis>,
|
||||
extra_genesis_skip_phantom_data_field: bool,
|
||||
) -> Result<TokenStream2> {
|
||||
|
||||
let InstanceOpts {
|
||||
comma_instance,
|
||||
equal_default_instance,
|
||||
bound_instantiable,
|
||||
instance,
|
||||
@@ -197,13 +200,14 @@ fn decl_store_extra_genesis(
|
||||
} = instance_opts;
|
||||
|
||||
let mut is_trait_needed = false;
|
||||
let mut has_trait_field = false;
|
||||
let mut serde_complete_bound = Vec::new();
|
||||
let mut config_field = TokenStream2::new();
|
||||
let mut config_field_default = TokenStream2::new();
|
||||
let mut builders = TokenStream2::new();
|
||||
for sline in storage_lines.inner.iter() {
|
||||
let mut assimilate_require_generic = instance.is_some();
|
||||
let mut builders_clone_bound = Vec::new();
|
||||
|
||||
for sline in storage_lines.inner.iter() {
|
||||
let DeclStorageLine {
|
||||
attrs,
|
||||
name,
|
||||
@@ -217,9 +221,17 @@ fn decl_store_extra_genesis(
|
||||
|
||||
let type_infos = get_type_infos(storage_type);
|
||||
|
||||
let opt_build;
|
||||
let opt_build = build
|
||||
.inner
|
||||
.as_ref()
|
||||
.map(|b| {
|
||||
assimilate_require_generic |= ext::expr_contains_ident(&b.expr.content, traitinstance);
|
||||
&b.expr.content
|
||||
})
|
||||
.map(|b| quote!( #b ));
|
||||
|
||||
// need build line
|
||||
if let Some(ref config) = config.inner {
|
||||
let builder = if let Some(ref config) = config.inner {
|
||||
let ident = if let Some(ident) = config.expr.content.as_ref() {
|
||||
quote!( #ident )
|
||||
} else if let Some(ref getter) = getter.inner {
|
||||
@@ -234,19 +246,37 @@ fn decl_store_extra_genesis(
|
||||
)
|
||||
);
|
||||
};
|
||||
if type_infos.kind.is_simple() && ext::has_parametric_type(type_infos.value_type, traitinstance) {
|
||||
|
||||
if ext::type_contains_ident(type_infos.value_type, traitinstance) {
|
||||
is_trait_needed = true;
|
||||
has_trait_field = true;
|
||||
}
|
||||
|
||||
if opt_build.is_none() {
|
||||
builders_clone_bound.push(type_infos.value_type.clone());
|
||||
}
|
||||
|
||||
let value_type = &type_infos.value_type;
|
||||
serde_complete_bound.push(quote!( #value_type ));
|
||||
match type_infos.kind {
|
||||
DeclStorageTypeInfosKind::Map { key_type, .. } =>
|
||||
serde_complete_bound.push(quote!( #key_type )),
|
||||
DeclStorageTypeInfosKind::Map { key_type, .. } => {
|
||||
serde_complete_bound.push(quote!( #key_type ));
|
||||
is_trait_needed = is_trait_needed
|
||||
|| ext::type_contains_ident(key_type, traitinstance);
|
||||
|
||||
if opt_build.is_none() {
|
||||
builders_clone_bound.push(key_type.clone());
|
||||
}
|
||||
},
|
||||
DeclStorageTypeInfosKind::DoubleMap { key1_type, key2_type, .. } => {
|
||||
serde_complete_bound.push(quote!( #key1_type ));
|
||||
serde_complete_bound.push(quote!( #key2_type ));
|
||||
is_trait_needed = is_trait_needed
|
||||
|| ext::type_contains_ident(key1_type, traitinstance)
|
||||
|| ext::type_contains_ident(key2_type, traitinstance);
|
||||
if opt_build.is_none() {
|
||||
builders_clone_bound.push(key1_type.clone());
|
||||
builders_clone_bound.push(key2_type.clone());
|
||||
}
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
@@ -270,8 +300,6 @@ fn decl_store_extra_genesis(
|
||||
quote!( #( #[ #attrs ] )* pub #ident: Vec<(#key1_type, #key2_type, #storage_type)>, )
|
||||
},
|
||||
});
|
||||
opt_build = Some(build.inner.as_ref().map(|b| &b.expr.content).map(|b|quote!( #b ))
|
||||
.unwrap_or_else(|| quote!( (|config: &GenesisConfig<#traitinstance, #instance>| config.#ident.clone()) )));
|
||||
|
||||
let fielddefault = default_value.inner.as_ref().map(|d| &d.expr).map(|d|
|
||||
if type_infos.is_option {
|
||||
@@ -281,48 +309,74 @@ fn decl_store_extra_genesis(
|
||||
}).unwrap_or_else(|| quote!( Default::default() ));
|
||||
|
||||
config_field_default.extend(quote!( #ident: #fielddefault, ));
|
||||
|
||||
opt_build.or_else(|| Some(quote!( (|config: &Self| config.#ident.clone()) )))
|
||||
} else {
|
||||
opt_build = build.inner.as_ref().map(|b| &b.expr.content).map(|b| quote!( #b ));
|
||||
}
|
||||
opt_build
|
||||
};
|
||||
|
||||
let typ = type_infos.typ;
|
||||
if let Some(builder) = opt_build {
|
||||
is_trait_needed = true;
|
||||
if let Some(builder) = builder {
|
||||
builders.extend(match type_infos.kind {
|
||||
DeclStorageTypeInfosKind::Simple => {
|
||||
quote!{{
|
||||
use #scrate::rstd::{cell::RefCell, marker::PhantomData};
|
||||
use #scrate::codec::{Encode, Decode};
|
||||
let struct_trait = if ext::type_contains_ident(&type_infos.value_type, traitinstance) {
|
||||
assimilate_require_generic = true;
|
||||
quote!(#traitinstance,)
|
||||
} else {
|
||||
quote!()
|
||||
};
|
||||
|
||||
quote!{{
|
||||
let v = (#builder)(&self);
|
||||
<#name<#traitinstance, #instance> as #scrate::storage::hashed::generator::StorageValue<#typ>>::put(&v, storage);
|
||||
<
|
||||
#name<#struct_trait #instance> as
|
||||
#scrate::storage::hashed::generator::StorageValue<#typ>
|
||||
>::put(&v, storage);
|
||||
}}
|
||||
},
|
||||
DeclStorageTypeInfosKind::Map { key_type, .. } => {
|
||||
quote!{{
|
||||
use #scrate::rstd::{cell::RefCell, marker::PhantomData};
|
||||
use #scrate::codec::{Encode, Decode};
|
||||
let struct_trait = if ext::type_contains_ident(&type_infos.value_type, traitinstance)
|
||||
|| ext::type_contains_ident(key_type, traitinstance)
|
||||
{
|
||||
assimilate_require_generic = true;
|
||||
quote!(#traitinstance,)
|
||||
} else {
|
||||
quote!()
|
||||
};
|
||||
|
||||
quote!{{
|
||||
let data = (#builder)(&self);
|
||||
for (k, v) in data.into_iter() {
|
||||
<#name<#traitinstance, #instance> as #scrate::storage::hashed::generator::StorageMap<#key_type, #typ>>::insert(&k, &v, storage);
|
||||
}
|
||||
data.into_iter().for_each(|(k, v)| {
|
||||
<
|
||||
#name<#struct_trait #instance> as
|
||||
#scrate::storage::hashed::generator::StorageMap<#key_type, #typ>
|
||||
>::insert(&k, &v, storage);
|
||||
});
|
||||
}}
|
||||
},
|
||||
DeclStorageTypeInfosKind::DoubleMap { key1_type, key2_type, .. } => {
|
||||
quote!{{
|
||||
use #scrate::rstd::{cell::RefCell, marker::PhantomData};
|
||||
use #scrate::codec::{Encode, Decode};
|
||||
let struct_trait = if ext::type_contains_ident(&type_infos.value_type, traitinstance)
|
||||
|| ext::type_contains_ident(key1_type, traitinstance)
|
||||
|| ext::type_contains_ident(key2_type, traitinstance)
|
||||
{
|
||||
assimilate_require_generic = true;
|
||||
quote!(#traitinstance,)
|
||||
} else {
|
||||
quote!()
|
||||
};
|
||||
|
||||
quote!{{
|
||||
let data = (#builder)(&self);
|
||||
for (k1, k2, v) in data.into_iter() {
|
||||
<#name<#traitinstance, #instance> as #scrate::storage::unhashed::generator::StorageDoubleMap<#key1_type, #key2_type, #typ>>::insert(&k1, &k2, &v, storage);
|
||||
}
|
||||
data.into_iter().for_each(|(k1, k2, v)| {
|
||||
<
|
||||
#name<#struct_trait #instance> as
|
||||
#scrate::storage::unhashed::generator::StorageDoubleMap<#key1_type, #key2_type, #typ>
|
||||
>::insert(&k1, &k2, &v, storage);
|
||||
});
|
||||
}}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
let mut has_scall = false;
|
||||
@@ -341,9 +395,8 @@ fn decl_store_extra_genesis(
|
||||
default_value,
|
||||
..
|
||||
}) => {
|
||||
if ext::has_parametric_type(&extra_type, traitinstance) {
|
||||
if ext::type_contains_ident(&extra_type, traitinstance) {
|
||||
is_trait_needed = true;
|
||||
has_trait_field = true;
|
||||
}
|
||||
|
||||
serde_complete_bound.push(quote!( #extra_type ));
|
||||
@@ -362,6 +415,7 @@ fn decl_store_extra_genesis(
|
||||
if has_scall {
|
||||
return Err(Error::new(expr.span(), "Only one build expression allowed for extra genesis"));
|
||||
}
|
||||
assimilate_require_generic |= ext::expr_contains_ident(&expr.content, traitinstance);
|
||||
let content = &expr.content;
|
||||
scall = quote!( ( #content ) );
|
||||
has_scall = true;
|
||||
@@ -370,7 +424,6 @@ fn decl_store_extra_genesis(
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
let serde_bug_bound = if !serde_complete_bound.is_empty() {
|
||||
let mut b_ser = String::new();
|
||||
let mut b_dser = String::new();
|
||||
@@ -393,46 +446,54 @@ fn decl_store_extra_genesis(
|
||||
|| !config_field.is_empty()
|
||||
|| !genesis_extrafields.is_empty()
|
||||
|| !builders.is_empty();
|
||||
Ok(if is_extra_genesis_needed {
|
||||
let (fparam_struct, fparam_impl, sparam, ph_field, ph_default) = if is_trait_needed {
|
||||
if (has_trait_field && instance.is_none()) || extra_genesis_skip_phantom_data_field {
|
||||
// no phantom data required
|
||||
(
|
||||
quote!(<#traitinstance: #traittype, #instance #bound_instantiable #equal_default_instance>),
|
||||
quote!(<#traitinstance: #traittype, #instance #bound_instantiable>),
|
||||
quote!(<#traitinstance, #instance>),
|
||||
quote!(),
|
||||
quote!(),
|
||||
)
|
||||
} else {
|
||||
// need phantom data
|
||||
(
|
||||
quote!(<#traitinstance: #traittype, #instance #bound_instantiable #equal_default_instance>),
|
||||
quote!(<#traitinstance: #traittype, #instance #bound_instantiable>),
|
||||
quote!(<#traitinstance, #instance>),
|
||||
if is_extra_genesis_needed {
|
||||
let (inherent_instance, inherent_bound_instantiable) = if instance.is_some() {
|
||||
(instance.clone(), bound_instantiable.clone())
|
||||
} else {
|
||||
let instantiable = Ident::new(DEFAULT_INSTANTIABLE_TRAIT_NAME, Span::call_site());
|
||||
(
|
||||
Some(Ident::new(DEFAULT_INSTANCE_NAME, Span::call_site())),
|
||||
quote!(: #instantiable),
|
||||
)
|
||||
};
|
||||
|
||||
quote!{
|
||||
#[serde(skip)]
|
||||
pub _genesis_phantom_data: #scrate::rstd::marker::PhantomData<(#traitinstance #comma_instance)>,
|
||||
},
|
||||
quote!{
|
||||
_genesis_phantom_data: Default::default(),
|
||||
},
|
||||
)
|
||||
}
|
||||
let (fparam_struct, fparam_impl, sparam, build_storage_impl) = if is_trait_needed {
|
||||
(
|
||||
quote!(<#traitinstance: #traittype, #instance #bound_instantiable #equal_default_instance>),
|
||||
quote!(<#traitinstance: #traittype, #instance #bound_instantiable>),
|
||||
quote!(<#traitinstance, #instance>),
|
||||
quote!(<#traitinstance: #traittype, #inherent_instance #inherent_bound_instantiable>),
|
||||
)
|
||||
} else {
|
||||
// do not even need type parameter
|
||||
(quote!(), quote!(), quote!(), quote!(), quote!())
|
||||
(
|
||||
quote!(),
|
||||
quote!(),
|
||||
quote!(),
|
||||
quote!(<#traitinstance: #traittype, #inherent_instance #inherent_bound_instantiable>),
|
||||
)
|
||||
};
|
||||
quote!{
|
||||
|
||||
let (fn_generic, fn_traitinstance) = if !is_trait_needed && assimilate_require_generic {
|
||||
(
|
||||
quote!( <#traitinstance: #traittype, #instance #bound_instantiable> ),
|
||||
quote!( #traitinstance, #instance )
|
||||
)
|
||||
} else {
|
||||
(quote!(), quote!())
|
||||
};
|
||||
|
||||
let impl_trait = quote!(BuildModuleGenesisStorage<#traitinstance, #inherent_instance>);
|
||||
|
||||
let builders_clone_bound = quote!( #( #builders_clone_bound: Clone ),* );
|
||||
|
||||
let res = quote!{
|
||||
#[derive(#scrate::Serialize, #scrate::Deserialize)]
|
||||
#[cfg(feature = "std")]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[serde(deny_unknown_fields)]
|
||||
#serde_bug_bound
|
||||
pub struct GenesisConfig#fparam_struct {
|
||||
#ph_field
|
||||
#config_field
|
||||
#genesis_extrafields
|
||||
}
|
||||
@@ -441,7 +502,6 @@ fn decl_store_extra_genesis(
|
||||
impl#fparam_impl Default for GenesisConfig#sparam {
|
||||
fn default() -> Self {
|
||||
GenesisConfig {
|
||||
#ph_default
|
||||
#config_field_default
|
||||
#genesis_extrafields_default
|
||||
}
|
||||
@@ -449,23 +509,83 @@ fn decl_store_extra_genesis(
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl#fparam_impl #scrate::runtime_primitives::BuildStorage for GenesisConfig#sparam {
|
||||
fn assimilate_storage(self, r: &mut #scrate::runtime_primitives::StorageOverlay, c: &mut #scrate::runtime_primitives::ChildrenStorageOverlay) -> ::std::result::Result<(), String> {
|
||||
impl#fparam_impl GenesisConfig#sparam where #builders_clone_bound {
|
||||
pub fn build_storage #fn_generic (self) -> std::result::Result<
|
||||
(
|
||||
#scrate::runtime_primitives::StorageOverlay,
|
||||
#scrate::runtime_primitives::ChildrenStorageOverlay,
|
||||
),
|
||||
String
|
||||
> {
|
||||
let mut storage = Default::default();
|
||||
let mut child_storage = Default::default();
|
||||
self.assimilate_storage::<#fn_traitinstance>(&mut storage, &mut child_storage)?;
|
||||
Ok((storage, child_storage))
|
||||
}
|
||||
|
||||
/// Assimilate the storage for this module into pre-existing overlays.
|
||||
pub fn assimilate_storage #fn_generic (
|
||||
self,
|
||||
r: &mut #scrate::runtime_primitives::StorageOverlay,
|
||||
c: &mut #scrate::runtime_primitives::ChildrenStorageOverlay,
|
||||
) -> std::result::Result<(), String> {
|
||||
let storage = r;
|
||||
|
||||
#builders
|
||||
|
||||
let r = storage;
|
||||
|
||||
#scall(r, c, &self);
|
||||
#scall(storage, c, &self);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl#build_storage_impl #scrate::runtime_primitives::#impl_trait
|
||||
for GenesisConfig#sparam where #builders_clone_bound
|
||||
{
|
||||
fn build_module_genesis_storage(
|
||||
self,
|
||||
r: &mut #scrate::runtime_primitives::StorageOverlay,
|
||||
c: &mut #scrate::runtime_primitives::ChildrenStorageOverlay,
|
||||
) -> std::result::Result<(), String> {
|
||||
self.assimilate_storage::<#fn_traitinstance> (r, c)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Ok(res)
|
||||
} else {
|
||||
quote!()
|
||||
})
|
||||
Ok(quote!())
|
||||
}
|
||||
}
|
||||
|
||||
fn create_and_impl_instance(
|
||||
prefix: &str,
|
||||
ident: &Ident,
|
||||
doc: &TokenStream2,
|
||||
const_names: &[(Ident, String)],
|
||||
scrate: &TokenStream2,
|
||||
instantiable: &Ident,
|
||||
) -> TokenStream2 {
|
||||
let mut const_impls = TokenStream2::new();
|
||||
|
||||
for (const_name, partial_const_value) in const_names {
|
||||
let const_value = format!("{}{}", partial_const_value, prefix);
|
||||
const_impls.extend(quote! {
|
||||
const #const_name: &'static str = #const_value;
|
||||
});
|
||||
}
|
||||
|
||||
quote! {
|
||||
// Those trait are derived because of wrong bounds for generics
|
||||
#[cfg_attr(feature = "std", derive(Debug))]
|
||||
#[derive(Clone, Eq, PartialEq, #scrate::codec::Encode, #scrate::codec::Decode)]
|
||||
#doc
|
||||
pub struct #ident;
|
||||
impl #instantiable for #ident {
|
||||
#const_impls
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn decl_storage_items(
|
||||
@@ -489,82 +609,103 @@ fn decl_storage_items(
|
||||
let build_prefix = |cratename, name| format!("{} {}", cratename, name);
|
||||
|
||||
// Build Instantiable trait
|
||||
if instance.is_some() {
|
||||
let mut const_names = vec![];
|
||||
let mut const_names = vec![];
|
||||
|
||||
for sline in storage_lines.inner.iter() {
|
||||
let DeclStorageLine {
|
||||
storage_type,
|
||||
name,
|
||||
..
|
||||
} = sline;
|
||||
for sline in storage_lines.inner.iter() {
|
||||
let DeclStorageLine {
|
||||
storage_type,
|
||||
name,
|
||||
..
|
||||
} = sline;
|
||||
|
||||
let prefix = build_prefix(cratename, name);
|
||||
let prefix = build_prefix(cratename, name);
|
||||
|
||||
let type_infos = get_type_infos(storage_type);
|
||||
let type_infos = get_type_infos(storage_type);
|
||||
|
||||
let const_name = syn::Ident::new(&format!("{}{}", impls::PREFIX_FOR, name.to_string()), proc_macro2::Span::call_site());
|
||||
let partial_const_value = prefix.clone();
|
||||
let const_name = syn::Ident::new(
|
||||
&format!("{}{}", impls::PREFIX_FOR, name.to_string()), proc_macro2::Span::call_site()
|
||||
);
|
||||
let partial_const_value = prefix.clone();
|
||||
const_names.push((const_name, partial_const_value));
|
||||
|
||||
if let DeclStorageTypeInfosKind::Map { is_linked: true, .. } = type_infos.kind {
|
||||
let const_name = syn::Ident::new(
|
||||
&format!("{}{}", impls::HEAD_KEY_FOR, name.to_string()), proc_macro2::Span::call_site()
|
||||
);
|
||||
let partial_const_value = format!("head of {}", prefix);
|
||||
const_names.push((const_name, partial_const_value));
|
||||
|
||||
if let DeclStorageTypeInfosKind::Map { is_linked: true, .. } = type_infos.kind {
|
||||
let const_name = syn::Ident::new(&format!("{}{}", impls::HEAD_KEY_FOR, name.to_string()), proc_macro2::Span::call_site());
|
||||
let partial_const_value = format!("head of {}", prefix);
|
||||
const_names.push((const_name, partial_const_value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Declare Instance trait
|
||||
{
|
||||
let mut const_impls = TokenStream2::new();
|
||||
for (const_name, _) in &const_names {
|
||||
const_impls.extend(quote! {
|
||||
const #const_name: &'static str;
|
||||
});
|
||||
}
|
||||
let instantiable = instantiable
|
||||
.clone()
|
||||
.unwrap_or_else(|| Ident::new(DEFAULT_INSTANTIABLE_TRAIT_NAME, Span::call_site()));
|
||||
|
||||
impls.extend(quote! {
|
||||
/// Tag a type as an instance of a module.
|
||||
///
|
||||
/// Defines storage prefixes, they must be unique.
|
||||
pub trait #instantiable: 'static {
|
||||
#const_impls
|
||||
}
|
||||
// Declare Instance trait
|
||||
{
|
||||
let mut const_impls = TokenStream2::new();
|
||||
for (const_name, _) in &const_names {
|
||||
const_impls.extend(quote! {
|
||||
const #const_name: &'static str;
|
||||
});
|
||||
}
|
||||
|
||||
let hide = if instance.is_some() {
|
||||
quote!()
|
||||
} else {
|
||||
quote!(#[doc(hidden)])
|
||||
};
|
||||
|
||||
impls.extend(quote! {
|
||||
/// Tag a type as an instance of a module.
|
||||
///
|
||||
/// Defines storage prefixes, they must be unique.
|
||||
#hide
|
||||
pub trait #instantiable: 'static {
|
||||
#const_impls
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if instance.is_some() {
|
||||
let instances = (0..NUMBER_OF_INSTANCE)
|
||||
.map(|i| {
|
||||
let name = format!("Instance{}", i);
|
||||
let ident = syn::Ident::new(&name, proc_macro2::Span::call_site());
|
||||
let ident = Ident::new(&name, proc_macro2::Span::call_site());
|
||||
(name, ident, quote! {#[doc=r"Module instance"]})
|
||||
})
|
||||
.chain(default_instance.clone().map(|ident| (String::new(), ident, quote! {#[doc=r"Default module instance"]})));
|
||||
.chain(
|
||||
default_instance
|
||||
.clone()
|
||||
.map(|ident|
|
||||
(String::new(), ident, quote! {#[doc=r"Default module instance"]})
|
||||
)
|
||||
);
|
||||
|
||||
// Impl Instance trait for instances
|
||||
for (prefix, ident, doc) in instances {
|
||||
let mut const_impls = TokenStream2::new();
|
||||
|
||||
for (const_name, partial_const_value) in &const_names {
|
||||
let const_value = format!("{}{}", partial_const_value, prefix);
|
||||
const_impls.extend(quote! {
|
||||
const #const_name: &'static str = #const_value;
|
||||
});
|
||||
}
|
||||
|
||||
impls.extend(quote! {
|
||||
// Those trait are derived because of wrong bounds for generics
|
||||
#[cfg_attr(feature = "std", derive(Debug))]
|
||||
#[derive(Clone, Eq, PartialEq, #scrate::codec::Encode, #scrate::codec::Decode)]
|
||||
#doc
|
||||
pub struct #ident;
|
||||
impl #instantiable for #ident {
|
||||
#const_impls
|
||||
}
|
||||
});
|
||||
impls.extend(
|
||||
create_and_impl_instance(&prefix, &ident, &doc, &const_names, scrate, &instantiable)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// The name of the inherently available instance.
|
||||
let inherent_instance = Ident::new(INHERENT_INSTANCE_NAME, Span::call_site());
|
||||
|
||||
if default_instance.is_some() {
|
||||
impls.extend(quote! {
|
||||
#[doc(hidden)]
|
||||
pub type #inherent_instance = #default_instance;
|
||||
});
|
||||
} else {
|
||||
impls.extend(
|
||||
create_and_impl_instance(
|
||||
"", &inherent_instance, "e!(#[doc(hidden)]), &const_names, scrate, &instantiable
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
for sline in storage_lines.inner.iter() {
|
||||
let DeclStorageLine {
|
||||
attrs,
|
||||
@@ -630,15 +771,39 @@ fn impl_store_items(
|
||||
instance: &Option<syn::Ident>,
|
||||
storage_lines: &ext::Punctuated<DeclStorageLine, Token![;]>,
|
||||
) -> TokenStream2 {
|
||||
storage_lines.inner.iter().map(|sline| &sline.name)
|
||||
.fold(TokenStream2::new(), |mut items, name| {
|
||||
storage_lines.inner
|
||||
.iter()
|
||||
.fold(TokenStream2::new(), |mut items, line| {
|
||||
let name = &line.name;
|
||||
let type_infos = get_type_infos(&line.storage_type);
|
||||
let requires_trait = match type_infos.kind {
|
||||
DeclStorageTypeInfosKind::Simple => {
|
||||
ext::type_contains_ident(&type_infos.value_type, traitinstance)
|
||||
},
|
||||
DeclStorageTypeInfosKind::Map { key_type, .. } => {
|
||||
ext::type_contains_ident(&type_infos.value_type, traitinstance)
|
||||
|| ext::type_contains_ident(key_type, traitinstance)
|
||||
}
|
||||
DeclStorageTypeInfosKind::DoubleMap { key1_type, key2_type, .. } => {
|
||||
ext::type_contains_ident(&type_infos.value_type, traitinstance)
|
||||
|| ext::type_contains_ident(key1_type, traitinstance)
|
||||
|| ext::type_contains_ident(key2_type, traitinstance)
|
||||
}
|
||||
};
|
||||
|
||||
let struct_trait = if requires_trait {
|
||||
quote!(#traitinstance,)
|
||||
} else {
|
||||
quote!()
|
||||
};
|
||||
|
||||
items.extend(
|
||||
quote!(
|
||||
type #name = #name<#traitinstance, #instance>;
|
||||
type #name = #name<#struct_trait #instance>;
|
||||
)
|
||||
);
|
||||
items
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
fn impl_store_fns(
|
||||
@@ -669,29 +834,61 @@ fn impl_store_fns(
|
||||
let typ = type_infos.typ;
|
||||
let item = match type_infos.kind {
|
||||
DeclStorageTypeInfosKind::Simple => {
|
||||
let struct_trait = if ext::type_contains_ident(&type_infos.value_type, traitinstance) {
|
||||
quote!(#traitinstance,)
|
||||
} else {
|
||||
quote!()
|
||||
};
|
||||
|
||||
quote!{
|
||||
#( #[ #attrs ] )*
|
||||
pub fn #get_fn() -> #value_type {
|
||||
<#name<#traitinstance, #instance> as #scrate::storage::hashed::generator::StorageValue<#typ>> :: get(&#scrate::storage::RuntimeStorage)
|
||||
<#name<#struct_trait #instance> as
|
||||
#scrate::storage::hashed::generator::StorageValue<#typ>> :: get(
|
||||
&#scrate::storage::RuntimeStorage
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
DeclStorageTypeInfosKind::Map { key_type, .. } => {
|
||||
let struct_trait = if ext::type_contains_ident(&type_infos.value_type, traitinstance)
|
||||
|| ext::type_contains_ident(key_type, traitinstance)
|
||||
{
|
||||
quote!(#traitinstance,)
|
||||
} else {
|
||||
quote!()
|
||||
};
|
||||
|
||||
quote!{
|
||||
#( #[ #attrs ] )*
|
||||
pub fn #get_fn<K: #scrate::rstd::borrow::Borrow<#key_type>>(key: K) -> #value_type {
|
||||
<#name<#traitinstance, #instance> as #scrate::storage::hashed::generator::StorageMap<#key_type, #typ>> :: get(key.borrow(), &#scrate::storage::RuntimeStorage)
|
||||
<
|
||||
#name<#struct_trait #instance> as
|
||||
#scrate::storage::hashed::generator::StorageMap<#key_type, #typ>
|
||||
>::get(key.borrow(), &#scrate::storage::RuntimeStorage)
|
||||
}
|
||||
}
|
||||
}
|
||||
DeclStorageTypeInfosKind::DoubleMap { key1_type, key2_type, .. } => {
|
||||
let struct_trait = if ext::type_contains_ident(&type_infos.value_type, traitinstance)
|
||||
|| ext::type_contains_ident(key1_type, traitinstance)
|
||||
|| ext::type_contains_ident(key2_type, traitinstance)
|
||||
{
|
||||
quote!(#traitinstance,)
|
||||
} else {
|
||||
quote!()
|
||||
};
|
||||
|
||||
quote!{
|
||||
pub fn #get_fn<KArg1, KArg2>(k1: KArg1, k2: KArg2) -> #value_type
|
||||
where
|
||||
KArg1: #scrate::rstd::borrow::Borrow<#key1_type>,
|
||||
KArg2: #scrate::rstd::borrow::Borrow<#key2_type>,
|
||||
{
|
||||
<#name<#traitinstance> as #scrate::storage::unhashed::generator::StorageDoubleMap<#key1_type, #key2_type, #typ>> :: get(k1.borrow(), k2.borrow(), &#scrate::storage::RuntimeStorage)
|
||||
<
|
||||
#name<#struct_trait #instance> as
|
||||
#scrate::storage::unhashed::generator::StorageDoubleMap<#key1_type, #key2_type, #typ>
|
||||
>::get(k1.borrow(), k2.borrow(), &#scrate::storage::RuntimeStorage)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -799,6 +996,7 @@ fn store_functions_to_metadata (
|
||||
let str_name = name.to_string();
|
||||
let struct_name = proc_macro2::Ident::new(&("__GetByteStruct".to_string() + &str_name), name.span());
|
||||
let cache_name = proc_macro2::Ident::new(&("__CACHE_GET_BYTE_STRUCT_".to_string() + &str_name), name.span());
|
||||
|
||||
let item = quote! {
|
||||
#scrate::metadata::StorageFunctionMetadata {
|
||||
name: #scrate::metadata::DecodeDifferent::Encode(#str_name),
|
||||
@@ -813,6 +1011,7 @@ fn store_functions_to_metadata (
|
||||
},
|
||||
};
|
||||
items.extend(item);
|
||||
|
||||
let def_get = quote! {
|
||||
#[doc(hidden)]
|
||||
pub struct #struct_name<#traitinstance, #instance #bound_instantiable #equal_default_instance>(pub #scrate::rstd::marker::PhantomData<(#traitinstance #comma_instance)>);
|
||||
@@ -838,6 +1037,7 @@ fn store_functions_to_metadata (
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
default_getter_struct_def.extend(def_get);
|
||||
}
|
||||
(default_getter_struct_def, quote!{
|
||||
@@ -874,15 +1074,6 @@ enum DeclStorageTypeInfosKind<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> DeclStorageTypeInfosKind<'a> {
|
||||
fn is_simple(&self) -> bool {
|
||||
match *self {
|
||||
DeclStorageTypeInfosKind::Simple => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_type_infos(storage_type: &DeclStorageType) -> DeclStorageTypeInfos {
|
||||
let (value_type, kind) = match storage_type {
|
||||
DeclStorageType::Simple(ref st) => (st, DeclStorageTypeInfosKind::Simple),
|
||||
@@ -919,29 +1110,29 @@ fn get_type_infos(storage_type: &DeclStorageType) -> DeclStorageTypeInfos {
|
||||
|
||||
#[derive(Default)]
|
||||
pub(crate) struct InstanceOpts {
|
||||
pub instance: Option<syn::Ident>,
|
||||
pub default_instance: Option<syn::Ident>,
|
||||
pub instantiable: Option<syn::Ident>,
|
||||
pub instance: Option<Ident>,
|
||||
pub default_instance: Option<Ident>,
|
||||
pub instantiable: Option<Ident>,
|
||||
pub comma_instance: TokenStream2,
|
||||
pub equal_default_instance: TokenStream2,
|
||||
pub bound_instantiable: TokenStream2,
|
||||
}
|
||||
|
||||
fn get_instance_opts(
|
||||
instance: Option<syn::Ident>,
|
||||
instantiable: Option<syn::Ident>,
|
||||
default_instance: Option<syn::Ident>,
|
||||
) -> syn::Result<InstanceOpts> {
|
||||
|
||||
instance: Option<Ident>,
|
||||
instantiable: Option<Ident>,
|
||||
default_instance: Option<Ident>,
|
||||
) -> Result<InstanceOpts> {
|
||||
let right_syntax = "Should be $Instance: $Instantiable = $DefaultInstance";
|
||||
|
||||
match (instance, instantiable, default_instance) {
|
||||
(Some(instance), Some(instantiable), default_instance_def) => {
|
||||
let (equal_default_instance, default_instance) = if let Some(default_instance) = default_instance_def {
|
||||
(quote!{= #default_instance}, Some(default_instance))
|
||||
(Some(instance), Some(instantiable), default_instance) => {
|
||||
let (equal_default_instance, default_instance) = if let Some(def) = default_instance {
|
||||
(quote!{= #def}, Some(def))
|
||||
} else {
|
||||
(quote!{}, None)
|
||||
(quote!(), None)
|
||||
};
|
||||
|
||||
Ok(InstanceOpts {
|
||||
comma_instance: quote!{, #instance},
|
||||
equal_default_instance,
|
||||
@@ -952,8 +1143,35 @@ fn get_instance_opts(
|
||||
})
|
||||
},
|
||||
(None, None, None) => Ok(Default::default()),
|
||||
(Some(instance), None, _) => Err(syn::Error::new(instance.span(), format!("Expect instantiable trait bound for instance: {}. {}", instance, right_syntax))),
|
||||
(None, Some(instantiable), _) => Err(syn::Error::new(instantiable.span(), format!("Expect instance generic for bound instantiable: {}. {}", instantiable, right_syntax))),
|
||||
(None, _, Some(default_instance)) => Err(syn::Error::new(default_instance.span(), format!("Expect instance generic for default instance: {}. {}", default_instance, right_syntax))),
|
||||
(Some(instance), None, _) => Err(
|
||||
Error::new(
|
||||
instance.span(),
|
||||
format!(
|
||||
"Expect instantiable trait bound for instance: {}. {}",
|
||||
instance,
|
||||
right_syntax,
|
||||
)
|
||||
)
|
||||
),
|
||||
(None, Some(instantiable), _) => Err(
|
||||
Error::new(
|
||||
instantiable.span(),
|
||||
format!(
|
||||
"Expect instance generic for bound instantiable: {}. {}",
|
||||
instantiable,
|
||||
right_syntax,
|
||||
)
|
||||
)
|
||||
),
|
||||
(None, _, Some(default_instance)) => Err(
|
||||
Error::new(
|
||||
default_instance.span(),
|
||||
format!(
|
||||
"Expect instance generic for default instance: {}. {}",
|
||||
default_instance,
|
||||
right_syntax,
|
||||
)
|
||||
)
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user