mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-07-02 17:37:23 +00:00
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:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user