Traitify Runtime (#104)

* Factor out safe-mix and dispatch

* Refactor dispatch into something more modular.

* Fix wasm build.

* Fix up timestamp

* fix warnings.

* Borked timestamp example

* Fix build

* Timestamp as skeleton for traity runtime.

* New storage macro.

* Dispatch module has traity API.

* Move consensus module to new API

* Refactoring and outer dispatch

* Avoid unnecessary derives.

* Abstract the low-level half of system.

* nicer outer dispatch syntax.

* Make runtime compile again (albeit in a heavily simplified state)

* Reworking runtime and the upper levels of system.

* Initial reworking of runtime:

- Introduced executive module;
- Introduced trait primitives module;
- Provided an API endpoint.

* Expose an additional function in system

* Another couple of functions traitified in executive.

* another function in executive traitified.

* One more function traitified.

* Finish traitifying executive!

* Traitify session module.

* Cleanups and ensure session gets run.

* First part of traitification of staking module.

* Bit more of staking traitified.

* Additional stuff in staking. Fix up session.

* Penultimate part of staking module.

* Final part of staking (code)

* Update demo runtime to include staking.

* Final tweaks for staking integration.

* Remove old runtime files.

* Schedule staking.

* Minor fixes

* First bits of democracy.

* Democracy module integrated.

* Fix warning.

* Traitify and integrate council module

* Council voting.

* Runtime binary and tweaks.

* Binary update.

* Fix `*Type` grumble.

* Fix up genesis_map

* Remove NonTrivialSlicable

* Staking "test externalities" stuff along with refactor.

* Add session test externalities constructor

* Fixed executor tests.

* Make one test in executive module work.

* Remove test framework stuff into common module.

* Enable other tests in executive

* Session tests reinstated, minor refactoring of keyring.

* Fix staking tests.

* Fix up democracy tests.

* First few tests in council.

* Council tests reinstated :)

* Avoid hardcoding blake2 into Header.

* Fix last few tests.

* Make all primitives generic.

* Fix tests.

* Refactor runtime to remove genesismap.

* Streamline runtime more with macrofied config.

* Clean paths

* Fix warning.

* Consolidate demo runtime crate.

* Remove stale code.

* Refactor away dodgy trait.

* Add corresponding Aux type.

* Fixes

* Rename Digesty -> Digest

* Rename Headery -> Header

* Blocky -> Block

* Fix wasm build.

* kill warnings

* more docs

