mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-28 17:57:56 +00:00
Implement construct_runtime! macro (#751)
* Make `system` module renamable in `impl_outer_event!` * Implement `construct_runtime!` macro This macro generates code for calling all the common `impl_outer_*` macros. * Add documentation * Fixes wrong declaration of `contract` * Update dependencies to work on `no_std` * One more `Cargo.lock` update * Address comments
This commit is contained in:
@@ -273,6 +273,21 @@ macro_rules! impl_outer_event {
|
||||
(
|
||||
$(#[$attr:meta])*
|
||||
pub enum $name:ident for $runtime:ident {
|
||||
$( $rest:tt $( <$t:ident> )*, )*
|
||||
}
|
||||
) => {
|
||||
impl_outer_event!(
|
||||
$( #[$attr] )*;
|
||||
$name;
|
||||
$runtime;
|
||||
system;
|
||||
Modules { $( $rest $(<$t>)*, )* };
|
||||
;
|
||||
);
|
||||
};
|
||||
(
|
||||
$(#[$attr:meta])*
|
||||
pub enum $name:ident for $runtime:ident where system = $system:ident {
|
||||
$module:ident<T>,
|
||||
$( $rest:tt $( <$t:ident> )*, )*
|
||||
}
|
||||
@@ -281,13 +296,14 @@ macro_rules! impl_outer_event {
|
||||
$( #[$attr] )*;
|
||||
$name;
|
||||
$runtime;
|
||||
$system;
|
||||
Modules { $( $rest $(<$t>)*, )* };
|
||||
$module::Event<$runtime>,;
|
||||
);
|
||||
};
|
||||
(
|
||||
$(#[$attr:meta])*
|
||||
pub enum $name:ident for $runtime:ident {
|
||||
pub enum $name:ident for $runtime:ident where system = $system:ident {
|
||||
$module:ident,
|
||||
$( $rest:tt $( <$t:ident> )*, )*
|
||||
}
|
||||
@@ -296,6 +312,7 @@ macro_rules! impl_outer_event {
|
||||
$( #[$attr] )*;
|
||||
$name;
|
||||
$runtime;
|
||||
$system;
|
||||
Modules { $( $rest $(<$t>)*, )* };
|
||||
$module::Event,;
|
||||
);
|
||||
@@ -304,6 +321,7 @@ macro_rules! impl_outer_event {
|
||||
$(#[$attr:meta])*;
|
||||
$name:ident;
|
||||
$runtime:ident;
|
||||
$system:ident;
|
||||
Modules {
|
||||
$module:ident<T>,
|
||||
$( $rest:tt $( <$t:ident> )*, )*
|
||||
@@ -314,6 +332,7 @@ macro_rules! impl_outer_event {
|
||||
$( #[$attr] )*;
|
||||
$name;
|
||||
$runtime;
|
||||
$system;
|
||||
Modules { $( $rest $(<$t>)*, )* };
|
||||
$( $module_name::Event $( <$generic_param> )*, )* $module::Event<$runtime>,;
|
||||
);
|
||||
@@ -322,6 +341,7 @@ macro_rules! impl_outer_event {
|
||||
$(#[$attr:meta])*;
|
||||
$name:ident;
|
||||
$runtime:ident;
|
||||
$system:ident;
|
||||
Modules {
|
||||
$module:ident,
|
||||
$( $rest:tt, )*
|
||||
@@ -332,6 +352,7 @@ macro_rules! impl_outer_event {
|
||||
$( #[$attr] )*;
|
||||
$name;
|
||||
$runtime;
|
||||
$system;
|
||||
Modules { $( $rest, )* };
|
||||
$( $module_name::Event $( <$generic_param> )*, )* $module::Event,;
|
||||
);
|
||||
@@ -340,6 +361,7 @@ macro_rules! impl_outer_event {
|
||||
$(#[$attr:meta])*;
|
||||
$name:ident;
|
||||
$runtime:ident;
|
||||
$system:ident;
|
||||
Modules {};
|
||||
$( $module_name:ident::Event $( <$generic_param:ident> )*, )*;
|
||||
) => {
|
||||
@@ -349,13 +371,13 @@ macro_rules! impl_outer_event {
|
||||
$(#[$attr])*
|
||||
#[allow(non_camel_case_types)]
|
||||
pub enum $name {
|
||||
system(system::Event),
|
||||
system($system::Event),
|
||||
$(
|
||||
$module_name( $module_name::Event $( <$generic_param> )* ),
|
||||
)*
|
||||
}
|
||||
impl From<system::Event> for $name {
|
||||
fn from(x: system::Event) -> Self {
|
||||
impl From<$system::Event> for $name {
|
||||
fn from(x: $system::Event) -> Self {
|
||||
$name::system(x)
|
||||
}
|
||||
}
|
||||
@@ -369,6 +391,7 @@ macro_rules! impl_outer_event {
|
||||
__impl_outer_event_json_metadata!(
|
||||
$runtime;
|
||||
$name;
|
||||
$system;
|
||||
$( $module_name::Event $( <$generic_param> )*, )*;
|
||||
);
|
||||
}
|
||||
@@ -380,13 +403,14 @@ macro_rules! __impl_outer_event_json_metadata {
|
||||
(
|
||||
$runtime:ident;
|
||||
$event_name:ident;
|
||||
$system:ident;
|
||||
$( $module_name:ident::Event $( <$generic_param:ident> )*, )*;
|
||||
) => {
|
||||
impl $runtime {
|
||||
#[allow(dead_code)]
|
||||
pub fn outer_event_json_metadata() -> (&'static str, &'static [(&'static str, fn() -> &'static str)]) {
|
||||
static METADATA: &[(&str, fn() -> &'static str)] = &[
|
||||
("system", system::Event::event_json_metadata)
|
||||
("system", $system::Event::event_json_metadata)
|
||||
$(
|
||||
, (
|
||||
stringify!($module_name),
|
||||
@@ -425,6 +449,22 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
mod system_renamed {
|
||||
pub trait Trait {
|
||||
type Origin;
|
||||
}
|
||||
|
||||
decl_module! {
|
||||
pub struct Module<T: Trait> for enum Call where origin: T::Origin {}
|
||||
}
|
||||
|
||||
decl_event!(
|
||||
pub enum Event {
|
||||
SystemEvent,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
mod event_module {
|
||||
pub trait Trait {
|
||||
type Origin;
|
||||
@@ -488,6 +528,17 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Encode, Decode, Deserialize, Serialize)]
|
||||
pub struct TestRuntime2;
|
||||
|
||||
impl_outer_event! {
|
||||
pub enum TestEventSystemRenamed for TestRuntime2 where system = system_renamed {
|
||||
event_module<T>,
|
||||
event_module2<T>,
|
||||
event_module3,
|
||||
}
|
||||
}
|
||||
|
||||
impl event_module::Trait for TestRuntime {
|
||||
type Origin = u32;
|
||||
type Balance = u32;
|
||||
@@ -502,6 +553,20 @@ mod tests {
|
||||
type Origin = u32;
|
||||
}
|
||||
|
||||
impl event_module::Trait for TestRuntime2 {
|
||||
type Origin = u32;
|
||||
type Balance = u32;
|
||||
}
|
||||
|
||||
impl event_module2::Trait for TestRuntime2 {
|
||||
type Origin = u32;
|
||||
type Balance = u32;
|
||||
}
|
||||
|
||||
impl system_renamed::Trait for TestRuntime2 {
|
||||
type Origin = u32;
|
||||
}
|
||||
|
||||
const EXPECTED_METADATA: (&str, &[(&str, &str)]) = (
|
||||
"TestEvent", &[
|
||||
("system", r#"{ "SystemEvent": { "params": null, "description": [ ] } }"#),
|
||||
|
||||
@@ -32,6 +32,8 @@ extern crate sr_io as runtime_io;
|
||||
extern crate substrate_primitives as primitives;
|
||||
extern crate substrate_metadata;
|
||||
|
||||
extern crate mashup;
|
||||
|
||||
#[cfg(test)]
|
||||
#[macro_use]
|
||||
extern crate pretty_assertions;
|
||||
@@ -65,6 +67,8 @@ mod event;
|
||||
pub mod metadata;
|
||||
#[macro_use]
|
||||
mod origin;
|
||||
#[macro_use]
|
||||
mod runtime;
|
||||
|
||||
pub use self::storage::{StorageVec, StorageList, StorageValue, StorageMap};
|
||||
pub use self::hashable::Hashable;
|
||||
@@ -122,3 +126,6 @@ macro_rules! assert_ok {
|
||||
#[derive(Clone, Eq, PartialEq)]
|
||||
#[cfg_attr(feature = "std", derive(Debug))]
|
||||
pub enum Void {}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub use mashup::*;
|
||||
|
||||
@@ -0,0 +1,999 @@
|
||||
// Copyright 2018 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Substrate is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Substrate is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/// Construct a runtime, with the given name and the given modules.
|
||||
///
|
||||
/// # Example:
|
||||
///
|
||||
/// ```nocompile
|
||||
/// construct_runtime!(
|
||||
/// pub enum Runtime with Log(interalIdent: DigestItem<SessionKey>) {
|
||||
/// System: system,
|
||||
/// Test: test::{default, Log(Test)},
|
||||
/// Test2: test_with_long_module::{Module},
|
||||
/// }
|
||||
/// )
|
||||
/// ```
|
||||
///
|
||||
/// The module `System: system` will expand to `System: system::{Module, Call, Storage, Event<T>, Config}`.
|
||||
/// The identifier `System` is the name of the module and the lower case identifier `system` is the
|
||||
/// name of the rust module for this module.
|
||||
/// The module `Test: test::{default, Log(Test)}` will expand to
|
||||
/// `Test: test::{Module, Call, Storage, Event<T>, Config, Log(Test)}`.
|
||||
/// The module `Test2: test_with_long_module::{Module}` will expand to
|
||||
/// `Test2: test_with_long_module::{Module}`.
|
||||
///
|
||||
/// We provide support for the following types in a module:
|
||||
/// - `Module`
|
||||
/// - `Call`
|
||||
/// - `Storage`
|
||||
/// - `Event` or `Event<T>` (if the event is generic)
|
||||
/// - `Origin` or `Origin<T>` (if the origin is generic)
|
||||
/// - `Config`
|
||||
/// - `Log( $(IDENT),* )`
|
||||
#[macro_export]
|
||||
macro_rules! construct_runtime {
|
||||
(
|
||||
pub enum $runtime:ident with Log ($log_internal:ident: DigestItem<$( $log_genarg:ty ),+>) {
|
||||
$( $rest:tt )*
|
||||
}
|
||||
) => {
|
||||
construct_runtime!(
|
||||
$runtime;
|
||||
$log_internal < $( $log_genarg ),* >;
|
||||
;
|
||||
$( $rest )*
|
||||
);
|
||||
};
|
||||
(
|
||||
$runtime:ident;
|
||||
$log_internal:ident <$( $log_genarg:ty ),+>;
|
||||
$(
|
||||
$expanded_name:ident: $expanded_module:ident::{
|
||||
$(
|
||||
$expanded_modules:ident
|
||||
$( <$expanded_modules_generic:ident> )*
|
||||
$( ( $( $expanded_modules_args:ident ),* ) )*
|
||||
),*
|
||||
}
|
||||
),*;
|
||||
$name:ident: $module:ident,
|
||||
$(
|
||||
$rest_name:ident: $rest_module:ident $(
|
||||
::{
|
||||
$(
|
||||
$rest_modules:ident
|
||||
$( <$rest_modules_generic:ident> )*
|
||||
$( ( $( $rest_modules_args:ident ),* ) )*
|
||||
),*
|
||||
}
|
||||
)*,
|
||||
)*
|
||||
) => {
|
||||
construct_runtime!(
|
||||
$runtime;
|
||||
$log_internal < $( $log_genarg ),* >;
|
||||
$(
|
||||
$expanded_name: $expanded_module::{
|
||||
$(
|
||||
$expanded_modules
|
||||
$( <$expanded_modules_generic> )*
|
||||
$( ( $( $expanded_modules_args ),* ) )*
|
||||
),*
|
||||
},
|
||||
)* $name: $module::{Module, Call, Storage, Event<T>, Config};
|
||||
$(
|
||||
$rest_name: $rest_module $(
|
||||
::{
|
||||
$(
|
||||
$rest_modules
|
||||
$( <$rest_modules_generic> )*
|
||||
$( ( $( $rest_modules_args ),* ) )*
|
||||
),*
|
||||
}
|
||||
)*,
|
||||
)*
|
||||
);
|
||||
};
|
||||
(
|
||||
$runtime:ident;
|
||||
$log_internal:ident <$( $log_genarg:ty ),+>;
|
||||
$(
|
||||
$expanded_name:ident: $expanded_module:ident::{
|
||||
$(
|
||||
$expanded_modules:ident
|
||||
$( <$expanded_modules_generic:ident> )*
|
||||
$( ( $( $expanded_modules_args:ident ),* ) )*
|
||||
),*
|
||||
}
|
||||
),*;
|
||||
$name:ident: $module:ident::{
|
||||
default,
|
||||
$(
|
||||
$modules:ident
|
||||
$( <$modules_generic:ident> )*
|
||||
$( ( $( $modules_args:ident ),* ) )*
|
||||
),*
|
||||
},
|
||||
$(
|
||||
$rest_name:ident: $rest_module:ident $(
|
||||
::{
|
||||
$(
|
||||
$rest_modules:ident
|
||||
$( <$rest_modules_generic:ident> )*
|
||||
$( ( $( $rest_modules_args:ident ),* ) )*
|
||||
),*
|
||||
}
|
||||
)*,
|
||||
)*
|
||||
) => {
|
||||
construct_runtime!(
|
||||
$runtime;
|
||||
$log_internal < $( $log_genarg ),* >;
|
||||
$(
|
||||
$expanded_name: $expanded_module::{
|
||||
$(
|
||||
$expanded_modules
|
||||
$( <$expanded_modules_generic> )*
|
||||
$( ( $( $expanded_modules_args ),* ) )*
|
||||
),*
|
||||
},
|
||||
)*
|
||||
$name: $module::{
|
||||
Module, Call, Storage, Event<T>, Config,
|
||||
$(
|
||||
$modules $( <$modules_generic> )* $( ( $( $modules_args ),* ) )*
|
||||
),*
|
||||
};
|
||||
$(
|
||||
$rest_name: $rest_module $(
|
||||
::{
|
||||
$(
|
||||
$rest_modules
|
||||
$( <$rest_modules_generic> )*
|
||||
$( ( $( $rest_modules_args ),* ) )*
|
||||
),*
|
||||
}
|
||||
)*,
|
||||
)*
|
||||
);
|
||||
};
|
||||
(
|
||||
$runtime:ident;
|
||||
$log_internal:ident <$( $log_genarg:ty ),+>;
|
||||
$(
|
||||
$expanded_name:ident: $expanded_module:ident::{
|
||||
$(
|
||||
$expanded_modules:ident
|
||||
$( <$expanded_modules_generic:ident> )*
|
||||
$( ( $( $expanded_modules_args:ident ),* ) )*
|
||||
),*
|
||||
}
|
||||
),*;
|
||||
$name:ident: $module:ident::{
|
||||
$(
|
||||
$modules:ident
|
||||
$( <$modules_generic:ident> )*
|
||||
$( ( $( $modules_args:ident ),* ) )*
|
||||
),*
|
||||
},
|
||||
$(
|
||||
$rest_name:ident: $rest_module:ident $(
|
||||
::{
|
||||
$(
|
||||
$rest_modules:ident
|
||||
$( <$rest_modules_generic:ident> )*
|
||||
$( ( $( $rest_modules_args:ident ),* ) )*
|
||||
),*
|
||||
}
|
||||
)*,
|
||||
)*
|
||||
) => {
|
||||
construct_runtime!(
|
||||
$runtime;
|
||||
$log_internal < $( $log_genarg ),* >;
|
||||
$(
|
||||
$expanded_name: $expanded_module::{
|
||||
$(
|
||||
$expanded_modules
|
||||
$( <$expanded_modules_generic> )*
|
||||
$( ( $( $expanded_modules_args ),* ) )*
|
||||
),*
|
||||
},
|
||||
)*
|
||||
$name: $module::{
|
||||
$(
|
||||
$modules $( <$modules_generic> )* $( ( $( $modules_args ),* ) )*
|
||||
),*
|
||||
};
|
||||
$(
|
||||
$rest_name: $rest_module $(
|
||||
::{
|
||||
$(
|
||||
$rest_modules
|
||||
$( <$rest_modules_generic> )*
|
||||
$( ( $( $rest_modules_args ),* ) )*
|
||||
),*
|
||||
}
|
||||
)*,
|
||||
)*
|
||||
);
|
||||
};
|
||||
(
|
||||
$runtime:ident;
|
||||
$log_internal:ident <$( $log_genarg:ty ),+>;
|
||||
$(
|
||||
$name:ident: $module:ident::{
|
||||
$(
|
||||
$modules:ident
|
||||
$( <$modules_generic:ident> )*
|
||||
$( ( $( $modules_args:ident ),* ) )*
|
||||
),*
|
||||
}
|
||||
),*;
|
||||
) => {
|
||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))]
|
||||
pub struct $runtime;
|
||||
__decl_outer_event!(
|
||||
$runtime;
|
||||
$(
|
||||
$name: $module::{ $( $modules $( <$modules_generic> )* ),* }
|
||||
),*
|
||||
);
|
||||
__decl_outer_origin!(
|
||||
$runtime;
|
||||
$(
|
||||
$name: $module::{ $( $modules $( <$modules_generic> )* ),* }
|
||||
),*
|
||||
);
|
||||
__decl_all_modules!(
|
||||
$runtime;
|
||||
;
|
||||
;
|
||||
$(
|
||||
$name: $module::{ $( $modules $( <$modules_generic> )* ),* }
|
||||
),*;
|
||||
);
|
||||
__decl_outer_dispatch!(
|
||||
$runtime;
|
||||
;
|
||||
$(
|
||||
$name: $module::{ $( $modules $( <$modules_generic> )* ),* }
|
||||
),*;
|
||||
);
|
||||
__decl_json_metadata!(
|
||||
$runtime;
|
||||
;
|
||||
;
|
||||
$(
|
||||
$name: $module::{ $( $modules $( <$modules_generic> )* ),* }
|
||||
),*;
|
||||
);
|
||||
__decl_outer_log!(
|
||||
$runtime;
|
||||
$log_internal < $( $log_genarg ),* >;
|
||||
;
|
||||
$(
|
||||
$name: $module::{ $( $modules $( ( $( $modules_args ),* ) )* ),* }
|
||||
),*;
|
||||
);
|
||||
__decl_outer_config!(
|
||||
$runtime;
|
||||
;
|
||||
$(
|
||||
$name: $module::{ $( $modules $( <$modules_generic> )* ),* }
|
||||
),*;
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
#[doc(hidden)]
|
||||
macro_rules! __create_decl_macro {
|
||||
(
|
||||
// Parameter $d is a hack for the following issue:
|
||||
// https://github.com/rust-lang/rust/issues/35853
|
||||
$macro_name:ident, $macro_outer_name:ident, $macro_enum_name:ident, $d:tt
|
||||
) => {
|
||||
#[macro_export]
|
||||
#[doc(hidden)]
|
||||
macro_rules! $macro_name {
|
||||
(
|
||||
$runtime:ident;
|
||||
System: $module:ident::{
|
||||
$ingore:ident $d( <$ignor:ident> )* $d(, $modules:ident $d( <$modules_generic:ident> )* )*
|
||||
}
|
||||
$d(, $rest_name:ident : $rest_module:ident::{
|
||||
$d( $rest_modules:ident $d( <$rest_modules_generic:ident> )* ),*
|
||||
})*
|
||||
) => {
|
||||
$macro_name!(
|
||||
$runtime;
|
||||
$module;
|
||||
;
|
||||
$d(
|
||||
$rest_name: $rest_module::{
|
||||
$d( $rest_modules $d( <$rest_modules_generic> )* ),*
|
||||
}
|
||||
),*;
|
||||
);
|
||||
};
|
||||
(
|
||||
$runtime:ident;
|
||||
; // there can not be multiple `System`s
|
||||
$d( $parsed_modules:ident $d( <$parsed_generic:ident> )* ),*;
|
||||
System: $module:ident::{
|
||||
$ingore:ident $d( <$ignor:ident> )* $d(, $modules:ident $d( <$modules_generic:ident> )* )*
|
||||
}
|
||||
$d(, $rest_name:ident : $rest_module:ident::{
|
||||
$d( $rest_modules:ident $d( <$rest_modules_generic:ident> )* ),*
|
||||
})*;
|
||||
) => {
|
||||
$macro_name!(
|
||||
$runtime;
|
||||
$module;
|
||||
$d( $parsed_modules $d( <$parsed_generic> )* ),*;
|
||||
$d(
|
||||
$rest_name: $rest_module::{
|
||||
$d( $rest_modules $d( <$rest_modules_generic> )* ),*
|
||||
}
|
||||
)*;
|
||||
);
|
||||
};
|
||||
(
|
||||
$runtime:ident;
|
||||
$name:ident: $module:ident::{
|
||||
$ingore:ident $d( <$ignor:ident> )* $d(, $modules:ident $d( <$modules_generic:ident> )* )*
|
||||
}
|
||||
$d(, $rest_name:ident : $rest_module:ident::{
|
||||
$d( $rest_modules:ident $d( <$rest_modules_generic:ident> )* ),*
|
||||
})*
|
||||
) => {
|
||||
$macro_name!(
|
||||
$runtime;
|
||||
;
|
||||
;
|
||||
$name: $module::{ $d( $modules $d( <$modules_generic> )* ),* }
|
||||
$d(
|
||||
, $rest_name: $rest_module::{
|
||||
$d( $rest_modules $d( <$rest_modules_generic> )* ),*
|
||||
}
|
||||
)*;
|
||||
);
|
||||
};
|
||||
(
|
||||
$runtime:ident;
|
||||
$d( $system:ident )*;
|
||||
$d( $parsed_modules:ident $d( <$parsed_generic:ident> )* ),*;
|
||||
$name:ident: $module:ident::{
|
||||
$macro_enum_name $d( <$event_gen:ident> )* $d(, $modules:ident $d( <$modules_generic:ident> )* )*
|
||||
}
|
||||
$d(, $rest_name:ident : $rest_module:ident::{
|
||||
$d( $rest_modules:ident $d( <$rest_modules_generic:ident> )* ),*
|
||||
})*;
|
||||
) => {
|
||||
$macro_name!(
|
||||
$runtime;
|
||||
$d( $system )*;
|
||||
$d(
|
||||
$parsed_modules $d( <$parsed_generic> )* , )*
|
||||
$module $d( <$event_gen> )*;
|
||||
$d(
|
||||
$rest_name: $rest_module::{
|
||||
$d( $rest_modules $d( <$rest_modules_generic> )* ),*
|
||||
}
|
||||
),*;
|
||||
);
|
||||
};
|
||||
(
|
||||
$runtime:ident;
|
||||
$d( $system:ident )*;
|
||||
$d( $parsed_modules:ident $d( <$parsed_generic:ident> )* ),*;
|
||||
$name:ident: $module:ident::{
|
||||
$ingore:ident $d( <$ignor:ident> )* $d(, $modules:ident $d( <$modules_generic:ident> )* )*
|
||||
}
|
||||
$d(, $rest_name:ident : $rest_module:ident::{
|
||||
$d( $rest_modules:ident $d( <$rest_modules_generic:ident> )* ),*
|
||||
})*;
|
||||
) => {
|
||||
$macro_name!(
|
||||
$runtime;
|
||||
$d( $system )*;
|
||||
$d( $parsed_modules $d( <$parsed_generic> )* ),*;
|
||||
$name: $module::{ $d( $modules $d( <$modules_generic> )* ),* }
|
||||
$d(
|
||||
, $rest_name: $rest_module::{
|
||||
$d( $rest_modules $d( <$rest_modules_generic> )* ),*
|
||||
}
|
||||
)*;
|
||||
);
|
||||
};
|
||||
(
|
||||
$runtime:ident;
|
||||
$d( $system:ident )*;
|
||||
$d( $parsed_modules:ident $d( <$parsed_generic:ident> )* ),*;
|
||||
$name:ident: $module:ident::{}
|
||||
$d(, $rest_name:ident : $rest_module:ident::{
|
||||
$d( $rest_modules:ident $d( <$rest_modules_generic:ident> )* ),*
|
||||
})*;
|
||||
) => {
|
||||
$macro_name!(
|
||||
$runtime;
|
||||
$d( $system )*;
|
||||
$d( $parsed_modules $d( <$parsed_generic> )* ),*;
|
||||
$d(
|
||||
$rest_name: $rest_module::{
|
||||
$d( $rest_modules $d( <$rest_modules_generic> )* ),*
|
||||
}
|
||||
),*;
|
||||
);
|
||||
};
|
||||
(
|
||||
$runtime:ident;
|
||||
$d( $system:ident )+;
|
||||
$d( $parsed_modules:ident $d( <$parsed_generic:ident> )* ),*;
|
||||
;
|
||||
) => {
|
||||
$macro_outer_name! {
|
||||
pub enum $macro_enum_name for $runtime where system = $d( $system )* {
|
||||
$d(
|
||||
$parsed_modules $d( <$parsed_generic> )*,
|
||||
)*
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__create_decl_macro!(__decl_outer_event, impl_outer_event, Event, $);
|
||||
__create_decl_macro!(__decl_outer_origin, impl_outer_origin, Origin, $);
|
||||
|
||||
#[macro_export]
|
||||
#[doc(hidden)]
|
||||
macro_rules! __decl_all_modules {
|
||||
(
|
||||
$runtime:ident;
|
||||
;
|
||||
$( $parsed_modules:ident :: $parsed_name:ident ),*;
|
||||
System: $module:ident::{
|
||||
Module $(, $modules:ident $( <$modules_generic:ident> )* )*
|
||||
}
|
||||
$(, $rest_name:ident : $rest_module:ident::{
|
||||
$( $rest_modules:ident $( <$rest_modules_generic:ident> )* ),*
|
||||
})*;
|
||||
) => {
|
||||
__decl_all_modules!(
|
||||
$runtime;
|
||||
$module;
|
||||
$( $parsed_modules :: $parsed_name ),*;
|
||||
$(
|
||||
$rest_name: $rest_module::{
|
||||
$( $rest_modules $( <$rest_modules_generic> )* ),*
|
||||
}
|
||||
),*;
|
||||
);
|
||||
};
|
||||
(
|
||||
$runtime:ident;
|
||||
$( $system:ident )*;
|
||||
$( $parsed_modules:ident :: $parsed_name:ident ),*;
|
||||
$name:ident: $module:ident::{
|
||||
Module $(, $modules:ident $( <$modules_generic:ident> )* )*
|
||||
}
|
||||
$(, $rest_name:ident : $rest_module:ident::{
|
||||
$( $rest_modules:ident $( <$rest_modules_generic:ident> )* ),*
|
||||
})*;
|
||||
) => {
|
||||
__decl_all_modules!(
|
||||
$runtime;
|
||||
$( $system )*;
|
||||
$( $parsed_modules :: $parsed_name, )* $module::$name;
|
||||
$(
|
||||
$rest_name: $rest_module::{
|
||||
$( $rest_modules $( <$rest_modules_generic> )* ),*
|
||||
}
|
||||
),*;
|
||||
);
|
||||
};
|
||||
(
|
||||
$runtime:ident;
|
||||
$( $system:ident )*;
|
||||
$( $parsed_modules:ident :: $parsed_name:ident ),*;
|
||||
$name:ident: $module:ident::{
|
||||
$ingore:ident $( <$ignor:ident> )* $(, $modules:ident $( <$modules_generic:ident> )* )*
|
||||
}
|
||||
$(, $rest_name:ident : $rest_module:ident::{
|
||||
$( $rest_modules:ident $( <$rest_modules_generic:ident> )* ),*
|
||||
})*;
|
||||
) => {
|
||||
__decl_all_modules!(
|
||||
$runtime;
|
||||
$( $system )*;
|
||||
$( $parsed_modules :: $parsed_name ),*;
|
||||
$name: $module::{ $( $modules $( <$modules_generic> )* ),* }
|
||||
$(
|
||||
, $rest_name: $rest_module::{
|
||||
$( $rest_modules $( <$rest_modules_generic> )* ),*
|
||||
}
|
||||
)*;
|
||||
);
|
||||
};
|
||||
(
|
||||
$runtime:ident;
|
||||
$( $system:ident )*;
|
||||
$( $parsed_modules:ident :: $parsed_name:ident ),*;
|
||||
$name:ident: $module:ident::{}
|
||||
$(, $rest_name:ident : $rest_module:ident::{
|
||||
$( $rest_modules:ident $( <$rest_modules_generic:ident> )* ),*
|
||||
})*;
|
||||
) => {
|
||||
__decl_all_modules!(
|
||||
$runtime;
|
||||
$( $system )*;
|
||||
$( $parsed_modules :: $parsed_name ),*;
|
||||
$(
|
||||
$rest_name: $rest_module::{
|
||||
$( $rest_modules $( <$rest_modules_generic> )* ),*
|
||||
}
|
||||
),*;
|
||||
);
|
||||
};
|
||||
(
|
||||
$runtime:ident;
|
||||
$system:ident;
|
||||
$( $parsed_modules:ident :: $parsed_name:ident ),*;
|
||||
;
|
||||
) => {
|
||||
pub type System = system::Module<$runtime>;
|
||||
$(
|
||||
pub type $parsed_name = $parsed_modules::Module<$runtime>;
|
||||
)*
|
||||
type AllModules = ( $( $parsed_name, )* );
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
#[doc(hidden)]
|
||||
macro_rules! __decl_outer_dispatch {
|
||||
(
|
||||
$runtime:ident;
|
||||
$( $parsed_modules:ident :: $parsed_name:ident ),*;
|
||||
System: $module:ident::{
|
||||
$ingore:ident $( <$ignor:ident> )* $(, $modules:ident $( <$modules_generic:ident> )* )*
|
||||
}
|
||||
$(, $rest_name:ident : $rest_module:ident::{
|
||||
$( $rest_modules:ident $( <$rest_modules_generic:ident> )* ),*
|
||||
})*;
|
||||
) => {
|
||||
__decl_outer_dispatch!(
|
||||
$runtime;
|
||||
$( $parsed_modules :: $parsed_name ),*;
|
||||
$(
|
||||
$rest_name: $rest_module::{
|
||||
$( $rest_modules $( <$rest_modules_generic> )* ),*
|
||||
}
|
||||
),*;
|
||||
);
|
||||
};
|
||||
(
|
||||
$runtime:ident;
|
||||
$( $parsed_modules:ident :: $parsed_name:ident ),*;
|
||||
$name:ident: $module:ident::{
|
||||
Call $(, $modules:ident $( <$modules_generic:ident> )* )*
|
||||
}
|
||||
$(, $rest_name:ident : $rest_module:ident::{
|
||||
$( $rest_modules:ident $( <$rest_modules_generic:ident> )* ),*
|
||||
})*;
|
||||
) => {
|
||||
__decl_outer_dispatch!(
|
||||
$runtime;
|
||||
$( $parsed_modules :: $parsed_name, )* $module::$name;
|
||||
$(
|
||||
$rest_name: $rest_module::{
|
||||
$( $rest_modules $( <$rest_modules_generic> )* ),*
|
||||
}
|
||||
),*;
|
||||
);
|
||||
};
|
||||
(
|
||||
$runtime:ident;
|
||||
$( $parsed_modules:ident :: $parsed_name:ident ),*;
|
||||
$name:ident: $module:ident::{
|
||||
$ingore:ident $( <$ignor:ident> )* $(, $modules:ident $( <$modules_generic:ident> )* )*
|
||||
}
|
||||
$(, $rest_name:ident : $rest_module:ident::{
|
||||
$( $rest_modules:ident $( <$rest_modules_generic:ident> )* ),*
|
||||
})*;
|
||||
) => {
|
||||
__decl_outer_dispatch!(
|
||||
$runtime;
|
||||
$( $parsed_modules :: $parsed_name ),*;
|
||||
$name: $module::{ $( $modules $( <$modules_generic> )* ),* }
|
||||
$(
|
||||
, $rest_name: $rest_module::{
|
||||
$( $rest_modules $( <$rest_modules_generic> )* ),*
|
||||
}
|
||||
)*;
|
||||
);
|
||||
};
|
||||
(
|
||||
$runtime:ident;
|
||||
$( $parsed_modules:ident :: $parsed_name:ident ),*;
|
||||
$name:ident: $module:ident::{}
|
||||
$(, $rest_name:ident : $rest_module:ident::{
|
||||
$( $rest_modules:ident $( <$rest_modules_generic:ident> )* ),*
|
||||
})*;
|
||||
) => {
|
||||
__decl_outer_dispatch!(
|
||||
$runtime;
|
||||
$( $parsed_modules :: $parsed_name ),*;
|
||||
$(
|
||||
$rest_name: $rest_module::{
|
||||
$( $rest_modules $( <$rest_modules_generic> )* ),*
|
||||
}
|
||||
),*;
|
||||
);
|
||||
};
|
||||
(
|
||||
$runtime:ident;
|
||||
$( $parsed_modules:ident :: $parsed_name:ident ),*;
|
||||
;
|
||||
) => {
|
||||
impl_outer_dispatch!(
|
||||
pub enum Call where origin: Origin {
|
||||
$( $parsed_name, )*
|
||||
}
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
#[doc(hidden)]
|
||||
macro_rules! __decl_json_metadata {
|
||||
(
|
||||
$runtime:ident;
|
||||
;
|
||||
$( $parsed_modules:ident { Module $( with $parsed_storage:ident )* } ),*;
|
||||
$name:ident: $module:ident::{
|
||||
Module $(, $modules:ident $( <$modules_generic:ident> )* )*
|
||||
}
|
||||
$(, $rest_name:ident : $rest_module:ident::{
|
||||
$( $rest_modules:ident $( <$rest_modules_generic:ident> )* ),*
|
||||
})*;
|
||||
) => {
|
||||
__decl_json_metadata!(
|
||||
$runtime;
|
||||
$module { Module, };
|
||||
$( $parsed_modules { Module $( with $parsed_storage )* } ),*;
|
||||
$name: $module::{ $( $modules $( <$modules_generic> )* ),* }
|
||||
$(
|
||||
, $rest_name: $rest_module::{
|
||||
$( $rest_modules $( <$rest_modules_generic> )* ),*
|
||||
}
|
||||
)*;
|
||||
);
|
||||
};
|
||||
(
|
||||
$runtime:ident;
|
||||
$current_module:ident { , Storage };
|
||||
$( $parsed_modules:ident { Module $( with $parsed_storage:ident )* } ),*;
|
||||
$name:ident: $module:ident::{
|
||||
Module $(, $modules:ident $( <$modules_generic:ident> )* )*
|
||||
}
|
||||
$(, $rest_name:ident : $rest_module:ident::{
|
||||
$( $rest_modules:ident $( <$rest_modules_generic:ident> )* ),*
|
||||
})*;
|
||||
) => {
|
||||
__decl_json_metadata!(
|
||||
$runtime;
|
||||
;
|
||||
$( $parsed_modules { Module $( with $parsed_storage )* }, )* $module { Module with Storage };
|
||||
$(
|
||||
$rest_name: $rest_module::{
|
||||
$( $rest_modules $( <$rest_modules_generic> )* ),*
|
||||
}
|
||||
),*;
|
||||
);
|
||||
};
|
||||
(
|
||||
$runtime:ident;
|
||||
;
|
||||
$( $parsed_modules:ident { Module $( with $parsed_storage:ident )* } ),*;
|
||||
$name:ident: $module:ident::{
|
||||
Storage $(, $modules:ident $( <$modules_generic:ident> )* )*
|
||||
}
|
||||
$(, $rest_name:ident : $rest_module:ident::{
|
||||
$( $rest_modules:ident $( <$rest_modules_generic:ident> )* ),*
|
||||
})*;
|
||||
) => {
|
||||
__decl_json_metadata!(
|
||||
$runtime;
|
||||
$module { , Storage };
|
||||
$( $parsed_modules { Module $( with $parsed_storage )* } ),*;
|
||||
$name: $module::{ $( $modules $( <$modules_generic> )* ),* }
|
||||
$(
|
||||
, $rest_name: $rest_module::{
|
||||
$( $rest_modules $( <$rest_modules_generic> )* ),*
|
||||
}
|
||||
)*;
|
||||
);
|
||||
};
|
||||
(
|
||||
$runtime:ident;
|
||||
$current_module:ident { Module, };
|
||||
$( $parsed_modules:ident { Module $( with $parsed_storage:ident )* } ),*;
|
||||
$name:ident: $module:ident::{
|
||||
Storage $(, $modules:ident $( <$modules_generic:ident> )* )*
|
||||
}
|
||||
$(, $rest_name:ident : $rest_module:ident::{
|
||||
$( $rest_modules:ident $( <$rest_modules_generic:ident> )* ),*
|
||||
})*;
|
||||
) => {
|
||||
__decl_json_metadata!(
|
||||
$runtime;
|
||||
;
|
||||
$( $parsed_modules { Module $( with $parsed_storage )* }, )* $module { Module with Storage };
|
||||
$(
|
||||
$rest_name: $rest_module::{
|
||||
$( $rest_modules $( <$rest_modules_generic> )* ),*
|
||||
}
|
||||
),*;
|
||||
);
|
||||
};
|
||||
(
|
||||
$runtime:ident;
|
||||
$( $current_module:ident { $( $current_module_storage:tt )* } )*;
|
||||
$( $parsed_modules:ident { Module $( with $parsed_storage:ident )* } ),*;
|
||||
$name:ident: $module:ident::{
|
||||
$ingore:ident $( <$ignor:ident> )* $(, $modules:ident $( <$modules_generic:ident> )* )*
|
||||
}
|
||||
$(, $rest_name:ident : $rest_module:ident::{
|
||||
$( $rest_modules:ident $( <$rest_modules_generic:ident> )* ),*
|
||||
})*;
|
||||
) => {
|
||||
__decl_json_metadata!(
|
||||
$runtime;
|
||||
$( $current_module { $( $current_module_storage )* } )*;
|
||||
$( $parsed_modules { Module $( with $parsed_storage )* } ),*;
|
||||
$name: $module::{ $( $modules $( <$modules_generic> )* ),* }
|
||||
$(
|
||||
, $rest_name: $rest_module::{
|
||||
$( $rest_modules $( <$rest_modules_generic> )* ),*
|
||||
}
|
||||
)*;
|
||||
);
|
||||
};
|
||||
(
|
||||
$runtime:ident;
|
||||
$current_module:ident { Module, };
|
||||
$( $parsed_modules:ident { Module $( with $parsed_storage:ident )* } ),*;
|
||||
$name:ident: $module:ident::{}
|
||||
$(, $rest_name:ident : $rest_module:ident::{
|
||||
$( $rest_modules:ident $( <$rest_modules_generic:ident> )* ),*
|
||||
})*;
|
||||
) => {
|
||||
__decl_json_metadata!(
|
||||
$runtime;
|
||||
;
|
||||
$( $parsed_modules { Module $( with $parsed_storage )* }, )* $module { Module };
|
||||
$(
|
||||
$rest_name: $rest_module::{
|
||||
$( $rest_modules $( <$rest_modules_generic> )* ),*
|
||||
}
|
||||
),*;
|
||||
);
|
||||
};
|
||||
(
|
||||
$runtime:ident;
|
||||
$( $current_module:ident { $( $ignore:tt )* } )*;
|
||||
$( $parsed_modules:ident { Module $( with $parsed_storage:ident )* } ),*;
|
||||
$name:ident: $module:ident::{}
|
||||
$(, $rest_name:ident : $rest_module:ident::{
|
||||
$( $rest_modules:ident $( <$rest_modules_generic:ident> )* ),*
|
||||
})*;
|
||||
) => {
|
||||
__decl_json_metadata!(
|
||||
$runtime;
|
||||
;
|
||||
$( $parsed_modules { Module $( with $parsed_storage )* } ),*;
|
||||
$(
|
||||
$rest_name: $rest_module::{
|
||||
$( $rest_modules $( <$rest_modules_generic> )* ),*
|
||||
}
|
||||
),*;
|
||||
);
|
||||
};
|
||||
(
|
||||
$runtime:ident;
|
||||
;
|
||||
$( $parsed_modules:ident { Module $( with $parsed_storage:ident )* } ),*;
|
||||
;
|
||||
) => {
|
||||
impl_json_metadata!(
|
||||
for $runtime with modules
|
||||
$( $parsed_modules::Module $(with $parsed_storage)*, )*
|
||||
);
|
||||
}
|
||||
}
|
||||
#[macro_export]
|
||||
#[doc(hidden)]
|
||||
macro_rules! __decl_outer_log {
|
||||
(
|
||||
$runtime:ident;
|
||||
$log_internal:ident <$( $log_genarg:ty ),+>;
|
||||
$( $parsed_modules:ident( $( $parsed_args:ident ),* ) ),*;
|
||||
$name:ident: $module:ident::{
|
||||
Log ( $( $args:ident ),* ) $(, $modules:ident $( ( $( $modules_args:ident )* ) )* )*
|
||||
}
|
||||
$(, $rest_name:ident : $rest_module:ident::{
|
||||
$( $rest_modules:ident $( ( $( $rest_modules_args:ident )* ) )* ),*
|
||||
})*;
|
||||
) => {
|
||||
__decl_outer_log!(
|
||||
$runtime;
|
||||
$log_internal < $( $log_genarg ),* >;
|
||||
$( $parsed_modules ( $( $parsed_args ),* ), )* $module ( $( $args ),* );
|
||||
$(
|
||||
$rest_name: $rest_module::{
|
||||
$( $rest_modules $( ( $( $rest_modules_args ),* ) )* ),*
|
||||
}
|
||||
),*;
|
||||
);
|
||||
};
|
||||
(
|
||||
$runtime:ident;
|
||||
$log_internal:ident <$( $log_genarg:ty ),+>;
|
||||
$( $parsed_modules:ident( $( $parsed_args:ident ),* ) ),*;
|
||||
$name:ident: $module:ident::{
|
||||
$ignore:ident $( ( $( $args_ignore:ident ),* ) )*
|
||||
$(, $modules:ident $( ( $( $modules_args:ident ),* ) )* )*
|
||||
}
|
||||
$(, $rest_name:ident : $rest_module:ident::{
|
||||
$( $rest_modules:ident $( ( $( $rest_modules_args:ident )* ) )* ),*
|
||||
})*;
|
||||
) => {
|
||||
__decl_outer_log!(
|
||||
$runtime;
|
||||
$log_internal < $( $log_genarg ),* >;
|
||||
$( $parsed_modules ( $( $parsed_args ),* ) ),*;
|
||||
$name: $module::{ $( $modules $( ( $( $modules_args ),* ) )* ),* }
|
||||
$(
|
||||
, $rest_name: $rest_module::{
|
||||
$( $rest_modules $( ( $( $rest_modules_args ),* ) )* ),*
|
||||
}
|
||||
)*;
|
||||
);
|
||||
};
|
||||
(
|
||||
$runtime:ident;
|
||||
$log_internal:ident <$( $log_genarg:ty ),+>;
|
||||
$( $parsed_modules:ident( $( $parsed_args:ident ),* ) ),*;
|
||||
$name:ident: $module:ident::{}
|
||||
$(, $rest_name:ident : $rest_module:ident::{
|
||||
$( $rest_modules:ident $( ( $( $rest_modules_args:ident )* ) )* ),*
|
||||
})*;
|
||||
) => {
|
||||
__decl_outer_log!(
|
||||
$runtime;
|
||||
$log_internal < $( $log_genarg ),* >;
|
||||
$( $parsed_modules ( $( $parsed_args ),* ) ),*;
|
||||
$(
|
||||
$rest_name: $rest_module::{
|
||||
$( $rest_modules $( ( $( $rest_modules_args ),* ) )* ),*
|
||||
}
|
||||
),*;
|
||||
);
|
||||
};
|
||||
(
|
||||
$runtime:ident;
|
||||
$log_internal:ident <$( $log_genarg:ty ),+>;
|
||||
$( $parsed_modules:ident( $( $parsed_args:ident ),* ) ),*;
|
||||
;
|
||||
) => {
|
||||
impl_outer_log!(
|
||||
pub enum Log($log_internal: DigestItem<$( $log_genarg)* >) for $runtime {
|
||||
$( $parsed_modules ( $( $parsed_args ),* ) ),*
|
||||
}
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
#[doc(hidden)]
|
||||
macro_rules! __decl_outer_config {
|
||||
(
|
||||
$runtime:ident;
|
||||
$( $parsed_modules:ident :: $parsed_name:ident ),*;
|
||||
$name:ident: $module:ident::{
|
||||
Config $(, $modules:ident $( <$modules_generic:ident> )* )*
|
||||
}
|
||||
$(, $rest_name:ident : $rest_module:ident::{
|
||||
$( $rest_modules:ident $( <$rest_modules_generic:ident> )* ),*
|
||||
})*;
|
||||
) => {
|
||||
__decl_outer_config!(
|
||||
$runtime;
|
||||
$( $parsed_modules :: $parsed_name, )* $module::$name;
|
||||
$(
|
||||
$rest_name: $rest_module::{
|
||||
$( $rest_modules $( <$rest_modules_generic> )* ),*
|
||||
}
|
||||
),*;
|
||||
);
|
||||
};
|
||||
(
|
||||
$runtime:ident;
|
||||
$( $parsed_modules:ident :: $parsed_name:ident ),*;
|
||||
$name:ident: $module:ident::{
|
||||
$ingore:ident $( <$ignor:ident> )* $(, $modules:ident $( <$modules_generic:ident> )* )*
|
||||
}
|
||||
$(, $rest_name:ident : $rest_module:ident::{
|
||||
$( $rest_modules:ident $( <$rest_modules_generic:ident> )* ),*
|
||||
})*;
|
||||
) => {
|
||||
__decl_outer_config!(
|
||||
$runtime;
|
||||
$( $parsed_modules :: $parsed_name ),*;
|
||||
$name: $module::{ $( $modules $( <$modules_generic> )* ),* }
|
||||
$(
|
||||
, $rest_name: $rest_module::{
|
||||
$( $rest_modules $( <$rest_modules_generic> )* ),*
|
||||
}
|
||||
)*;
|
||||
);
|
||||
};
|
||||
(
|
||||
$runtime:ident;
|
||||
$( $parsed_modules:ident :: $parsed_name:ident ),*;
|
||||
$name:ident: $module:ident::{}
|
||||
$(, $rest_name:ident : $rest_module:ident::{
|
||||
$( $rest_modules:ident $( <$rest_modules_generic:ident> )* ),*
|
||||
})*;
|
||||
) => {
|
||||
__decl_outer_config!(
|
||||
$runtime;
|
||||
$( $parsed_modules :: $parsed_name ),*;
|
||||
$(
|
||||
$rest_name: $rest_module::{
|
||||
$( $rest_modules $( <$rest_modules_generic> )* ),*
|
||||
}
|
||||
),*;
|
||||
);
|
||||
};
|
||||
(
|
||||
$runtime:ident;
|
||||
$( $parsed_modules:ident :: $parsed_name:ident ),*;
|
||||
;
|
||||
) => {
|
||||
mashup! {
|
||||
$(
|
||||
substrate_generate_config_name["config-name" $parsed_name] = $parsed_name Config;
|
||||
)*
|
||||
}
|
||||
|
||||
substrate_generate_config_name! {
|
||||
impl_outer_config!(
|
||||
pub struct GenesisConfig for $runtime {
|
||||
$(
|
||||
"config-name" $parsed_name => $parsed_modules,
|
||||
)*
|
||||
}
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user