Implement parameterisable modules (#1800)

* first implementation

* remove done comment

* origin done

* impl log for instance

* impl inherent for instance

* Fix wasm build + full example build

this requires parity codec implements codec for core::marker::PhantomData

* patch parity-codec link to github branch

* improve internal names and fix instance prefix

* Fix in macros

* add test modules for support

this allow to test for construct_runtime as well.

The reason to have put that in another crate is:
* if we put test in `tests/` dir of srml/support then decl_storage fails to get
  srml-support access because it believes it is inside srml-support
  crate and so derive access to `quote!{ crate }` but this is wrong
  (and I don't see any way to prevent that, and it only bother us so I
  don't think that matters that much)
* if we put test inside lib.rs then contruct_runtime cannot be used
  because it call some macros that are defined with macros
  (decl_outer_event and decl_outer_origin) and thus rustc complains.

* defaultinstance to its own struct to avoid errors

* enforce <T, I> for Event and Config, impl test

* add origin, log, inherent to test

* test more code generation

* basic storage test

* fix typo

* rename a few imports and field

* delete wip test in example and runtime

* change default prefix to make it backward compatible with test

* rename Instance to I and Instantiable to Instance

note: the name of generic parameter I is only enforce by decl_module!
and this could be rewritten

* doc

* clean old TODOs

* update parity-codec to 3.2

* update node impl version + builds

* fix warning

* fix unrelated grandpa test

* refactor code
This commit is contained in:
thiolliere
2019-03-15 19:25:18 +01:00
committed by Gav Wood
parent c52c528ee8
commit d743a8b71f
80 changed files with 1632 additions and 1016 deletions
+2 -1
View File
@@ -8,7 +8,7 @@ edition = "2018"
hex-literal = { version = "0.1.0", optional = true }
serde = { version = "1.0", optional = true }
serde_derive = { version = "1.0", optional = true }
parity-codec = { version = "3.1", default-features = false, features = ["derive"] }
parity-codec = { version = "3.2", default-features = false, features = ["derive"] }
srml-metadata = { path = "../metadata", default-features = false }
sr-std = { path = "../../core/sr-std", default-features = false }
runtime_io = { package = "sr-io", path = "../../core/sr-io", default-features = false }
@@ -17,6 +17,7 @@ inherents = { package = "substrate-inherents", path = "../../core/inherents", de
srml-support-procedural = { path = "./procedural" }
paste = "0.1"
once_cell = { version = "0.1.6", default-features = false, optional = true }
spin = "0.5"
bitmask = { git = "https://github.com/paritytech/bitmask", default-features = false }
[dev-dependencies]
@@ -58,6 +58,18 @@ use proc_macro::TokenStream;
/// ```
/// or when at least one storage field requires default initialization (both `get` and `config` or `build`).
/// This struct can be expose as `Config` by `decl_runtime` macro.
///
/// ### Module with instances
///
/// `decl_storage!` macro support building modules with instances with the following syntax: (DefaultInstance type
/// is optionnal)
/// ```nocompile
/// trait Store for Module<T: Trait<I>, I: Instance=DefaultInstance> as Example {}
/// ```
///
/// Then the genesis config is generated with two generic parameter `GenesisConfig<T, I>`
/// and storages are now accessible using two generic parameters like:
/// `<Dummy<T, I>>::get()` or `Dummy::<T, I>::get()`
#[proc_macro]
pub fn decl_storage(input: TokenStream) -> TokenStream {
storage::transformation::decl_storage_impl(input)
@@ -17,7 +17,7 @@
use proc_macro2::TokenStream as TokenStream2;
use syn;
use quote::quote;
use crate::storage::transformation::DeclStorageTypeInfos;
use crate::storage::transformation::{DeclStorageTypeInfos, InstanceOpts};
pub fn option_unwrap(is_option: bool) -> TokenStream2 {
if !is_option {
@@ -34,9 +34,11 @@ pub(crate) struct Impls<'a, I: Iterator<Item=syn::Meta>> {
pub visibility: &'a syn::Visibility,
pub traitinstance: &'a syn::Ident,
pub traittype: &'a syn::TypeParamBound,
pub instance_opts: &'a InstanceOpts,
pub type_infos: DeclStorageTypeInfos<'a>,
pub fielddefault: TokenStream2,
pub prefix: String,
pub cratename: &'a syn::Ident,
pub name: &'a syn::Ident,
pub attrs: I,
}
@@ -48,11 +50,13 @@ impl<'a, I: Iterator<Item=syn::Meta>> Impls<'a, I> {
visibility,
traitinstance,
traittype,
instance_opts,
type_infos,
fielddefault,
prefix,
name,
attrs,
..
} = self;
let DeclStorageTypeInfos { typ, value_type, is_option, .. } = type_infos;
let option_simple_1 = option_unwrap(is_option);
@@ -70,17 +74,32 @@ impl<'a, I: Iterator<Item=syn::Meta>> Impls<'a, I> {
}
};
let InstanceOpts {
comma_instance,
equal_default_instance,
bound_instantiable,
instance,
..
} = instance_opts;
let final_prefix = if let Some(instance) = instance {
let method_name = syn::Ident::new(&format!("build_prefix_once_for_{}", name.to_string()), proc_macro2::Span::call_site());
quote!{ #instance::#method_name(#prefix.as_bytes()) }
} else {
quote!{ #prefix.as_bytes() }
};
// generator for value
quote!{
#( #[ #attrs ] )*
#visibility struct #name<#traitinstance: #traittype>(#scrate::storage::generator::PhantomData<#traitinstance>);
#visibility struct #name<#traitinstance: #traittype, #instance #bound_instantiable #equal_default_instance>(#scrate::storage::generator::PhantomData<(#traitinstance #comma_instance)>);
impl<#traitinstance: #traittype> #scrate::storage::generator::StorageValue<#typ> for #name<#traitinstance> {
impl<#traitinstance: #traittype, #instance #bound_instantiable> #scrate::storage::generator::StorageValue<#typ> for #name<#traitinstance, #instance> {
type Query = #value_type;
/// Get the storage key.
fn key() -> &'static [u8] {
#prefix.as_bytes()
#final_prefix
}
/// Load the value from the provided storage instance.
@@ -113,11 +132,13 @@ impl<'a, I: Iterator<Item=syn::Meta>> Impls<'a, I> {
visibility,
traitinstance,
traittype,
instance_opts,
type_infos,
fielddefault,
prefix,
name,
attrs,
..
} = self;
let DeclStorageTypeInfos { typ, value_type, is_option, .. } = type_infos;
let option_simple_1 = option_unwrap(is_option);
@@ -134,22 +155,38 @@ impl<'a, I: Iterator<Item=syn::Meta>> Impls<'a, I> {
}
}
};
let InstanceOpts {
comma_instance,
equal_default_instance,
bound_instantiable,
instance,
..
} = instance_opts;
let final_prefix = if let Some(instance) = instance {
let method_name = syn::Ident::new(&format!("build_prefix_once_for_{}", name.to_string()), proc_macro2::Span::call_site());
quote!{ #instance::#method_name(#prefix.as_bytes()) }
} else {
quote!{ #prefix.as_bytes() }
};
// generator for map
quote!{
#( #[ #attrs ] )*
#visibility struct #name<#traitinstance: #traittype>(#scrate::storage::generator::PhantomData<#traitinstance>);
#visibility struct #name<#traitinstance: #traittype, #instance #bound_instantiable #equal_default_instance>(#scrate::storage::generator::PhantomData<(#traitinstance #comma_instance)>);
impl<#traitinstance: #traittype> #scrate::storage::generator::StorageMap<#kty, #typ> for #name<#traitinstance> {
impl<#traitinstance: #traittype, #instance #bound_instantiable> #scrate::storage::generator::StorageMap<#kty, #typ> for #name<#traitinstance, #instance> {
type Query = #value_type;
/// Get the prefix key in storage.
fn prefix() -> &'static [u8] {
#prefix.as_bytes()
#final_prefix
}
/// Get the storage key used to fetch a value corresponding to a specific key.
fn key_for(x: &#kty) -> #scrate::rstd::vec::Vec<u8> {
let mut key = #prefix.as_bytes().to_vec();
let mut key = <Self as #scrate::storage::generator::StorageMap<#kty, #typ>>::prefix().to_vec();
#scrate::codec::Encode::encode_to(x, &mut key);
key
}
@@ -185,16 +222,41 @@ impl<'a, I: Iterator<Item=syn::Meta>> Impls<'a, I> {
visibility,
traitinstance,
traittype,
instance_opts,
type_infos,
fielddefault,
prefix,
name,
attrs,
..
} = self;
let InstanceOpts {
comma_instance,
equal_default_instance,
bound_instantiable,
instance,
..
} = instance_opts;
let final_prefix = if let Some(instance) = instance {
let method_name = syn::Ident::new(&format!("build_prefix_once_for_{}", name.to_string()), proc_macro2::Span::call_site());
quote!{ #instance::#method_name(#prefix.as_bytes()) }
} else {
quote!{ #prefix.as_bytes() }
};
// make sure to use different prefix for head and elements.
let final_head_key = if let Some(instance) = instance {
let method_name = syn::Ident::new(&format!("build_head_key_once_for_{}", name.to_string()), proc_macro2::Span::call_site());
quote!{ #instance::#method_name(#prefix.as_bytes()) }
} else {
let final_head_key = format!("head of {}", prefix);
quote!{ #final_head_key.as_bytes() }
};
let DeclStorageTypeInfos { typ, value_type, is_option, .. } = type_infos;
let option_simple_1 = option_unwrap(is_option);
// make sure to use different prefix for head and elements.
let head_key = format!("head of {}", prefix);
let name_lowercase = name.to_string().to_lowercase();
let inner_module = syn::Ident::new(&format!("__linked_map_details_for_{}_do_not_use", name_lowercase), name.span());
let linkage = syn::Ident::new(&format!("__LinkageFor{}DoNotUse", name), name.span());
@@ -250,30 +312,22 @@ impl<'a, I: Iterator<Item=syn::Meta>> Impls<'a, I> {
pub _data: #phantom_data<V>,
}
impl<'a, S: #scrate::GenericStorage, K, V> Iterator for Enumerator<'a, S, K, V> where
K: 'a + #scrate::codec::Codec,
V: 'a + #scrate::codec::Decode,
impl<'a, S: #scrate::GenericStorage, #traitinstance: #traittype, #instance #bound_instantiable> Iterator for Enumerator<'a, S, #kty, (#typ, #traitinstance, #instance)>
where #traitinstance: 'a
{
type Item = (K, V);
type Item = (#kty, #typ);
fn next(&mut self) -> Option<Self::Item> {
let next = self.next.take()?;
let key_for = key_for(&next);
let (val, linkage): (V, Linkage<K>) = self.storage.get(&*key_for)
let key_for = <super::#name<#traitinstance, #instance> as #scrate::storage::generator::StorageMap<#kty, #typ>>::key_for(&next);
let (val, linkage): (#typ, Linkage<#kty>) = self.storage.get(&*key_for)
.expect("previous/next only contain existing entires; we enumerate using next; entry exists; qed");
self.next = linkage.next;
Some((next, val))
}
}
/// Generate a storage key for given item.
pub(crate) fn key_for<Key: #scrate::codec::Encode>(key: &Key) -> #scrate::rstd::vec::Vec<u8> {
let mut key_for = #prefix.as_bytes().to_vec();
#scrate::codec::Encode::encode_to(&key, &mut key_for);
key_for
}
pub(crate) trait Utils<#traitinstance: #traittype> {
pub(crate) trait Utils<#traitinstance: #traittype, #instance #bound_instantiable> {
/// Update linkage when this element is removed.
///
/// Takes care of updating previous and next elements points
@@ -304,17 +358,17 @@ impl<'a, I: Iterator<Item=syn::Meta>> Impls<'a, I> {
let structure = quote! {
#( #[ #attrs ] )*
#visibility struct #name<#traitinstance: #traittype>(#phantom_data<#traitinstance>);
#visibility struct #name<#traitinstance: #traittype, #instance #bound_instantiable #equal_default_instance>(#phantom_data<(#traitinstance #comma_instance)>);
impl<#traitinstance: #traittype> self::#inner_module::Utils<#traitinstance> for #name<#traitinstance> {
impl<#traitinstance: #traittype, #instance #bound_instantiable> self::#inner_module::Utils<#traitinstance, #instance> for #name<#traitinstance, #instance> {
fn remove_linkage<S: #scrate::GenericStorage>(
linkage: self::#inner_module::Linkage<#kty>,
storage: &S,
) {
use self::#inner_module::{key_for, Utils};
use self::#inner_module::Utils;
let next_key = linkage.next.as_ref().map(|x| key_for(x));
let prev_key = linkage.previous.as_ref().map(|x| key_for(x));
let next_key = linkage.next.as_ref().map(|x| #as_map::key_for(x));
let prev_key = linkage.previous.as_ref().map(|x| #as_map::key_for(x));
if let Some(prev_key) = prev_key {
// Retrieve previous element and update `next`
@@ -347,12 +401,12 @@ impl<'a, I: Iterator<Item=syn::Meta>> Impls<'a, I> {
storage: &S,
key: &#kty,
) -> self::#inner_module::Linkage<#kty> {
use self::#inner_module::{key_for, Utils};
use self::#inner_module::Utils;
if let Some(head) = Self::read_head(storage) {
// update previous head predecessor
{
let head_key = key_for(&head);
let head_key = #as_map::key_for(&head);
let (data, linkage) = Self::read_with_linkage(storage, &*head_key).expect(r#"
head is set when first element is inserted and unset when last element is removed;
if head is Some then it points to existing key; qed
@@ -376,13 +430,13 @@ impl<'a, I: Iterator<Item=syn::Meta>> Impls<'a, I> {
}
fn read_head<S: #scrate::GenericStorage>(storage: &S) -> Option<#kty> {
storage.get(#head_key.as_bytes())
storage.get(#final_head_key)
}
fn write_head<S: #scrate::GenericStorage>(storage: &S, head: Option<&#kty>) {
match head {
Some(head) => storage.put(#head_key.as_bytes(), head),
None => storage.kill(#head_key.as_bytes()),
Some(head) => storage.put(#final_head_key, head),
None => storage.kill(#final_head_key),
}
}
}
@@ -393,17 +447,19 @@ impl<'a, I: Iterator<Item=syn::Meta>> Impls<'a, I> {
#structure
impl<#traitinstance: #traittype> #scrate::storage::generator::StorageMap<#kty, #typ> for #name<#traitinstance> {
impl<#traitinstance: #traittype, #instance #bound_instantiable> #scrate::storage::generator::StorageMap<#kty, #typ> for #name<#traitinstance, #instance> {
type Query = #value_type;
/// Get the prefix key in storage.
fn prefix() -> &'static [u8] {
#prefix.as_bytes()
#final_prefix
}
/// Get the storage key used to fetch a value corresponding to a specific key.
fn key_for(x: &#kty) -> #scrate::rstd::vec::Vec<u8> {
self::#inner_module::key_for(x)
fn key_for(key: &#kty) -> #scrate::rstd::vec::Vec<u8> {
let mut key_for = #as_map::prefix().to_vec();
#scrate::codec::Encode::encode_to(&key, &mut key_for);
key_for
}
/// Load the value associated with the given key from the map.
@@ -413,9 +469,9 @@ impl<'a, I: Iterator<Item=syn::Meta>> Impls<'a, I> {
/// Take the value, reading and removing it.
fn take<S: #scrate::GenericStorage>(key: &#kty, storage: &S) -> Self::Query {
use self::#inner_module::{Utils, key_for};
use self::#inner_module::Utils;
let res: Option<(#value_type, self::#inner_module::Linkage<#kty>)> = storage.take(&*key_for(key));
let res: Option<(#value_type, self::#inner_module::Linkage<#kty>)> = storage.take(&*#as_map::key_for(key));
match res {
Some((data, linkage)) => {
Self::remove_linkage(linkage, storage);
@@ -432,9 +488,9 @@ impl<'a, I: Iterator<Item=syn::Meta>> Impls<'a, I> {
/// Store a value to be associated with the given key from the map.
fn insert<S: #scrate::GenericStorage>(key: &#kty, val: &#typ, storage: &S) {
use self::#inner_module::{Utils, key_for};
use self::#inner_module::Utils;
let key_for = &*key_for(key);
let key_for = &*#as_map::key_for(key);
let linkage = match Self::read_with_linkage(storage, key_for) {
// overwrite but reuse existing linkage
Some((_data, linkage)) => linkage,
@@ -446,9 +502,9 @@ impl<'a, I: Iterator<Item=syn::Meta>> Impls<'a, I> {
/// Mutate the value under a key
fn mutate<R, F: FnOnce(&mut Self::Query) -> R, S: #scrate::GenericStorage>(key: &#kty, f: F, storage: &S) -> R {
use self::#inner_module::{Utils, key_for};
use self::#inner_module::Utils;
let key_for = &*key_for(key);
let key_for = &*#as_map::key_for(key);
let (mut val, linkage) = Self::read_with_linkage(storage, key_for)
.map(|(data, linkage)| (data, Some(linkage)))
.unwrap_or_else(|| (#fielddefault, None));
@@ -459,7 +515,7 @@ impl<'a, I: Iterator<Item=syn::Meta>> Impls<'a, I> {
}
}
impl<#traitinstance: #traittype> #scrate::storage::generator::EnumerableStorageMap<#kty, #typ> for #name<#traitinstance> {
impl<#traitinstance: 'static + #traittype, #instance #bound_instantiable> #scrate::storage::generator::EnumerableStorageMap<#kty, #typ> for #name<#traitinstance, #instance> {
fn head<S: #scrate::GenericStorage>(storage: &S) -> Option<#kty> {
use self::#inner_module::Utils;
@@ -475,7 +531,7 @@ impl<'a, I: Iterator<Item=syn::Meta>> Impls<'a, I> {
#scrate::storage::generator::Box::new(Enumerator {
next: Self::read_head(storage),
storage,
_data: #phantom_data::<#typ>::default(),
_data: #phantom_data::<(#typ, #traitinstance, #instance)>::default(),
})
}
}
@@ -39,14 +39,20 @@ struct StorageDefinition {
pub module_ident: Ident,
pub mod_lt_token: Token![<],
pub mod_param: syn::GenericParam,
pub mod_instance_param_token: Option<Token![,]>,
pub mod_instance: Option<syn::Ident>,
pub mod_instantiable_token: Option<Token![:]>,
pub mod_instantiable: Option<syn::Ident>,
pub mod_default_instance_token: Option<Token![=]>,
pub mod_default_instance: Option<syn::Ident>,
pub mod_gt_token: Token![>],
pub as_token: Token![as],
pub crate_ident: Ident,
pub content: ext::Braces<ext::Punctuated<DeclStorageLine, Token![;]>>,
pub extra_genesis: Option<AddExtraGenesis>,
pub extra_genesis_skip_phantom_data_field: Option<ExtraGenesisSkipPhantomDataField>,
}
#[derive(Parse, ToTokens, Debug)]
struct SpecificHiddenCrate {
pub keyword: ext::CustomToken<SpecificHiddenCrate>,
@@ -59,6 +65,12 @@ struct AddExtraGenesis {
pub content: ext::Braces<AddExtraGenesisContent>,
}
#[derive(Parse, ToTokens, Debug)]
struct ExtraGenesisSkipPhantomDataField {
pub genesis_phantom_keyword: ext::CustomToken<ExtraGenesisSkipPhantomDataField>,
pub token: Token![;],
}
#[derive(Parse, ToTokens, Debug)]
struct AddExtraGenesisContent {
pub lines: ext::Punctuated<AddExtraGenesisLineEnum, Token![;]>,
@@ -153,3 +165,4 @@ custom_keyword_impl!(AddExtraGenesis, "add_extra_genesis", "storage extra genesi
custom_keyword_impl!(DeclStorageGetter, "get", "storage getter");
custom_keyword!(MapKeyword, "map", "map as keyword");
custom_keyword!(LinkedMapKeyword, "linked_map", "linked_map as keyword");
custom_keyword_impl!(ExtraGenesisSkipPhantomDataField, "extra_genesis_skip_phantom_data_field", "extra_genesis_skip_phantom_data_field as keyword");
@@ -38,6 +38,8 @@ use quote::quote;
use super::*;
const NUMBER_OF_INSTANCE: usize = 16;
// try macro but returning tokenized error
macro_rules! try_tok(( $expre : expr ) => {
match $expre {
@@ -57,11 +59,21 @@ pub fn decl_storage_impl(input: TokenStream) -> TokenStream {
ident: storetype,
module_ident,
mod_param: strait,
mod_instance,
mod_instantiable,
mod_default_instance,
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) {
Ok(opts) => opts,
Err(err) => return err.to_compile_error().into(),
};
let hidden_crate_name = hidden_crate.map(|rc| rc.ident.content).map(|i| i.to_string())
.unwrap_or_else(|| "decl_storage".to_string());
let scrate = generate_crate_access(&hidden_crate_name, "srml-support");
@@ -89,13 +101,16 @@ pub fn decl_storage_impl(input: TokenStream) -> TokenStream {
&scrate,
&traitinstance,
&traittype,
&instance_opts,
&storage_lines,
&extra_genesis,
extra_genesis_skip_phantom_data_field.is_some(),
));
let decl_storage_items = decl_storage_items(
&scrate,
&traitinstance,
&traittype,
&instance_opts,
&cratename,
&storage_lines,
);
@@ -104,19 +119,29 @@ pub fn decl_storage_impl(input: TokenStream) -> TokenStream {
);
let impl_store_items = impl_store_items(
&traitinstance,
&instance_opts.instance,
&storage_lines,
);
let impl_store_fns = impl_store_fns(
&scrate,
&traitinstance,
&instance_opts.instance,
&storage_lines,
);
let (store_default_struct, store_functions_to_metadata) = store_functions_to_metadata(
&scrate,
&traitinstance,
&traittype,
&instance_opts,
&storage_lines,
);
let InstanceOpts {
instance,
bound_instantiable,
..
} = instance_opts;
let cratename_string = cratename.to_string();
let expanded = quote! {
#scrate_decl
@@ -125,10 +150,10 @@ pub fn decl_storage_impl(input: TokenStream) -> TokenStream {
#decl_store_items
}
#store_default_struct
impl<#traitinstance: #traittype> #storetype for #module_ident<#traitinstance> {
impl<#traitinstance: #traittype, #instance #bound_instantiable> #storetype for #module_ident<#traitinstance, #instance> {
#impl_store_items
}
impl<#traitinstance: 'static + #traittype> #module_ident<#traitinstance> {
impl<#traitinstance: 'static + #traittype, #instance #bound_instantiable> #module_ident<#traitinstance, #instance> {
#impl_store_fns
#[doc(hidden)]
pub fn store_metadata() -> #scrate::storage::generator::StorageMetadata {
@@ -157,10 +182,20 @@ fn decl_store_extra_genesis(
scrate: &TokenStream2,
traitinstance: &Ident,
traittype: &syn::TypeParamBound,
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,
..
} = instance_opts;
let mut is_trait_needed = false;
let mut has_trait_field = false;
let mut serde_complete_bound = std::collections::HashSet::new();
@@ -222,7 +257,7 @@ fn decl_store_extra_genesis(
},
});
opt_build = Some(build.as_ref().map(|b| &b.expr.content).map(|b|quote!( #b ))
.unwrap_or_else(|| quote!( (|config: &GenesisConfig<#traitinstance>| config.#ident.clone()) )));
.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 {
@@ -246,8 +281,7 @@ fn decl_store_extra_genesis(
use #scrate::codec::{Encode, Decode};
let v = (#builder)(&self);
<#name<#traitinstance> as #scrate::storage::generator::StorageValue<#typ>>::put(&v, &storage);
<#name<#traitinstance, #instance> as #scrate::storage::generator::StorageValue<#typ>>::put(&v, &storage);
}}
},
DeclStorageTypeInfosKind::Map { key_type, .. } => {
@@ -257,7 +291,7 @@ fn decl_store_extra_genesis(
let data = (#builder)(&self);
for (k, v) in data.into_iter() {
<#name<#traitinstance> as #scrate::storage::generator::StorageMap<#key_type, #typ>>::insert(&k, &v, &storage);
<#name<#traitinstance, #instance> as #scrate::storage::generator::StorageMap<#key_type, #typ>>::insert(&k, &v, &storage);
}
}}
},
@@ -335,24 +369,26 @@ fn decl_store_extra_genesis(
|| !genesis_extrafields.is_empty()
|| !builders.is_empty();
Ok(if is_extra_genesis_needed {
let (fparam, sparam, ph_field, ph_default) = if is_trait_needed {
if has_trait_field {
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>),
quote!(<#traitinstance>),
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>),
quote!(<#traitinstance>),
quote!(<#traitinstance: #traittype, #instance #bound_instantiable #equal_default_instance>),
quote!(<#traitinstance: #traittype, #instance #bound_instantiable>),
quote!(<#traitinstance, #instance>),
quote!{
#[serde(skip)]
pub _genesis_phantom_data: #scrate::storage::generator::PhantomData<#traitinstance>,
pub _genesis_phantom_data: #scrate::storage::generator::PhantomData<(#traitinstance #comma_instance)>,
},
quote!{
_genesis_phantom_data: Default::default(),
@@ -361,7 +397,7 @@ fn decl_store_extra_genesis(
}
} else {
// do not even need type parameter
(quote!(), quote!(), quote!(), quote!())
(quote!(), quote!(), quote!(), quote!(), quote!())
};
quote!{
@@ -370,14 +406,14 @@ fn decl_store_extra_genesis(
#[serde(rename_all = "camelCase")]
#[serde(deny_unknown_fields)]
#serde_bug_bound
pub struct GenesisConfig#fparam {
pub struct GenesisConfig#fparam_struct {
#ph_field
#config_field
#genesis_extrafields
}
#[cfg(feature = "std")]
impl#fparam Default for GenesisConfig#sparam {
impl#fparam_impl Default for GenesisConfig#sparam {
fn default() -> Self {
GenesisConfig {
#ph_default
@@ -388,7 +424,7 @@ fn decl_store_extra_genesis(
}
#[cfg(feature = "std")]
impl#fparam #scrate::runtime_primitives::BuildStorage for GenesisConfig#sparam {
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> {
use #scrate::rstd::{cell::RefCell, marker::PhantomData};
let storage = (RefCell::new(r), PhantomData::<Self>::default());
@@ -412,11 +448,96 @@ fn decl_storage_items(
scrate: &TokenStream2,
traitinstance: &Ident,
traittype: &syn::TypeParamBound,
instance_opts: &InstanceOpts,
cratename: &Ident,
storage_lines: &ext::Punctuated<DeclStorageLine, Token![;]>,
) -> TokenStream2 {
let mut impls = TokenStream2::new();
let InstanceOpts {
instance,
default_instance,
instantiable,
..
} = instance_opts;
// Build Instantiable trait
if instance.is_some() {
let mut method_defs = TokenStream2::new();
let mut method_impls = TokenStream2::new();
for sline in storage_lines.inner.iter() {
let DeclStorageLine {
storage_type,
name,
..
} = sline;
let type_infos = get_type_infos(storage_type);
let method_name = syn::Ident::new(&format!("build_prefix_once_for_{}", name.to_string()), proc_macro2::Span::call_site());
method_defs.extend(quote!{ fn #method_name(prefix: &'static [u8]) -> &'static [u8]; });
method_impls.extend(quote!{
fn #method_name(prefix: &'static [u8]) -> &'static [u8] {
static LAZY: #scrate::lazy::Lazy<#scrate::rstd::vec::Vec<u8>> = #scrate::lazy::Lazy::INIT;
LAZY.get(|| {
let mut final_prefix = #scrate::rstd::vec::Vec::new();
final_prefix.extend_from_slice(prefix);
final_prefix.extend_from_slice(Self::INSTANCE_PREFIX.as_bytes());
final_prefix
})
}
});
if let DeclStorageTypeInfosKind::Map { is_linked: true, .. } = type_infos.kind {
let method_name = syn::Ident::new(&format!("build_head_key_once_for_{}", name.to_string()), proc_macro2::Span::call_site());
method_defs.extend(quote!{ fn #method_name(prefix: &'static [u8]) -> &'static [u8]; });
method_impls.extend(quote!{
fn #method_name(prefix: &'static [u8]) -> &'static [u8] {
static LAZY: #scrate::lazy::Lazy<#scrate::rstd::vec::Vec<u8>> = #scrate::lazy::Lazy::INIT;
LAZY.get(|| {
let mut final_prefix = #scrate::rstd::vec::Vec::new();
final_prefix.extend_from_slice("head of ".as_bytes());
final_prefix.extend_from_slice(prefix);
final_prefix.extend_from_slice(Self::INSTANCE_PREFIX.as_bytes());
final_prefix
})
}
});
}
}
impls.extend(quote! {
pub trait #instantiable: 'static {
const INSTANCE_PREFIX: &'static str;
#method_defs
}
});
let instances = (0..NUMBER_OF_INSTANCE)
.map(|i| {
let name = format!("Instance{}", i);
let ident = syn::Ident::new(&name, proc_macro2::Span::call_site());
(name, ident)
})
.chain(default_instance.clone().map(|ident| (String::new(), ident)));
for (prefix, ident) in instances {
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)]
pub struct #ident;
impl #instantiable for #ident {
const INSTANCE_PREFIX: &'static str = #prefix;
#method_impls
}
});
}
}
for sline in storage_lines.inner.iter() {
let DeclStorageLine {
attrs,
@@ -435,8 +556,10 @@ fn decl_storage_items(
let i = impls::Impls {
scrate,
visibility,
cratename,
traitinstance,
traittype,
instance_opts,
type_infos,
fielddefault: default_value.inner.as_ref().map(|d| &d.expr).map(|d| quote!( #d ))
.unwrap_or_else(|| quote!{ Default::default() }),
@@ -474,13 +597,14 @@ fn decl_store_items(
fn impl_store_items(
traitinstance: &Ident,
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| {
items.extend(
quote!(
type #name = #name<#traitinstance>;
type #name = #name<#traitinstance, #instance>;
)
);
items
@@ -490,6 +614,7 @@ fn impl_store_items(
fn impl_store_fns(
scrate: &TokenStream2,
traitinstance: &Ident,
instance: &Option<syn::Ident>,
storage_lines: &ext::Punctuated<DeclStorageLine, Token![;]>,
) -> TokenStream2 {
let mut items = TokenStream2::new();
@@ -517,7 +642,7 @@ fn impl_store_fns(
quote!{
#( #[ #attrs ] )*
pub fn #get_fn() -> #value_type {
<#name<#traitinstance> as #scrate::storage::generator::StorageValue<#typ>> :: get(&#scrate::storage::RuntimeStorage)
<#name<#traitinstance, #instance> as #scrate::storage::generator::StorageValue<#typ>> :: get(&#scrate::storage::RuntimeStorage)
}
}
},
@@ -525,7 +650,7 @@ fn impl_store_fns(
quote!{
#( #[ #attrs ] )*
pub fn #get_fn<K: #scrate::storage::generator::Borrow<#key_type>>(key: K) -> #value_type {
<#name<#traitinstance> as #scrate::storage::generator::StorageMap<#key_type, #typ>> :: get(key.borrow(), &#scrate::storage::RuntimeStorage)
<#name<#traitinstance, #instance> as #scrate::storage::generator::StorageMap<#key_type, #typ>> :: get(key.borrow(), &#scrate::storage::RuntimeStorage)
}
}
}
@@ -540,9 +665,18 @@ fn store_functions_to_metadata (
scrate: &TokenStream2,
traitinstance: &Ident,
traittype: &syn::TypeParamBound,
instance_opts: &InstanceOpts,
storage_lines: &ext::Punctuated<DeclStorageLine, Token![;]>,
) -> (TokenStream2, TokenStream2) {
let InstanceOpts {
comma_instance,
equal_default_instance,
bound_instantiable,
instance,
..
} = instance_opts;
let mut items = TokenStream2::new();
let mut default_getter_struct_def = TokenStream2::new();
for sline in storage_lines.inner.iter() {
@@ -613,7 +747,7 @@ fn store_functions_to_metadata (
ty: #stype,
default: #scrate::storage::generator::DecodeDifferent::Encode(
#scrate::storage::generator::DefaultByteGetter(
&#struct_name::<#traitinstance>(#scrate::rstd::marker::PhantomData)
&#struct_name::<#traitinstance, #instance>(#scrate::rstd::marker::PhantomData)
)
),
documentation: #scrate::storage::generator::DecodeDifferent::Encode(&[ #docs ]),
@@ -622,12 +756,12 @@ fn store_functions_to_metadata (
items.extend(item);
let def_get = quote! {
#[doc(hidden)]
pub struct #struct_name<#traitinstance>(pub #scrate::rstd::marker::PhantomData<#traitinstance>);
pub struct #struct_name<#traitinstance, #instance #bound_instantiable #equal_default_instance>(pub #scrate::rstd::marker::PhantomData<(#traitinstance #comma_instance)>);
#[cfg(feature = "std")]
#[allow(non_upper_case_globals)]
static #cache_name: #scrate::once_cell::sync::OnceCell<#scrate::rstd::vec::Vec<u8>> = #scrate::once_cell::sync::OnceCell::INIT;
#[cfg(feature = "std")]
impl<#traitinstance: #traittype> #scrate::storage::generator::DefaultByte for #struct_name<#traitinstance> {
impl<#traitinstance: #traittype, #instance #bound_instantiable> #scrate::storage::generator::DefaultByte for #struct_name<#traitinstance, #instance> {
fn default_byte(&self) -> #scrate::rstd::vec::Vec<u8> {
use #scrate::codec::Encode;
#cache_name.get_or_init(|| {
@@ -637,7 +771,7 @@ fn store_functions_to_metadata (
}
}
#[cfg(not(feature = "std"))]
impl<#traitinstance: #traittype> #scrate::storage::generator::DefaultByte for #struct_name<#traitinstance> {
impl<#traitinstance: #traittype, #instance #bound_instantiable> #scrate::storage::generator::DefaultByte for #struct_name<#traitinstance, #instance> {
fn default_byte(&self) -> #scrate::rstd::vec::Vec<u8> {
use #scrate::codec::Encode;
let def_val: #value_type = #default;
@@ -708,3 +842,44 @@ 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 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> {
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))
} else {
(quote!{}, None)
};
Ok(InstanceOpts {
comma_instance: quote!{, #instance},
equal_default_instance,
bound_instantiable: quote!{: #instantiable},
instance: Some(instance),
default_instance,
instantiable: Some(instantiable),
})
},
(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))),
}
}
+102 -107
View File
@@ -91,20 +91,28 @@ impl<T> Parameter for T where T: Codec + Clone + Eq {}
///
/// The `on_initialise` and `on_finalise` functions are special, since it can either take no
/// parameters, or one parameter, which has the runtime's block number type.
///
/// ### Module with instances
///
/// decl_module! support modules with instances with the following syntax: (DefaultInstance type is
/// optionnal)
/// ```nocompile
/// pub struct Module<T: Trait<I>, I: Instance = DefaultInstance> for enum Call where origin: T::Origin {}
/// ```
#[macro_export]
macro_rules! decl_module {
// Macro transformations (to convert invocations with incomplete parameters to the canonical
// form)
(
$(#[$attr:meta])*
pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident>
pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident$(<I>, I: $instantiable:path $(= $module_default_instance:path)?)?>
for enum $call_type:ident where origin: $origin_type:ty {
$($t:tt)*
}
) => {
decl_module!(@normalize
$(#[$attr])*
pub struct $mod_type<$trait_instance: $trait_name>
pub struct $mod_type<$trait_instance: $trait_name$(<I>, I: $instantiable $(= $module_default_instance)?)?>
for enum $call_type where origin: $origin_type, system = system
{}
{}
@@ -115,14 +123,14 @@ macro_rules! decl_module {
};
(
$(#[$attr:meta])*
pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident>
pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident$(<I>, I: $instantiable:path $(= $module_default_instance:path)?)?>
for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident {
$($t:tt)*
}
) => {
decl_module!(@normalize
$(#[$attr])*
pub struct $mod_type<$trait_instance: $trait_name>
pub struct $mod_type<$trait_instance: $trait_name$(<I>, I: $instantiable $(= $module_default_instance)?)?>
for enum $call_type where origin: $origin_type, system = $system
{}
{}
@@ -134,21 +142,21 @@ macro_rules! decl_module {
(@normalize
$(#[$attr:meta])*
pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident>
pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident$(<I>, I: $instantiable:path $(= $module_default_instance:path)?)?>
for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident
{}
{ $( $on_initialise:tt )* }
{ $( $on_finalise:tt )* }
[ $($t:tt)* ]
$(#[doc = $doc_attr:tt])*
$vis:vis fn deposit_event $(<$dpeg:ident>)* () = default;
$vis:vis fn deposit_event $(<$dpeg:ident $(, $dpeg_instance:ident)?>)* () = default;
$($rest:tt)*
) => {
decl_module!(@normalize
$(#[$attr])*
pub struct $mod_type<$trait_instance: $trait_name>
pub struct $mod_type<$trait_instance: $trait_name$(<I>, I: $instantiable $(= $module_default_instance)?)?>
for enum $call_type where origin: $origin_type, system = $system
{ $vis fn deposit_event $(<$dpeg>)* () = default; }
{ $vis fn deposit_event $(<$dpeg $(, $dpeg_instance)?>)* () = default; }
{ $( $on_initialise )* }
{ $( $on_finalise )* }
[ $($t)* ]
@@ -157,23 +165,23 @@ macro_rules! decl_module {
};
(@normalize
$(#[$attr:meta])*
pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident>
pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident$(<I>, I: $instantiable:path $(= $module_default_instance:path)?)?>
for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident
{}
{ $( $on_initialise:tt )* }
{ $( $on_finalise:tt )* }
[ $($t:tt)* ]
$(#[doc = $doc_attr:tt])*
$vis:vis fn deposit_event $(<$dpeg:ident>)* (
$vis:vis fn deposit_event $(<$dpeg:ident $(, $dpeg_instance:ident)?>)* (
$($param_name:ident : $param:ty),*
) { $( $impl:tt )* }
$($rest:tt)*
) => {
decl_module!(@normalize
$(#[$attr])*
pub struct $mod_type<$trait_instance: $trait_name>
pub struct $mod_type<$trait_instance: $trait_name$(<I>, I: $instantiable $(= $module_default_instance)?)?>
for enum $call_type where origin: $origin_type, system = $system
{ $vis fn deposit_event $(<$dpeg>)* ($( $param_name: $param ),* ) { $( $impl )* } }
{ $vis fn deposit_event $(<$dpeg $(, $dpeg_instance)?>)* ($( $param_name: $param ),* ) { $( $impl )* } }
{ $( $on_initialise )* }
{ $( $on_finalise )* }
[ $($t)* ]
@@ -182,7 +190,7 @@ macro_rules! decl_module {
};
(@normalize
$(#[$attr:meta])*
pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident>
pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident$(<I>, I: $instantiable:path $(= $module_default_instance:path)?)?>
for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident
{ $( $deposit_event:tt )* }
{ $( $on_initialise:tt )* }
@@ -194,7 +202,7 @@ macro_rules! decl_module {
) => {
decl_module!(@normalize
$(#[$attr])*
pub struct $mod_type<$trait_instance: $trait_name>
pub struct $mod_type<$trait_instance: $trait_name$(<I>, I: $instantiable $(= $module_default_instance)?)?>
for enum $call_type where origin: $origin_type, system = $system
{ $( $deposit_event )* }
{ $( $on_initialise )* }
@@ -205,7 +213,7 @@ macro_rules! decl_module {
};
(@normalize
$(#[$attr:meta])*
pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident>
pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident$(<I>, I: $instantiable:path $(= $module_default_instance:path)?)?>
for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident
{ $( $deposit_event:tt )* }
{}
@@ -217,7 +225,7 @@ macro_rules! decl_module {
) => {
decl_module!(@normalize
$(#[$attr])*
pub struct $mod_type<$trait_instance: $trait_name>
pub struct $mod_type<$trait_instance: $trait_name$(<I>, I: $instantiable $(= $module_default_instance)?)?>
for enum $call_type where origin: $origin_type, system = $system
{ $( $deposit_event )* }
{ fn on_initialise( $( $param_name : $param ),* ) { $( $impl )* } }
@@ -228,7 +236,7 @@ macro_rules! decl_module {
};
(@normalize
$(#[$attr:meta])*
pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident>
pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident$(<I>, $instance:ident: $instantiable:path $(= $module_default_instance:path)?)?>
for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident
{ $( $deposit_event:tt )* }
{ $( $on_initialise:tt )* }
@@ -242,7 +250,7 @@ macro_rules! decl_module {
) => {
decl_module!(@normalize
$(#[$attr])*
pub struct $mod_type<$trait_instance: $trait_name>
pub struct $mod_type<$trait_instance: $trait_name$(<I>, $instance: $instantiable $(= $module_default_instance)?)?>
for enum $call_type where origin: $origin_type, system = $system
{ $( $deposit_event )* }
{ $( $on_initialise )* }
@@ -253,13 +261,14 @@ macro_rules! decl_module {
$fn_vis fn $fn_name(
$origin $( , $(#[$codec_attr])* $param_name : $param )*
) $( -> $result )* { $( $impl )* }
{ $($instance: $instantiable)? }
]
$($rest)*
);
};
(@normalize
$(#[$attr:meta])*
pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident>
pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident$(<I>, I: $instantiable:path $(= $module_default_instance:path)?)?>
for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident
{ $( $deposit_event:tt )* }
{ $( $on_initialise:tt )* }
@@ -279,7 +288,7 @@ macro_rules! decl_module {
};
(@normalize
$(#[$attr:meta])*
pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident>
pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident$(<I>, I: $instantiable:path $(= $module_default_instance:path)?)?>
for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident
{ $( $deposit_event:tt )* }
{ $( $on_initialise:tt )* }
@@ -299,7 +308,7 @@ macro_rules! decl_module {
};
(@normalize
$(#[$attr:meta])*
pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident>
pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident$(<I>, $instance:ident: $instantiable:path $(= $module_default_instance:path)?)?>
for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident
{ $( $deposit_event:tt )* }
{ $( $on_initialise:tt )* }
@@ -313,7 +322,7 @@ macro_rules! decl_module {
) => {
decl_module!(@normalize
$(#[$attr])*
pub struct $mod_type<$trait_instance: $trait_name>
pub struct $mod_type<$trait_instance: $trait_name$(<I>, $instance: $instantiable $(= $module_default_instance)?)?>
for enum $call_type where origin: $origin_type, system = $system
{ $( $deposit_event )* }
{ $( $on_initialise )* }
@@ -324,13 +333,14 @@ macro_rules! decl_module {
$fn_vis fn $fn_name(
root $( , $(#[$codec_attr])* $param_name : $param )*
) $( -> $result )* { $( $impl )* }
{ $($instance: $instantiable)? }
]
$($rest)*
);
};
(@normalize
$(#[$attr:meta])*
pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident>
pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident$(<I>, I: $instantiable:path $(= $module_default_instance:path)?)?>
for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident
{ $( $deposit_event:tt )* }
{ $( $on_initialise:tt )* }
@@ -339,7 +349,7 @@ macro_rules! decl_module {
) => {
decl_module!(@imp
$(#[$attr])*
pub struct $mod_type<$trait_instance: $trait_name>
pub struct $mod_type<$trait_instance: $trait_name$(<I>, I: $instantiable $(= $module_default_instance)?)?>
for enum $call_type where origin: $origin_type, system = $system {
$($t)*
}
@@ -354,62 +364,46 @@ macro_rules! decl_module {
(@call
root
$mod_type:ident $trait_instance:ident $fn_name:ident $origin:ident $system:ident [ $( $param_name:ident),* ]
$mod_type:ident<$trait_instance:ident $(, $instance:ident)?> $fn_name:ident $origin:ident $system:ident [ $( $param_name:ident),* ]
) => {
{
$system::ensure_root($origin)?;
<$mod_type<$trait_instance>>::$fn_name( $( $param_name ),* )
<$mod_type<$trait_instance $(, $instance)?>>::$fn_name( $( $param_name ),* )
}
};
(@call
$ingore:ident
$mod_type:ident $trait_instance:ident $fn_name:ident $origin:ident $system:ident [ $( $param_name:ident),* ]
$mod_type:ident<$trait_instance:ident $(, $instance:ident)?> $fn_name:ident $origin:ident $system:ident [ $( $param_name:ident),* ]
) => {
<$mod_type<$trait_instance>>::$fn_name( $origin $(, $param_name )* )
<$mod_type<$trait_instance $(, $instance)?>>::$fn_name( $origin $(, $param_name )* )
};
// no `deposit_event` function wanted
(@impl_deposit_event
$module:ident<$trait_instance:ident: $trait_name:ident>;
$module:ident<$trait_instance:ident: $trait_name:ident$(<I>, I: $instantiable:path)?>;
$system:ident;
) => {};
// Non-generic event
(@impl_deposit_event
$module:ident<$trait_instance:ident: $trait_name:ident>;
$module:ident<$trait_instance:ident: $trait_name:ident$(<I>, $instance:ident: $instantiable:path)?>;
$system:ident;
$vis:vis fn deposit_event() = default;
$vis:vis fn deposit_event$(<$event_trait_instance:ident $(, $event_instance:ident)?>)?() = default;
) => {
impl<$trait_instance: $trait_name> $module<$trait_instance> {
$vis fn deposit_event(event: Event) {
impl<$trait_instance: $trait_name$(<I>, $instance: $instantiable)?> $module<$trait_instance $(, $instance)?> {
$vis fn deposit_event(event: Event$(<$event_trait_instance $(, $event_instance)?>)?) {
<$system::Module<$trait_instance>>::deposit_event(
<$trait_instance as $trait_name>::Event::from(event).into()
);
}
}
};
// Generic event
(@impl_deposit_event
$module:ident<$trait_instance:ident: $trait_name:ident>;
$system:ident;
$vis:vis fn deposit_event<$ignore:ident>() = default;
) => {
impl<$trait_instance: $trait_name> $module<$trait_instance> {
$vis fn deposit_event(event: Event<$trait_instance>) {
<$system::Module<$trait_instance>>::deposit_event(
<$trait_instance as $trait_name>::Event::from(event).into()
<$trait_instance as $trait_name$(<$instance>)?>::Event::from(event).into()
);
}
}
};
(@impl_deposit_event
$module:ident<$trait_instance:ident: $trait_name:ident>;
$module:ident<$trait_instance:ident: $trait_name:ident$(<I>, $instance:ident: $instantiable:path)?>;
$system:ident;
$vis:vis fn deposit_event($param:ident : $param_ty:ty) { $( $impl:tt )* }
) => {
impl<$trait_instance: $trait_name> $module<$trait_instance> {
impl<$trait_instance: $trait_name$(<I>, $instance: $instantiable)?> $module<$trait_instance $(, $instance)?> {
$vis fn deposit_event($param: $param_ty) {
$( $impl )*
}
@@ -417,74 +411,74 @@ macro_rules! decl_module {
};
(@impl_on_initialise
$module:ident<$trait_instance:ident: $trait_name:ident>;
$module:ident<$trait_instance:ident: $trait_name:ident$(<I>, $instance:ident: $instantiable:path)?>;
fn on_initialise() { $( $impl:tt )* }
) => {
impl<$trait_instance: $trait_name>
impl<$trait_instance: $trait_name$(<I>, $instance: $instantiable)?>
$crate::runtime_primitives::traits::OnInitialise<$trait_instance::BlockNumber>
for $module<$trait_instance>
for $module<$trait_instance$(, $instance)?>
{
fn on_initialise(_block_number_not_used: $trait_instance::BlockNumber) { $( $impl )* }
}
};
(@impl_on_initialise
$module:ident<$trait_instance:ident: $trait_name:ident>;
$module:ident<$trait_instance:ident: $trait_name:ident$(<I>, $instance:ident: $instantiable:path)?>;
fn on_initialise($param:ident : $param_ty:ty) { $( $impl:tt )* }
) => {
impl<$trait_instance: $trait_name>
impl<$trait_instance: $trait_name$(<I>, $instance: $instantiable)?>
$crate::runtime_primitives::traits::OnInitialise<$trait_instance::BlockNumber>
for $module<$trait_instance>
for $module<$trait_instance$(, $instance)?>
{
fn on_initialise($param: $param_ty) { $( $impl )* }
}
};
(@impl_on_initialise
$module:ident<$trait_instance:ident: $trait_name:ident>;
$module:ident<$trait_instance:ident: $trait_name:ident$(<I>, $instance:ident: $instantiable:path)?>;
) => {
impl<$trait_instance: $trait_name>
impl<$trait_instance: $trait_name$(<I>, $instance: $instantiable)?>
$crate::runtime_primitives::traits::OnInitialise<$trait_instance::BlockNumber>
for $module<$trait_instance>
for $module<$trait_instance$(, $instance)?>
{}
};
(@impl_on_finalise
$module:ident<$trait_instance:ident: $trait_name:ident>;
$module:ident<$trait_instance:ident: $trait_name:ident$(<I>, $instance:ident: $instantiable:path)?>;
fn on_finalise() { $( $impl:tt )* }
) => {
impl<$trait_instance: $trait_name>
impl<$trait_instance: $trait_name$(<I>, $instance: $instantiable)?>
$crate::runtime_primitives::traits::OnFinalise<$trait_instance::BlockNumber>
for $module<$trait_instance>
for $module<$trait_instance$(, $instance)?>
{
fn on_finalise(_block_number_not_used: $trait_instance::BlockNumber) { $( $impl )* }
}
};
(@impl_on_finalise
$module:ident<$trait_instance:ident: $trait_name:ident>;
$module:ident<$trait_instance:ident: $trait_name:ident$(<I>, $instance:ident: $instantiable:path)?>;
fn on_finalise($param:ident : $param_ty:ty) { $( $impl:tt )* }
) => {
impl<$trait_instance: $trait_name>
impl<$trait_instance: $trait_name$(<I>, $instance: $instantiable)?>
$crate::runtime_primitives::traits::OnFinalise<$trait_instance::BlockNumber>
for $module<$trait_instance>
for $module<$trait_instance$(, $instance)?>
{
fn on_finalise($param: $param_ty) { $( $impl )* }
}
};
(@impl_on_finalise
$module:ident<$trait_instance:ident: $trait_name:ident>;
$module:ident<$trait_instance:ident: $trait_name:ident$(<I>, $instance:ident: $instantiable:path)?>;
) => {
impl<$trait_instance: $trait_name>
impl<$trait_instance: $trait_name$(<I>, $instance: $instantiable)?>
$crate::runtime_primitives::traits::OnFinalise<$trait_instance::BlockNumber>
for $module<$trait_instance>
for $module<$trait_instance$(, $instance)?>
{
}
};
(@impl_function
$module:ident<$trait_instance:ident: $trait_name:ident>;
$module:ident<$trait_instance:ident: $trait_name:ident$(<I>, $instance:ident: $instantiable:path)?>;
$origin_ty:ty;
root;
$(#[doc = $doc_attr:tt])*
@@ -498,7 +492,7 @@ macro_rules! decl_module {
};
(@impl_function
$module:ident<$trait_instance:ident: $trait_name:ident>;
$module:ident<$trait_instance:ident: $trait_name:ident$(<I>, $instance:ident: $instantiable:path)?>;
$origin_ty:ty;
root;
$(#[doc = $doc_attr:tt])*
@@ -513,7 +507,7 @@ macro_rules! decl_module {
};
(@impl_function
$module:ident<$trait_instance:ident: $trait_name:ident>;
$module:ident<$trait_instance:ident: $trait_name:ident$(<I>, $instance:ident: $instantiable:path)?>;
$origin_ty:ty;
$ignore:ident;
$(#[doc = $doc_attr:tt])*
@@ -531,7 +525,7 @@ macro_rules! decl_module {
};
(@impl_function
$module:ident<$trait_instance:ident: $trait_name:ident>;
$module:ident<$trait_instance:ident: $trait_name:ident$(<I>, $instance:ident: $instantiable:path)?>;
$origin_ty:ty;
$ignore:ident;
$(#[doc = $doc_attr:tt])*
@@ -549,13 +543,14 @@ macro_rules! decl_module {
(@imp
$(#[$attr:meta])*
pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident>
pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident$(<I>, $instance:ident: $instantiable:path $(= $module_default_instance:path)?)?>
for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident {
$(
$(#[doc = $doc_attr:tt])*
$fn_vis:vis fn $fn_name:ident(
$from:ident $( , $(#[$codec_attr:ident])* $param_name:ident : $param:ty)*
) $( -> $result:ty )* { $( $impl:tt )* }
{ $($fn_instance:ident: $fn_instantiable:path)? }
)*
}
{ $( $deposit_event:tt )* }
@@ -569,29 +564,29 @@ macro_rules! decl_module {
// serde-derive for when we attempt to derive `Deserialize` on these types,
// in a situation where we've imported `srml_support` as another name.
#[cfg(feature = "std")]
pub struct $mod_type<$trait_instance: $trait_name>(::std::marker::PhantomData<$trait_instance>);
pub struct $mod_type<$trait_instance: $trait_name $(<I>, $instance: $instantiable $( = $module_default_instance)?)?>(::std::marker::PhantomData<($trait_instance $(, $instance)?)>);
// Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted.
#[derive(Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "std", derive(Debug))]
#[cfg(not(feature = "std"))]
pub struct $mod_type<$trait_instance: $trait_name>(::core::marker::PhantomData<$trait_instance>);
pub struct $mod_type<$trait_instance: $trait_name $(<I>, $instance: $instantiable $( = $module_default_instance)?)?>(::core::marker::PhantomData<($trait_instance $(, $instance)?)>);
decl_module! {
@impl_on_initialise
$mod_type<$trait_instance: $trait_name>;
$mod_type<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?>;
$( $on_initialise )*
}
decl_module! {
@impl_on_finalise
$mod_type<$trait_instance: $trait_name>;
$mod_type<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?>;
$( $on_finalise )*
}
decl_module! {
@impl_deposit_event
$mod_type<$trait_instance: $trait_name>;
$mod_type<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?>;
$system;
$( $deposit_event )*
}
@@ -599,11 +594,11 @@ macro_rules! decl_module {
/// Can also be called using [`Call`].
///
/// [`Call`]: enum.Call.html
impl<$trait_instance: $trait_name> $mod_type<$trait_instance> {
impl<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?> $mod_type<$trait_instance $(, $instance)?> {
$(
decl_module! {
@impl_function
$mod_type<$trait_instance: $trait_name>;
$mod_type<$trait_instance: $trait_name $(<I>, $fn_instance: $fn_instantiable)?>;
$origin_type;
$from;
$(#[doc = $doc_attr])*
@@ -616,9 +611,9 @@ macro_rules! decl_module {
#[cfg(feature = "std")]
$(#[$attr])*
pub enum $call_type<$trait_instance: $trait_name> {
pub enum $call_type<$trait_instance: $trait_name$(<I>, $instance: $instantiable $( = $module_default_instance)?)?> {
#[doc(hidden)]
__PhantomItem(::std::marker::PhantomData<$trait_instance>, $crate::dispatch::Never),
__PhantomItem(::std::marker::PhantomData<($trait_instance $(, $instance)?)>, $crate::dispatch::Never),
$(
#[allow(non_camel_case_types)]
$(#[doc = $doc_attr])*
@@ -628,9 +623,9 @@ macro_rules! decl_module {
#[cfg(not(feature = "std"))]
$(#[$attr])*
pub enum $call_type<$trait_instance: $trait_name> {
pub enum $call_type<$trait_instance: $trait_name$(<I>, $instance: $instantiable $( = $module_default_instance)?)?> {
#[doc(hidden)]
__PhantomItem(::core::marker::PhantomData<$trait_instance>, $crate::dispatch::Never),
__PhantomItem(::core::marker::PhantomData<($trait_instance $(, $instance)?)>, $crate::dispatch::Never),
$(
#[allow(non_camel_case_types)]
$(#[doc = $doc_attr])*
@@ -640,8 +635,8 @@ macro_rules! decl_module {
// manual implementation of clone/eq/partialeq because using derive erroneously requires
// clone/eq/partialeq from T.
impl<$trait_instance: $trait_name> $crate::dispatch::Clone
for $call_type<$trait_instance>
impl<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?> $crate::dispatch::Clone
for $call_type<$trait_instance $(, $instance)?>
{
fn clone(&self) -> Self {
match *self {
@@ -653,8 +648,8 @@ macro_rules! decl_module {
}
}
}
impl<$trait_instance: $trait_name> $crate::dispatch::PartialEq
for $call_type<$trait_instance>
impl<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?> $crate::dispatch::PartialEq
for $call_type<$trait_instance $(, $instance)?>
{
fn eq(&self, _other: &Self) -> bool {
match *self {
@@ -675,13 +670,13 @@ macro_rules! decl_module {
}
}
}
impl<$trait_instance: $trait_name> $crate::dispatch::Eq
for $call_type<$trait_instance>
impl<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?> $crate::dispatch::Eq
for $call_type<$trait_instance $(, $instance)?>
{}
#[cfg(feature = "std")]
impl<$trait_instance: $trait_name> $crate::dispatch::fmt::Debug
for $call_type<$trait_instance>
impl<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?> $crate::dispatch::fmt::Debug
for $call_type<$trait_instance $(, $instance)?>
{
fn fmt(&self, _f: &mut $crate::dispatch::fmt::Formatter) -> $crate::dispatch::result::Result<(), $crate::dispatch::fmt::Error> {
match *self {
@@ -697,20 +692,20 @@ macro_rules! decl_module {
}
}
impl<$trait_instance: $trait_name> $crate::dispatch::Decode for $call_type<$trait_instance> {
fn decode<I: $crate::dispatch::Input>(input: &mut I) -> Option<Self> {
impl<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?> $crate::dispatch::Decode for $call_type<$trait_instance $(, $instance)?> {
fn decode<Input: $crate::dispatch::Input>(input: &mut Input) -> Option<Self> {
let _input_id = input.read_byte()?;
$crate::__impl_decode!(input; _input_id; 0; $call_type; $( fn $fn_name( $( $(#[$codec_attr on type $param])* $param_name ),* ); )*)
}
}
impl<$trait_instance: $trait_name> $crate::dispatch::Encode for $call_type<$trait_instance> {
impl<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?> $crate::dispatch::Encode for $call_type<$trait_instance $(, $instance)?> {
fn encode_to<W: $crate::dispatch::Output>(&self, _dest: &mut W) {
$crate::__impl_encode!(_dest; *self; 0; $call_type; $( fn $fn_name( $( $(#[$codec_attr on type $param])* $param_name ),* ); )*);
}
}
impl<$trait_instance: $trait_name> $crate::dispatch::Dispatchable
for $call_type<$trait_instance>
impl<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?> $crate::dispatch::Dispatchable
for $call_type<$trait_instance $(, $instance)?>
{
type Trait = $trait_instance;
type Origin = $origin_type;
@@ -721,7 +716,7 @@ macro_rules! decl_module {
$crate::decl_module!(
@call
$from
$mod_type $trait_instance $fn_name _origin $system [ $( $param_name ),* ]
$mod_type<$trait_instance $(, $fn_instance)?> $fn_name _origin $system [ $( $param_name ),* ]
)
},
)*
@@ -729,20 +724,20 @@ macro_rules! decl_module {
}
}
}
impl<$trait_instance: $trait_name> $crate::dispatch::Callable
for $mod_type<$trait_instance>
impl<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?> $crate::dispatch::Callable
for $mod_type<$trait_instance $(, $instance)?>
{
type Call = $call_type<$trait_instance>;
type Call = $call_type<$trait_instance $(, $instance)?>;
}
impl<$trait_instance: $trait_name> $mod_type<$trait_instance> {
impl<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?> $mod_type<$trait_instance $(, $instance)?> {
#[doc(hidden)]
pub fn dispatch<D: $crate::dispatch::Dispatchable<Trait = $trait_instance>>(d: D, origin: D::Origin) -> $crate::dispatch::Result {
d.dispatch(origin)
}
}
$crate::__dispatch_impl_metadata! {
$mod_type $trait_instance $trait_name $call_type $origin_type
$mod_type<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?> $call_type $origin_type
{$( $(#[doc = $doc_attr])* fn $fn_name($from $(, $(#[$codec_attr])* $param_name : $param )*); )*}
}
}
@@ -949,10 +944,10 @@ macro_rules! __impl_outer_dispatch_common {
#[doc(hidden)]
macro_rules! __dispatch_impl_metadata {
(
$mod_type:ident $trait_instance:ident $trait_name:ident
$mod_type:ident<$trait_instance:ident: $trait_name:ident$(<I>, $instance:ident: $instantiable:path)?>
$($rest:tt)*
) => {
impl<$trait_instance: $trait_name> $mod_type<$trait_instance> {
impl<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?> $mod_type<$trait_instance $(, $instance)?> {
#[doc(hidden)]
pub fn call_functions() -> &'static [$crate::dispatch::FunctionMetadata] {
$crate::__call_to_functions!($($rest)*)
+74 -27
View File
@@ -88,16 +88,48 @@ pub use srml_metadata::{EventMetadata, DecodeDifferent, OuterEventMetadata, FnEn
/// ```
///
/// The syntax for generic events requires the `where`.
///
/// # Generic Event with Instance Example:
///
/// ```rust
/// #[macro_use]
/// extern crate srml_support;
/// extern crate parity_codec as codec;
/// #[macro_use]
/// extern crate parity_codec;
/// #[macro_use]
/// extern crate serde_derive;
///
///# struct DefaultInstance;
///# trait Instance {}
///# impl Instance for DefaultInstance {}
/// trait Trait<I: Instance=DefaultInstance> {
/// type Balance;
/// type Token;
/// }
///
/// // For module with instances, DefaultInstance is optionnal
/// decl_event!(
/// pub enum Event<T, I: Instance = DefaultInstance> where
/// <T as Trait>::Balance,
/// <T as Trait>::Token
/// {
/// Message(Balance, Token),
/// }
/// );
///# fn main() {}
/// ```
#[macro_export]
macro_rules! decl_event {
(
$(#[$attr:meta])*
pub enum Event<$evt_generic_param:ident> where
pub enum Event<$evt_generic_param:ident $(, $instance:ident $(: $instantiable:ident)? $( = $event_default_instance:path)? )?> where
$( $tt:tt )*
) => {
$crate::__decl_generic_event!(
$( #[ $attr ] )*;
$evt_generic_param;
$($instance $( = $event_default_instance)? )?;
{ $( $tt )* };
);
};
@@ -138,11 +170,13 @@ macro_rules! __decl_generic_event {
(
$(#[$attr:meta])*;
$event_generic_param:ident;
$($instance:ident $( = $event_default_instance:path)? )?;
{ $( $tt:tt )* };
) => {
$crate::__decl_generic_event!(@format_generic
$( #[ $attr ] )*;
$event_generic_param;
$($instance $( = $event_default_instance)? )?;
{ $( $tt )* };
{};
);
@@ -151,12 +185,14 @@ macro_rules! __decl_generic_event {
(@format_generic
$(#[$attr:meta])*;
$event_generic_param:ident;
$($instance:ident $( = $event_default_instance:path)? )?;
{ $generic_rename:ident = $generic_type:ty, $($rest:tt)* };
{$( $parsed:tt)*};
) => {
$crate::__decl_generic_event!(@format_generic
$( #[ $attr ] )*;
$event_generic_param;
$($instance $( = $event_default_instance)? )?;
{ $($rest)* };
{ $($parsed)*, $generic_rename = $generic_type };
);
@@ -165,12 +201,14 @@ macro_rules! __decl_generic_event {
(@format_generic
$(#[$attr:meta])*;
$event_generic_param:ident;
$($instance:ident $( = $event_default_instance:path)? )?;
{ <$generic:ident as $trait:path>::$trait_type:ident, $($rest:tt)* };
{$($parsed:tt)*};
) => {
$crate::__decl_generic_event!(@format_generic
$( #[ $attr ] )*;
$event_generic_param;
$($instance $( = $event_default_instance)? )?;
{ $($rest)* };
{ $($parsed)*, $trait_type = <$generic as $trait>::$trait_type };
);
@@ -179,6 +217,7 @@ macro_rules! __decl_generic_event {
(@format_generic
$(#[$attr:meta])*;
$event_generic_param:ident;
$($instance:ident $( = $event_default_instance:path)? )?;
{ $generic_type:ty, $($rest:tt)* };
{$($parsed:tt)*};
) => {
@@ -188,12 +227,14 @@ macro_rules! __decl_generic_event {
(@format_generic
$(#[$attr:meta])*;
$event_generic_param:ident;
$($instance:ident $( = $event_default_instance:path)? )?;
{ <$generic:ident as $trait:path>::$trait_type:ident { $( $events:tt )* } };
{$( $parsed:tt)*};
) => {
$crate::__decl_generic_event!(@generate
$( #[ $attr ] )*;
$event_generic_param;
$($instance $( = $event_default_instance)? )?;
{ $($events)* };
{ $($parsed)*, $trait_type = <$generic as $trait>::$trait_type};
);
@@ -202,12 +243,14 @@ macro_rules! __decl_generic_event {
(@format_generic
$(#[$attr:meta])*;
$event_generic_param:ident;
$($instance:ident $( = $event_default_instance:path)? )?;
{ $generic_rename:ident = $generic_type:ty { $( $events:tt )* } };
{$( $parsed:tt)*};
) => {
$crate::__decl_generic_event!(@generate
$(#[$attr])*;
$event_generic_param;
$($instance $( = $event_default_instance)? )?;
{ $($events)* };
{ $($parsed)*, $generic_rename = $generic_type};
);
@@ -216,6 +259,7 @@ macro_rules! __decl_generic_event {
(@format_generic
$(#[$attr:meta])*;
$event_generic_param:ident;
$($instance:ident $( = $event_default_instance:path)? )?;
{ $generic_type:ty { $( $events:tt )* } };
{$( $parsed:tt)*};
) => {
@@ -224,6 +268,7 @@ macro_rules! __decl_generic_event {
(@generate
$(#[$attr:meta])*;
$event_generic_param:ident;
$($instance:ident $( = $event_default_instance:path)? )?;
{ $( $events:tt )* };
{ ,$( $generic_param:ident = $generic_type:ty ),* };
) => {
@@ -231,20 +276,22 @@ macro_rules! __decl_generic_event {
///
/// [`RawEvent`]: enum.RawEvent.html
/// [`Trait`]: trait.Trait.html
pub type Event<$event_generic_param> = RawEvent<$( $generic_type ),*>;
pub type Event<$event_generic_param $(, $instance $( = $event_default_instance)? )?> = RawEvent<$( $generic_type ),* $(, $instance)? >;
// Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted.
#[derive(Clone, PartialEq, Eq, $crate::codec::Encode, $crate::codec::Decode)]
#[cfg_attr(feature = "std", derive(Debug))]
$(#[$attr])*
pub enum RawEvent<$( $generic_param ),*> {
pub enum RawEvent<$( $generic_param ),* $(, $instance)? > {
#[doc(hidden)]
$(PhantomData($crate::rstd::marker::PhantomData<$instance>),)?
$(
$events
)*
}
impl<$( $generic_param ),*> From<RawEvent<$( $generic_param ),*>> for () {
fn from(_: RawEvent<$( $generic_param ),*>) -> () { () }
impl<$( $generic_param ),* $(, $instance)? > From<RawEvent<$( $generic_param ),* $(, $instance)?>> for () {
fn from(_: RawEvent<$( $generic_param ),* $(, $instance)?>) -> () { () }
}
impl<$( $generic_param ),*> RawEvent<$( $generic_param ),*> {
impl<$( $generic_param ),* $(, $instance)?> RawEvent<$( $generic_param ),* $(, $instance)?> {
#[allow(dead_code)]
pub fn metadata() -> &'static [$crate::event::EventMetadata] {
$crate::__events_to_metadata!(; $( $events )* )
@@ -297,7 +344,7 @@ macro_rules! impl_outer_event {
(
$(#[$attr:meta])*
pub enum $name:ident for $runtime:ident {
$( $rest:tt $( <$t:ident> )*, )*
$( $rest:tt $( <$t:ident $(, $rest_instance:path)? > )*, )*
}
) => {
$crate::impl_outer_event!(
@@ -305,14 +352,14 @@ macro_rules! impl_outer_event {
$name;
$runtime;
system;
Modules { $( $rest $(<$t>)*, )* };
Modules { $( $rest $(<$t $(, $rest_instance)? >)*, )* };
;
);
};
(
$(#[$attr:meta])*
pub enum $name:ident for $runtime:ident where system = $system:ident {
$( $rest:tt $( <$t:ident> )*, )*
$( $rest:tt $( <$t:ident $(, $rest_instance:path)? > )*, )*
}
) => {
$crate::impl_outer_event!(
@@ -320,7 +367,7 @@ macro_rules! impl_outer_event {
$name;
$runtime;
$system;
Modules { $( $rest $(<$t>)*, )* };
Modules { $( $rest $(<$t $(, $rest_instance)? >)*, )* };
;
);
};
@@ -330,18 +377,18 @@ macro_rules! impl_outer_event {
$runtime:ident;
$system:ident;
Modules {
$module:ident<T>,
$( $rest:tt $( <$t:ident> )*, )*
$module:ident<T $(, $instance:path)? >,
$( $rest:tt $( <$t:ident $(, $rest_instance:path)? > )*, )*
};
$( $module_name:ident::Event $( <$generic_param:ident> )*, )*;
$( $module_name:ident::Event $( <$generic_param:ident $(, $generic_instance:path)? > )*, )*;
) => {
$crate::impl_outer_event!(
$( #[$attr] )*;
$name;
$runtime;
$system;
Modules { $( $rest $(<$t>)*, )* };
$( $module_name::Event $( <$generic_param> )*, )* $module::Event<$runtime>,;
Modules { $( $rest $(<$t $(, $rest_instance)? >)*, )* };
$( $module_name::Event $( <$generic_param $(, $generic_instance)? > )*, )* $module::Event<$runtime $(, $instance)? >,;
);
};
(
@@ -351,17 +398,17 @@ macro_rules! impl_outer_event {
$system:ident;
Modules {
$module:ident,
$( $rest:tt, )*
$( $rest:tt )*
};
$( $module_name:ident::Event $( <$generic_param:ident> )*, )*;
$( $module_name:ident::Event $( <$generic_param:ident $(, $generic_instance:path)? > )*, )*;
) => {
$crate::impl_outer_event!(
$( #[$attr] )*;
$name;
$runtime;
$system;
Modules { $( $rest, )* };
$( $module_name::Event $( <$generic_param> )*, )* $module::Event,;
Modules { $( $rest )* };
$( $module_name::Event $( <$generic_param $(, $generic_instance)? > )*, )* $module::Event,;
);
};
@@ -373,7 +420,7 @@ macro_rules! impl_outer_event {
$runtime:ident;
$system:ident;
Modules {};
$( $module_name:ident::Event $( <$generic_param:ident> )*, )*;
$( $module_name:ident::Event $( <$generic_param:ident $(, $generic_instance:path)? > )*, )*;
) => {
// Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted.
#[derive(Clone, PartialEq, Eq, $crate::codec::Encode, $crate::codec::Decode)]
@@ -383,7 +430,7 @@ macro_rules! impl_outer_event {
pub enum $name {
system($system::Event),
$(
$module_name( $module_name::Event $( <$generic_param> )* ),
$module_name( $module_name::Event $( <$generic_param $(, $generic_instance)? > )* ),
)*
}
impl From<$system::Event> for $name {
@@ -392,8 +439,8 @@ macro_rules! impl_outer_event {
}
}
$(
impl From<$module_name::Event $( <$generic_param> )*> for $name {
fn from(x: $module_name::Event $( <$generic_param> )*) -> Self {
impl From<$module_name::Event $( <$generic_param $(, $generic_instance)? > )*> for $name {
fn from(x: $module_name::Event $( <$generic_param $(, $generic_instance)? > )*) -> Self {
$name::$module_name(x)
}
}
@@ -402,7 +449,7 @@ macro_rules! impl_outer_event {
$runtime;
$name;
$system;
$( $module_name::Event $( <$generic_param> )*, )*;
$( $module_name::Event $( <$generic_param $(, $generic_instance)? > )*, )*;
);
}
}
@@ -414,7 +461,7 @@ macro_rules! __impl_outer_event_json_metadata {
$runtime:ident;
$event_name:ident;
$system:ident;
$( $module_name:ident::Event $( <$generic_param:ident> )*, )*;
$( $module_name:ident::Event $( <$generic_param:ident $(, $generic_instance:path)? > )*, )*;
) => {
impl $runtime {
#[allow(dead_code)]
@@ -427,7 +474,7 @@ macro_rules! __impl_outer_event_json_metadata {
, (
stringify!($module_name),
$crate::event::FnEncode(
$module_name::Event $( ::<$generic_param> )* ::metadata
$module_name::Event $( ::<$generic_param $(, $generic_instance)? > )* ::metadata
)
)
)*
@@ -442,7 +489,7 @@ macro_rules! __impl_outer_event_json_metadata {
#[allow(dead_code)]
$crate::paste::item!{
pub fn [< __module_events_ $module_name >] () -> &'static [$crate::event::EventMetadata] {
$module_name::Event $( ::<$generic_param> )* ::metadata()
$module_name::Event $( ::<$generic_param $(, $generic_instance)? > )* ::metadata()
}
}
)*
+15
View File
@@ -64,6 +64,21 @@ pub use runtime_io::print;
#[doc(inline)]
pub use srml_support_procedural::decl_storage;
pub mod lazy {
use spin::Once;
pub struct Lazy<T: Sync>(Once<T>);
impl <T: Sync> Lazy<T> {
pub const INIT: Self = Lazy(Once::INIT);
#[inline(always)]
pub fn get<F>(&'static self, builder: F) -> &T where F: FnOnce() -> T {
self.0.call_once(builder)
}
}
}
#[macro_export]
macro_rules! fail {
( $y:expr ) => {{
+26 -26
View File
@@ -52,17 +52,17 @@ macro_rules! __runtime_modules_to_metadata {
(
$runtime: ident;
$( $metadata:expr ),*;
$mod:ident::$module:ident $(with)+ $($kw:ident)*,
$mod:ident::$module:ident $( < $instance:ident > )? $(with)+ $($kw:ident)*,
$( $rest:tt )*
) => {
$crate::__runtime_modules_to_metadata!(
$runtime;
$( $metadata, )* $crate::metadata::ModuleMetadata {
name: $crate::metadata::DecodeDifferent::Encode(stringify!($mod)),
prefix: $crate::__runtime_modules_to_metadata_calls_storagename!($mod, $module, $runtime, $(with $kw)*),
storage: $crate::__runtime_modules_to_metadata_calls_storage!($mod, $module, $runtime, $(with $kw)*),
calls: $crate::__runtime_modules_to_metadata_calls_call!($mod, $module, $runtime, $(with $kw)*),
event: $crate::__runtime_modules_to_metadata_calls_event!($mod, $module, $runtime, $(with $kw)*),
prefix: $crate::__runtime_modules_to_metadata_calls_storagename!($mod, $module $( <$instance> )?, $runtime, $(with $kw)*),
storage: $crate::__runtime_modules_to_metadata_calls_storage!($mod, $module $( <$instance> )?, $runtime, $(with $kw)*),
calls: $crate::__runtime_modules_to_metadata_calls_call!($mod, $module $( <$instance> )?, $runtime, $(with $kw)*),
event: $crate::__runtime_modules_to_metadata_calls_event!($mod, $module $( <$instance> )?, $runtime, $(with $kw)*),
};
$( $rest )*
)
@@ -81,7 +81,7 @@ macro_rules! __runtime_modules_to_metadata_calls_call {
// skip system
(
system,
$skip_module: ident,
$skip_module: ident $( <$instance:ident> )?,
$skip_runtime: ident,
with Call
$(with $kws:ident)*
@@ -90,29 +90,29 @@ macro_rules! __runtime_modules_to_metadata_calls_call {
};
(
$mod: ident,
$module: ident,
$module: ident $( <$instance:ident> )?,
$runtime: ident,
with Call
$(with $kws:ident)*
) => {
Some($crate::metadata::DecodeDifferent::Encode(
$crate::metadata::FnEncode(
$mod::$module::<$runtime>::call_functions
$mod::$module::<$runtime $(, $mod::$instance )?>::call_functions
)
))
};
(
$mod: ident,
$module: ident,
$module: ident $( <$instance:ident> )?,
$runtime: ident,
with $_:ident
$(with $kws:ident)*
) => {
$crate::__runtime_modules_to_metadata_calls_call!( $mod, $module, $runtime, $(with $kws)* );
$crate::__runtime_modules_to_metadata_calls_call!( $mod, $module $( <$instance> )?, $runtime, $(with $kws)* );
};
(
$mod: ident,
$module: ident,
$module: ident $( <$instance:ident> )?,
$runtime: ident,
) => {
None
@@ -125,7 +125,7 @@ macro_rules! __runtime_modules_to_metadata_calls_call {
macro_rules! __runtime_modules_to_metadata_calls_event {
(
$mod: ident,
$module: ident,
$module: ident $( <$instance:ident> )?,
$runtime: ident,
with Event
$(with $kws:ident)*
@@ -133,23 +133,23 @@ macro_rules! __runtime_modules_to_metadata_calls_event {
Some($crate::metadata::DecodeDifferent::Encode(
$crate::metadata::FnEncode(
$crate::paste::expr!{
$runtime:: [< __module_events_ $mod >]
$runtime:: [< __module_events_ $mod $(_ $instance)?>]
}
)
))
};
(
$mod: ident,
$module: ident,
$module: ident $( <$instance:ident> )?,
$runtime: ident,
with $_:ident
$(with $kws:ident)*
) => {
$crate::__runtime_modules_to_metadata_calls_event!( $mod, $module, $runtime, $(with $kws)* );
$crate::__runtime_modules_to_metadata_calls_event!( $mod, $module $( <$instance> )?, $runtime, $(with $kws)* );
};
(
$mod: ident,
$module: ident,
$module: ident $( <$instance:ident> )?,
$runtime: ident,
) => {
None
@@ -161,29 +161,29 @@ macro_rules! __runtime_modules_to_metadata_calls_event {
macro_rules! __runtime_modules_to_metadata_calls_storagename {
(
$mod: ident,
$module: ident,
$module: ident $( <$instance:ident> )?,
$runtime: ident,
with Storage
$(with $kws:ident)*
) => {
$crate::metadata::DecodeDifferent::Encode(
$crate::metadata::FnEncode(
$mod::$module::<$runtime>::store_metadata_name
$mod::$module::<$runtime $(, $mod::$instance )?>::store_metadata_name
)
)
};
(
$mod: ident,
$module: ident,
$module: ident $( <$instance:ident> )?,
$runtime: ident,
with $_:ident
$(with $kws:ident)*
) => {
$crate::__runtime_modules_to_metadata_calls_storagename!( $mod, $module, $runtime, $(with $kws)* );
$crate::__runtime_modules_to_metadata_calls_storagename!( $mod, $module $( <$instance> )?, $runtime, $(with $kws)* );
};
(
$mod: ident,
$module: ident,
$module: ident $( <$instance:ident> )?,
$runtime: ident,
) => {
$crate::metadata::DecodeDifferent::Encode(
@@ -197,29 +197,29 @@ macro_rules! __runtime_modules_to_metadata_calls_storagename {
macro_rules! __runtime_modules_to_metadata_calls_storage {
(
$mod: ident,
$module: ident,
$module: ident $( <$instance:ident> )?,
$runtime: ident,
with Storage
$(with $kws:ident)*
) => {
Some($crate::metadata::DecodeDifferent::Encode(
$crate::metadata::FnEncode(
$mod::$module::<$runtime>::store_metadata_functions
$mod::$module::<$runtime $(, $mod::$instance )?>::store_metadata_functions
)
))
};
(
$mod: ident,
$module: ident,
$module: ident $( <$instance:ident> )?,
$runtime: ident,
with $_:ident
$(with $kws:ident)*
) => {
$crate::__runtime_modules_to_metadata_calls_storage!( $mod, $module, $runtime, $(with $kws)* );
$crate::__runtime_modules_to_metadata_calls_storage!( $mod, $module $( <$instance> )?, $runtime, $(with $kws)* );
};
(
$mod: ident,
$module: ident,
$module: ident $( <$instance:ident> )?,
$runtime: ident,
) => {
None
+19 -67
View File
@@ -28,34 +28,20 @@ macro_rules! impl_outer_origin {
(
$(#[$attr:meta])*
pub enum $name:ident for $runtime:ident {
$( $module:ident $( <$generic:ident> )* ),* $(,)*
$( $module:ident $( <$generic:ident $(, $instance:path )? > )? ),* $(,)?
}
) => {
$crate::impl_outer_origin! {
$(#[$attr])*
pub enum $name for $runtime where system = system {
$( $module $( <$generic> )*, )*
$( $module $( <$generic $(, $instance )? > )?, )*
}
}
};
(
$(#[$attr:meta])*
pub enum $name:ident for $runtime:ident where system = $system:ident {}
) => {
$crate::impl_outer_origin!(
$( #[$attr] )*;
$name;
$runtime;
$system;
Modules { };
;
);
};
(
$(#[$attr:meta])*
pub enum $name:ident for $runtime:ident where system = $system:ident {
$module:ident,
$( $rest_module:ident $( <$rest_generic:ident> )* ),* $(,)*
$( $module:ident $( <$generic:ident $(, $instance:path )?> )? ),* $(,)?
}
) => {
$crate::impl_outer_origin!(
@@ -63,64 +49,30 @@ macro_rules! impl_outer_origin {
$name;
$runtime;
$system;
Modules { $( $rest_module $( <$rest_generic> )*, )* };
$module;
);
};
(
$(#[$attr:meta])*
pub enum $name:ident for $runtime:ident where system = $system:ident {
$module:ident<T>,
$( $rest_module:ident $( <$rest_generic:ident> )* ),* $(,)*
}
) => {
$crate::impl_outer_origin!(
$( #[$attr] )*;
$name;
$runtime;
$system;
Modules { $( $rest_module $( <$rest_generic> )*, )* };
$module<$runtime>;
Modules { $( $module $( <$generic $(, $instance )? > )*, )* };
);
};
// Replace generic param with runtime
(
$(#[$attr:meta])*;
$name:ident;
$runtime:ident;
$system:ident;
Modules {
$module:ident,
$( $rest_module:ident $( <$rest_generic:ident> )*, )*
$module:ident $( <T $(, $instance:path )? > )?,
$( $rest_module:tt )*
};
$( $parsed_module:ident $( <$generic_param:ident> )* ),*;
$( $parsed:tt )*
) => {
$crate::impl_outer_origin!(
$( #[$attr] )*;
$name;
$runtime;
$system;
Modules { $( $rest_module $( <$rest_generic> )*, )* };
$( $parsed_module $( <$generic_param> )* ),*, $module;
);
};
(
$(#[$attr:meta])*;
$name:ident;
$runtime:ident;
$system:ident;
Modules {
$module:ident<T>,
$( $rest_module:ident $( <$rest_generic:ident> )*, )*
};
$( $parsed_module:ident $( <$generic_param:ident> )* ),*;
) => {
$crate::impl_outer_origin!(
$( #[$attr] )*;
$name;
$runtime;
$system;
Modules { $( $rest_module $( <$rest_generic> )*, )* };
$( $parsed_module $( <$generic_param> )* ),*, $module<$runtime>;
Modules { $( $rest_module )* };
$( $parsed )* $module $( <$runtime $(, $instance )? > )?,
);
};
@@ -131,8 +83,8 @@ macro_rules! impl_outer_origin {
$name:ident;
$runtime:ident;
$system:ident;
Modules {};
$( $module:ident $( <$generic_param:ident> )* ),*;
Modules { };
$( $module:ident $( <$generic_param:ident $(, $generic_instance:path )? > )* ,)*
) => {
// Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted.
#[derive(Clone, PartialEq, Eq)]
@@ -142,7 +94,7 @@ macro_rules! impl_outer_origin {
pub enum $name {
system($system::Origin<$runtime>),
$(
$module($module::Origin $( <$generic_param> )* ),
$module($module::Origin $( <$generic_param $(, $generic_instance )? > )* ),
)*
#[allow(dead_code)]
Void($crate::Void)
@@ -175,13 +127,13 @@ macro_rules! impl_outer_origin {
}
}
$(
impl From<$module::Origin $( <$generic_param> )*> for $name {
fn from(x: $module::Origin $( <$generic_param> )*) -> Self {
impl From<$module::Origin $( <$generic_param $(, $generic_instance )? > )*> for $name {
fn from(x: $module::Origin $( <$generic_param $(, $generic_instance )? > )*) -> Self {
$name::$module(x)
}
}
impl Into<Option<$module::Origin $( <$generic_param> )*>> for $name {
fn into(self) -> Option<$module::Origin $( <$generic_param> )*> {
impl Into<Option<$module::Origin $( <$generic_param $(, $generic_instance )? > )*>> for $name {
fn into(self) -> Option<$module::Origin $( <$generic_param $(, $generic_instance )? > )*> {
if let $name::$module(l) = self {
Some(l)
} else {
File diff suppressed because it is too large Load Diff
+25
View File
@@ -0,0 +1,25 @@
[package]
name = "srml-support-test"
version = "0.1.0"
authors = ["thiolliere <gui.thiolliere@gmail.com>"]
edition = "2018"
[dev-dependencies]
serde = { version = "1.0", default-features = false }
serde_derive = { version = "1.0" }
parity-codec = { version = "3.2", default-features = false, features = ["derive"] }
runtime_io = { package = "sr-io", path = "../../../core/sr-io", default-features = false }
srml-support = { path = "../", default-features = false }
inherents = { package = "substrate-inherents", path = "../../../core/inherents", default-features = false }
primitives = { package = "substrate-primitives", path = "../../../core/primitives", default-features = false }
[features]
default = ["std"]
std = [
"serde/std",
"parity-codec/std",
"runtime_io/std",
"srml-support/std",
"inherents/std",
"primitives/std",
]
@@ -0,0 +1,457 @@
// Copyright 2019 Parity Technologies (UK) Ltd.
// This file is part of Substrate.
// Substrate is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Substrate is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
#![recursion_limit="128"]
#[cfg(feature = "std")]
use serde_derive::Serialize;
use runtime_io::{with_externalities, Blake2Hasher};
use srml_support::rstd::prelude::*;
use srml_support::rstd as rstd;
use srml_support::codec::{Encode, Decode};
use srml_support::runtime_primitives::{generic, BuildStorage};
use srml_support::runtime_primitives::traits::{BlakeTwo256, Block as _, Verify, Digest};
use srml_support::{Parameter, construct_runtime, decl_module, decl_storage, decl_event};
use inherents::{
ProvideInherent, InherentData, InherentIdentifier, RuntimeString, MakeFatalError
};
use srml_support::{StorageValue, StorageMap};
use primitives::{H256, sr25519};
pub trait Currency {
}
// Mock
mod system {
use super::*;
pub trait Trait: 'static + Eq + Clone {
type Origin: Into<Option<RawOrigin<Self::AccountId>>> + From<RawOrigin<Self::AccountId>>;
type BlockNumber;
type Digest: Digest<Hash = H256>;
type Hash;
type AccountId;
type Event: From<Event>;
type Log: From<Log<Self>> + Into<DigestItemOf<Self>>;
}
pub type DigestItemOf<T> = <<T as Trait>::Digest as Digest>::Item;
decl_module! {
pub struct Module<T: Trait> for enum Call where origin: T::Origin {
pub fn deposit_event(_event: T::Event) {
}
}
}
impl<T: Trait> Module<T> {
pub fn deposit_log(_item: <T::Digest as Digest>::Item) {
unimplemented!();
}
}
decl_event!(
pub enum Event {
ExtrinsicSuccess,
ExtrinsicFailed,
}
);
/// Origin for the system module.
#[derive(PartialEq, Eq, Clone)]
#[cfg_attr(feature = "std", derive(Debug))]
pub enum RawOrigin<AccountId> {
Root,
Signed(AccountId),
Inherent,
}
impl<AccountId> From<Option<AccountId>> for RawOrigin<AccountId> {
fn from(s: Option<AccountId>) -> RawOrigin<AccountId> {
match s {
Some(who) => RawOrigin::Signed(who),
None => RawOrigin::Inherent,
}
}
}
pub type Origin<T> = RawOrigin<<T as Trait>::AccountId>;
pub type Log<T> = RawLog<
<T as Trait>::Hash,
>;
#[cfg_attr(feature = "std", derive(Serialize, Debug))]
#[derive(Encode, Decode, PartialEq, Eq, Clone)]
pub enum RawLog<H> {
ChangesTrieRoot(H),
}
pub fn ensure_root<OuterOrigin, AccountId>(o: OuterOrigin) -> Result<(), &'static str>
where OuterOrigin: Into<Option<RawOrigin<AccountId>>>
{
match o.into() {
Some(RawOrigin::Root) => Ok(()),
_ => Err("bad origin: expected to be a root origin"),
}
}
}
// Test for:
// * No default instance
// * Custom InstantiableTrait
// * Origin, Inherent, Log, Event
mod module1 {
use super::*;
pub trait Trait<I>: system::Trait {
type Event: From<Event<Self, I>> + Into<<Self as system::Trait>::Event>;
type Origin: From<Origin<Self, I>>;
type Log: From<Log<Self, I>> + Into<system::DigestItemOf<Self>>;
}
decl_module! {
pub struct Module<T: Trait<I>, I: InstantiableThing> for enum Call where origin: <T as system::Trait>::Origin {
fn deposit_event<T, I>() = default;
fn one() {
Self::deposit_event(RawEvent::AnotherVariant(3));
Self::deposit_log(RawLog::AmountChange(3));
}
}
}
impl<T: Trait<I>, I: InstantiableThing> Module<T, I> {
/// Deposit one of this module's logs.
fn deposit_log(log: Log<T, I>) {
<system::Module<T>>::deposit_log(<T as Trait<I>>::Log::from(log).into());
}
}
decl_storage! {
trait Store for Module<T: Trait<I>, I: InstantiableThing> as Module1 {
pub Value config(value): u64;
pub Map: map u32 => u64;
pub LinkedMap: linked_map u32 => u64;
}
}
decl_event! {
pub enum Event<T, I> where Phantom = rstd::marker::PhantomData<T> {
_Phantom(Phantom),
AnotherVariant(u32),
}
}
#[derive(PartialEq, Eq, Clone)]
#[cfg_attr(feature = "std", derive(Debug))]
pub enum Origin<T: Trait<I>, I> {
Members(u32),
_Phantom(rstd::marker::PhantomData<(T, I)>),
}
pub type Log<T, I> = RawLog<
T,
I,
>;
/// A logs in this module.
#[cfg_attr(feature = "std", derive(serde_derive::Serialize, Debug))]
#[derive(parity_codec::Encode, parity_codec::Decode, PartialEq, Eq, Clone)]
pub enum RawLog<T, I> {
_Phantom(rstd::marker::PhantomData<(T, I)>),
AmountChange(u32),
}
pub const INHERENT_IDENTIFIER: InherentIdentifier = *b"12345678";
impl<T: Trait<I>, I: InstantiableThing> ProvideInherent for Module<T, I> {
type Call = Call<T, I>;
type Error = MakeFatalError<RuntimeString>;
const INHERENT_IDENTIFIER: InherentIdentifier = INHERENT_IDENTIFIER;
fn create_inherent(_data: &InherentData) -> Option<Self::Call> {
unimplemented!();
}
fn check_inherent(_call: &Self::Call, _data: &InherentData) -> rstd::result::Result<(), Self::Error> {
unimplemented!();
}
}
}
// Test for:
// * default instance
// * use of no_genesis_config_phantom_data
mod module2 {
use super::*;
pub trait Trait<I=DefaultInstance>: system::Trait {
type Amount: Parameter + Default;
type Event: From<Event<Self, I>> + Into<<Self as system::Trait>::Event>;
type Origin: From<Origin<Self, I>>;
type Log: From<Log<Self, I>> + Into<system::DigestItemOf<Self>>;
}
impl<T: Trait<I>, I: Instance> Currency for Module<T, I> {}
decl_module! {
pub struct Module<T: Trait<I>, I: Instance=DefaultInstance> for enum Call where origin: <T as system::Trait>::Origin {
fn deposit_event<T, I>() = default;
}
}
decl_storage! {
trait Store for Module<T: Trait<I>, I: Instance=DefaultInstance> as Module2 {
pub Value config(value): T::Amount;
pub Map config(map): map u64 => u64;
pub LinkedMap config(linked_map): linked_map u64 => u64;
}
extra_genesis_skip_phantom_data_field;
}
decl_event! {
pub enum Event<T, I=DefaultInstance> where Amount = <T as Trait<I>>::Amount {
Variant(Amount),
}
}
#[derive(PartialEq, Eq, Clone)]
#[cfg_attr(feature = "std", derive(Debug))]
pub enum Origin<T: Trait<I>, I=DefaultInstance> {
Members(u32),
_Phantom(rstd::marker::PhantomData<(T, I)>),
}
pub type Log<T, I=DefaultInstance> = RawLog<
T,
I,
>;
/// A logs in this module.
#[cfg_attr(feature = "std", derive(serde_derive::Serialize, Debug))]
#[derive(parity_codec::Encode, parity_codec::Decode, PartialEq, Eq, Clone)]
pub enum RawLog<T, I=DefaultInstance> {
_Phantom(rstd::marker::PhantomData<(T, I)>),
AmountChange(u32),
}
pub const INHERENT_IDENTIFIER: InherentIdentifier = *b"12345678";
impl<T: Trait<I>, I: Instance> ProvideInherent for Module<T, I> {
type Call = Call<T, I>;
type Error = MakeFatalError<RuntimeString>;
const INHERENT_IDENTIFIER: InherentIdentifier = INHERENT_IDENTIFIER;
fn create_inherent(_data: &InherentData) -> Option<Self::Call> {
unimplemented!();
}
fn check_inherent(_call: &Self::Call, _data: &InherentData) -> rstd::result::Result<(), Self::Error> {
unimplemented!();
}
}
}
// Test for:
// * Depends on multiple instances of a module with instances
mod module3 {
use super::*;
pub trait Trait: module2::Trait + module2::Trait<module2::Instance1> + system::Trait {
type Currency: Currency;
type Currency2: Currency;
}
decl_module! {
pub struct Module<T: Trait> for enum Call where origin: <T as system::Trait>::Origin {
}
}
}
impl module1::Trait<module1::Instance1> for Runtime {
type Event = Event;
type Origin = Origin;
type Log = Log;
}
impl module1::Trait<module1::Instance2> for Runtime {
type Event = Event;
type Origin = Origin;
type Log = Log;
}
impl module2::Trait for Runtime {
type Amount = u16;
type Event = Event;
type Origin = Origin;
type Log = Log;
}
impl module2::Trait<module2::Instance1> for Runtime {
type Amount = u32;
type Event = Event;
type Origin = Origin;
type Log = Log;
}
impl module2::Trait<module2::Instance2> for Runtime {
type Amount = u32;
type Event = Event;
type Origin = Origin;
type Log = Log;
}
impl module2::Trait<module2::Instance3> for Runtime {
type Amount = u64;
type Event = Event;
type Origin = Origin;
type Log = Log;
}
impl module3::Trait for Runtime {
type Currency = Module2_2;
type Currency2 = Module2_3;
}
pub type Signature = sr25519::Signature;
pub type AccountId = <Signature as Verify>::Signer;
pub type BlockNumber = u64;
pub type Index = u64;
impl system::Trait for Runtime {
type Hash = H256;
type Origin = Origin;
type BlockNumber = BlockNumber;
type Digest = generic::Digest<Log>;
type AccountId = AccountId;
type Event = Event;
type Log = Log;
}
construct_runtime!(
pub enum Runtime with Log(InternalLog: DigestItem<H256, (), ()>) where
Block = Block,
NodeBlock = Block,
UncheckedExtrinsic = UncheckedExtrinsic
{
System: system::{Module, Call, Event, Log(ChangesTrieRoot)},
Module1_1: module1::<Instance1>::{Module, Call, Storage, Event<T, I>, Config<T, I>, Origin<T, I>, Log(), Inherent},
Module1_2: module1::<Instance2>::{Module, Call, Storage, Event<T, I>, Config<T, I>, Origin<T, I>, Log(), Inherent},
Module2: module2::{Module, Call, Storage, Event<T>, Config<T>, Origin<T>, Log(), Inherent},
Module2_1: module2::<Instance1>::{Module, Call, Storage, Event<T, I>, Config<T, I>, Origin<T, I>, Log(), Inherent},
Module2_2: module2::<Instance2>::{Module, Call, Storage, Event<T, I>, Config<T, I>, Origin<T, I>, Log(), Inherent},
Module2_3: module2::<Instance3>::{Module, Call, Storage, Event<T, I>, Config<T, I>, Origin<T, I>, Log(), Inherent},
Module3: module3::{Module, Call},
}
);
pub type Header = generic::Header<BlockNumber, BlakeTwo256, Log>;
pub type Block = generic::Block<Header, UncheckedExtrinsic>;
pub type UncheckedExtrinsic = generic::UncheckedMortalCompactExtrinsic<u32, Index, Call, Signature>;
fn new_test_ext() -> runtime_io::TestExternalities<Blake2Hasher> {
GenesisConfig{
module1_Instance1: Some(module1::GenesisConfig {
value: 3,
.. Default::default()
}),
module1_Instance2: Some(module1::GenesisConfig {
value: 4,
_genesis_phantom_data: Default::default(),
}),
module2: Some(module2::GenesisConfig {
value: 4,
map: vec![],
linked_map: vec![],
}),
module2_Instance1: None,
module2_Instance2: None,
module2_Instance3: None,
}.build_storage().unwrap().0.into()
}
#[test]
fn storage_instance_independance() {
with_externalities(&mut new_test_ext(), || {
let mut map = rstd::collections::btree_map::BTreeMap::new();
for key in &[
module2::Value::<Runtime>::key().to_vec(),
module2::Value::<Runtime, module2::Instance1>::key().to_vec(),
module2::Value::<Runtime, module2::Instance2>::key().to_vec(),
module2::Value::<Runtime, module2::Instance3>::key().to_vec(),
module2::Map::<Runtime>::prefix().to_vec(),
module2::Map::<Runtime, module2::Instance1>::prefix().to_vec(),
module2::Map::<Runtime, module2::Instance2>::prefix().to_vec(),
module2::Map::<Runtime, module2::Instance3>::prefix().to_vec(),
module2::LinkedMap::<Runtime>::prefix().to_vec(),
module2::LinkedMap::<Runtime, module2::Instance1>::prefix().to_vec(),
module2::LinkedMap::<Runtime, module2::Instance2>::prefix().to_vec(),
module2::LinkedMap::<Runtime, module2::Instance3>::prefix().to_vec(),
module2::Map::<Runtime>::key_for(0),
module2::Map::<Runtime, module2::Instance1>::key_for(0).to_vec(),
module2::Map::<Runtime, module2::Instance2>::key_for(0).to_vec(),
module2::Map::<Runtime, module2::Instance3>::key_for(0).to_vec(),
module2::LinkedMap::<Runtime>::key_for(0),
module2::LinkedMap::<Runtime, module2::Instance1>::key_for(0).to_vec(),
module2::LinkedMap::<Runtime, module2::Instance2>::key_for(0).to_vec(),
module2::LinkedMap::<Runtime, module2::Instance3>::key_for(0).to_vec(),
module2::Map::<Runtime>::key_for(1),
module2::Map::<Runtime, module2::Instance1>::key_for(1).to_vec(),
module2::Map::<Runtime, module2::Instance2>::key_for(1).to_vec(),
module2::Map::<Runtime, module2::Instance3>::key_for(1).to_vec(),
module2::LinkedMap::<Runtime>::key_for(1),
module2::LinkedMap::<Runtime, module2::Instance1>::key_for(1).to_vec(),
module2::LinkedMap::<Runtime, module2::Instance2>::key_for(1).to_vec(),
module2::LinkedMap::<Runtime, module2::Instance3>::key_for(1).to_vec(),
] {
assert!(map.insert(key, ()).is_none())
}
});
}
#[test]
fn storage_with_instance_basic_operation() {
with_externalities(&mut new_test_ext(), || {
type Value = module2::Value<Runtime, module2::Instance1>;
type Map = module2::Map<Runtime, module2::Instance1>;
type LinkedMap = module2::LinkedMap<Runtime, module2::Instance1>;
assert_eq!(Value::exists(), false);
Value::put(1);
assert_eq!(Value::get(), 1);
assert_eq!(Value::take(), 1);
assert_eq!(Value::get(), 0);
Value::mutate(|a| *a=2);
assert_eq!(Value::get(), 2);
Value::kill();
assert_eq!(Value::get(), 0);
let key = 1;
assert_eq!(Map::exists(1), false);
Map::insert(key, 1);
assert_eq!(Map::get(key), 1);
assert_eq!(Map::take(key), 1);
assert_eq!(Map::get(key), 0);
Map::mutate(key, |a| *a=2);
assert_eq!(Map::get(key), 2);
Map::remove(key);
assert_eq!(Map::get(key), 0);
assert_eq!(LinkedMap::exists(1), false);
LinkedMap::insert(key, 1);
assert_eq!(LinkedMap::get(key), 1);
assert_eq!(LinkedMap::take(key), 1);
assert_eq!(LinkedMap::get(key), 0);
LinkedMap::mutate(key, |a| *a=2);
assert_eq!(LinkedMap::get(key), 2);
LinkedMap::remove(key);
assert_eq!(LinkedMap::get(key), 0);
});
}