* minor cleanups
This commit is contained in:
Gav Wood
2018-04-04 12:06:39 +02:00
committed by GitHub
parent 3ec6d2dde6
commit bd066e27a6
92 changed files with 7890 additions and 5243 deletions
@@ -6,9 +6,10 @@ authors = ["Parity Technologies <admin@parity.io>"]
[dependencies]
ed25519 = { path = "../ed25519", optional = true }
hex-literal = { version = "0.1.0", optional = true }
serde = { version = "1.0", default_features = false }
serde_derive = { version = "1.0", optional = true }
substrate-runtime-std = { path = "../runtime-std", default_features = false }
substrate-runtime-io = { path = "../runtime-io", default_features = false }
environmental = { path = "../environmental", optional = true }
substrate-primitives = { path = "../primitives", default_features = false }
substrate-codec = { path = "../codec", default_features = false }
@@ -17,7 +18,8 @@ default = ["std"]
std = [
"ed25519",
"hex-literal",
"environmental",
"serde/std",
"serde_derive",
"substrate-primitives/std",
"substrate-runtime-io/std",
"substrate-codec/std",
@@ -0,0 +1,510 @@
// Copyright 2017 Parity Technologies (UK) Ltd.
// This file is part of Substrate Demo.
// Substrate Demo is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Substrate Demo is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Substrate Demo. If not, see <http://www.gnu.org/licenses/>.
//! Dispatch system. Just dispatches calls.
pub use rstd::prelude::{Vec, Clone, Eq, PartialEq};
#[cfg(feature = "std")]
pub use std::fmt;
pub use rstd::marker::PhantomData;
#[cfg(feature = "std")]
use serde;
pub use codec::{Slicable, Input};
pub trait Dispatchable {
type Trait;
fn dispatch(self);
}
pub trait AuxDispatchable {
type Aux;
type Trait;
fn dispatch(self, aux: &Self::Aux);
}
#[cfg(feature = "std")]
pub trait AuxCallable {
type Call: AuxDispatchable + Slicable + ::serde::Serialize + Clone + PartialEq + Eq;
}
#[cfg(not(feature = "std"))]
pub trait AuxCallable {
type Call: AuxDispatchable + Slicable + Clone + PartialEq + Eq;
}
#[cfg(feature = "std")]
pub trait Callable {
type Call: Dispatchable + Slicable + ::serde::Serialize + Clone + PartialEq + Eq;
}
#[cfg(not(feature = "std"))]
pub trait Callable {
type Call: Dispatchable + Slicable + Clone + PartialEq + Eq;
}
#[cfg(feature = "std")]
pub trait Parameter: Slicable + serde::Serialize + Clone + Eq + fmt::Debug {}
#[cfg(feature = "std")]
impl<T> Parameter for T where T: Slicable + serde::Serialize + Clone + Eq + fmt::Debug {}
#[cfg(not(feature = "std"))]
pub trait Parameter: Slicable + Clone + Eq {}
#[cfg(not(feature = "std"))]
impl<T> Parameter for T where T: Slicable + Clone + Eq {}
/// Declare a struct for this module, then implement dispatch logic to create a pairing of several
/// dispatch traits and enums.
#[macro_export]
macro_rules! decl_module {
(
pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident>;
$($rest:tt)*
) => {
pub struct $mod_type<$trait_instance: $trait_name>($crate::dispatch::PhantomData<$trait_instance>);
decl_dispatch! {
impl for $mod_type<$trait_instance: $trait_name>;
$($rest)*
}
};
(
struct $mod_type:ident<$trait_instance:ident: $trait_name:ident>;
$($rest:tt)*
) => {
struct $mod_type<$trait_instance: $trait_name>($crate::dispatch::PhantomData<$trait_instance>);
decl_dispatch! {
impl for $mod_type<$trait_instance: $trait_name>;
$($rest)*
}
}
}
/// Implement several dispatch modules to create a pairing of a dispatch trait and enum.
#[macro_export]
macro_rules! decl_dispatch {
// WITHOUT AUX
(
impl for $mod_type:ident<$trait_instance:ident: $trait_name:ident>;
pub enum $call_type:ident {
$(
fn $fn_name:ident(
$(
$param_name:ident : $param:ty
),*
)
= $id:expr ;
)*
}
$($rest:tt)*
) => {
__decl_dispatch_module_without_aux! {
impl for $mod_type<$trait_instance: $trait_name>;
pub enum $call_type;
$(
fn $fn_name( $( $param_name: $param ),* ) = $id;
)*
}
decl_dispatch! {
impl for $mod_type<$trait_instance: $trait_name>;
$($rest)*
}
};
// WITH AUX
(
impl for $mod_type:ident<$trait_instance:ident: $trait_name:ident>;
pub enum $call_type:ident where aux: $aux_type:ty {
$(
fn $fn_name:ident(aux
$(
, $param_name:ident : $param:ty
)*
)
= $id:expr ;
)*
}
$($rest:tt)*
) => {
__decl_dispatch_module_with_aux! {
impl for $mod_type<$trait_instance: $trait_name>;
pub enum $call_type where aux: $aux_type;
$(
fn $fn_name(aux $(, $param_name: $param )*)= $id;
)*
}
decl_dispatch! {
impl for $mod_type<$trait_instance: $trait_name>;
$($rest)*
}
};
// BASE CASE
(
impl for $mod_type:ident<$trait_instance:ident: $trait_name:ident>;
) => {
impl<$trait_instance: $trait_name> $mod_type<$trait_instance> {
pub fn aux_dispatch<D: $crate::dispatch::AuxDispatchable<Trait = $trait_instance>>(d: D, aux: &D::Aux) {
d.dispatch(aux);
}
pub fn dispatch<D: $crate::dispatch::Dispatchable<Trait = $trait_instance>>(d: D) {
d.dispatch();
}
}
}
}
#[macro_export]
/// Implement a single dispatch modules to create a pairing of a dispatch trait and enum.
macro_rules! __decl_dispatch_module_without_aux {
(
impl for $mod_type:ident<$trait_instance:ident: $trait_name:ident>;
pub enum $call_type:ident;
$(
fn $fn_name:ident(
$(
$param_name:ident : $param:ty
),*
)
= $id:expr ;
)*
) => {
__decl_dispatch_module_common! {
impl for $mod_type<$trait_instance: $trait_name>;
pub enum $call_type;
$( fn $fn_name( $( $param_name : $param ),* ) = $id ; )*
}
impl<$trait_instance: $trait_name> $crate::dispatch::Dispatchable
for $call_type<$trait_instance>
{
type Trait = $trait_instance;
fn dispatch(self) {
match self {
$(
$call_type::$fn_name( $( $param_name ),* ) =>
<$mod_type<$trait_instance>>::$fn_name( $( $param_name ),* ),
)*
$call_type::__PhantomItem(_) => { panic!("__PhantomItem should never be used.") },
}
}
}
impl<$trait_instance: $trait_name> $crate::dispatch::Callable
for $mod_type<$trait_instance>
{
type Call = $call_type<$trait_instance>;
}
}
}
#[macro_export]
/// Implement a single dispatch modules to create a pairing of a dispatch trait and enum.
macro_rules! __decl_dispatch_module_with_aux {
(
impl for $mod_type:ident<$trait_instance:ident: $trait_name:ident>;
pub enum $call_type:ident where aux: $aux_type:ty;
$(
fn $fn_name:ident(aux
$(
, $param_name:ident : $param:ty
)*
)
= $id:expr ;
)*
) => {
__decl_dispatch_module_common! {
impl for $mod_type<$trait_instance: $trait_name>;
pub enum $call_type;
$( fn $fn_name( $( $param_name : $param ),* ) = $id ; )*
}
impl<$trait_instance: $trait_name> $crate::dispatch::AuxDispatchable
for $call_type<$trait_instance>
{
type Trait = $trait_instance;
type Aux = $aux_type;
fn dispatch(self, aux: &Self::Aux) {
match self {
$(
$call_type::$fn_name( $( $param_name ),* ) =>
<$mod_type<$trait_instance>>::$fn_name( aux $(, $param_name )* ),
)*
$call_type::__PhantomItem(_) => { panic!("__PhantomItem should never be used.") },
}
}
}
impl<$trait_instance: $trait_name> $crate::dispatch::AuxCallable
for $mod_type<$trait_instance>
{
type Call = $call_type<$trait_instance>;
}
};
}
#[macro_export]
/// Implement a single dispatch modules to create a pairing of a dispatch trait and enum.
macro_rules! __decl_dispatch_module_common {
(
impl for $mod_type:ident<$trait_instance:ident: $trait_name:ident>;
pub enum $call_type:ident;
$(
fn $fn_name:ident(
$(
$param_name:ident : $param:ty
),*
)
= $id:expr ;
)*
) => {
#[cfg_attr(feature = "std", derive(Serialize))]
#[allow(missing_docs)]
pub enum $call_type<$trait_instance: $trait_name> {
__PhantomItem($crate::dispatch::PhantomData<$trait_instance>),
$(
#[allow(non_camel_case_types)]
$fn_name ( $( $param ),* ),
)*
}
// manual implementation of clone/eq/partialeq because using derive erroneously requires
// clone/eq/partialeq from T.
impl<$trait_instance: $trait_name> $crate::dispatch::Clone
for $call_type<$trait_instance>
{
fn clone(&self) -> Self {
match *self {
$(
$call_type::$fn_name( $( ref $param_name ),* ) =>
$call_type::$fn_name( $( $param_name.clone() ),* )
,)*
$call_type::__PhantomItem(_) => unreachable!(),
}
}
}
impl<$trait_instance: $trait_name> $crate::dispatch::PartialEq
for $call_type<$trait_instance>
{
fn eq(&self, other: &Self) -> bool {
match *self {
$(
$call_type::$fn_name( $( ref $param_name ),* ) => {
let self_params = ( $( $param_name, )* );
if let $call_type::$fn_name( $( ref $param_name ),* ) = *other {
self_params == ( $( $param_name, )* )
} else {
if let $call_type::__PhantomItem(_) = *other {
unreachable!()
} else {
false
}
}
}
)*
$call_type::__PhantomItem(_) => unreachable!(),
}
}
}
impl<$trait_instance: $trait_name> $crate::dispatch::Eq
for $call_type<$trait_instance>
{}
#[cfg(feature = "std")]
impl<$trait_instance: $trait_name> $crate::dispatch::fmt::Debug
for $call_type<$trait_instance>
{
fn fmt(&self, f: &mut $crate::dispatch::fmt::Formatter) -> Result<(), $crate::dispatch::fmt::Error> {
match *self {
$(
$call_type::$fn_name( $( ref $param_name ),* ) =>
write!(f, "{}{:?}",
stringify!($fn_name),
( $( $param_name.clone(), )* )
)
,)*
$call_type::__PhantomItem(_) => unreachable!(),
}
}
}
impl<$trait_instance: $trait_name> $crate::dispatch::Slicable for $call_type<$trait_instance> {
fn decode<I: $crate::dispatch::Input>(input: &mut I) -> Option<Self> {
match input.read_byte()? {
$(
$id => {
$(
let $param_name = $crate::dispatch::Slicable::decode(input)?;
)*
Some($call_type:: $fn_name( $( $param_name ),* ))
}
)*
_ => None,
}
}
fn encode(&self) -> $crate::dispatch::Vec<u8> {
let mut v = $crate::dispatch::Vec::new();
match *self {
$(
$call_type::$fn_name(
$(
ref $param_name
),*
) => {
v.push($id as u8);
$(
$param_name.using_encoded(|s| v.extend(s));
)*
}
)*
$call_type::__PhantomItem(_) => unreachable!(),
}
v
}
fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
f(self.encode().as_slice())
}
}
}
}
pub trait IsSubType<T: Callable> {
fn is_sub_type(&self) -> Option<&<T as Callable>::Call>;
}
pub trait IsAuxSubType<T: AuxCallable> {
fn is_aux_sub_type(&self) -> Option<&<T as AuxCallable>::Call>;
}
/// Implement a meta-dispatch module to dispatch to other dispatchers.
#[macro_export]
macro_rules! impl_outer_dispatch {
() => ();
(
pub enum $call_type:ident where aux: $aux:ty {
$(
$camelcase:ident = $id:expr,
)*
}
$( $rest:tt )*
) => {
#[derive(Clone, PartialEq, Eq)]
#[cfg_attr(feature = "std", derive(Serialize, Debug))]
#[allow(missing_docs)]
pub enum $call_type {
$(
$camelcase ( <$camelcase as $crate::dispatch::AuxCallable>::Call )
,)*
}
impl_outer_dispatch_common! { $call_type, $($camelcase = $id,)* }
impl $crate::dispatch::AuxDispatchable for $call_type {
type Aux = $aux;
type Trait = $call_type;
fn dispatch(self, aux: &$aux) {
match self {
$(
$call_type::$camelcase(call) => call.dispatch(&aux),
)*
}
}
}
$(
impl $crate::dispatch::IsAuxSubType<$camelcase> for $call_type {
fn is_aux_sub_type(&self) -> Option<&<$camelcase as $crate::dispatch::AuxCallable>::Call> {
if let $call_type::$camelcase ( ref r ) = *self {
Some(r)
} else {
None
}
}
}
)*
impl_outer_dispatch!{ $($rest)* }
};
(
pub enum $call_type:ident {
$(
$camelcase:ident = $id:expr,
)*
}
$( $rest:tt )*
) => {
#[derive(Clone, PartialEq, Eq)]
#[cfg_attr(feature = "std", derive(Serialize, Debug))]
#[allow(missing_docs)]
pub enum $call_type {
$(
$camelcase ( <$camelcase as $crate::dispatch::Callable>::Call )
,)*
}
impl_outer_dispatch_common! { $call_type, $($camelcase = $id,)* }
impl $crate::dispatch::Dispatchable for $call_type {
type Trait = $call_type;
fn dispatch(self) {
match self {
$(
$call_type::$camelcase(call) => call.dispatch(),
)*
}
}
}
$(
impl $crate::dispatch::IsSubType<$camelcase> for $call_type {
fn is_sub_type(&self) -> Option<&<$camelcase as $crate::dispatch::Callable>::Call> {
if let $call_type::$camelcase ( ref r ) = *self {
Some(r)
} else {
None
}
}
}
)*
impl_outer_dispatch!{ $($rest)* }
}
}
/// Implement a meta-dispatch module to dispatch to other dispatchers.
#[macro_export]
macro_rules! impl_outer_dispatch_common {
(
$call_type:ident, $( $camelcase:ident = $id:expr, )*
) => {
impl $crate::dispatch::Slicable for $call_type {
fn decode<I: $crate::dispatch::Input>(input: &mut I) -> Option<Self> {
match input.read_byte()? {
$(
$id =>
Some($call_type::$camelcase( $crate::dispatch::Slicable::decode(input)? )),
)*
_ => None,
}
}
fn encode(&self) -> $crate::dispatch::Vec<u8> {
let mut v = $crate::dispatch::Vec::new();
match *self {
$(
$call_type::$camelcase( ref sub ) => {
v.push($id as u8);
sub.using_encoded(|s| v.extend(s));
}
)*
}
v
}
fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
f(self.encode().as_slice())
}
}
}
}
@@ -18,6 +18,16 @@
#![cfg_attr(not(feature = "std"), no_std)]
#[cfg(feature = "std")]
extern crate serde;
#[cfg(feature = "std")]
#[allow(unused_imports)] #[macro_use] // can be removed when fixed: https://github.com/rust-lang/rust/issues/43497
extern crate serde_derive;
#[cfg(feature = "std")]
pub use serde_derive::*;
extern crate substrate_runtime_std as rstd;
extern crate substrate_runtime_io as runtime_io;
extern crate substrate_primitives as primitives;
@@ -26,8 +36,10 @@ extern crate substrate_primitives as primitives;
pub extern crate substrate_codec as codec;
pub use self::storage::generator::Storage as GenericStorage;
pub mod dispatch;
pub mod storage;
mod hashable;
pub use self::storage::{StorageVec, StorageList, StorageValue, StorageMap};
pub use self::hashable::Hashable;
pub use self::dispatch::{Parameter, Dispatchable, Callable, AuxDispatchable, AuxCallable, IsSubType, IsAuxSubType};
@@ -50,6 +50,8 @@ use codec;
use rstd::vec::Vec;
#[doc(hidden)]
pub use rstd::borrow::Borrow;
#[doc(hidden)]
pub use rstd::marker::PhantomData;
/// Abstraction around storage.
pub trait Storage {
@@ -384,52 +386,52 @@ macro_rules! storage_items {
};
// maps
($name:ident : $prefix:expr => map [$kty: ty => $ty:ty]; $($t:tt)*) => {
($name:ident : $prefix:expr => map [$kty:ty => $ty:ty]; $($t:tt)*) => {
__storage_items_internal!(() () (Option<$ty>) (get) (take) $name: $prefix => map [$kty => $ty]);
storage_items!($($t)*);
};
(pub $name:ident : $prefix:expr => map [$kty: ty => $ty:ty]; $($t:tt)*) => {
(pub $name:ident : $prefix:expr => map [$kty:ty => $ty:ty]; $($t:tt)*) => {
__storage_items_internal!((pub) () (Option<$ty>) (get) (take) $name: $prefix => map [$kty => $ty]);
storage_items!($($t)*);
};
($name:ident : $prefix:expr => default map [$kty: ty => $ty:ty]; $($t:tt)*) => {
($name:ident : $prefix:expr => default map [$kty:ty => $ty:ty]; $($t:tt)*) => {
__storage_items_internal!(() () ($ty) (get_or_default) (take_or_default) $name: $prefix => map [$kty => $ty]);
storage_items!($($t)*);
};
(pub $name:ident : $prefix:expr => default map [$kty: ty => $ty:ty]; $($t:tt)*) => {
(pub $name:ident : $prefix:expr => default map [$kty:ty => $ty:ty]; $($t:tt)*) => {
__storage_items_internal!((pub) () ($ty) (get_or_default) (take_or_default) $name: $prefix => map [$kty => $ty]);
storage_items!($($t)*);
};
($name:ident : $prefix:expr => required map [$kty: ty => $ty:ty]; $($t:tt)*) => {
($name:ident : $prefix:expr => required map [$kty:ty => $ty:ty]; $($t:tt)*) => {
__storage_items_internal!(() () ($ty) (require) (take_or_panic) $name: $prefix => map [$kty => $ty]);
storage_items!($($t)*);
};
(pub $name:ident : $prefix:expr => required map [$kty: ty => $ty:ty]; $($t:tt)*) => {
(pub $name:ident : $prefix:expr => required map [$kty:ty => $ty:ty]; $($t:tt)*) => {
__storage_items_internal!((pub) () ($ty) (require) (take_or_panic) $name: $prefix => map [$kty => $ty]);
storage_items!($($t)*);
};
($name:ident get($getfn:ident) : $prefix:expr => map [$kty: ty => $ty:ty]; $($t:tt)*) => {
($name:ident get($getfn:ident) : $prefix:expr => map [$kty:ty => $ty:ty]; $($t:tt)*) => {
__storage_items_internal!(() ($getfn) (Option<$ty>) (get) (take) $name: $prefix => map [$kty => $ty]);
storage_items!($($t)*);
};
(pub $name:ident get($getfn:ident) : $prefix:expr => map [$kty: ty => $ty:ty]; $($t:tt)*) => {
(pub $name:ident get($getfn:ident) : $prefix:expr => map [$kty:ty => $ty:ty]; $($t:tt)*) => {
__storage_items_internal!((pub) ($getfn) (Option<$ty>) (get) (take) $name: $prefix => map [$kty => $ty]);
storage_items!($($t)*);
};
($name:ident get($getfn:ident) : $prefix:expr => default map [$kty: ty => $ty:ty]; $($t:tt)*) => {
($name:ident get($getfn:ident) : $prefix:expr => default map [$kty:ty => $ty:ty]; $($t:tt)*) => {
__storage_items_internal!(() ($getfn) ($ty) (get_or_default) (take_or_default) $name: $prefix => map [$kty => $ty]);
storage_items!($($t)*);
};
(pub $name:ident get($getfn:ident) : $prefix:expr => default map [$kty: ty => $ty:ty]; $($t:tt)*) => {
(pub $name:ident get($getfn:ident) : $prefix:expr => default map [$kty:ty => $ty:ty]; $($t:tt)*) => {
__storage_items_internal!((pub) ($getfn) ($ty) (get_or_default) (take_or_default) $name: $prefix => map [$kty => $ty]);
storage_items!($($t)*);
};
($name:ident get($getfn:ident) : $prefix:expr => required map [$kty: ty => $ty:ty]; $($t:tt)*) => {
($name:ident get($getfn:ident) : $prefix:expr => required map [$kty:ty => $ty:ty]; $($t:tt)*) => {
__storage_items_internal!(() ($getfn) ($ty) (require) (take_or_panic) $name: $prefix => map [$kty => $ty]);
storage_items!($($t)*);
};
(pub $name:ident get($getfn:ident) : $prefix:expr => required map [$kty: ty => $ty:ty]; $($t:tt)*) => {
(pub $name:ident get($getfn:ident) : $prefix:expr => required map [$kty:ty => $ty:ty]; $($t:tt)*) => {
__storage_items_internal!((pub) ($getfn) ($ty) (require) (take_or_panic) $name: $prefix => map [$kty => $ty]);
storage_items!($($t)*);
};
@@ -447,6 +449,544 @@ macro_rules! storage_items {
() => ()
}
#[macro_export]
#[doc(hidden)]
macro_rules! __decl_storage_item {
// generator for values.
(($($vis:tt)*) ($traittype:ident as $traitinstance:ident) ($get_fn:ident) ($gettype:ty) ($getter:ident) ($taker:ident) $name:ident : $key:expr => $ty:ty) => {
__decl_storage_item!{ ($($vis)*) ($traittype as $traitinstance) () ($gettype) ($getter) ($taker) $name : $key => $ty }
};
(($($vis:tt)*) ($traittype:ident as $traitinstance:ident) () ($gettype:ty) ($getter:ident) ($taker:ident) $name:ident : $key:expr => $ty:ty) => {
$($vis)* struct $name<$traitinstance: $traittype>($crate::storage::generator::PhantomData<$traitinstance>);
impl<$traitinstance: $traittype> $crate::storage::generator::StorageValue<$ty> for $name<$traitinstance> {
type Query = $gettype;
/// Get the storage key.
fn key() -> &'static [u8] {
$key
}
/// Load the value from the provided storage instance.
fn get<S: $crate::GenericStorage>(storage: &S) -> Self::Query {
storage.$getter($key)
}
/// Take a value from storage, removing it afterwards.
fn take<S: $crate::GenericStorage>(storage: &S) -> Self::Query {
storage.$taker($key)
}
}
};
// generator for maps.
(($($vis:tt)*) ($traittype:ident as $traitinstance:ident) ($get_fn:ident) ($gettype:ty) ($getter:ident) ($taker:ident) $name:ident : $prefix:expr => map [$kty:ty => $ty:ty]) => {
__decl_storage_item!{ ($($vis)*) ($traittype as $traitinstance) () ($gettype) ($getter) ($taker) $name : $prefix => map [$kty => $ty] }
};
(($($vis:tt)*) ($traittype:ident as $traitinstance:ident) () ($gettype:ty) ($getter:ident) ($taker:ident) $name:ident : $prefix:expr => map [$kty:ty => $ty:ty]) => {
$($vis)* struct $name<$traitinstance: $traittype>($crate::storage::generator::PhantomData<$traitinstance>);
impl<$traitinstance: $traittype> $crate::storage::generator::StorageMap<$kty, $ty> for $name<$traitinstance> {
type Query = $gettype;
/// Get the prefix key in storage.
fn prefix() -> &'static [u8] {
$prefix
}
/// Get the storage key used to fetch a value corresponding to a specific key.
fn key_for(x: &$kty) -> Vec<u8> {
let mut key = $prefix.to_vec();
key.extend($crate::codec::Slicable::encode(x));
key
}
/// Load the value associated with the given key from the map.
fn get<S: $crate::GenericStorage>(key: &$kty, storage: &S) -> Self::Query {
let key = <$name<$traitinstance> as $crate::storage::generator::StorageMap<$kty, $ty>>::key_for(key);
storage.$getter(&key[..])
}
/// Take the value, reading and removing it.
fn take<S: $crate::GenericStorage>(key: &$kty, storage: &S) -> Self::Query {
let key = <$name<$traitinstance> as $crate::storage::generator::StorageMap<$kty, $ty>>::key_for(key);
storage.$taker(&key[..])
}
}
};
}
// TODO: revisit this idiom once we get `type`s in `impl`s.
/*impl<T: Trait> Module<T> {
type Now = super::Now<T>;
}*/
/// Declares strongly-typed wrappers around codec-compatible types in storage.
///
/// For now we implement a convenience trait with pre-specialised associated types, one for each
/// storage item. This allows you to gain access to publicly visisible storage items from a
/// module type. Currently you must disambiguate by using `<Module as Store>::Item` rather than
/// the simpler `Module::Item`. Hopefully the rust guys with fix this soon.
#[macro_export]
macro_rules! decl_storage {
(
trait $storetype:ident for $modulename:ident<$traitinstance:ident: $traittype:ident>;
$($t:tt)*
) => {
__decl_storage_items!($traittype $traitinstance $($t)*);
trait $storetype {
__decl_store_items!($($t)*);
}
impl<$traitinstance: $traittype> $storetype for $modulename<$traitinstance> {
__impl_store_items!($traitinstance $($t)*);
}
impl<$traitinstance: $traittype> $modulename<$traitinstance> {
__impl_store_fns!($traitinstance $($t)*);
}
};
(
pub trait $storetype:ident for $modulename:ident<$traitinstance:ident: $traittype:ident>;
$($t:tt)*
) => {
__decl_storage_items!($traittype $traitinstance $($t)*);
pub trait $storetype {
__decl_store_items!($($t)*);
}
impl<$traitinstance: $traittype> $storetype for $modulename<$traitinstance> {
__impl_store_items!($traitinstance $($t)*);
}
impl<$traitinstance: $traittype> $modulename<$traitinstance> {
__impl_store_fns!($traitinstance $($t)*);
}
}
}
#[macro_export]
#[doc(hidden)]
macro_rules! __decl_store_item {
($name:ident) => { type $name; }
}
#[macro_export]
#[doc(hidden)]
macro_rules! __decl_store_items {
// simple values
($name:ident : $key:expr => $ty:ty; $($t:tt)*) => {
__decl_store_item!($name); __decl_store_items!($($t)*);
};
(pub $name:ident : $key:expr => $ty:ty; $($t:tt)*) => {
__decl_store_item!($name); __decl_store_items!($($t)*);
};
($name:ident : $key:expr => default $ty:ty; $($t:tt)*) => {
__decl_store_item!($name); __decl_store_items!($($t)*);
};
(pub $name:ident : $key:expr => default $ty:ty; $($t:tt)*) => {
__decl_store_item!($name); __decl_store_items!($($t)*);
};
($name:ident : $key:expr => required $ty:ty; $($t:tt)*) => {
__decl_store_item!($name); __decl_store_items!($($t)*);
};
(pub $name:ident : $key:expr => required $ty:ty; $($t:tt)*) => {
__decl_store_item!($name); __decl_store_items!($($t)*);
};
($name:ident get($getfn:ident) : $key:expr => $ty:ty; $($t:tt)*) => {
__decl_store_item!($name); __decl_store_items!($($t)*);
};
(pub $name:ident get($getfn:ident) : $key:expr => $ty:ty; $($t:tt)*) => {
__decl_store_item!($name); __decl_store_items!($($t)*);
};
($name:ident get($getfn:ident) : $key:expr => default $ty:ty; $($t:tt)*) => {
__decl_store_item!($name); __decl_store_items!($($t)*);
};
(pub $name:ident get($getfn:ident) : $key:expr => default $ty:ty; $($t:tt)*) => {
__decl_store_item!($name); __decl_store_items!($($t)*);
};
($name:ident get($getfn:ident) : $key:expr => required $ty:ty; $($t:tt)*) => {
__decl_store_item!($name); __decl_store_items!($($t)*);
};
(pub $name:ident get($getfn:ident) : $key:expr => required $ty:ty; $($t:tt)*) => {
__decl_store_item!($name); __decl_store_items!($($t)*);
};
// maps
($name:ident : $prefix:expr => map [$kty:ty => $ty:ty]; $($t:tt)*) => {
__decl_store_item!($name); __decl_store_items!($($t)*);
};
(pub $name:ident : $prefix:expr => map [$kty:ty => $ty:ty]; $($t:tt)*) => {
__decl_store_item!($name); __decl_store_items!($($t)*);
};
($name:ident : $prefix:expr => default map [$kty:ty => $ty:ty]; $($t:tt)*) => {
__decl_store_item!($name); __decl_store_items!($($t)*);
};
(pub $name:ident : $prefix:expr => default map [$kty:ty => $ty:ty]; $($t:tt)*) => {
__decl_store_item!($name); __decl_store_items!($($t)*);
};
($name:ident : $prefix:expr => required map [$kty:ty => $ty:ty]; $($t:tt)*) => {
__decl_store_item!($name); __decl_store_items!($($t)*);
};
(pub $name:ident : $prefix:expr => required map [$kty:ty => $ty:ty]; $($t:tt)*) => {
__decl_store_item!($name); __decl_store_items!($($t)*);
};
($name:ident get($getfn:ident) : $prefix:expr => map [$kty:ty => $ty:ty]; $($t:tt)*) => {
__decl_store_item!($name); __decl_store_items!($($t)*);
};
(pub $name:ident get($getfn:ident) : $prefix:expr => map [$kty:ty => $ty:ty]; $($t:tt)*) => {
__decl_store_item!($name); __decl_store_items!($($t)*);
};
($name:ident get($getfn:ident) : $prefix:expr => default map [$kty:ty => $ty:ty]; $($t:tt)*) => {
__decl_store_item!($name); __decl_store_items!($($t)*);
};
(pub $name:ident get($getfn:ident) : $prefix:expr => default map [$kty:ty => $ty:ty]; $($t:tt)*) => {
__decl_store_item!($name); __decl_store_items!($($t)*);
};
($name:ident get($getfn:ident) : $prefix:expr => required map [$kty:ty => $ty:ty]; $($t:tt)*) => {
__decl_store_item!($name); __decl_store_items!($($t)*);
};
(pub $name:ident get($getfn:ident) : $prefix:expr => required map [$kty:ty => $ty:ty]; $($t:tt)*) => {
__decl_store_item!($name); __decl_store_items!($($t)*);
};
// exit
() => ()
}
#[macro_export]
#[doc(hidden)]
macro_rules! __impl_store_fn {
($traitinstance:ident $name:ident $get_fn:ident ($gettype:ty) $key:expr => $ty:ty) => {
pub fn $get_fn() -> $gettype {
<$name<$traitinstance> as $crate::storage::generator::StorageValue<$ty>> :: get(&$crate::storage::RuntimeStorage)
}
};
($traitinstance:ident $name:ident $get_fn:ident ($gettype:ty) $prefix:expr => map [$kty:ty => $ty:ty]) => {
pub fn $get_fn<K: $crate::storage::generator::Borrow<$kty>>(key: K) -> $gettype {
<$name<$traitinstance> as $crate::storage::generator::StorageMap<$kty, $ty>> :: get(key.borrow(), &$crate::storage::RuntimeStorage)
}
}
}
#[macro_export]
#[doc(hidden)]
macro_rules! __impl_store_fns {
// simple values
($traitinstance:ident $name:ident : $key:expr => $ty:ty; $($t:tt)*) => {
__impl_store_fns!($traitinstance $($t)*);
};
($traitinstance:ident pub $name:ident : $key:expr => $ty:ty; $($t:tt)*) => {
__impl_store_fns!($traitinstance $($t)*);
};
($traitinstance:ident $name:ident : $key:expr => default $ty:ty; $($t:tt)*) => {
__impl_store_fns!($traitinstance $($t)*);
};
($traitinstance:ident pub $name:ident : $key:expr => default $ty:ty; $($t:tt)*) => {
__impl_store_fns!($traitinstance $($t)*);
};
($traitinstance:ident $name:ident : $key:expr => required $ty:ty; $($t:tt)*) => {
__impl_store_fns!($traitinstance $($t)*);
};
($traitinstance:ident pub $name:ident : $key:expr => required $ty:ty; $($t:tt)*) => {
__impl_store_fns!($traitinstance $($t)*);
};
($traitinstance:ident $name:ident get($getfn:ident) : $key:expr => $ty:ty; $($t:tt)*) => {
__impl_store_fn!($traitinstance $name $getfn (Option<$ty>) $gettype $key => $ty);
__impl_store_fns!($traitinstance $($t)*);
};
($traitinstance:ident pub $name:ident get($getfn:ident) : $key:expr => $ty:ty; $($t:tt)*) => {
__impl_store_fn!($traitinstance $name $getfn (Option<$ty>) $key => $ty);
__impl_store_fns!($traitinstance $($t)*);
};
($traitinstance:ident $name:ident get($getfn:ident) : $key:expr => default $ty:ty; $($t:tt)*) => {
__impl_store_fn!($traitinstance $name $getfn ($ty) $key => $ty);
__impl_store_fns!($traitinstance $($t)*);
};
($traitinstance:ident pub $name:ident get($getfn:ident) : $key:expr => default $ty:ty; $($t:tt)*) => {
__impl_store_fn!($traitinstance $name $getfn ($ty) $key => $ty);
__impl_store_fns!($traitinstance $($t)*);
};
($traitinstance:ident $name:ident get($getfn:ident) : $key:expr => required $ty:ty; $($t:tt)*) => {
__impl_store_fn!($traitinstance $name $getfn ($ty) $key => $ty);
__impl_store_fns!($traitinstance $($t)*);
};
($traitinstance:ident pub $name:ident get($getfn:ident) : $key:expr => required $ty:ty; $($t:tt)*) => {
__impl_store_fn!($traitinstance $name $getfn ($ty) $key => $ty);
__impl_store_fns!($traitinstance $($t)*);
};
// maps
($traitinstance:ident $name:ident : $prefix:expr => map [$kty:ty => $ty:ty]; $($t:tt)*) => {
__impl_store_fns!($traitinstance $($t)*);
};
($traitinstance:ident pub $name:ident : $prefix:expr => map [$kty:ty => $ty:ty]; $($t:tt)*) => {
__impl_store_fns!($traitinstance $($t)*);
};
($traitinstance:ident $name:ident : $prefix:expr => default map [$kty:ty => $ty:ty]; $($t:tt)*) => {
__impl_store_fns!($traitinstance $($t)*);
};
($traitinstance:ident pub $name:ident : $prefix:expr => default map [$kty:ty => $ty:ty]; $($t:tt)*) => {
__impl_store_fns!($traitinstance $($t)*);
};
($traitinstance:ident $name:ident : $prefix:expr => required map [$kty:ty => $ty:ty]; $($t:tt)*) => {
__impl_store_fns!($traitinstance $($t)*);
};
($traitinstance:ident pub $name:ident : $prefix:expr => required map [$kty:ty => $ty:ty]; $($t:tt)*) => {
__impl_store_fns!($traitinstance $($t)*);
};
($traitinstance:ident $name:ident get($getfn:ident) : $prefix:expr => map [$kty:ty => $ty:ty]; $($t:tt)*) => {
__impl_store_fn!($traitinstance $name $getfn (Option<$ty>) $prefix:expr => map [$kty => $ty]);
__impl_store_fns!($traitinstance $($t)*);
};
($traitinstance:ident pub $name:ident get($getfn:ident) : $prefix:expr => map [$kty:ty => $ty:ty]; $($t:tt)*) => {
__impl_store_fn!($traitinstance $name $getfn (Option<$ty>) $prefix:expr => map [$kty => $ty]);
__impl_store_fns!($traitinstance $($t)*);
};
($traitinstance:ident $name:ident get($getfn:ident) : $prefix:expr => default map [$kty:ty => $ty:ty]; $($t:tt)*) => {
__impl_store_fn!($traitinstance $name $getfn ($ty) $prefix:expr => map [$kty => $ty]);
__impl_store_fns!($traitinstance $($t)*);
};
($traitinstance:ident pub $name:ident get($getfn:ident) : $prefix:expr => default map [$kty:ty => $ty:ty]; $($t:tt)*) => {
__impl_store_fn!($traitinstance $name $getfn ($ty) $prefix:expr => map [$kty => $ty]);
__impl_store_fns!($traitinstance $($t)*);
};
($traitinstance:ident $name:ident get($getfn:ident) : $prefix:expr => required map [$kty:ty => $ty:ty]; $($t:tt)*) => {
__impl_store_fn!($traitinstance $name $getfn ($ty) $prefix:expr => map [$kty => $ty]);
__impl_store_fns!($traitinstance $($t)*);
};
($traitinstance:ident pub $name:ident get($getfn:ident) : $prefix:expr => required map [$kty:ty => $ty:ty]; $($t:tt)*) => {
__impl_store_fn!($traitinstance $name $getfn ($ty) $prefix:expr => map [$kty => $ty]);
__impl_store_fns!($traitinstance $($t)*);
};
// exit
($traitinstance:ident) => ()
}
#[macro_export]
#[doc(hidden)]
macro_rules! __impl_store_item {
($name:ident $traitinstance:ident) => { type $name = $name<$traitinstance>; }
}
#[macro_export]
#[doc(hidden)]
macro_rules! __impl_store_items {
// simple values
($traitinstance:ident $name:ident : $key:expr => $ty:ty; $($t:tt)*) => {
__impl_store_item!($name $traitinstance);
__impl_store_items!($traitinstance $($t)*);
};
($traitinstance:ident pub $name:ident : $key:expr => $ty:ty; $($t:tt)*) => {
__impl_store_item!($name $traitinstance);
__impl_store_items!($traitinstance $($t)*);
};
($traitinstance:ident $name:ident : $key:expr => default $ty:ty; $($t:tt)*) => {
__impl_store_item!($name $traitinstance);
__impl_store_items!($traitinstance $($t)*);
};
($traitinstance:ident pub $name:ident : $key:expr => default $ty:ty; $($t:tt)*) => {
__impl_store_item!($name $traitinstance);
__impl_store_items!($traitinstance $($t)*);
};
($traitinstance:ident $name:ident : $key:expr => required $ty:ty; $($t:tt)*) => {
__impl_store_item!($name $traitinstance);
__impl_store_items!($traitinstance $($t)*);
};
($traitinstance:ident pub $name:ident : $key:expr => required $ty:ty; $($t:tt)*) => {
__impl_store_item!($name $traitinstance);
__impl_store_items!($traitinstance $($t)*);
};
($traitinstance:ident $name:ident get($getfn:ident) : $key:expr => $ty:ty; $($t:tt)*) => {
__impl_store_item!($name $traitinstance);
__impl_store_items!($traitinstance $($t)*);
};
($traitinstance:ident pub $name:ident get($getfn:ident) : $key:expr => $ty:ty; $($t:tt)*) => {
__impl_store_item!($name $traitinstance);
__impl_store_items!($traitinstance $($t)*);
};
($traitinstance:ident $name:ident get($getfn:ident) : $key:expr => default $ty:ty; $($t:tt)*) => {
__impl_store_item!($name $traitinstance);
__impl_store_items!($traitinstance $($t)*);
};
($traitinstance:ident pub $name:ident get($getfn:ident) : $key:expr => default $ty:ty; $($t:tt)*) => {
__impl_store_item!($name $traitinstance);
__impl_store_items!($traitinstance $($t)*);
};
($traitinstance:ident $name:ident get($getfn:ident) : $key:expr => required $ty:ty; $($t:tt)*) => {
__impl_store_item!($name $traitinstance);
__impl_store_items!($traitinstance $($t)*);
};
($traitinstance:ident pub $name:ident get($getfn:ident) : $key:expr => required $ty:ty; $($t:tt)*) => {
__impl_store_item!($name $traitinstance);
__impl_store_items!($traitinstance $($t)*);
};
// maps
($traitinstance:ident $name:ident : $prefix:expr => map [$kty:ty => $ty:ty]; $($t:tt)*) => {
__impl_store_item!($name $traitinstance);
__impl_store_items!($traitinstance $($t)*);
};
($traitinstance:ident pub $name:ident : $prefix:expr => map [$kty:ty => $ty:ty]; $($t:tt)*) => {
__impl_store_item!($name $traitinstance);
__impl_store_items!($traitinstance $($t)*);
};
($traitinstance:ident $name:ident : $prefix:expr => default map [$kty:ty => $ty:ty]; $($t:tt)*) => {
__impl_store_item!($name $traitinstance);
__impl_store_items!($traitinstance $($t)*);
};
($traitinstance:ident pub $name:ident : $prefix:expr => default map [$kty:ty => $ty:ty]; $($t:tt)*) => {
__impl_store_item!($name $traitinstance);
__impl_store_items!($traitinstance $($t)*);
};
($traitinstance:ident $name:ident : $prefix:expr => required map [$kty:ty => $ty:ty]; $($t:tt)*) => {
__impl_store_item!($name $traitinstance);
__impl_store_items!($traitinstance $($t)*);
};
($traitinstance:ident pub $name:ident : $prefix:expr => required map [$kty:ty => $ty:ty]; $($t:tt)*) => {
__impl_store_item!($name $traitinstance);
__impl_store_items!($traitinstance $($t)*);
};
($traitinstance:ident $name:ident get($getfn:ident) : $prefix:expr => map [$kty:ty => $ty:ty]; $($t:tt)*) => {
__impl_store_item!($name $traitinstance);
__impl_store_items!($traitinstance $($t)*);
};
($traitinstance:ident pub $name:ident get($getfn:ident) : $prefix:expr => map [$kty:ty => $ty:ty]; $($t:tt)*) => {
__impl_store_item!($name $traitinstance);
__impl_store_items!($traitinstance $($t)*);
};
($traitinstance:ident $name:ident get($getfn:ident) : $prefix:expr => default map [$kty:ty => $ty:ty]; $($t:tt)*) => {
__impl_store_item!($name $traitinstance);
__impl_store_items!($traitinstance $($t)*);
};
($traitinstance:ident pub $name:ident get($getfn:ident) : $prefix:expr => default map [$kty:ty => $ty:ty]; $($t:tt)*) => {
__impl_store_item!($name $traitinstance);
__impl_store_items!($traitinstance $($t)*);
};
($traitinstance:ident $name:ident get($getfn:ident) : $prefix:expr => required map [$kty:ty => $ty:ty]; $($t:tt)*) => {
__impl_store_item!($name $traitinstance);
__impl_store_items!($traitinstance $($t)*);
};
($traitinstance:ident pub $name:ident get($getfn:ident) : $prefix:expr => required map [$kty:ty => $ty:ty]; $($t:tt)*) => {
__impl_store_item!($name $traitinstance);
__impl_store_items!($traitinstance $($t)*);
};
// exit
($traitinstance:ident) => ()
}
#[macro_export]
#[doc(hidden)]
macro_rules! __decl_storage_items {
// simple values
($traittype:ident $traitinstance:ident $name:ident : $key:expr => $ty:ty; $($t:tt)*) => {
__decl_storage_item!(() ($traittype as $traitinstance) () (Option<$ty>) (get) (take) $name: $key => $ty);
__decl_storage_items!($traittype $traitinstance $($t)*);
};
($traittype:ident $traitinstance:ident pub $name:ident : $key:expr => $ty:ty; $($t:tt)*) => {
__decl_storage_item!((pub) ($traittype as $traitinstance) () (Option<$ty>) (get) (take) $name: $key => $ty);
__decl_storage_items!($traittype $traitinstance $($t)*);
};
($traittype:ident $traitinstance:ident $name:ident : $key:expr => default $ty:ty; $($t:tt)*) => {
__decl_storage_item!(() ($traittype as $traitinstance) () ($ty) (get_or_default) (take_or_default) $name: $key => $ty);
__decl_storage_items!($traittype $traitinstance $($t)*);
};
($traittype:ident $traitinstance:ident pub $name:ident : $key:expr => default $ty:ty; $($t:tt)*) => {
__decl_storage_item!((pub) ($traittype as $traitinstance) () ($ty) (get_or_default) (take_or_default) $name: $key => $ty);
__decl_storage_items!($traittype $traitinstance $($t)*);
};
($traittype:ident $traitinstance:ident $name:ident : $key:expr => required $ty:ty; $($t:tt)*) => {
__decl_storage_item!(() ($traittype as $traitinstance) () ($ty) (require) (take_or_panic) $name: $key => $ty);
__decl_storage_items!($traittype $traitinstance $($t)*);
};
($traittype:ident $traitinstance:ident pub $name:ident : $key:expr => required $ty:ty; $($t:tt)*) => {
__decl_storage_item!((pub) ($traittype as $traitinstance) () ($ty) (require) (take_or_panic) $name: $key => $ty);
__decl_storage_items!($traittype $traitinstance $($t)*);
};
($traittype:ident $traitinstance:ident $name:ident get($getfn:ident) : $key:expr => $ty:ty; $($t:tt)*) => {
__decl_storage_item!(() ($traittype as $traitinstance) ($getfn) (Option<$ty>) (get) (take) $name: $key => $ty);
__decl_storage_items!($traittype $traitinstance $($t)*);
};
($traittype:ident $traitinstance:ident pub $name:ident get($getfn:ident) : $key:expr => $ty:ty; $($t:tt)*) => {
__decl_storage_item!((pub) ($traittype as $traitinstance) ($getfn) (Option<$ty>) (get) (take) $name: $key => $ty);
__decl_storage_items!($traittype $traitinstance $($t)*);
};
($traittype:ident $traitinstance:ident $name:ident get($getfn:ident) : $key:expr => default $ty:ty; $($t:tt)*) => {
__decl_storage_item!(() ($traittype as $traitinstance) ($getfn) ($ty) (get_or_default) (take_or_default) $name: $key => $ty);
__decl_storage_items!($traittype $traitinstance $($t)*);
};
($traittype:ident $traitinstance:ident pub $name:ident get($getfn:ident) : $key:expr => default $ty:ty; $($t:tt)*) => {
__decl_storage_item!((pub) ($traittype as $traitinstance) ($getfn) ($ty) (get_or_default) (take_or_default) $name: $key => $ty);
__decl_storage_items!($traittype $traitinstance $($t)*);
};
($traittype:ident $traitinstance:ident $name:ident get($getfn:ident) : $key:expr => required $ty:ty; $($t:tt)*) => {
__decl_storage_item!(() ($traittype as $traitinstance) ($getfn) ($ty) (require) (take_or_panic) $name: $key => $ty);
__decl_storage_items!($traittype $traitinstance $($t)*);
};
($traittype:ident $traitinstance:ident pub $name:ident get($getfn:ident) : $key:expr => required $ty:ty; $($t:tt)*) => {
__decl_storage_item!((pub) ($traittype as $traitinstance) ($getfn) ($ty) (require) (take_or_panic) $name: $key => $ty);
__decl_storage_items!($traittype $traitinstance $($t)*);
};
// maps
($traittype:ident $traitinstance:ident $name:ident : $prefix:expr => map [$kty:ty => $ty:ty]; $($t:tt)*) => {
__decl_storage_item!(() ($traittype as $traitinstance) () (Option<$ty>) (get) (take) $name: $prefix => map [$kty => $ty]);
__decl_storage_items!($traittype $traitinstance $($t)*);
};
($traittype:ident $traitinstance:ident pub $name:ident : $prefix:expr => map [$kty:ty => $ty:ty]; $($t:tt)*) => {
__decl_storage_item!((pub) ($traittype as $traitinstance) () (Option<$ty>) (get) (take) $name: $prefix => map [$kty => $ty]);
__decl_storage_items!($traittype $traitinstance $($t)*);
};
($traittype:ident $traitinstance:ident $name:ident : $prefix:expr => default map [$kty:ty => $ty:ty]; $($t:tt)*) => {
__decl_storage_item!(() ($traittype as $traitinstance) () ($ty) (get_or_default) (take_or_default) $name: $prefix => map [$kty => $ty]);
__decl_storage_items!($traittype $traitinstance $($t)*);
};
($traittype:ident $traitinstance:ident pub $name:ident : $prefix:expr => default map [$kty:ty => $ty:ty]; $($t:tt)*) => {
__decl_storage_item!((pub) ($traittype as $traitinstance) () ($ty) (get_or_default) (take_or_default) $name: $prefix => map [$kty => $ty]);
__decl_storage_items!($traittype $traitinstance $($t)*);
};
($traittype:ident $traitinstance:ident $name:ident : $prefix:expr => required map [$kty:ty => $ty:ty]; $($t:tt)*) => {
__decl_storage_item!(() ($traittype as $traitinstance) () ($ty) (require) (take_or_panic) $name: $prefix => map [$kty => $ty]);
__decl_storage_items!($traittype $traitinstance $($t)*);
};
($traittype:ident $traitinstance:ident pub $name:ident : $prefix:expr => required map [$kty:ty => $ty:ty]; $($t:tt)*) => {
__decl_storage_item!((pub) ($traittype as $traitinstance) () ($ty) (require) (take_or_panic) $name: $prefix => map [$kty => $ty]);
__decl_storage_items!($traittype $traitinstance $($t)*);
};
($traittype:ident $traitinstance:ident $name:ident get($getfn:ident) : $prefix:expr => map [$kty:ty => $ty:ty]; $($t:tt)*) => {
__decl_storage_item!(() ($traittype as $traitinstance) ($getfn) (Option<$ty>) (get) (take) $name: $prefix => map [$kty => $ty]);
__decl_storage_items!($traittype $traitinstance $($t)*);
};
($traittype:ident $traitinstance:ident pub $name:ident get($getfn:ident) : $prefix:expr => map [$kty:ty => $ty:ty]; $($t:tt)*) => {
__decl_storage_item!((pub) ($traittype as $traitinstance) ($getfn) (Option<$ty>) (get) (take) $name: $prefix => map [$kty => $ty]);
__decl_storage_items!($traittype $traitinstance $($t)*);
};
($traittype:ident $traitinstance:ident $name:ident get($getfn:ident) : $prefix:expr => default map [$kty:ty => $ty:ty]; $($t:tt)*) => {
__decl_storage_item!(() ($traittype as $traitinstance) ($getfn) ($ty) (get_or_default) (take_or_default) $name: $prefix => map [$kty => $ty]);
__decl_storage_items!($traittype $traitinstance $($t)*);
};
($traittype:ident $traitinstance:ident pub $name:ident get($getfn:ident) : $prefix:expr => default map [$kty:ty => $ty:ty]; $($t:tt)*) => {
__decl_storage_item!((pub) ($traittype as $traitinstance) ($getfn) ($ty) (get_or_default) (take_or_default) $name: $prefix => map [$kty => $ty]);
__decl_storage_items!($traittype $traitinstance $($t)*);
};
($traittype:ident $traitinstance:ident $name:ident get($getfn:ident) : $prefix:expr => required map [$kty:ty => $ty:ty]; $($t:tt)*) => {
__decl_storage_item!(() ($traittype as $traitinstance) ($getfn) ($ty) (require) (take_or_panic) $name: $prefix => map [$kty => $ty]);
__decl_storage_items!($traittype $traitinstance $($t)*);
};
($traittype:ident $traitinstance:ident pub $name:ident get($getfn:ident) : $prefix:expr => required map [$kty:ty => $ty:ty]; $($t:tt)*) => {
__decl_storage_item!((pub) ($traittype as $traitinstance) ($getfn) ($ty) (require) (take_or_panic) $name: $prefix => map [$kty => $ty]);
__decl_storage_items!($traittype $traitinstance $($t)*);
};
// exit
($traittype:ident $traitinstance:ident) => ()
}
#[cfg(test)]
mod tests {
use std::collections::HashMap;