[FRAME] Remove V1 Module Syntax (#14685)

* Remove V1 pallet syntax

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Remove more

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* More...

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Move no_bound derives to own folder

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* fmt

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Keep re-exports

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

---------

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>
This commit is contained in:
Oliver Tale-Yazdi
2023-07-31 18:49:39 +02:00
committed by GitHub
parent 49816ff4d9
commit 0853bbba72
22 changed files with 48 additions and 6418 deletions
+8 -238
View File
@@ -20,19 +20,15 @@
#![recursion_limit = "512"]
mod benchmark;
mod clone_no_bound;
mod construct_runtime;
mod crate_version;
mod debug_no_bound;
mod default_no_bound;
mod derive_impl;
mod dummy_part_checker;
mod key_prefix;
mod match_and_insert;
mod no_bound;
mod pallet;
mod pallet_error;
mod partial_eq_no_bound;
mod storage;
mod storage_alias;
mod transactional;
mod tt_macro;
@@ -42,9 +38,10 @@ use macro_magic::import_tokens_attr;
use proc_macro::TokenStream;
use quote::{quote, ToTokens};
use std::{cell::RefCell, str::FromStr};
pub(crate) use storage::INHERENT_INSTANCE_NAME;
use syn::{parse_macro_input, Error, ItemImpl, ItemMod};
pub(crate) const INHERENT_INSTANCE_NAME: &str = "__InherentHiddenInstance";
thread_local! {
/// A global counter, can be used to generate a relatively unique identifier.
static COUNTER: RefCell<Counter> = RefCell::new(Counter(0));
@@ -79,233 +76,6 @@ fn counter_prefix(prefix: &str) -> String {
format!("CounterFor{}", prefix)
}
/// Declares strongly-typed wrappers around codec-compatible types in storage.
///
/// ## Example
///
/// ```nocompile
/// decl_storage! {
/// trait Store for Module<T: Config> as Example {
/// Foo get(fn foo) config(): u32=12;
/// Bar: map hasher(identity) u32 => u32;
/// pub Zed build(|config| vec![(0, 0)]): map hasher(identity) u32 => u32;
/// }
/// }
/// ```
///
/// Declaration is set with the header `(pub) trait Store for Module<T: Config> as Example`,
/// with `Store` a (pub) trait generated associating each storage item to the `Module` and
/// `as Example` setting the prefix used for storage items of this module. `Example` must be unique:
/// another module with the same name and the same inner storage item name will conflict.
/// `Example` is called the module prefix.
///
/// note: For instantiable modules the module prefix is prepended with instance
/// prefix. Instance prefix is "" for default instance and "Instance$n" for instance number $n.
/// Thus, instance 3 of module Example has a module prefix of `Instance3Example`
///
/// Basic storage consists of a name and a type; supported types are:
///
/// * Value: `Foo: type`: Implements the
/// [`StorageValue`](../frame_support/storage/trait.StorageValue.html) trait using the
/// [`StorageValue generator`](../frame_support/storage/generator/trait.StorageValue.html).
///
/// The generator is implemented with:
/// * `module_prefix`: module_prefix
/// * `storage_prefix`: storage_name
///
/// Thus the storage value is finally stored at:
/// ```nocompile
/// Twox128(module_prefix) ++ Twox128(storage_prefix)
/// ```
///
/// * Map: `Foo: map hasher($hash) type => type`: Implements the
/// [`StorageMap`](../frame_support/storage/trait.StorageMap.html) trait using the [`StorageMap
/// generator`](../frame_support/storage/generator/trait.StorageMap.html). And
/// [`StoragePrefixedMap`](../frame_support/storage/trait.StoragePrefixedMap.html).
///
/// `$hash` representing a choice of hashing algorithms available in the
/// [`Hashable`](../frame_support/trait.Hashable.html) trait. You will generally want to use one
/// of three hashers:
/// * `blake2_128_concat`: The default, safe choice. Use if you are unsure or don't care. It is
/// secure against user-tainted keys, fairly fast and memory-efficient and supports iteration
/// over its keys and values. This must be used if the keys of your map can be selected *en
/// masse* by untrusted users.
/// * `twox_64_concat`: This is an insecure hasher and can only be used safely if you know that
/// the preimages cannot be chosen at will by untrusted users. It is memory-efficient, extremely
/// performant and supports iteration over its keys and values. You can safely use this is the
/// key is:
/// - A (slowly) incrementing index.
/// - Known to be the result of a cryptographic hash (though `identity` is a better choice
/// here).
/// - Known to be the public key of a cryptographic key pair in existence.
/// * `identity`: This is not a hasher at all, and just uses the key material directly. Since it
/// does no hashing or appending, it's the fastest possible hasher, however, it's also the least
/// secure. It can be used only if you know that the key will be cryptographically/securely
/// randomly distributed over the binary encoding space. In most cases this will not be true.
/// One case where it is true, however, if where the key is itself the result of a cryptographic
/// hash of some existent data.
///
/// Other hashers will tend to be "opaque" and not support iteration over the keys in the
/// map. It is not recommended to use these.
///
/// The generator is implemented with:
/// * `module_prefix`: $module_prefix
/// * `storage_prefix`: storage_name
/// * `Hasher`: $hash
///
/// Thus the keys are stored at:
/// ```nocompile
/// twox128(module_prefix) ++ twox128(storage_prefix) ++ hasher(encode(key))
/// ```
///
/// * Double map: `Foo: double_map hasher($hash1) u32, hasher($hash2) u32 => u32`: Implements the
/// [`StorageDoubleMap`](../frame_support/storage/trait.StorageDoubleMap.html) trait using the
/// [`StorageDoubleMap
/// generator`](../frame_support/storage/generator/trait.StorageDoubleMap.html). And
/// [`StoragePrefixedMap`](../frame_support/storage/trait.StoragePrefixedMap.html).
///
/// `$hash1` and `$hash2` representing choices of hashing algorithms available in the
/// [`Hashable`](../frame_support/trait.Hashable.html) trait. They must be chosen with care, see
/// generator documentation.
///
/// The generator is implemented with:
/// * `module_prefix`: $module_prefix
/// * `storage_prefix`: storage_name
/// * `Hasher1`: $hash1
/// * `Hasher2`: $hash2
///
/// Thus keys are stored at:
/// ```nocompile
/// Twox128(module_prefix) ++ Twox128(storage_prefix) ++ Hasher1(encode(key1)) ++
/// Hasher2(encode(key2)) ```
///
/// Supported hashers (ordered from least to best security):
///
/// * `identity` - Just the unrefined key material. Use only when it is known to be a secure hash
/// already. The most efficient and iterable over keys.
/// * `twox_64_concat` - TwoX with 64bit + key concatenated. Use only when an untrusted source
/// cannot select and insert key values. Very efficient and iterable over keys.
/// * `blake2_128_concat` - Blake2 with 128bit + key concatenated. Slower but safe to use in all
/// circumstances. Iterable over keys.
///
/// Deprecated hashers, which do not support iteration over keys include:
/// * `twox_128` - TwoX with 128bit.
/// * `twox_256` - TwoX with with 256bit.
/// * `blake2_128` - Blake2 with 128bit.
/// * `blake2_256` - Blake2 with 256bit.
///
/// Basic storage can be extended as such:
///
/// `#vis #name get(fn #getter) config(#field_name) build(#closure): #type = #default;`
///
/// * `#vis`: Set the visibility of the structure. `pub` or nothing.
/// * `#name`: Name of the storage item, used as a prefix in storage.
/// * \[optional\] `get(fn #getter)`: Implements the function #getter to `Module`.
/// * \[optional\] `config(#field_name)`: `field_name` is optional if get is set.
/// Will include the item in `GenesisConfig`.
/// * \[optional\] `build(#closure)`: Closure called with storage overlays.
/// * \[optional\] `max_values(#expr)`: `expr` is an expression returning a `u32`. It is used to
/// implement `StorageInfoTrait`. Note this attribute is not available for storage value as the
/// maximum number of values is 1.
/// * `#type`: Storage type.
/// * \[optional\] `#default`: Value returned when none.
///
/// Storage items are accessible in multiple ways:
///
/// * 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()`
///
/// ## GenesisConfig
///
/// An optional `GenesisConfig` struct for storage initialization can be defined, either
/// when at least one storage field requires default initialization
/// (both `get` and `config` or `build`), or specifically as in:
///
/// ```nocompile
/// decl_storage! {
/// trait Store for Module<T: Config> as Example {
///
/// // Your storage items
/// }
/// add_extra_genesis {
/// config(genesis_field): GenesisFieldType;
/// config(genesis_field2): GenesisFieldType;
/// ...
/// build(|_: &Self| {
/// // Modification of storage
/// })
/// }
/// }
/// ```
///
/// This struct can be exposed as `ExampleConfig` by the `construct_runtime!` macro like follows:
///
/// ```nocompile
/// construct_runtime!(
/// pub enum Runtime with ... {
/// ...,
/// Example: example::{Pallet, Storage, ..., Config<T>},
/// ...,
/// }
/// );
/// ```
///
/// ### Module with Instances
///
/// The `decl_storage!` macro supports building modules with instances with the following syntax
/// (`DefaultInstance` type is optional):
///
/// ```nocompile
/// trait Store for Module<T: Config<I>, I: Instance=DefaultInstance> as Example {}
/// ```
///
/// 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
///
/// ## Where clause
///
/// This macro supports a where clause which will be replicated to all generated types.
///
/// ```nocompile
/// trait Store for Module<T: Config> as Example where T::AccountId: std::fmt::Display {}
/// ```
///
/// ## Limitations
///
/// # Instancing and generic `GenesisConfig`
///
/// If your module supports instancing and you see an error like `parameter `I` is never used` for
/// your `decl_storage!`, you are hitting a limitation of the current implementation. You probably
/// try to use an associated type of a non-instantiable trait. To solve this, add the following to
/// your macro call:
///
/// ```nocompile
/// add_extra_genesis {
/// config(phantom): std::marker::PhantomData<I>,
/// }
/// ```
///
/// This adds a field to your `GenesisConfig` with the name `phantom` that you can initialize with
/// `Default::default()`.
///
/// ## PoV information
///
/// To implement the trait `StorageInfoTrait` for storages an additional attribute can be used
/// `generate_storage_info`:
/// ```nocompile
/// decl_storage! { generate_storage_info
/// trait Store for ...
/// }
/// ```
#[proc_macro]
#[deprecated(note = "Will be removed after July 2023; use the attribute `#[pallet]` macro instead.
For more info, see: <https://github.com/paritytech/substrate/pull/13705>")]
pub fn decl_storage(input: TokenStream) -> TokenStream {
storage::decl_storage_impl(input)
}
/// Construct a runtime, with the given name and the given pallets.
///
/// The parameters here are specific types for `Block`, `NodeBlock`, and `UncheckedExtrinsic`
@@ -645,13 +415,13 @@ pub fn require_transactional(attr: TokenStream, input: TokenStream) -> TokenStre
/// Derive [`Clone`] but do not bound any generic. Docs are at `frame_support::CloneNoBound`.
#[proc_macro_derive(CloneNoBound)]
pub fn derive_clone_no_bound(input: TokenStream) -> TokenStream {
clone_no_bound::derive_clone_no_bound(input)
no_bound::clone::derive_clone_no_bound(input)
}
/// Derive [`Debug`] but do not bound any generics. Docs are at `frame_support::DebugNoBound`.
#[proc_macro_derive(DebugNoBound)]
pub fn derive_debug_no_bound(input: TokenStream) -> TokenStream {
debug_no_bound::derive_debug_no_bound(input)
no_bound::debug::derive_debug_no_bound(input)
}
/// Derive [`Debug`], if `std` is enabled it uses `frame_support::DebugNoBound`, if `std` is not
@@ -660,7 +430,7 @@ pub fn derive_debug_no_bound(input: TokenStream) -> TokenStream {
#[proc_macro_derive(RuntimeDebugNoBound)]
pub fn derive_runtime_debug_no_bound(input: TokenStream) -> TokenStream {
if cfg!(any(feature = "std", feature = "try-runtime")) {
debug_no_bound::derive_debug_no_bound(input)
no_bound::debug::derive_debug_no_bound(input)
} else {
let input: syn::DeriveInput = match syn::parse(input) {
Ok(input) => input,
@@ -687,7 +457,7 @@ pub fn derive_runtime_debug_no_bound(input: TokenStream) -> TokenStream {
/// `frame_support::PartialEqNoBound`.
#[proc_macro_derive(PartialEqNoBound)]
pub fn derive_partial_eq_no_bound(input: TokenStream) -> TokenStream {
partial_eq_no_bound::derive_partial_eq_no_bound(input)
no_bound::partial_eq::derive_partial_eq_no_bound(input)
}
/// derive Eq but do no bound any generic. Docs are at `frame_support::EqNoBound`.
@@ -712,7 +482,7 @@ pub fn derive_eq_no_bound(input: TokenStream) -> TokenStream {
/// derive `Default` but do no bound any generic. Docs are at `frame_support::DefaultNoBound`.
#[proc_macro_derive(DefaultNoBound, attributes(default))]
pub fn derive_default_no_bound(input: TokenStream) -> TokenStream {
default_no_bound::derive_default_no_bound(input)
no_bound::default::derive_default_no_bound(input)
}
#[proc_macro]
@@ -0,0 +1,23 @@
// This file is part of Substrate.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! Derive macros to derive traits without bounding generic parameters.
pub mod clone;
pub mod debug;
pub mod default;
pub mod partial_eq;
@@ -1,151 +0,0 @@
// This file is part of Substrate.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! Builder logic definition used to build genesis storage.
use super::super::{DeclStorageDefExt, StorageLineTypeDef};
use frame_support_procedural_tools::syn_ext as ext;
use proc_macro2::TokenStream;
use quote::{quote, quote_spanned};
use syn::spanned::Spanned;
/// Definition of builder blocks, each block insert some value in the storage.
/// They must be called inside externalities, and with `self` being the genesis config.
pub struct BuilderDef {
/// Contains:
/// * build block for storage with build attribute.
/// * build block for storage with config attribute and no build attribute.
/// * build block for extra genesis build expression.
pub blocks: Vec<TokenStream>,
/// The build blocks requires generic traits.
pub is_generic: bool,
}
impl BuilderDef {
pub fn from_def(scrate: &TokenStream, def: &DeclStorageDefExt) -> Self {
let mut blocks = Vec::new();
let mut is_generic = false;
for line in def.storage_lines.iter() {
let storage_struct = &line.storage_struct;
let storage_trait = &line.storage_trait;
let value_type = &line.value_type;
// Defines the data variable to use for insert at genesis either from build or config.
let mut data = None;
if let Some(builder) = &line.build {
is_generic |= ext::expr_contains_ident(builder, &def.module_runtime_generic);
is_generic |= line.is_generic;
data = Some(match &line.storage_type {
StorageLineTypeDef::Simple(_) if line.is_option => {
quote_spanned!(builder.span() =>
// NOTE: the type of `data` is specified when used later in the code
let builder: fn(&Self) -> _ = #builder;
let data = builder(self);
let data = Option::as_ref(&data);
)
},
_ => quote_spanned!(builder.span() =>
// NOTE: the type of `data` is specified when used later in the code
let builder: fn(&Self) -> _ = #builder;
let data = &builder(self);
),
});
} else if let Some(config) = &line.config {
is_generic |= line.is_generic;
data = Some(match &line.storage_type {
StorageLineTypeDef::Simple(_) if line.is_option => {
quote!( let data = Some(&self.#config); )
},
_ => quote!( let data = &self.#config; ),
});
};
if let Some(data) = data {
blocks.push(match &line.storage_type {
StorageLineTypeDef::Simple(_) if line.is_option => {
quote! {{
#data
let v: Option<&#value_type>= data;
if let Some(v) = v {
<#storage_struct as #scrate::#storage_trait>::put::<&#value_type>(v);
}
}}
},
StorageLineTypeDef::Simple(_) if !line.is_option => {
quote! {{
#data
let v: &#value_type = data;
<#storage_struct as #scrate::#storage_trait>::put::<&#value_type>(v);
}}
},
StorageLineTypeDef::Simple(_) => unreachable!(),
StorageLineTypeDef::Map(map) => {
let key = &map.key;
quote! {{
#data
let data: &#scrate::sp_std::vec::Vec<(#key, #value_type)> = data;
data.iter().for_each(|(k, v)| {
<#storage_struct as #scrate::#storage_trait>::insert::<
&#key, &#value_type
>(k, v);
});
}}
},
StorageLineTypeDef::DoubleMap(map) => {
let key1 = &map.key1;
let key2 = &map.key2;
quote! {{
#data
let data: &#scrate::sp_std::vec::Vec<(#key1, #key2, #value_type)> = data;
data.iter().for_each(|(k1, k2, v)| {
<#storage_struct as #scrate::#storage_trait>::insert::<
&#key1, &#key2, &#value_type
>(k1, k2, v);
});
}}
},
StorageLineTypeDef::NMap(map) => {
let key_tuple = map.to_key_tuple();
let key_arg = if map.keys.len() == 1 { quote!((k,)) } else { quote!(k) };
quote! {{
#data
let data: &#scrate::sp_std::vec::Vec<(#key_tuple, #value_type)> = data;
data.iter().for_each(|(k, v)| {
<#storage_struct as #scrate::#storage_trait>::insert(#key_arg, v);
});
}}
},
});
}
}
if let Some(builder) = def.extra_genesis_build.as_ref() {
is_generic |= ext::expr_contains_ident(builder, &def.module_runtime_generic);
blocks.push(quote_spanned! { builder.span() =>
let extra_genesis_builder: fn(&Self) = #builder;
extra_genesis_builder(self);
});
}
Self { blocks, is_generic }
}
}
@@ -1,162 +0,0 @@
// This file is part of Substrate.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! Genesis config definition.
use super::super::{DeclStorageDefExt, StorageLineTypeDef};
use frame_support_procedural_tools::syn_ext as ext;
use proc_macro2::TokenStream;
use quote::quote;
use syn::{parse_quote, spanned::Spanned};
pub struct GenesisConfigFieldDef {
pub name: syn::Ident,
pub typ: syn::Type,
pub attrs: Vec<syn::Meta>,
pub default: TokenStream,
}
pub struct GenesisConfigDef {
pub is_generic: bool,
pub fields: Vec<GenesisConfigFieldDef>,
/// For example: `<T: Config<I>, I: Instance=DefaultInstance>`.
pub genesis_struct_decl: TokenStream,
/// For example: `<T, I>`.
pub genesis_struct: TokenStream,
/// For example: `<T: Config<I>, I: Instance>`.
pub genesis_impl: TokenStream,
/// The where clause to use to constrain generics if genesis config is generic.
pub genesis_where_clause: Option<syn::WhereClause>,
}
impl GenesisConfigDef {
pub fn from_def(def: &DeclStorageDefExt) -> syn::Result<Self> {
let fields = Self::get_genesis_config_field_defs(def)?;
let is_generic = fields
.iter()
.any(|field| ext::type_contains_ident(&field.typ, &def.module_runtime_generic));
let (genesis_struct_decl, genesis_impl, genesis_struct, genesis_where_clause) =
if is_generic {
let runtime_generic = &def.module_runtime_generic;
let runtime_trait = &def.module_runtime_trait;
let optional_instance = &def.optional_instance;
let optional_instance_bound = &def.optional_instance_bound;
let optional_instance_bound_optional_default =
&def.optional_instance_bound_optional_default;
let where_clause = &def.where_clause;
(
quote!(<#runtime_generic: #runtime_trait, #optional_instance_bound_optional_default>),
quote!(<#runtime_generic: #runtime_trait, #optional_instance_bound>),
quote!(<#runtime_generic, #optional_instance>),
where_clause.clone(),
)
} else {
(quote!(), quote!(), quote!(), None)
};
Ok(Self {
is_generic,
fields,
genesis_struct_decl,
genesis_struct,
genesis_impl,
genesis_where_clause,
})
}
fn get_genesis_config_field_defs(
def: &DeclStorageDefExt,
) -> syn::Result<Vec<GenesisConfigFieldDef>> {
let mut config_field_defs = Vec::new();
for (config_field, line) in def.storage_lines.iter().filter_map(|line| {
line.config.as_ref().map(|config_field| (config_field.clone(), line))
}) {
let value_type = &line.value_type;
let typ = match &line.storage_type {
StorageLineTypeDef::Simple(_) => (*value_type).clone(),
StorageLineTypeDef::Map(map) => {
let key = &map.key;
parse_quote!( Vec<(#key, #value_type)> )
},
StorageLineTypeDef::DoubleMap(map) => {
let key1 = &map.key1;
let key2 = &map.key2;
parse_quote!( Vec<(#key1, #key2, #value_type)> )
},
StorageLineTypeDef::NMap(map) => {
let key_tuple = map.to_key_tuple();
parse_quote!( Vec<(#key_tuple, #value_type)> )
},
};
let default =
line.default_value
.as_ref()
.map(|d| {
if line.is_option {
quote!( #d.unwrap_or_default() )
} else {
quote!( #d )
}
})
.unwrap_or_else(|| quote!(Default::default()));
config_field_defs.push(GenesisConfigFieldDef {
name: config_field,
typ,
attrs: line.doc_attrs.clone(),
default,
});
}
for line in &def.extra_genesis_config_lines {
let attrs = line
.attrs
.iter()
.map(|attr| {
if attr.meta.path().is_ident("cfg") {
return Err(syn::Error::new(
attr.meta.span(),
"extra genesis config items do not support `cfg` attribute",
))
}
Ok(attr.meta.clone())
})
.collect::<syn::Result<_>>()?;
let default = line
.default
.as_ref()
.map(|e| quote!( #e ))
.unwrap_or_else(|| quote!(Default::default()));
config_field_defs.push(GenesisConfigFieldDef {
name: line.name.clone(),
typ: line.typ.clone(),
attrs,
default,
});
}
Ok(config_field_defs)
}
}
@@ -1,196 +0,0 @@
// This file is part of Substrate.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! Declaration of genesis config structure and implementation of build storage trait and
//! functions.
use super::DeclStorageDefExt;
pub use builder_def::BuilderDef;
pub use genesis_config_def::GenesisConfigDef;
use proc_macro2::{Span, TokenStream};
use quote::quote;
mod builder_def;
mod genesis_config_def;
const DEFAULT_INSTANCE_NAME: &str = "__GeneratedInstance";
fn decl_genesis_config_and_impl_default(
scrate: &TokenStream,
genesis_config: &GenesisConfigDef,
) -> TokenStream {
let config_fields = genesis_config.fields.iter().map(|field| {
let (name, typ, attrs) = (&field.name, &field.typ, &field.attrs);
quote!( #( #[ #attrs] )* pub #name: #typ, )
});
let config_field_defaults = genesis_config.fields.iter().map(|field| {
let (name, default) = (&field.name, &field.default);
quote!( #name: #default, )
});
let serde_bug_bound = if !genesis_config.fields.is_empty() {
let mut b_ser = String::new();
let mut b_dser = String::new();
for typ in genesis_config.fields.iter().map(|c| &c.typ) {
let typ = quote!( #typ );
b_ser.push_str(&format!("{} : {}::serde::Serialize, ", typ, scrate));
b_dser.push_str(&format!("{} : {}::serde::de::DeserializeOwned, ", typ, scrate));
}
quote! {
#[serde(bound(serialize = #b_ser))]
#[serde(bound(deserialize = #b_dser))]
}
} else {
quote!()
};
let genesis_struct_decl = &genesis_config.genesis_struct_decl;
let genesis_struct = &genesis_config.genesis_struct;
let genesis_impl = &genesis_config.genesis_impl;
let genesis_where_clause = &genesis_config.genesis_where_clause;
let serde_crate = format!("{}::serde", scrate);
quote!(
/// Genesis config for the module, allow to build genesis storage.
#[derive(#scrate::Serialize, #scrate::Deserialize)]
#[cfg(feature = "std")]
#[serde(rename_all = "camelCase")]
#[serde(deny_unknown_fields)]
#[serde(crate = #serde_crate)]
#serde_bug_bound
pub struct GenesisConfig #genesis_struct_decl #genesis_where_clause {
#( #config_fields )*
}
#[cfg(feature = "std")]
impl #genesis_impl Default for GenesisConfig #genesis_struct #genesis_where_clause {
fn default() -> Self {
GenesisConfig {
#( #config_field_defaults )*
}
}
}
)
}
fn impl_build_storage(
scrate: &TokenStream,
def: &DeclStorageDefExt,
genesis_config: &GenesisConfigDef,
builders: &BuilderDef,
) -> TokenStream {
let runtime_generic = &def.module_runtime_generic;
let runtime_trait = &def.module_runtime_trait;
let optional_instance = &def.optional_instance;
let optional_instance_bound = &def.optional_instance_bound;
let where_clause = &def.where_clause;
let inherent_instance = def.optional_instance.clone().unwrap_or_else(|| {
let name = syn::Ident::new(DEFAULT_INSTANCE_NAME, Span::call_site());
quote!( #name )
});
let inherent_instance_bound = quote!(
#inherent_instance: #scrate::traits::Instance
);
let build_storage_impl = quote!(
<#runtime_generic: #runtime_trait, #inherent_instance_bound>
);
let genesis_struct = &genesis_config.genesis_struct;
let genesis_impl = &genesis_config.genesis_impl;
let genesis_where_clause = &genesis_config.genesis_where_clause;
let (fn_generic, fn_traitinstance, fn_where_clause) =
if !genesis_config.is_generic && builders.is_generic {
(
quote!( <#runtime_generic: #runtime_trait, #optional_instance_bound> ),
quote!( #runtime_generic, #optional_instance ),
Some(&def.where_clause),
)
} else {
(quote!(), quote!(), None)
};
let builder_blocks = &builders.blocks;
let build_storage_impl_trait = quote!(
#scrate::sp_runtime::BuildModuleGenesisStorage<#runtime_generic, #inherent_instance>
);
quote! {
#[cfg(feature = "std")]
impl #genesis_impl GenesisConfig #genesis_struct #genesis_where_clause {
/// Build the storage for this module.
pub fn build_storage #fn_generic (&self) -> std::result::Result<
#scrate::sp_runtime::Storage,
String
> #fn_where_clause {
let mut storage = Default::default();
self.assimilate_storage::<#fn_traitinstance>(&mut storage)?;
Ok(storage)
}
/// Assimilate the storage for this module into pre-existing overlays.
pub fn assimilate_storage #fn_generic (
&self,
storage: &mut #scrate::sp_runtime::Storage,
) -> std::result::Result<(), String> #fn_where_clause {
#scrate::BasicExternalities::execute_with_storage(storage, || {
#( #builder_blocks )*
Ok(())
})
}
}
#[cfg(feature = "std")]
impl #build_storage_impl #build_storage_impl_trait for GenesisConfig #genesis_struct
#where_clause
{
fn build_module_genesis_storage(
&self,
storage: &mut #scrate::sp_runtime::Storage,
) -> std::result::Result<(), String> {
self.assimilate_storage::<#fn_traitinstance> (storage)
}
}
}
}
pub fn genesis_config_and_build_storage(def: &DeclStorageDefExt) -> TokenStream {
let scrate = &def.hidden_crate;
let builders = BuilderDef::from_def(scrate, def);
if !builders.blocks.is_empty() {
let genesis_config = match GenesisConfigDef::from_def(def) {
Ok(genesis_config) => genesis_config,
Err(err) => return err.to_compile_error(),
};
let decl_genesis_config_and_impl_default =
decl_genesis_config_and_impl_default(scrate, &genesis_config);
let impl_build_storage = impl_build_storage(scrate, def, &genesis_config, &builders);
quote! {
#decl_genesis_config_and_impl_default
#impl_build_storage
}
} else {
quote!()
}
}
@@ -1,99 +0,0 @@
// This file is part of Substrate.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! Implementation of getters on module structure.
use super::{DeclStorageDefExt, StorageLineTypeDef};
use proc_macro2::TokenStream;
use quote::quote;
pub fn impl_getters(def: &DeclStorageDefExt) -> TokenStream {
let scrate = &def.hidden_crate;
let mut getters = TokenStream::new();
for (get_fn, line) in def
.storage_lines
.iter()
.filter_map(|line| line.getter.as_ref().map(|get_fn| (get_fn, line)))
{
let attrs = &line.doc_attrs;
let storage_struct = &line.storage_struct;
let storage_trait = &line.storage_trait;
let getter = match &line.storage_type {
StorageLineTypeDef::Simple(value) => {
quote! {
#( #[ #attrs ] )*
pub fn #get_fn() -> #value {
<#storage_struct as #scrate::#storage_trait>::get()
}
}
},
StorageLineTypeDef::Map(map) => {
let key = &map.key;
let value = &map.value;
quote! {
#( #[ #attrs ] )*
pub fn #get_fn<K: #scrate::codec::EncodeLike<#key>>(key: K) -> #value {
<#storage_struct as #scrate::#storage_trait>::get(key)
}
}
},
StorageLineTypeDef::DoubleMap(map) => {
let key1 = &map.key1;
let key2 = &map.key2;
let value = &map.value;
quote! {
pub fn #get_fn<KArg1, KArg2>(k1: KArg1, k2: KArg2) -> #value
where
KArg1: #scrate::codec::EncodeLike<#key1>,
KArg2: #scrate::codec::EncodeLike<#key2>,
{
<#storage_struct as #scrate::#storage_trait>::get(k1, k2)
}
}
},
StorageLineTypeDef::NMap(map) => {
let keygen = map.to_keygen_struct(&def.hidden_crate);
let value = &map.value;
quote! {
pub fn #get_fn<KArg>(key: KArg) -> #value
where
KArg: #scrate::storage::types::EncodeLikeTuple<
<#keygen as #scrate::storage::types::KeyGenerator>::KArg
>
+ #scrate::storage::types::TupleToEncodedIter,
{
<#storage_struct as #scrate::#storage_trait>::get(key)
}
}
},
};
getters.extend(getter);
}
let module_struct = &def.module_struct;
let module_impl = &def.module_impl;
let where_clause = &def.where_clause;
quote!(
impl #module_impl #module_struct #where_clause {
#getters
}
)
}
@@ -1,139 +0,0 @@
// This file is part of Substrate.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! Implementation of the trait instance and the instance structures implementing it.
//! (For not instantiable traits there is still the inherent instance implemented).
use super::DeclStorageDefExt;
use crate::NUMBER_OF_INSTANCE;
use proc_macro2::{Span, TokenStream};
use quote::quote;
pub(crate) const INHERENT_INSTANCE_NAME: &str = "__InherentHiddenInstance";
// Used to generate an instance implementation.
struct InstanceDef {
prefix: String,
instance_struct: syn::Ident,
doc: TokenStream,
// Index is same as instance number. Default is 0.
index: u8,
}
pub fn decl_and_impl(def: &DeclStorageDefExt) -> TokenStream {
let scrate = &def.hidden_crate;
let mut impls = TokenStream::new();
impls.extend(reexport_instance_trait(scrate, def));
// Implementation of instances.
if let Some(module_instance) = &def.module_instance {
let instance_defs = (1..=NUMBER_OF_INSTANCE)
.map(|i| {
let name = format!("Instance{}", i);
InstanceDef {
instance_struct: syn::Ident::new(&name, proc_macro2::Span::call_site()),
prefix: name,
doc: quote!(#[doc=r"Module instance"]),
index: i,
}
})
.chain(module_instance.instance_default.as_ref().map(|ident| InstanceDef {
prefix: String::new(),
instance_struct: ident.clone(),
doc: quote!(#[doc=r"Default module instance"]),
index: 0,
}));
for instance_def in instance_defs {
impls.extend(create_and_impl_instance_struct(scrate, &instance_def, def));
}
}
// The name of the inherently available instance.
let inherent_instance = syn::Ident::new(INHERENT_INSTANCE_NAME, Span::call_site());
// Implementation of inherent instance.
if let Some(default_instance) =
def.module_instance.as_ref().and_then(|i| i.instance_default.as_ref())
{
impls.extend(quote! {
/// Hidden instance generated to be internally used when module is used without
/// instance.
#[doc(hidden)]
pub type #inherent_instance = #default_instance;
});
} else {
let instance_def = InstanceDef {
prefix: String::new(),
instance_struct: inherent_instance,
doc: quote!(
/// Hidden instance generated to be internally used when module is used without
/// instance.
#[doc(hidden)]
),
// This is just to make the type system happy. Not actually used.
index: 0,
};
impls.extend(create_and_impl_instance_struct(scrate, &instance_def, def));
}
impls
}
fn reexport_instance_trait(scrate: &TokenStream, def: &DeclStorageDefExt) -> TokenStream {
if let Some(i) = def.module_instance.as_ref() {
let instance_trait = &i.instance_trait;
quote!(
/// Local import of frame_support::traits::Instance
// This import is not strictly needed but made in order not to have breaking change.
use #scrate::traits::Instance as #instance_trait;
)
} else {
quote!()
}
}
fn create_and_impl_instance_struct(
scrate: &TokenStream,
instance_def: &InstanceDef,
def: &DeclStorageDefExt,
) -> TokenStream {
let instance_trait = quote!( #scrate::traits::Instance );
let instance_struct = &instance_def.instance_struct;
let prefix = format!("{}{}", instance_def.prefix, def.crate_name);
let doc = &instance_def.doc;
let index = instance_def.index;
quote! {
// Those trait are derived because of wrong bounds for generics
#[derive(
Clone, Eq, PartialEq,
#scrate::codec::Encode,
#scrate::codec::Decode,
#scrate::scale_info::TypeInfo,
#scrate::RuntimeDebug,
)]
#doc
pub struct #instance_struct;
impl #instance_trait for #instance_struct {
const PREFIX: &'static str = #prefix;
const INDEX: u8 = #index;
}
}
}
@@ -1,217 +0,0 @@
// This file is part of Substrate.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! Implementation of `storage_metadata` on module structure, used by construct_runtime.
use super::{DeclStorageDefExt, StorageLineDefExt, StorageLineTypeDef};
use frame_support_procedural_tools::get_doc_literals;
use proc_macro2::TokenStream;
use quote::quote;
fn storage_line_metadata_type(scrate: &TokenStream, line: &StorageLineDefExt) -> TokenStream {
let value_type = &line.value_type;
match &line.storage_type {
StorageLineTypeDef::Simple(_) => {
quote! {
#scrate::metadata_ir::StorageEntryTypeIR::Plain(
#scrate::scale_info::meta_type::<#value_type>()
)
}
},
StorageLineTypeDef::Map(map) => {
let hasher = map.hasher.into_metadata();
let key = &map.key;
quote! {
#scrate::metadata_ir::StorageEntryTypeIR::Map {
hashers: #scrate::sp_std::vec! [ #scrate::metadata_ir::#hasher ],
key: #scrate::scale_info::meta_type::<#key>(),
value: #scrate::scale_info::meta_type::<#value_type>(),
}
}
},
StorageLineTypeDef::DoubleMap(map) => {
let hasher1 = map.hasher1.into_metadata();
let hasher2 = map.hasher2.into_metadata();
let key1 = &map.key1;
let key2 = &map.key2;
quote! {
#scrate::metadata_ir::StorageEntryTypeIR::Map {
hashers: #scrate::sp_std::vec! [
#scrate::metadata_ir::#hasher1,
#scrate::metadata_ir::#hasher2,
],
key: #scrate::scale_info::meta_type::<(#key1, #key2)>(),
value: #scrate::scale_info::meta_type::<#value_type>(),
}
}
},
StorageLineTypeDef::NMap(map) => {
let key_tuple = &map.to_key_tuple();
let hashers = map
.hashers
.iter()
.map(|hasher| hasher.to_storage_hasher_struct())
.collect::<Vec<_>>();
quote! {
#scrate::metadata_ir::StorageEntryTypeIR::Map {
hashers: #scrate::sp_std::vec! [
#( #scrate::metadata_ir::StorageHasherIR::#hashers, )*
],
key: #scrate::scale_info::meta_type::<#key_tuple>(),
value: #scrate::scale_info::meta_type::<#value_type>(),
}
}
},
}
}
fn default_byte_getter(
scrate: &TokenStream,
line: &StorageLineDefExt,
def: &DeclStorageDefExt,
) -> (TokenStream, TokenStream) {
let default = line
.default_value
.as_ref()
.map(|d| quote!( #d ))
.unwrap_or_else(|| quote!(Default::default()));
let str_name = line.name.to_string();
let struct_name =
syn::Ident::new(&("__GetByteStruct".to_string() + &str_name), line.name.span());
let cache_name =
syn::Ident::new(&("__CACHE_GET_BYTE_STRUCT_".to_string() + &str_name), line.name.span());
let runtime_generic = &def.module_runtime_generic;
let runtime_trait = &def.module_runtime_trait;
let optional_instance_bound_optional_default = &def.optional_instance_bound_optional_default;
let optional_instance_bound = &def.optional_instance_bound;
let optional_instance = &def.optional_instance;
let optional_comma_instance = optional_instance.as_ref().map(|i| quote!(, #i));
let where_clause = &def.where_clause;
let query_type = &line.query_type;
let struct_def = quote! {
#[doc(hidden)]
pub struct #struct_name<
#runtime_generic, #optional_instance_bound_optional_default
>(pub #scrate::sp_std::marker::PhantomData<(#runtime_generic #optional_comma_instance)>);
#[cfg(feature = "std")]
#[allow(non_upper_case_globals)]
static #cache_name: ::core::sync::OnceLock<#scrate::sp_std::vec::Vec<u8>> =
::core::sync::OnceLock::new();
#[cfg(feature = "std")]
impl<#runtime_generic: #runtime_trait, #optional_instance_bound>
#struct_name<#runtime_generic, #optional_instance>
#where_clause
{
fn default_byte(&self) -> #scrate::sp_std::vec::Vec<u8> {
use #scrate::codec::Encode;
#cache_name.get_or_init(|| {
let def_val: #query_type = #default;
<#query_type as Encode>::encode(&def_val)
}).clone()
}
}
#[cfg(not(feature = "std"))]
impl<#runtime_generic: #runtime_trait, #optional_instance_bound>
#struct_name<#runtime_generic, #optional_instance>
#where_clause
{
fn default_byte(&self) -> #scrate::sp_std::vec::Vec<u8> {
use #scrate::codec::Encode;
let def_val: #query_type = #default;
<#query_type as Encode>::encode(&def_val)
}
}
};
let struct_instance = quote!(
#struct_name::<#runtime_generic, #optional_instance>(#scrate::sp_std::marker::PhantomData)
);
(struct_def, struct_instance)
}
pub fn impl_metadata(def: &DeclStorageDefExt) -> TokenStream {
let scrate = &def.hidden_crate;
let mut entries = TokenStream::new();
let mut default_byte_getter_struct_defs = TokenStream::new();
for line in def.storage_lines.iter() {
let str_name = line.name.to_string();
let modifier = if line.is_option {
quote!(#scrate::metadata_ir::StorageEntryModifierIR::Optional)
} else {
quote!(#scrate::metadata_ir::StorageEntryModifierIR::Default)
};
let ty = storage_line_metadata_type(scrate, line);
let (default_byte_getter_struct_def, default_byte_getter_struct_instance) =
default_byte_getter(scrate, line, def);
let docs = get_doc_literals(&line.attrs);
let entry = quote! {
#scrate::metadata_ir::StorageEntryMetadataIR {
name: #str_name,
modifier: #modifier,
ty: #ty,
default: #default_byte_getter_struct_instance.default_byte(),
docs: #scrate::sp_std::vec![ #( #docs ),* ],
},
};
default_byte_getter_struct_defs.extend(default_byte_getter_struct_def);
entries.extend(entry);
}
let prefix = if let Some(instance) = &def.module_instance {
let instance_generic = &instance.instance_generic;
quote!(#instance_generic::PREFIX)
} else {
let prefix = def.crate_name.to_string();
quote!(#prefix)
};
let store_metadata = quote!(
#scrate::metadata_ir::PalletStorageMetadataIR {
prefix: #prefix,
entries: #scrate::sp_std::vec![ #entries ],
}
);
let module_struct = &def.module_struct;
let module_impl = &def.module_impl;
let where_clause = &def.where_clause;
quote!(
#default_byte_getter_struct_defs
impl #module_impl #module_struct #where_clause {
#[doc(hidden)]
pub fn storage_metadata() -> #scrate::metadata_ir::PalletStorageMetadataIR {
#store_metadata
}
}
)
}
@@ -1,507 +0,0 @@
// This file is part of Substrate.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! `decl_storage` input definition and expansion.
mod genesis_config;
mod getters;
mod instance_trait;
mod metadata;
mod parse;
mod print_pallet_upgrade;
mod storage_info;
mod storage_struct;
mod store_trait;
pub(crate) use instance_trait::INHERENT_INSTANCE_NAME;
use frame_support_procedural_tools::{
generate_crate_access, generate_hidden_includes, syn_ext as ext,
};
use quote::quote;
/// All information contained in input of decl_storage
pub struct DeclStorageDef {
/// Whether to generate the storage info
generate_storage_info: bool,
/// Name of the module used to import hidden imports.
hidden_crate: Option<syn::Ident>,
/// Visibility of store trait.
visibility: syn::Visibility,
/// Name of store trait: usually `Store`.
store_trait: syn::Ident,
/// Module name used by construct_runtime: usually `Module`.
module_name: syn::Ident,
/// Usually `T`.
module_runtime_generic: syn::Ident,
/// Usually `Config`
module_runtime_trait: syn::Path,
/// For instantiable module: usually `I: Instance=DefaultInstance`.
module_instance: Option<ModuleInstanceDef>,
/// Where claused used to constrain T and I even more.
where_clause: Option<syn::WhereClause>,
/// The extra build function used to build storage at genesis.
extra_genesis_build: Option<syn::Expr>,
/// The extra genesis config fields.
extra_genesis_config_lines: Vec<ExtraGenesisLineDef>,
/// Definition of storages.
storage_lines: Vec<StorageLineDef>,
/// Name of the crate, used for storage prefixes.
crate_name: syn::Ident,
}
impl syn::parse::Parse for DeclStorageDef {
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
parse::parse(input)
}
}
/// Extended version of `DeclStorageDef` with useful precomputed value.
pub struct DeclStorageDefExt {
/// Whether to generate the storage info
generate_storage_info: bool,
/// Name of the module used to import hidden imports.
hidden_crate: proc_macro2::TokenStream,
/// Hidden imports used by the module.
hidden_imports: proc_macro2::TokenStream,
/// Visibility of store trait.
visibility: syn::Visibility,
/// Name of store trait: usually `Store`.
store_trait: syn::Ident,
/// Module name used by construct_runtime: usually `Module`.
#[allow(unused)]
module_name: syn::Ident,
/// Usually `T`.
module_runtime_generic: syn::Ident,
/// Usually `Config`.
module_runtime_trait: syn::Path,
/// For instantiable module: usually `I: Instance=DefaultInstance`.
module_instance: Option<ModuleInstanceDef>,
/// Where claused used to constrain T and I even more.
where_clause: Option<syn::WhereClause>,
/// The extra build function used to build storage at genesis.
extra_genesis_build: Option<syn::Expr>,
/// The extra genesis config fields.
extra_genesis_config_lines: Vec<ExtraGenesisLineDef>,
/// Definition of storages.
storage_lines: Vec<StorageLineDefExt>,
/// Name of the crate, used for storage prefixes.
crate_name: syn::Ident,
/// Full struct expansion: `Module<T, I>`.
module_struct: proc_macro2::TokenStream,
/// Impl block for module: `<T: Config, I: Instance>`.
module_impl: proc_macro2::TokenStream,
/// For instantiable: `I`.
optional_instance: Option<proc_macro2::TokenStream>,
/// For instantiable: `I: Instance`.
optional_instance_bound: Option<proc_macro2::TokenStream>,
/// For instantiable: `I: Instance = DefaultInstance`.
optional_instance_bound_optional_default: Option<proc_macro2::TokenStream>,
}
impl From<DeclStorageDef> for DeclStorageDefExt {
fn from(mut def: DeclStorageDef) -> Self {
let hidden_crate_name = def
.hidden_crate
.as_ref()
.map(|i| i.to_string())
.unwrap_or_else(|| "decl_storage".to_string());
let hidden_crate = generate_crate_access(&hidden_crate_name, "frame-support");
let hidden_imports = generate_hidden_includes(&hidden_crate_name, "frame-support");
let storage_lines = def.storage_lines.drain(..).collect::<Vec<_>>();
let storage_lines = storage_lines
.into_iter()
.map(|line| StorageLineDefExt::from_def(line, &def, &hidden_crate))
.collect();
let (optional_instance, optional_instance_bound, optional_instance_bound_optional_default) =
if let Some(instance) = def.module_instance.as_ref() {
let instance_generic = &instance.instance_generic;
let instance_trait = &instance.instance_trait;
let optional_equal_instance_default =
instance.instance_default.as_ref().map(|d| quote!( = #d ));
(
Some(quote!(#instance_generic)),
Some(quote!(#instance_generic: #instance_trait)),
Some(
quote!(#instance_generic: #instance_trait #optional_equal_instance_default),
),
)
} else {
(None, None, None)
};
let module_runtime_generic = &def.module_runtime_generic;
let module_runtime_trait = &def.module_runtime_trait;
let module_name = &def.module_name;
let module_struct = quote!(
#module_name<#module_runtime_generic, #optional_instance>
);
let module_impl = quote!(
<#module_runtime_generic: #module_runtime_trait + 'static, #optional_instance_bound>
);
Self {
hidden_crate,
hidden_imports,
generate_storage_info: def.generate_storage_info,
visibility: def.visibility,
store_trait: def.store_trait,
module_name: def.module_name,
module_runtime_generic: def.module_runtime_generic,
module_runtime_trait: def.module_runtime_trait,
module_instance: def.module_instance,
where_clause: def.where_clause,
extra_genesis_build: def.extra_genesis_build,
extra_genesis_config_lines: def.extra_genesis_config_lines,
crate_name: def.crate_name,
storage_lines,
module_struct,
module_impl,
optional_instance,
optional_instance_bound,
optional_instance_bound_optional_default,
}
}
}
/// Usually `I: Instance=DefaultInstance`.
pub struct ModuleInstanceDef {
/// Usually: `I`.
instance_generic: syn::Ident,
/// Usually: `Instance`.
instance_trait: syn::Ident,
/// Usually: `DefaultInstance`.
instance_default: Option<syn::Ident>,
}
pub struct StorageLineDef {
attrs: Vec<syn::Attribute>,
/// Visibility of the storage struct.
visibility: syn::Visibility,
name: syn::Ident,
/// The name of getter function to be implemented on Module struct.
getter: Option<syn::Ident>,
/// The name of the field to be used in genesis config if any.
config: Option<syn::Ident>,
/// The given max values with `max_values` attribute, or a none if not specified.
max_values: Option<syn::Expr>,
/// The build function of the storage if any.
build: Option<syn::Expr>,
/// Default value of genesis config field and also for storage when no value available.
default_value: Option<syn::Expr>,
storage_type: StorageLineTypeDef,
}
pub struct StorageLineDefExt {
#[allow(unused)]
attrs: Vec<syn::Attribute>,
/// Visibility of the storage struct.
visibility: syn::Visibility,
name: syn::Ident,
/// The name of getter function to be implemented on Module struct.
getter: Option<syn::Ident>,
/// The name of the field to be used in genesis config if any.
config: Option<syn::Ident>,
/// The given max values with `max_values` attribute, or a none if not specified.
max_values: Option<syn::Expr>,
/// The build function of the storage if any.
build: Option<syn::Expr>,
/// Default value of genesis config field and also for storage when no value available.
default_value: Option<syn::Expr>,
storage_type: StorageLineTypeDef,
doc_attrs: Vec<syn::Meta>,
/// Either the type stored in storage or wrapped in an Option.
query_type: syn::Type,
/// The type stored in storage.
value_type: syn::Type,
/// Full struct, for example: `StorageName<T, I>`.
storage_struct: proc_macro2::TokenStream,
/// If storage is generic over runtime then `T`.
optional_storage_runtime_comma: Option<proc_macro2::TokenStream>,
/// If storage is generic over runtime then `T: Config`.
optional_storage_runtime_bound_comma: Option<proc_macro2::TokenStream>,
/// The where clause to use to constrain generics if storage is generic over runtime.
optional_storage_where_clause: Option<proc_macro2::TokenStream>,
/// Full trait, for example: `storage::StorageMap<u32, u32>`.
storage_trait: proc_macro2::TokenStream,
/// Full trait, for example: `storage::generator::StorageMap<u32, u32>`.
storage_generator_trait: proc_macro2::TokenStream,
/// Whether the storage is generic.
is_generic: bool,
/// Whether the storage value is an option.
is_option: bool,
}
impl StorageLineDefExt {
fn from_def(
storage_def: StorageLineDef,
def: &DeclStorageDef,
hidden_crate: &proc_macro2::TokenStream,
) -> Self {
let is_generic = match &storage_def.storage_type {
StorageLineTypeDef::Simple(value) =>
ext::type_contains_ident(value, &def.module_runtime_generic),
StorageLineTypeDef::Map(map) =>
ext::type_contains_ident(&map.key, &def.module_runtime_generic) ||
ext::type_contains_ident(&map.value, &def.module_runtime_generic),
StorageLineTypeDef::DoubleMap(map) =>
ext::type_contains_ident(&map.key1, &def.module_runtime_generic) ||
ext::type_contains_ident(&map.key2, &def.module_runtime_generic) ||
ext::type_contains_ident(&map.value, &def.module_runtime_generic),
StorageLineTypeDef::NMap(map) =>
map.keys
.iter()
.any(|key| ext::type_contains_ident(key, &def.module_runtime_generic)) ||
ext::type_contains_ident(&map.value, &def.module_runtime_generic),
};
let query_type = match &storage_def.storage_type {
StorageLineTypeDef::Simple(value) => value.clone(),
StorageLineTypeDef::Map(map) => map.value.clone(),
StorageLineTypeDef::DoubleMap(map) => map.value.clone(),
StorageLineTypeDef::NMap(map) => map.value.clone(),
};
let is_option = ext::extract_type_option(&query_type).is_some();
let value_type =
ext::extract_type_option(&query_type).unwrap_or_else(|| query_type.clone());
let module_runtime_generic = &def.module_runtime_generic;
let module_runtime_trait = &def.module_runtime_trait;
let optional_storage_runtime_comma =
if is_generic { Some(quote!( #module_runtime_generic, )) } else { None };
let optional_storage_runtime_bound_comma = if is_generic {
Some(quote!( #module_runtime_generic: #module_runtime_trait, ))
} else {
None
};
let storage_name = &storage_def.name;
let optional_instance_generic = def.module_instance.as_ref().map(|i| {
let instance_generic = &i.instance_generic;
quote!( #instance_generic )
});
let storage_struct = quote!(
#storage_name<#optional_storage_runtime_comma #optional_instance_generic>
);
let optional_storage_where_clause =
if is_generic { def.where_clause.as_ref().map(|w| quote!( #w )) } else { None };
let storage_trait_truncated = match &storage_def.storage_type {
StorageLineTypeDef::Simple(_) => {
quote!( StorageValue<#value_type> )
},
StorageLineTypeDef::Map(map) => {
let key = &map.key;
quote!( StorageMap<#key, #value_type> )
},
StorageLineTypeDef::DoubleMap(map) => {
let key1 = &map.key1;
let key2 = &map.key2;
quote!( StorageDoubleMap<#key1, #key2, #value_type> )
},
StorageLineTypeDef::NMap(map) => {
let keygen = map.to_keygen_struct(hidden_crate);
quote!( StorageNMap<#keygen, #value_type> )
},
};
let storage_trait = quote!( storage::#storage_trait_truncated );
let storage_generator_trait = quote!( storage::generator::#storage_trait_truncated );
let doc_attrs = storage_def
.attrs
.iter()
.filter(|a| a.meta.path().is_ident("doc"))
.map(|a| a.meta.clone())
.collect();
Self {
attrs: storage_def.attrs,
visibility: storage_def.visibility,
name: storage_def.name,
getter: storage_def.getter,
config: storage_def.config,
max_values: storage_def.max_values,
build: storage_def.build,
default_value: storage_def.default_value,
storage_type: storage_def.storage_type,
doc_attrs,
query_type,
value_type,
storage_struct,
optional_storage_runtime_comma,
optional_storage_runtime_bound_comma,
optional_storage_where_clause,
storage_trait,
storage_generator_trait,
is_generic,
is_option,
}
}
}
pub enum StorageLineTypeDef {
Map(MapDef),
DoubleMap(Box<DoubleMapDef>),
NMap(NMapDef),
Simple(syn::Type),
}
pub struct MapDef {
pub hasher: HasherKind,
pub key: syn::Type,
/// This is the query value not the inner value used in storage trait implementation.
pub value: syn::Type,
}
pub struct DoubleMapDef {
pub hasher1: HasherKind,
pub hasher2: HasherKind,
pub key1: syn::Type,
pub key2: syn::Type,
/// This is the query value not the inner value used in storage trait implementation.
pub value: syn::Type,
}
pub struct NMapDef {
pub hashers: Vec<HasherKind>,
pub keys: Vec<syn::Type>,
pub value: syn::Type,
}
impl NMapDef {
fn to_keygen_struct(&self, scrate: &proc_macro2::TokenStream) -> proc_macro2::TokenStream {
if self.keys.len() == 1 {
let hasher = &self.hashers[0].to_storage_hasher_struct();
let key = &self.keys[0];
return quote!( #scrate::storage::types::Key<#scrate::#hasher, #key> )
}
let key_hasher = self
.keys
.iter()
.zip(&self.hashers)
.map(|(key, hasher)| {
let hasher = hasher.to_storage_hasher_struct();
quote!( #scrate::storage::types::Key<#scrate::#hasher, #key> )
})
.collect::<Vec<_>>();
quote!(( #(#key_hasher,)* ))
}
fn to_key_tuple(&self) -> proc_macro2::TokenStream {
if self.keys.len() == 1 {
let key = &self.keys[0];
return quote!(#key)
}
let tuple = self.keys.iter().map(|key| quote!(#key)).collect::<Vec<_>>();
quote!(( #(#tuple,)* ))
}
}
pub struct ExtraGenesisLineDef {
attrs: Vec<syn::Attribute>,
name: syn::Ident,
typ: syn::Type,
default: Option<syn::Expr>,
}
#[derive(Debug, Clone)]
pub enum HasherKind {
Blake2_256,
Blake2_128,
Blake2_128Concat,
Twox256,
Twox128,
Twox64Concat,
Identity,
}
impl HasherKind {
fn to_storage_hasher_struct(&self) -> proc_macro2::TokenStream {
match self {
HasherKind::Blake2_256 => quote!(Blake2_256),
HasherKind::Blake2_128 => quote!(Blake2_128),
HasherKind::Blake2_128Concat => quote!(Blake2_128Concat),
HasherKind::Twox256 => quote!(Twox256),
HasherKind::Twox128 => quote!(Twox128),
HasherKind::Twox64Concat => quote!(Twox64Concat),
HasherKind::Identity => quote!(Identity),
}
}
fn into_metadata(&self) -> proc_macro2::TokenStream {
match self {
HasherKind::Blake2_256 => quote!(StorageHasherIR::Blake2_256),
HasherKind::Blake2_128 => quote!(StorageHasherIR::Blake2_128),
HasherKind::Blake2_128Concat => quote!(StorageHasherIR::Blake2_128Concat),
HasherKind::Twox256 => quote!(StorageHasherIR::Twox256),
HasherKind::Twox128 => quote!(StorageHasherIR::Twox128),
HasherKind::Twox64Concat => quote!(StorageHasherIR::Twox64Concat),
HasherKind::Identity => quote!(StorageHasherIR::Identity),
}
}
}
/// Full implementation of decl_storage.
pub fn decl_storage_impl(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let def = syn::parse_macro_input!(input as DeclStorageDef);
let def_ext = DeclStorageDefExt::from(def);
print_pallet_upgrade::maybe_print_pallet_upgrade(&def_ext);
let scrate = &def_ext.hidden_crate;
let scrate_decl = &def_ext.hidden_imports;
let store_trait = store_trait::decl_and_impl(&def_ext);
let getters = getters::impl_getters(&def_ext);
let metadata = metadata::impl_metadata(&def_ext);
let instance_trait = instance_trait::decl_and_impl(&def_ext);
let genesis_config = genesis_config::genesis_config_and_build_storage(&def_ext);
let storage_struct = storage_struct::decl_and_impl(&def_ext);
let storage_info = storage_info::impl_storage_info(&def_ext);
quote!(
use #scrate::{
StorageValue as _,
StorageMap as _,
StorageDoubleMap as _,
StorageNMap as _,
StoragePrefixedMap as _,
IterableStorageMap as _,
IterableStorageNMap as _,
IterableStorageDoubleMap as _,
};
#scrate_decl
#store_trait
#getters
#metadata
#instance_trait
#genesis_config
#storage_struct
#storage_info
)
.into()
}
@@ -1,562 +0,0 @@
// This file is part of Substrate.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! Parsing of decl_storage input.
use frame_support_procedural_tools::{syn_ext as ext, Parse, ToTokens};
use syn::{spanned::Spanned, Ident, Token};
mod keyword {
syn::custom_keyword!(generate_storage_info);
syn::custom_keyword!(hiddencrate);
syn::custom_keyword!(add_extra_genesis);
syn::custom_keyword!(extra_genesis_skip_phantom_data_field);
syn::custom_keyword!(config);
syn::custom_keyword!(max_values);
syn::custom_keyword!(build);
syn::custom_keyword!(get);
syn::custom_keyword!(map);
syn::custom_keyword!(double_map);
syn::custom_keyword!(nmap);
syn::custom_keyword!(opaque_blake2_256);
syn::custom_keyword!(opaque_blake2_128);
syn::custom_keyword!(blake2_128_concat);
syn::custom_keyword!(opaque_twox_256);
syn::custom_keyword!(opaque_twox_128);
syn::custom_keyword!(twox_64_concat);
syn::custom_keyword!(identity);
syn::custom_keyword!(hasher);
syn::custom_keyword!(tainted);
syn::custom_keyword!(natural);
syn::custom_keyword!(prehashed);
}
/// Specific `Opt` to implement structure with optional parsing
#[derive(Debug, Clone)]
pub struct Opt<P> {
pub inner: Option<P>,
}
impl<P: quote::ToTokens> quote::ToTokens for Opt<P> {
fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
if let Some(ref p) = self.inner {
p.to_tokens(tokens);
}
}
}
macro_rules! impl_parse_for_opt {
($struct:ident => $token:path) => {
impl syn::parse::Parse for Opt<$struct> {
fn parse(input: syn::parse::ParseStream) -> syn::parse::Result<Self> {
if input.peek($token) {
input.parse().map(|p| Opt { inner: Some(p) })
} else {
Ok(Opt { inner: None })
}
}
}
};
}
/// Parsing usage only
#[derive(Parse, ToTokens, Debug)]
struct StorageDefinition {
pub generate_storage_info: Opt<GenerateStorageInfo>,
pub hidden_crate: Opt<SpecificHiddenCrate>,
pub visibility: syn::Visibility,
pub trait_token: Token![trait],
pub ident: Ident,
pub for_token: Token![for],
pub module_ident: Ident,
pub mod_lt_token: Token![<],
pub mod_param_generic: syn::Ident,
pub mod_param_bound_token: Option<Token![:]>,
pub mod_param_bound: syn::Path,
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 where_clause: Option<syn::WhereClause>,
pub content: ext::Braces<ext::Punctuated<DeclStorageLine, Token![;]>>,
pub extra_genesis: Opt<AddExtraGenesis>,
}
#[derive(Parse, ToTokens, Debug)]
struct GenerateStorageInfo {
pub keyword: keyword::generate_storage_info,
}
impl_parse_for_opt!(GenerateStorageInfo => keyword::generate_storage_info);
#[derive(Parse, ToTokens, Debug)]
struct SpecificHiddenCrate {
pub keyword: keyword::hiddencrate,
pub ident: ext::Parens<Ident>,
}
impl_parse_for_opt!(SpecificHiddenCrate => keyword::hiddencrate);
#[derive(Parse, ToTokens, Debug)]
struct AddExtraGenesis {
pub extragenesis_keyword: keyword::add_extra_genesis,
pub content: ext::Braces<AddExtraGenesisContent>,
}
impl_parse_for_opt!(AddExtraGenesis => keyword::add_extra_genesis);
#[derive(Parse, ToTokens, Debug)]
struct AddExtraGenesisContent {
pub lines: ext::Punctuated<AddExtraGenesisLineEnum, Token![;]>,
}
#[derive(ToTokens, Debug)]
enum AddExtraGenesisLineEnum {
AddExtraGenesisLine(AddExtraGenesisLine),
AddExtraGenesisBuild(DeclStorageBuild),
}
impl syn::parse::Parse for AddExtraGenesisLineEnum {
fn parse(input: syn::parse::ParseStream) -> syn::parse::Result<Self> {
let input_fork = input.fork();
// OuterAttributes are forbidden for build variant,
// However to have better documentation we match against the keyword after those attributes.
let _: ext::OuterAttributes = input_fork.parse()?;
let lookahead = input_fork.lookahead1();
if lookahead.peek(keyword::build) {
Ok(Self::AddExtraGenesisBuild(input.parse()?))
} else if lookahead.peek(keyword::config) {
Ok(Self::AddExtraGenesisLine(input.parse()?))
} else {
Err(lookahead.error())
}
}
}
#[derive(Parse, ToTokens, Debug)]
struct AddExtraGenesisLine {
pub attrs: ext::OuterAttributes,
pub config_keyword: keyword::config,
pub extra_field: ext::Parens<Ident>,
pub coldot_token: Token![:],
pub extra_type: syn::Type,
pub default_value: Opt<DeclStorageDefault>,
}
#[derive(Parse, ToTokens, Debug)]
struct DeclStorageLine {
// attrs (main use case is doc)
pub attrs: ext::OuterAttributes,
// visibility (no need to make optional
pub visibility: syn::Visibility,
// name
pub name: Ident,
pub getter: Opt<DeclStorageGetter>,
pub config: Opt<DeclStorageConfig>,
pub max_values: Opt<DeclStorageMaxValues>,
pub build: Opt<DeclStorageBuild>,
pub coldot_token: Token![:],
pub storage_type: DeclStorageType,
pub default_value: Opt<DeclStorageDefault>,
}
#[derive(Parse, ToTokens, Debug)]
struct DeclStorageGetterBody {
fn_keyword: Token![fn],
ident: Ident,
}
#[derive(Parse, ToTokens, Debug)]
struct DeclStorageGetter {
pub getter_keyword: keyword::get,
pub getfn: ext::Parens<DeclStorageGetterBody>,
}
impl_parse_for_opt!(DeclStorageGetter => keyword::get);
#[derive(Parse, ToTokens, Debug)]
struct DeclStorageConfig {
pub config_keyword: keyword::config,
pub expr: ext::Parens<Option<syn::Ident>>,
}
impl_parse_for_opt!(DeclStorageConfig => keyword::config);
#[derive(Parse, ToTokens, Debug)]
struct DeclStorageMaxValues {
pub max_values_keyword: keyword::max_values,
pub expr: ext::Parens<syn::Expr>,
}
impl_parse_for_opt!(DeclStorageMaxValues => keyword::max_values);
#[derive(Parse, ToTokens, Debug)]
struct DeclStorageBuild {
pub build_keyword: keyword::build,
pub expr: ext::Parens<syn::Expr>,
}
impl_parse_for_opt!(DeclStorageBuild => keyword::build);
#[derive(ToTokens, Debug)]
enum DeclStorageType {
Map(DeclStorageMap),
DoubleMap(Box<DeclStorageDoubleMap>),
NMap(DeclStorageNMap),
Simple(syn::Type),
}
impl syn::parse::Parse for DeclStorageType {
fn parse(input: syn::parse::ParseStream) -> syn::parse::Result<Self> {
if input.peek(keyword::map) {
Ok(Self::Map(input.parse()?))
} else if input.peek(keyword::double_map) {
Ok(Self::DoubleMap(input.parse()?))
} else if input.peek(keyword::nmap) {
Ok(Self::NMap(input.parse()?))
} else {
Ok(Self::Simple(input.parse()?))
}
}
}
#[derive(Parse, ToTokens, Debug)]
struct DeclStorageMap {
pub map_keyword: keyword::map,
pub hasher: Opt<SetHasher>,
pub key: syn::Type,
pub ass_keyword: Token![=>],
pub value: syn::Type,
}
#[derive(Parse, ToTokens, Debug)]
struct DeclStorageDoubleMap {
pub map_keyword: keyword::double_map,
pub hasher1: Opt<SetHasher>,
pub key1: syn::Type,
pub comma_keyword: Token![,],
pub hasher2: Opt<SetHasher>,
pub key2: syn::Type,
pub ass_keyword: Token![=>],
pub value: syn::Type,
}
#[derive(Parse, ToTokens, Debug)]
struct DeclStorageKey {
pub hasher: Opt<SetHasher>,
pub key: syn::Type,
}
#[derive(Parse, ToTokens, Debug)]
struct DeclStorageNMap {
pub map_keyword: keyword::nmap,
pub storage_keys: ext::PunctuatedTrailing<DeclStorageKey, Token![,]>,
pub ass_keyword: Token![=>],
pub value: syn::Type,
}
#[derive(Clone, ToTokens, Debug)]
enum Hasher {
Blake2_256(keyword::opaque_blake2_256),
Blake2_128(keyword::opaque_blake2_128),
Blake2_128Concat(keyword::blake2_128_concat),
Twox256(keyword::opaque_twox_256),
Twox128(keyword::opaque_twox_128),
Twox64Concat(keyword::twox_64_concat),
Identity(keyword::identity),
}
impl syn::parse::Parse for Hasher {
fn parse(input: syn::parse::ParseStream) -> syn::parse::Result<Self> {
let lookahead = input.lookahead1();
if lookahead.peek(keyword::opaque_blake2_256) {
Ok(Self::Blake2_256(input.parse()?))
} else if lookahead.peek(keyword::opaque_blake2_128) {
Ok(Self::Blake2_128(input.parse()?))
} else if lookahead.peek(keyword::blake2_128_concat) {
Ok(Self::Blake2_128Concat(input.parse()?))
} else if lookahead.peek(keyword::opaque_twox_256) {
Ok(Self::Twox256(input.parse()?))
} else if lookahead.peek(keyword::opaque_twox_128) {
Ok(Self::Twox128(input.parse()?))
} else if lookahead.peek(keyword::twox_64_concat) {
Ok(Self::Twox64Concat(input.parse()?))
} else if lookahead.peek(keyword::identity) {
Ok(Self::Identity(input.parse()?))
} else if lookahead.peek(keyword::tainted) {
Ok(Self::Blake2_128Concat(input.parse()?))
} else if lookahead.peek(keyword::natural) {
Ok(Self::Twox64Concat(input.parse()?))
} else if lookahead.peek(keyword::prehashed) {
Ok(Self::Identity(input.parse()?))
} else {
Err(lookahead.error())
}
}
}
#[derive(Parse, ToTokens, Debug)]
struct DeclStorageDefault {
pub equal_token: Token![=],
pub expr: syn::Expr,
}
impl syn::parse::Parse for Opt<DeclStorageDefault> {
fn parse(input: syn::parse::ParseStream) -> syn::parse::Result<Self> {
if input.peek(Token![=]) {
input.parse().map(|p| Opt { inner: Some(p) })
} else {
Ok(Opt { inner: None })
}
}
}
#[derive(Clone, Parse, ToTokens, Debug)]
struct SetHasher {
pub hasher_keyword: keyword::hasher,
pub inner: ext::Parens<Hasher>,
}
impl_parse_for_opt!(SetHasher => keyword::hasher);
impl From<SetHasher> for super::HasherKind {
fn from(set_hasher: SetHasher) -> Self {
set_hasher.inner.content.into()
}
}
impl From<Hasher> for super::HasherKind {
fn from(hasher: Hasher) -> Self {
match hasher {
Hasher::Blake2_256(_) => super::HasherKind::Blake2_256,
Hasher::Blake2_128(_) => super::HasherKind::Blake2_128,
Hasher::Blake2_128Concat(_) => super::HasherKind::Blake2_128Concat,
Hasher::Twox256(_) => super::HasherKind::Twox256,
Hasher::Twox128(_) => super::HasherKind::Twox128,
Hasher::Twox64Concat(_) => super::HasherKind::Twox64Concat,
Hasher::Identity(_) => super::HasherKind::Identity,
}
}
}
fn get_module_instance(
instance: Option<syn::Ident>,
instantiable: Option<syn::Ident>,
default_instance: Option<syn::Ident>,
) -> syn::Result<Option<super::ModuleInstanceDef>> {
let right_syntax = "Should be $I: $Instance = $DefaultInstance";
if instantiable.as_ref().map_or(false, |i| i != "Instance") {
let msg = format!(
"Instance trait must be named `Instance`, other names are no longer supported, because \
it is now defined at frame_support::traits::Instance. Expect `Instance` found `{}`",
instantiable.as_ref().unwrap(),
);
return Err(syn::Error::new(instantiable.span(), msg))
}
match (instance, instantiable, default_instance) {
(Some(instance), Some(instantiable), default_instance) =>
Ok(Some(super::ModuleInstanceDef {
instance_generic: instance,
instance_trait: instantiable,
instance_default: default_instance,
})),
(None, None, None) => Ok(None),
(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,
),
)),
}
}
pub fn parse(input: syn::parse::ParseStream) -> syn::Result<super::DeclStorageDef> {
use syn::parse::Parse;
let def = StorageDefinition::parse(input)?;
let module_instance =
get_module_instance(def.mod_instance, def.mod_instantiable, def.mod_default_instance)?;
let mut extra_genesis_config_lines = vec![];
let mut extra_genesis_build = None;
for line in def
.extra_genesis
.inner
.into_iter()
.flat_map(|o| o.content.content.lines.inner.into_iter())
{
match line {
AddExtraGenesisLineEnum::AddExtraGenesisLine(def) => {
extra_genesis_config_lines.push(super::ExtraGenesisLineDef {
attrs: def.attrs.inner,
name: def.extra_field.content,
typ: def.extra_type,
default: def.default_value.inner.map(|o| o.expr),
});
},
AddExtraGenesisLineEnum::AddExtraGenesisBuild(def) => {
if extra_genesis_build.is_some() {
return Err(syn::Error::new(
def.span(),
"Only one build expression allowed for extra genesis",
))
}
extra_genesis_build = Some(def.expr.content);
},
}
}
let storage_lines = parse_storage_line_defs(def.content.content.inner.into_iter())?;
Ok(super::DeclStorageDef {
generate_storage_info: def.generate_storage_info.inner.is_some(),
hidden_crate: def.hidden_crate.inner.map(|i| i.ident.content),
visibility: def.visibility,
module_name: def.module_ident,
store_trait: def.ident,
module_runtime_generic: def.mod_param_generic,
module_runtime_trait: def.mod_param_bound,
where_clause: def.where_clause,
crate_name: def.crate_ident,
module_instance,
extra_genesis_build,
extra_genesis_config_lines,
storage_lines,
})
}
/// Parse the `DeclStorageLine` into `StorageLineDef`.
fn parse_storage_line_defs(
defs: impl Iterator<Item = DeclStorageLine>,
) -> syn::Result<Vec<super::StorageLineDef>> {
let mut storage_lines = Vec::<super::StorageLineDef>::new();
for line in defs {
let getter = line.getter.inner.map(|o| o.getfn.content.ident);
let config = if let Some(config) = line.config.inner {
if let Some(ident) = config.expr.content {
Some(ident)
} else if let Some(ref ident) = getter {
Some(ident.clone())
} else {
return Err(syn::Error::new(
config.span(),
"Invalid storage definition, couldn't find config identifier: storage must \
either have a get identifier `get(fn ident)` or a defined config identifier \
`config(ident)`",
))
}
} else {
None
};
if let Some(ref config) = config {
storage_lines.iter().filter_map(|sl| sl.config.as_ref()).try_for_each(
|other_config| {
if other_config == config {
Err(syn::Error::new(
config.span(),
"`config()`/`get()` with the same name already defined.",
))
} else {
Ok(())
}
},
)?;
}
let max_values = match &line.storage_type {
DeclStorageType::Map(_) | DeclStorageType::DoubleMap(_) | DeclStorageType::NMap(_) =>
line.max_values.inner.map(|i| i.expr.content),
DeclStorageType::Simple(_) =>
if let Some(max_values) = line.max_values.inner {
let msg = "unexpected max_values attribute for storage value.";
let span = max_values.max_values_keyword.span();
return Err(syn::Error::new(span, msg))
} else {
Some(syn::parse_quote!(1u32))
},
};
let span = line.storage_type.span();
let no_hasher_error = || {
syn::Error::new(
span,
"Default hasher has been removed, use explicit hasher(blake2_128_concat) instead.",
)
};
let storage_type = match line.storage_type {
DeclStorageType::Map(map) => super::StorageLineTypeDef::Map(super::MapDef {
hasher: map.hasher.inner.ok_or_else(no_hasher_error)?.into(),
key: map.key,
value: map.value,
}),
DeclStorageType::DoubleMap(map) =>
super::StorageLineTypeDef::DoubleMap(Box::new(super::DoubleMapDef {
hasher1: map.hasher1.inner.ok_or_else(no_hasher_error)?.into(),
hasher2: map.hasher2.inner.ok_or_else(no_hasher_error)?.into(),
key1: map.key1,
key2: map.key2,
value: map.value,
})),
DeclStorageType::NMap(map) => super::StorageLineTypeDef::NMap(super::NMapDef {
hashers: map
.storage_keys
.inner
.iter()
.map(|pair| Ok(pair.hasher.inner.clone().ok_or_else(no_hasher_error)?.into()))
.collect::<Result<Vec<_>, syn::Error>>()?,
keys: map.storage_keys.inner.iter().map(|pair| pair.key.clone()).collect(),
value: map.value,
}),
DeclStorageType::Simple(expr) => super::StorageLineTypeDef::Simple(expr),
};
storage_lines.push(super::StorageLineDef {
attrs: line.attrs.inner,
visibility: line.visibility,
name: line.name,
getter,
config,
max_values,
build: line.build.inner.map(|o| o.expr.content),
default_value: line.default_value.inner.map(|o| o.expr),
storage_type,
})
}
Ok(storage_lines)
}
@@ -1,385 +0,0 @@
use super::StorageLineTypeDef;
use frame_support_procedural_tools::clean_type_string;
use quote::ToTokens;
/// Environment variable that tells us to print pallet upgrade helper.
const PRINT_PALLET_UPGRADE: &str = "PRINT_PALLET_UPGRADE";
fn check_print_pallet_upgrade() -> bool {
std::env::var(PRINT_PALLET_UPGRADE).is_ok()
}
/// Convert visibilty as now objects are defined in a module.
fn convert_vis(vis: &syn::Visibility) -> &'static str {
match vis {
syn::Visibility::Inherited => "pub(super)",
syn::Visibility::Public(_) => "pub",
_ => "/* TODO_VISIBILITY */",
}
}
/// fn to convert to token stream then string using display and then call clean_type_string on it.
fn to_cleaned_string(t: impl quote::ToTokens) -> String {
clean_type_string(&format!("{}", t.into_token_stream()))
}
/// Print an incomplete upgrade from decl_storage macro to new pallet attribute.
pub fn maybe_print_pallet_upgrade(def: &super::DeclStorageDefExt) {
if !check_print_pallet_upgrade() {
return
}
let scrate = &quote::quote!(frame_support);
let config_gen =
if def.optional_instance.is_some() { "<I: 'static = ()>" } else { Default::default() };
let impl_gen =
if def.optional_instance.is_some() { "<T: Config<I>, I: 'static>" } else { "<T: Config>" };
let decl_gen = if def.optional_instance.is_some() { "<T, I=()>" } else { "<T>" };
let full_decl_gen = if def.optional_instance.is_some() {
"<T: Config<I>, I: 'static = ()>"
} else {
"<T: Config>"
};
let use_gen = if def.optional_instance.is_some() { "<T, I>" } else { "<T>" };
let use_gen_tuple = if def.optional_instance.is_some() { "<(T, I)>" } else { "<T>" };
let mut genesis_config = String::new();
let mut genesis_build = String::new();
let genesis_config_builder_def = super::genesis_config::BuilderDef::from_def(scrate, def);
if !genesis_config_builder_def.blocks.is_empty() {
let genesis_config_def = match super::genesis_config::GenesisConfigDef::from_def(def) {
Ok(g) => g,
Err(err) => {
println!("Could not print upgrade due compile error: {:?}", err);
return
},
};
let genesis_config_impl_gen =
if genesis_config_def.is_generic { impl_gen } else { Default::default() };
let genesis_config_use_gen =
if genesis_config_def.is_generic { use_gen } else { Default::default() };
let genesis_config_decl_gen = if genesis_config_def.is_generic {
if def.optional_instance.is_some() {
"<T: Config<I>, I: 'static = ()>"
} else {
"<T: Config>"
}
} else {
Default::default()
};
let mut genesis_config_decl_fields = String::new();
let mut genesis_config_default_fields = String::new();
for field in &genesis_config_def.fields {
genesis_config_decl_fields.push_str(&format!(
"
{attrs}pub {name}: {typ},",
attrs = field.attrs.iter().fold(String::new(), |res, attr| {
format!(
"{}#[{}]
",
res,
attr.to_token_stream()
)
}),
name = field.name,
typ = to_cleaned_string(&field.typ),
));
genesis_config_default_fields.push_str(&format!(
"
{name}: {default},",
name = field.name,
default = to_cleaned_string(&field.default),
));
}
genesis_config = format!(
"
#[pallet::genesis_config]
pub struct GenesisConfig{genesis_config_decl_gen}
// TODO_MAYBE_WHERE_CLAUSE
{{{genesis_config_decl_fields}
}}
#[cfg(feature = \"std\")]
impl{genesis_config_impl_gen} Default for GenesisConfig{genesis_config_use_gen}
// TODO_MAYBE_WHERE_CLAUSE
{{
fn default() -> Self {{
Self {{{genesis_config_default_fields}
}}
}}
}}",
genesis_config_decl_gen = genesis_config_decl_gen,
genesis_config_decl_fields = genesis_config_decl_fields,
genesis_config_impl_gen = genesis_config_impl_gen,
genesis_config_default_fields = genesis_config_default_fields,
genesis_config_use_gen = genesis_config_use_gen,
);
let genesis_config_build =
genesis_config_builder_def.blocks.iter().fold(String::new(), |res, block| {
format!(
"{}
{}",
res,
to_cleaned_string(block),
)
});
genesis_build = format!(
"
#[pallet::genesis_build]
impl{impl_gen} GenesisBuild{use_gen} for GenesisConfig{genesis_config_use_gen}
// TODO_MAYBE_WHERE_CLAUSE
{{
fn build(&self) {{{genesis_config_build}
}}
}}",
impl_gen = impl_gen,
use_gen = use_gen,
genesis_config_use_gen = genesis_config_use_gen,
genesis_config_build = genesis_config_build,
);
}
let mut storages = String::new();
for line in &def.storage_lines {
let storage_vis = convert_vis(&line.visibility);
let getter = if let Some(getter) = &line.getter {
format!(
"
#[pallet::getter(fn {getter})]",
getter = getter
)
} else {
Default::default()
};
let value_type = &line.value_type;
let default_value_type_value = line
.default_value
.as_ref()
.map(|default_expr| {
format!(
"
#[pallet::type_value]
{storage_vis} fn DefaultFor{name} /* TODO_MAYBE_GENERICS */ () -> {value_type} {{
{default_expr}
}}
",
name = line.name,
storage_vis = storage_vis,
value_type = to_cleaned_string(&line.value_type),
default_expr = to_cleaned_string(&default_expr),
)
})
.unwrap_or_else(String::new);
let comma_query_kind = if line.is_option {
if line.default_value.is_some() {
", OptionQuery"
} else {
Default::default()
}
} else {
", ValueQuery"
};
let comma_default_value_getter_name = line
.default_value
.as_ref()
.map(|_| format!(", DefaultFor{}", line.name))
.unwrap_or_else(String::new);
let typ = match &line.storage_type {
StorageLineTypeDef::Map(map) => {
format!(
"StorageMap<_, {hasher}, {key}, {value_type}{comma_query_kind}\
{comma_default_value_getter_name}>",
hasher = &map.hasher.to_storage_hasher_struct(),
key = to_cleaned_string(&map.key),
value_type = to_cleaned_string(&value_type),
comma_query_kind = comma_query_kind,
comma_default_value_getter_name = comma_default_value_getter_name,
)
},
StorageLineTypeDef::DoubleMap(double_map) => {
format!(
"StorageDoubleMap<_, {hasher1}, {key1}, {hasher2}, {key2}, {value_type}\
{comma_query_kind}{comma_default_value_getter_name}>",
hasher1 = double_map.hasher1.to_storage_hasher_struct(),
key1 = to_cleaned_string(&double_map.key1),
hasher2 = double_map.hasher2.to_storage_hasher_struct(),
key2 = to_cleaned_string(&double_map.key2),
value_type = to_cleaned_string(&value_type),
comma_query_kind = comma_query_kind,
comma_default_value_getter_name = comma_default_value_getter_name,
)
},
StorageLineTypeDef::NMap(map) => {
format!(
"StorageNMap<_, {keygen}, {value_type}{comma_query_kind}\
{comma_default_value_getter_name}>",
keygen = map.to_keygen_struct(&def.hidden_crate),
value_type = to_cleaned_string(&value_type),
comma_query_kind = comma_query_kind,
comma_default_value_getter_name = comma_default_value_getter_name,
)
},
StorageLineTypeDef::Simple(_) => {
format!(
"StorageValue<_, {value_type}{comma_query_kind}\
{comma_default_value_getter_name}>",
value_type = to_cleaned_string(&value_type),
comma_query_kind = comma_query_kind,
comma_default_value_getter_name = comma_default_value_getter_name,
)
},
};
let additional_comment = if line.is_option && line.default_value.is_some() {
" // TODO: This type of storage is no longer supported: `OptionQuery` cannot be used \
alongside a not-none value on empty storage. Please use `ValueQuery` instead."
} else {
""
};
storages.push_str(&format!(
"
{default_value_type_value}{doc}
#[pallet::storage]{getter}
{storage_vis} type {name}{full_decl_gen} = {typ};{additional_comment}",
default_value_type_value = default_value_type_value,
getter = getter,
storage_vis = storage_vis,
name = line.name,
full_decl_gen = full_decl_gen,
typ = typ,
additional_comment = additional_comment,
doc = line.doc_attrs.iter().fold(String::new(), |mut res, attr| {
if let syn::Meta::NameValue(name_value) = attr {
if name_value.path.is_ident("doc") {
res = format!(
"{}
///{}",
res,
name_value.value.to_token_stream(),
);
}
}
res
}),
));
}
let deprecated_instance_stuff = if def.optional_instance.is_some() {
"
/// Old name for default instance generated by decl_storage.
#[deprecated(note=\"use `()` instead\")]
pub type DefaultInstance = ();
/// Old name for instance trait used by old macros.
#[deprecated(note=\"use `'static` instead\")]
pub trait Instance: 'static {}
impl<I: 'static> Instance for I {}"
} else {
""
};
println!(
"
// Template for pallet upgrade for {pallet_name}
pub use pallet::*;
#[frame_support::pallet]
pub mod pallet {{
use frame_support::pallet_prelude::*;
use frame_system::pallet_prelude::*;
use super::*;
#[pallet::config]
pub trait Config{config_gen}: frame_system::Config
// TODO_MAYBE_ADDITIONAL_BOUNDS_AND_WHERE_CLAUSE
{{
// TODO_ASSOCIATED_TYPE_AND_CONSTANTS
}}
{deprecated_instance_stuff}
#[pallet::pallet]
#[pallet::generate_store({store_vis} trait Store)]
pub struct Pallet{decl_gen}(PhantomData{use_gen_tuple});
#[pallet::hooks]
impl{impl_gen} Hooks<BlockNumberFor<T>> for Pallet{use_gen}
// TODO_MAYBE_WHERE_CLAUSE
{{
// TODO_ON_FINALIZE
// TODO_ON_INITIALIZE
// TODO_ON_RUNTIME_UPGRADE
// TODO_INTEGRITY_TEST
// TODO_OFFCHAIN_WORKER
}}
#[pallet::call]
impl{impl_gen} Pallet{use_gen}
// TODO_MAYBE_WHERE_CLAUSE
{{
// TODO_UPGRADE_DISPATCHABLES
}}
#[pallet::inherent]
// TODO_INHERENT
#[pallet::event]
#[pallet::generate_deposit(pub(super) fn deposit_event)]
// TODO_EVENT
// TODO_REMOVE_IF_NO_EVENT
/// Old name generated by `decl_event`.
#[deprecated(note=\"use `Event` instead\")]
pub type RawEvent /* TODO_PUT_EVENT_GENERICS */ = Event /* TODO_PUT_EVENT_GENERICS */;
#[pallet::error]
// TODO_ERROR
#[pallet::origin]
// TODO_ORIGIN
#[pallet::validate_unsigned]
// TODO_VALIDATE_UNSIGNED
{storages}
{genesis_config}
{genesis_build}
}}",
config_gen = config_gen,
store_vis = convert_vis(&def.visibility),
impl_gen = impl_gen,
use_gen = use_gen,
use_gen_tuple = use_gen_tuple,
decl_gen = decl_gen,
storages = storages,
genesis_config = genesis_config,
genesis_build = genesis_build,
pallet_name = def.crate_name,
deprecated_instance_stuff = deprecated_instance_stuff,
);
}
@@ -1,59 +0,0 @@
// This file is part of Substrate.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! Implementation of trait `StorageInfoTrait` on module structure.
use super::DeclStorageDefExt;
use proc_macro2::TokenStream;
use quote::quote;
pub fn impl_storage_info(def: &DeclStorageDefExt) -> TokenStream {
let scrate = &def.hidden_crate;
let mut res_append_storage = TokenStream::new();
for line in def.storage_lines.iter() {
let storage_struct = &line.storage_struct;
let (trait_, method) = if def.generate_storage_info {
(quote!(#scrate::traits::StorageInfoTrait), quote!(storage_info))
} else {
(quote!(#scrate::traits::PartialStorageInfoTrait), quote!(partial_storage_info))
};
res_append_storage.extend(quote!(
let mut storage_info = <
#storage_struct as #trait_
>::#method();
res.append(&mut storage_info);
));
}
let module_struct = &def.module_struct;
let module_impl = &def.module_impl;
let where_clause = &def.where_clause;
quote!(
impl #module_impl #scrate::traits::StorageInfoTrait for #module_struct #where_clause {
fn storage_info() -> #scrate::sp_std::vec::Vec<#scrate::traits::StorageInfo> {
let mut res = #scrate::sp_std::vec![];
#res_append_storage
res
}
}
)
}
@@ -1,564 +0,0 @@
// This file is part of Substrate.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! Implementation of storage structures and implementation of storage traits on them.
use super::{instance_trait::INHERENT_INSTANCE_NAME, DeclStorageDefExt, StorageLineTypeDef};
use proc_macro2::{Ident, Span, TokenStream};
use quote::quote;
fn from_optional_value_to_query(is_option: bool, default: &Option<syn::Expr>) -> TokenStream {
let default = default
.as_ref()
.map(|d| quote!( #d ))
.unwrap_or_else(|| quote!(Default::default()));
if !is_option {
// raw type case
quote!( v.unwrap_or_else(|| #default ) )
} else {
// Option<> type case
quote!( v.or_else(|| #default ) )
}
}
fn from_query_to_optional_value(is_option: bool) -> TokenStream {
if !is_option {
// raw type case
quote!(Some(v))
} else {
// Option<> type case
quote!(v)
}
}
pub fn decl_and_impl(def: &DeclStorageDefExt) -> TokenStream {
let scrate = &def.hidden_crate;
let mut impls = TokenStream::new();
for line in &def.storage_lines {
// Propagate doc attributes.
let attrs = &line.doc_attrs;
let visibility = &line.visibility;
let optional_storage_runtime_comma = &line.optional_storage_runtime_comma;
let optional_storage_runtime_bound_comma = &line.optional_storage_runtime_bound_comma;
let optional_storage_where_clause = &line.optional_storage_where_clause;
let optional_instance_bound_optional_default =
&def.optional_instance_bound_optional_default;
let optional_instance_bound = &def.optional_instance_bound;
let optional_instance = &def.optional_instance;
let name = &line.name;
let struct_decl = quote!(
#( #[ #attrs ] )*
#visibility struct #name<
#optional_storage_runtime_bound_comma #optional_instance_bound_optional_default
>(
#scrate::sp_std::marker::PhantomData<
(#optional_storage_runtime_comma #optional_instance)
>
) #optional_storage_where_clause;
);
let from_query_to_optional_value = from_query_to_optional_value(line.is_option);
let from_optional_value_to_query =
from_optional_value_to_query(line.is_option, &line.default_value);
// Contains accessor to instance, used to get prefixes
let instance_or_inherent = if let Some(instance) = def.module_instance.as_ref() {
instance.instance_generic.clone()
} else {
Ident::new(INHERENT_INSTANCE_NAME, Span::call_site())
};
let storage_name_bstr =
syn::LitByteStr::new(line.name.to_string().as_ref(), line.name.span());
let storage_generator_trait = &line.storage_generator_trait;
let storage_struct = &line.storage_struct;
let impl_trait = quote!( #optional_storage_runtime_bound_comma #optional_instance_bound );
let value_type = &line.value_type;
let query_type = &line.query_type;
let struct_impl = match &line.storage_type {
StorageLineTypeDef::Simple(_) => {
quote!(
impl<#impl_trait> #scrate::#storage_generator_trait for #storage_struct
#optional_storage_where_clause
{
type Query = #query_type;
fn module_prefix() -> &'static [u8] {
<#instance_or_inherent as #scrate::traits::Instance>::PREFIX.as_bytes()
}
fn storage_prefix() -> &'static [u8] {
#storage_name_bstr
}
fn from_optional_value_to_query(v: Option<#value_type>) -> Self::Query {
#from_optional_value_to_query
}
fn from_query_to_optional_value(v: Self::Query) -> Option<#value_type> {
#from_query_to_optional_value
}
}
)
},
StorageLineTypeDef::Map(map) => {
let hasher = map.hasher.to_storage_hasher_struct();
quote!(
impl<#impl_trait> #scrate::storage::StoragePrefixedMap<#value_type>
for #storage_struct #optional_storage_where_clause
{
fn module_prefix() -> &'static [u8] {
<#instance_or_inherent as #scrate::traits::Instance>::PREFIX.as_bytes()
}
fn storage_prefix() -> &'static [u8] {
#storage_name_bstr
}
}
impl<#impl_trait> #scrate::#storage_generator_trait for #storage_struct
#optional_storage_where_clause
{
type Query = #query_type;
type Hasher = #scrate::#hasher;
fn module_prefix() -> &'static [u8] {
<#instance_or_inherent as #scrate::traits::Instance>::PREFIX.as_bytes()
}
fn storage_prefix() -> &'static [u8] {
#storage_name_bstr
}
fn from_optional_value_to_query(v: Option<#value_type>) -> Self::Query {
#from_optional_value_to_query
}
fn from_query_to_optional_value(v: Self::Query) -> Option<#value_type> {
#from_query_to_optional_value
}
}
)
},
StorageLineTypeDef::DoubleMap(map) => {
let hasher1 = map.hasher1.to_storage_hasher_struct();
let hasher2 = map.hasher2.to_storage_hasher_struct();
quote!(
impl<#impl_trait> #scrate::storage::StoragePrefixedMap<#value_type>
for #storage_struct #optional_storage_where_clause
{
fn module_prefix() -> &'static [u8] {
<#instance_or_inherent as #scrate::traits::Instance>::PREFIX.as_bytes()
}
fn storage_prefix() -> &'static [u8] {
#storage_name_bstr
}
}
impl<#impl_trait> #scrate::#storage_generator_trait for #storage_struct
#optional_storage_where_clause
{
type Query = #query_type;
type Hasher1 = #scrate::#hasher1;
type Hasher2 = #scrate::#hasher2;
fn module_prefix() -> &'static [u8] {
<#instance_or_inherent as #scrate::traits::Instance>::PREFIX.as_bytes()
}
fn storage_prefix() -> &'static [u8] {
#storage_name_bstr
}
fn from_optional_value_to_query(v: Option<#value_type>) -> Self::Query {
#from_optional_value_to_query
}
fn from_query_to_optional_value(v: Self::Query) -> Option<#value_type> {
#from_query_to_optional_value
}
}
)
},
StorageLineTypeDef::NMap(_) => {
quote!(
impl<#impl_trait> #scrate::storage::StoragePrefixedMap<#value_type>
for #storage_struct #optional_storage_where_clause
{
fn module_prefix() -> &'static [u8] {
<#instance_or_inherent as #scrate::traits::Instance>::PREFIX.as_bytes()
}
fn storage_prefix() -> &'static [u8] {
#storage_name_bstr
}
}
impl<#impl_trait> #scrate::#storage_generator_trait for #storage_struct
#optional_storage_where_clause
{
type Query = #query_type;
fn module_prefix() -> &'static [u8] {
<#instance_or_inherent as #scrate::traits::Instance>::PREFIX.as_bytes()
}
fn storage_prefix() -> &'static [u8] {
#storage_name_bstr
}
fn from_optional_value_to_query(v: Option<#value_type>) -> Self::Query {
#from_optional_value_to_query
}
fn from_query_to_optional_value(v: Self::Query) -> Option<#value_type> {
#from_query_to_optional_value
}
}
)
},
};
let max_values = if let Some(max_values) = &line.max_values {
quote::quote!({
let max_values: u32 = (|| #max_values)();
Some(max_values)
})
} else {
quote::quote!(None)
};
let storage_info_impl = if def.generate_storage_info {
match &line.storage_type {
StorageLineTypeDef::Simple(_) => {
quote!(
impl<#impl_trait> #scrate::traits::StorageInfoTrait for #storage_struct
#optional_storage_where_clause
{
fn storage_info()
-> #scrate::sp_std::vec::Vec<#scrate::traits::StorageInfo>
{
use #scrate::sp_runtime::SaturatedConversion;
let max_size = <
#value_type as #scrate::codec::MaxEncodedLen
>::max_encoded_len()
.saturated_into();
#scrate::sp_std::vec![
#scrate::traits::StorageInfo {
pallet_name: <
#storage_struct as #scrate::#storage_generator_trait
>::module_prefix().to_vec(),
storage_name: <
#storage_struct as #scrate::#storage_generator_trait
>::storage_prefix().to_vec(),
prefix: <
#storage_struct as #scrate::#storage_generator_trait
>::storage_value_final_key().to_vec(),
max_values: Some(1),
max_size: Some(max_size),
}
]
}
}
)
},
StorageLineTypeDef::Map(map) => {
let key = &map.key;
quote!(
impl<#impl_trait> #scrate::traits::StorageInfoTrait for #storage_struct
#optional_storage_where_clause
{
fn storage_info()
-> #scrate::sp_std::vec::Vec<#scrate::traits::StorageInfo>
{
use #scrate::sp_runtime::SaturatedConversion;
use #scrate::StorageHasher;
let key_max_size = <
Self as #scrate::storage::generator::StorageMap<_, _>
>::Hasher::max_len::<#key>();
let max_size = <
#value_type as #scrate::codec::MaxEncodedLen
>::max_encoded_len()
.saturating_add(key_max_size)
.saturated_into();
#scrate::sp_std::vec![
#scrate::traits::StorageInfo {
pallet_name: <
#storage_struct
as #scrate::storage::StoragePrefixedMap<#value_type>
>::module_prefix().to_vec(),
storage_name: <
#storage_struct
as #scrate::storage::StoragePrefixedMap<#value_type>
>::storage_prefix().to_vec(),
prefix: <
#storage_struct
as #scrate::storage::StoragePrefixedMap<#value_type>
>::final_prefix().to_vec(),
max_values: #max_values,
max_size: Some(max_size),
}
]
}
}
)
},
StorageLineTypeDef::DoubleMap(map) => {
let key1 = &map.key1;
let key2 = &map.key2;
quote!(
impl<#impl_trait> #scrate::traits::StorageInfoTrait for #storage_struct
#optional_storage_where_clause
{
fn storage_info()
-> #scrate::sp_std::vec::Vec<#scrate::traits::StorageInfo>
{
use #scrate::sp_runtime::SaturatedConversion;
use #scrate::StorageHasher;
let key1_max_size = <
Self as #scrate::storage::generator::StorageDoubleMap<_, _, _>
>::Hasher1::max_len::<#key1>();
let key2_max_size = <
Self as #scrate::storage::generator::StorageDoubleMap<_, _, _>
>::Hasher2::max_len::<#key2>();
let max_size = <
#value_type as #scrate::codec::MaxEncodedLen
>::max_encoded_len()
.saturating_add(key1_max_size)
.saturating_add(key2_max_size)
.saturated_into();
#scrate::sp_std::vec![
#scrate::traits::StorageInfo {
pallet_name: <
#storage_struct
as #scrate::storage::StoragePrefixedMap<#value_type>
>::module_prefix().to_vec(),
storage_name: <
#storage_struct
as #scrate::storage::StoragePrefixedMap<#value_type>
>::storage_prefix().to_vec(),
prefix: <
#storage_struct
as #scrate::storage::StoragePrefixedMap<#value_type>
>::final_prefix().to_vec(),
max_values: #max_values,
max_size: Some(max_size),
}
]
}
}
)
},
StorageLineTypeDef::NMap(map) => {
let key = &map.to_keygen_struct(scrate);
quote!(
impl<#impl_trait> #scrate::traits::StorageInfoTrait for #storage_struct
#optional_storage_where_clause
{
fn storage_info()
-> #scrate::sp_std::vec::Vec<#scrate::traits::StorageInfo>
{
use #scrate::sp_runtime::SaturatedConversion;
let key_max_size = <
#key as #scrate::storage::types::KeyGeneratorMaxEncodedLen
>::key_max_encoded_len();
let max_size = <
#value_type as #scrate::codec::MaxEncodedLen
>::max_encoded_len()
.saturating_add(key_max_size)
.saturated_into();
#scrate::sp_std::vec![
#scrate::traits::StorageInfo {
pallet_name: <
#storage_struct
as #scrate::storage::StoragePrefixedMap<#value_type>
>::module_prefix().to_vec(),
storage_name: <
#storage_struct
as #scrate::storage::StoragePrefixedMap<#value_type>
>::storage_prefix().to_vec(),
prefix: <
#storage_struct
as #scrate::storage::StoragePrefixedMap<#value_type>
>::final_prefix().to_vec(),
max_values: #max_values,
max_size: Some(max_size),
}
]
}
}
)
},
}
} else {
// Implement `__partial_storage_info` which doesn't require MaxEncodedLen on keys and
// values.
match &line.storage_type {
StorageLineTypeDef::Simple(_) => {
quote!(
impl<#impl_trait> #scrate::traits::PartialStorageInfoTrait
for #storage_struct
#optional_storage_where_clause
{
fn partial_storage_info()
-> #scrate::sp_std::vec::Vec<#scrate::traits::StorageInfo>
{
#scrate::sp_std::vec![
#scrate::traits::StorageInfo {
pallet_name: <
#storage_struct as #scrate::#storage_generator_trait
>::module_prefix().to_vec(),
storage_name: <
#storage_struct as #scrate::#storage_generator_trait
>::storage_prefix().to_vec(),
prefix: <
#storage_struct as #scrate::#storage_generator_trait
>::storage_value_final_key().to_vec(),
max_values: Some(1),
max_size: None,
}
]
}
}
)
},
StorageLineTypeDef::Map(_) => {
quote!(
impl<#impl_trait> #scrate::traits::PartialStorageInfoTrait
for #storage_struct
#optional_storage_where_clause
{
fn partial_storage_info()
-> #scrate::sp_std::vec::Vec<#scrate::traits::StorageInfo>
{
#scrate::sp_std::vec![
#scrate::traits::StorageInfo {
pallet_name: <
#storage_struct
as #scrate::storage::StoragePrefixedMap<#value_type>
>::module_prefix().to_vec(),
storage_name: <
#storage_struct
as #scrate::storage::StoragePrefixedMap<#value_type>
>::storage_prefix().to_vec(),
prefix: <
#storage_struct
as #scrate::storage::StoragePrefixedMap<#value_type>
>::final_prefix().to_vec(),
max_values: #max_values,
max_size: None,
}
]
}
}
)
},
StorageLineTypeDef::DoubleMap(_) => {
quote!(
impl<#impl_trait> #scrate::traits::PartialStorageInfoTrait
for #storage_struct
#optional_storage_where_clause
{
fn partial_storage_info()
-> #scrate::sp_std::vec::Vec<#scrate::traits::StorageInfo>
{
#scrate::sp_std::vec![
#scrate::traits::StorageInfo {
pallet_name: <
#storage_struct
as #scrate::storage::StoragePrefixedMap<#value_type>
>::module_prefix().to_vec(),
storage_name: <
#storage_struct
as #scrate::storage::StoragePrefixedMap<#value_type>
>::storage_prefix().to_vec(),
prefix: <
#storage_struct
as #scrate::storage::StoragePrefixedMap<#value_type>
>::final_prefix().to_vec(),
max_values: #max_values,
max_size: None,
}
]
}
}
)
},
StorageLineTypeDef::NMap(_) => {
quote!(
impl<#impl_trait> #scrate::traits::PartialStorageInfoTrait
for #storage_struct
#optional_storage_where_clause
{
fn partial_storage_info()
-> #scrate::sp_std::vec::Vec<#scrate::traits::StorageInfo>
{
#scrate::sp_std::vec![
#scrate::traits::StorageInfo {
pallet_name: <
#storage_struct
as #scrate::storage::StoragePrefixedMap<#value_type>
>::module_prefix().to_vec(),
storage_name: <
#storage_struct
as #scrate::storage::StoragePrefixedMap<#value_type>
>::storage_prefix().to_vec(),
prefix: <
#storage_struct
as #scrate::storage::StoragePrefixedMap<#value_type>
>::final_prefix().to_vec(),
max_values: #max_values,
max_size: None,
}
]
}
}
)
},
}
};
impls.extend(quote!(
#struct_decl
#struct_impl
#storage_info_impl
))
}
impls
}
@@ -1,55 +0,0 @@
// This file is part of Substrate.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! Declaration of store trait and implementation on module structure.
use super::DeclStorageDefExt;
use proc_macro2::TokenStream;
use quote::quote;
pub fn decl_and_impl(def: &DeclStorageDefExt) -> TokenStream {
let decl_store_items = def.storage_lines.iter().map(|sline| &sline.name).fold(
TokenStream::new(),
|mut items, name| {
items.extend(quote!(type #name;));
items
},
);
let impl_store_items = def.storage_lines.iter().fold(TokenStream::new(), |mut items, line| {
let name = &line.name;
let storage_struct = &line.storage_struct;
items.extend(quote!(type #name = #storage_struct;));
items
});
let visibility = &def.visibility;
let store_trait = &def.store_trait;
let module_struct = &def.module_struct;
let module_impl = &def.module_impl;
let where_clause = &def.where_clause;
quote!(
#visibility trait #store_trait {
#decl_store_items
}
impl #module_impl #store_trait for #module_struct #where_clause {
#impl_store_items
}
)
}
File diff suppressed because it is too large Load Diff
-118
View File
@@ -1,118 +0,0 @@
// This file is part of Substrate.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! Macro for declaring a module error.
#[doc(hidden)]
pub use sp_runtime::traits::{BadOrigin, LookupError};
/// Declare an error type for a runtime module.
#[macro_export]
#[deprecated(note = "Will be removed after July 2023; use the attribute `#[pallet]` macro instead.
For more info, see: <https://github.com/paritytech/substrate/pull/13705>")]
macro_rules! decl_error {
(
$(#[$attr:meta])*
pub enum $error:ident
for $module:ident<
$generic:ident: $trait:path
$(, $inst_generic:ident: $instance:path)?
>
$( where $( $where_ty:ty: $where_bound:path ),* $(,)? )?
{
$(
$( #[doc = $doc_attr:tt] )*
$name:ident
),*
$(,)?
}
) => {
$(#[$attr])*
#[derive(
$crate::codec::Encode,
$crate::codec::Decode,
$crate::scale_info::TypeInfo,
$crate::PalletError,
)]
#[scale_info(skip_type_params($generic $(, $inst_generic)?), capture_docs = "always")]
pub enum $error<$generic: $trait $(, $inst_generic: $instance)?>
$( where $( $where_ty: $where_bound ),* )?
{
#[doc(hidden)]
#[codec(skip)]
__Ignore(
$crate::sp_std::marker::PhantomData<($generic, $( $inst_generic)?)>,
$crate::Never,
),
$(
$( #[doc = $doc_attr] )*
$name
),*
}
impl<$generic: $trait $(, $inst_generic: $instance)?> $crate::sp_std::fmt::Debug
for $error<$generic $(, $inst_generic)?>
$( where $( $where_ty: $where_bound ),* )?
{
fn fmt(&self, f: &mut $crate::sp_std::fmt::Formatter<'_>) -> $crate::sp_std::fmt::Result {
f.write_str(self.as_str())
}
}
impl<$generic: $trait $(, $inst_generic: $instance)?> $error<$generic $(, $inst_generic)?>
$( where $( $where_ty: $where_bound ),* )?
{
fn as_str(&self) -> &'static str {
match self {
Self::__Ignore(_, _) => unreachable!("`__Ignore` can never be constructed"),
$(
$error::$name => stringify!($name),
)*
}
}
}
impl<$generic: $trait $(, $inst_generic: $instance)?> From<$error<$generic $(, $inst_generic)?>>
for &'static str
$( where $( $where_ty: $where_bound ),* )?
{
fn from(err: $error<$generic $(, $inst_generic)?>) -> &'static str {
err.as_str()
}
}
impl<$generic: $trait $(, $inst_generic: $instance)?> From<$error<$generic $(, $inst_generic)?>>
for $crate::sp_runtime::DispatchError
$( where $( $where_ty: $where_bound ),* )?
{
fn from(err: $error<$generic $(, $inst_generic)?>) -> Self {
use $crate::codec::Encode;
let index = <$generic::PalletInfo as $crate::traits::PalletInfo>
::index::<$module<$generic $(, $inst_generic)?>>()
.expect("Every active module has an index in the runtime; qed") as u8;
let mut error = err.encode();
error.resize($crate::MAX_MODULE_ERROR_ENCODED_SIZE, 0);
$crate::sp_runtime::DispatchError::Module($crate::sp_runtime::ModuleError {
index,
error: TryInto::try_into(error).expect("encoded error is resized to be equal to the maximum encoded error size; qed"),
message: Some(err.as_str()),
})
}
}
};
}
-294
View File
@@ -1,294 +0,0 @@
// This file is part of Substrate.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! Macros that define an Event types. Events can be used to easily report changes or conditions
//! in your runtime to external entities like users, chain explorers, or dApps.
// You should have received a copy of the GNU General Public License
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
/// Implement the `Event` for a module.
///
/// # Simple Event Example:
///
/// ```rust
/// frame_support::decl_event!(
/// pub enum Event {
/// Success,
/// Failure(String),
/// }
/// );
///
/// # fn main() {}
/// ```
///
/// # Generic Event Example:
///
/// ```rust
/// trait Config {
/// type Balance;
/// type Token;
/// }
///
/// mod event1 {
/// // Event that specifies the generic parameter explicitly (`Balance`).
/// frame_support::decl_event!(
/// pub enum Event<T> where Balance = <T as super::Config>::Balance {
/// Message(Balance),
/// }
/// );
/// }
///
/// mod event2 {
/// // Event that uses the generic parameter `Balance`.
/// // If no name for the generic parameter is specified explicitly,
/// // the name will be taken from the type name of the trait.
/// frame_support::decl_event!(
/// pub enum Event<T> where <T as super::Config>::Balance {
/// Message(Balance),
/// }
/// );
/// }
///
/// mod event3 {
/// // And we even support declaring multiple generic parameters!
/// frame_support::decl_event!(
/// pub enum Event<T> where <T as super::Config>::Balance, <T as super::Config>::Token {
/// Message(Balance, Token),
/// }
/// );
/// }
///
/// # fn main() {}
/// ```
///
/// The syntax for generic events requires the `where`.
///
/// # Generic Event with Instance Example:
///
/// ```rust
/// # struct DefaultInstance;
/// # trait Instance {}
/// # impl Instance for DefaultInstance {}
/// trait Config<I: Instance=DefaultInstance> {
/// type Balance;
/// type Token;
/// }
///
/// // For module with instances, DefaultInstance is optional
/// frame_support::decl_event!(
/// pub enum Event<T, I: Instance = DefaultInstance> where
/// <T as Config>::Balance,
/// <T as Config>::Token
/// {
/// Message(Balance, Token),
/// }
/// );
/// # fn main() {}
/// ```
#[macro_export]
#[deprecated(note = "Will be removed after July 2023; use the attribute `#[pallet]` macro instead.
For more info, see: <https://github.com/paritytech/substrate/pull/13705>")]
macro_rules! decl_event {
(
$(#[$attr:meta])*
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 )* };
);
};
(
$(#[$attr:meta])*
pub enum Event {
$(
$events:tt
)*
}
) => {
// Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted.
#[derive(
Clone, PartialEq, Eq,
$crate::codec::Encode,
$crate::codec::Decode,
$crate::scale_info::TypeInfo,
$crate::RuntimeDebug,
)]
#[scale_info(capture_docs = "always")]
/// Events for this module.
///
$(#[$attr])*
pub enum Event {
$(
$events
)*
}
impl From<Event> for () {
fn from(_: Event) -> () { () }
}
}
}
#[macro_export]
#[doc(hidden)]
// This parsing to retrieve last ident on unnamed generic could be improved.
// but user can still name it if the parsing fails. And improving parsing seems difficult.
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 )* };
{};
);
};
// Finish formatting on an unnamed one
(@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 };
);
};
// Finish formatting on a named one
(@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 };
);
};
// Parse named
(@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 };
);
};
// Parse unnamed
(@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 };
);
};
// Unnamed type can't be parsed
(@format_generic
$(#[$attr:meta])*;
$event_generic_param:ident;
$($instance:ident $( = $event_default_instance:path)? )?;
{ $generic_type:ty, $($rest:tt)* };
{ $($parsed:tt)* };
) => {
$crate::__decl_generic_event!(@cannot_parse $generic_type);
};
// Final unnamed type can't be parsed
(@format_generic
$(#[$attr:meta])*;
$event_generic_param:ident;
$($instance:ident $( = $event_default_instance:path)? )?;
{ $generic_type:ty { $( $events:tt )* } };
{$( $parsed:tt)*};
) => {
$crate::__decl_generic_event!(@cannot_parse $generic_type);
};
(@generate
$(#[$attr:meta])*;
$event_generic_param:ident;
$($instance:ident $( = $event_default_instance:path)? )?;
{ $( $events:tt )* };
{ ,$( $generic_param:ident = $generic_type:ty ),* };
) => {
/// [`RawEvent`] specialized for the configuration [`Config`]
///
/// [`RawEvent`]: enum.RawEvent.html
/// [`Config`]: trait.Config.html
pub type Event<$event_generic_param $(, $instance $( = $event_default_instance)? )?> = RawEvent<$( $generic_type ),* $(, $instance)? >;
#[derive(
Clone, PartialEq, Eq,
$crate::codec::Encode,
$crate::codec::Decode,
$crate::scale_info::TypeInfo,
$crate::RuntimeDebug,
)]
#[scale_info(capture_docs = "always")]
/// Events for this module.
///
$(#[$attr])*
pub enum RawEvent<$( $generic_param ),* $(, $instance)? > {
$(
$events
)*
$(
#[doc(hidden)]
#[codec(skip)]
PhantomData($crate::sp_std::marker::PhantomData<$instance>),
)?
}
impl<$( $generic_param ),* $(, $instance)? > From<RawEvent<$( $generic_param ),* $(, $instance)?>> for () {
fn from(_: RawEvent<$( $generic_param ),* $(, $instance)?>) -> () { () }
}
};
(@cannot_parse $ty:ty) => {
compile_error!(concat!("The type `", stringify!($ty), "` can't be parsed as an unnamed one, please name it `Name = ", stringify!($ty), "`"));
}
}
+10 -9
View File
@@ -67,17 +67,13 @@ pub use tt_call::*;
#[macro_use]
pub mod dispatch;
mod hash;
pub mod storage;
#[macro_use]
pub mod event;
pub mod inherent;
#[macro_use]
pub mod error;
pub mod crypto;
pub mod dispatch_context;
mod hash;
pub mod inherent;
pub mod instances;
pub mod migrations;
pub mod storage;
pub mod traits;
pub mod weights;
#[doc(hidden)]
@@ -531,8 +527,7 @@ pub fn debug(data: &impl sp_std::fmt::Debug) {
#[doc(inline)]
pub use frame_support_procedural::{
construct_runtime, decl_storage, match_and_insert, transactional, PalletError,
RuntimeDebugNoBound,
construct_runtime, match_and_insert, transactional, PalletError, RuntimeDebugNoBound,
};
#[doc(hidden)]
@@ -2910,6 +2905,12 @@ pub mod pallet_macros {
};
}
#[deprecated(note = "Will be removed after July 2023; Use `sp_runtime::traits` directly instead.")]
pub mod error {
#[doc(hidden)]
pub use sp_runtime::traits::{BadOrigin, LookupError};
}
#[doc(inline)]
pub use frame_support_procedural::register_default_impl;