diff --git a/srml/support/src/lib.rs b/srml/support/src/lib.rs index e467dc06795de..f4da761ea0db5 100644 --- a/srml/support/src/lib.rs +++ b/srml/support/src/lib.rs @@ -63,6 +63,8 @@ mod hashable; mod event; #[macro_use] pub mod metadata; +#[macro_use] +mod origin; pub use self::storage::{StorageVec, StorageList, StorageValue, StorageMap}; pub use self::hashable::Hashable; @@ -120,73 +122,3 @@ macro_rules! assert_ok { #[derive(Clone, Eq, PartialEq)] #[cfg_attr(feature = "std", derive(Debug))] pub enum Void {} - -#[macro_export] -macro_rules! impl_outer_origin { - ($(#[$attr:meta])* pub enum $name:ident for $trait:ident where system = $system:ident { $( $module:ident ),* }) => { - // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. - #[derive(Clone, PartialEq, Eq)] - #[cfg_attr(feature = "std", derive(Debug))] - $(#[$attr])* - #[allow(non_camel_case_types)] - pub enum $name { - system($system::Origin<$trait>), - $( - $module($module::Origin), - )* - #[allow(dead_code)] - Void($crate::Void) - } - #[allow(dead_code)] - impl $name { - pub const INHERENT: Self = $name::system($system::RawOrigin::Inherent); - pub const ROOT: Self = $name::system($system::RawOrigin::Root); - pub fn signed(by: <$trait as $system::Trait>::AccountId) -> Self { - $name::system($system::RawOrigin::Signed(by)) - } - } - impl From<$system::Origin<$trait>> for $name { - fn from(x: $system::Origin<$trait>) -> Self { - $name::system(x) - } - } - impl Into>> for $name { - fn into(self) -> Option<$system::Origin<$trait>> { - if let $name::system(l) = self { - Some(l) - } else { - None - } - } - } - impl From::AccountId>> for $name { - fn from(x: Option<<$trait as $system::Trait>::AccountId>) -> Self { - <$system::Origin<$trait>>::from(x).into() - } - } - $( - impl From<$module::Origin> for $name { - fn from(x: $module::Origin) -> Self { - $name::$module(x) - } - } - impl Into> for $name { - fn into(self) -> Option<$module::Origin> { - if let $name::$module(l) = self { - Some(l) - } else { - None - } - } - } - )* - }; - ($(#[$attr:meta])* pub enum $name:ident for $trait:ident { $( $module:ident ),* }) => { - impl_outer_origin! { - $(#[$attr])* - pub enum $name for $trait where system = system { - $( $module ),* - } - } - } -} diff --git a/srml/support/src/origin.rs b/srml/support/src/origin.rs new file mode 100644 index 0000000000000..5cc54794dbf1f --- /dev/null +++ b/srml/support/src/origin.rs @@ -0,0 +1,260 @@ +// 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 . + +#[macro_export] +macro_rules! impl_outer_origin { + ( + $(#[$attr:meta])* + pub enum $name:ident for $runtime:ident { + $( $module:ident $( <$generic:ident> )* ),* $(,)* + } + ) => { + impl_outer_origin! { + $(#[$attr])* + pub enum $name for $runtime where system = system { + $( $module $( <$generic> )*, )* + } + } + }; + ( + $(#[$attr:meta])* + pub enum $name:ident for $runtime:ident where system = $system:ident {} + ) => { + impl_outer_origin!( + $( #[$attr] )*; + $name; + $runtime; + $system; + Modules { }; + ; + ); + }; + ( + $(#[$attr:meta])* + pub enum $name:ident for $runtime:ident where system = $system:ident { + $module:ident, + $( $rest_module:ident $( <$rest_generic:ident> )* ),* $(,)* + } + ) => { + impl_outer_origin!( + $( #[$attr] )*; + $name; + $runtime; + $system; + Modules { $( $rest_module $( <$rest_generic> )*, )* }; + $module; + ); + }; + ( + $(#[$attr:meta])* + pub enum $name:ident for $runtime:ident where system = $system:ident { + $module:ident, + $( $rest_module:ident $( <$rest_generic:ident> )* ),* $(,)* + } + ) => { + impl_outer_origin!( + $( #[$attr] )*; + $name; + $runtime; + $system; + Modules { $( $rest_module $( <$rest_generic> )*, )* }; + $module<$runtime>; + ); + }; + ( + $(#[$attr:meta])*; + $name:ident; + $runtime:ident; + $system:ident; + Modules { + $module:ident, + $( $rest_module:ident $( <$rest_generic:ident> )*, )* + }; + $( $parsed_module:ident $( <$generic_param:ident> )* ),*; + ) => { + impl_outer_origin!( + $( #[$attr] )*; + $name; + $runtime; + $system; + Modules { $( $rest_module $( <$rest_generic> )*, )* }; + $( $parsed_module $( <$generic_param> )* ),*, $module; + ); + }; + ( + $(#[$attr:meta])*; + $name:ident; + $runtime:ident; + $system:ident; + Modules { + $module:ident, + $( $rest_module:ident $( <$rest_generic:ident> )*, )* + }; + $( $parsed_module:ident $( <$generic_param:ident> )* ),*; + ) => { + impl_outer_origin!( + $( #[$attr] )*; + $name; + $runtime; + $system; + Modules { $( $rest_module $( <$rest_generic> )*, )* }; + $( $parsed_module $( <$generic_param> )* ),*, $module<$runtime>; + ); + }; + ( + $(#[$attr:meta])*; + $name:ident; + $runtime:ident; + $system:ident; + Modules {}; + $( $module:ident $( <$generic_param:ident> )* ),*; + ) => { + // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. + #[derive(Clone, PartialEq, Eq)] + #[cfg_attr(feature = "std", derive(Debug))] + $(#[$attr])* + #[allow(non_camel_case_types)] + pub enum $name { + system($system::Origin<$runtime>), + $( + $module($module::Origin $( <$generic_param> )* ), + )* + #[allow(dead_code)] + Void($crate::Void) + } + #[allow(dead_code)] + impl $name { + pub const INHERENT: Self = $name::system($system::RawOrigin::Inherent); + pub const ROOT: Self = $name::system($system::RawOrigin::Root); + pub fn signed(by: <$runtime as $system::Trait>::AccountId) -> Self { + $name::system($system::RawOrigin::Signed(by)) + } + } + impl From<$system::Origin<$runtime>> for $name { + fn from(x: $system::Origin<$runtime>) -> Self { + $name::system(x) + } + } + impl Into>> for $name { + fn into(self) -> Option<$system::Origin<$runtime>> { + if let $name::system(l) = self { + Some(l) + } else { + None + } + } + } + impl From::AccountId>> for $name { + fn from(x: Option<<$runtime as $system::Trait>::AccountId>) -> Self { + <$system::Origin<$runtime>>::from(x).into() + } + } + $( + impl From<$module::Origin $( <$generic_param> )*> for $name { + fn from(x: $module::Origin $( <$generic_param> )*) -> Self { + $name::$module(x) + } + } + impl Into )*>> for $name { + fn into(self) -> Option<$module::Origin $( <$generic_param> )*> { + if let $name::$module(l) = self { + Some(l) + } else { + None + } + } + } + )* + } +} + +#[cfg(test)] +mod tests { + mod system { + pub trait Trait { + type AccountId; + } + + #[derive(Clone, PartialEq, Eq, Debug)] + pub enum RawOrigin { + Root, + Signed(AccountId), + Inherent, + } + + impl From> for RawOrigin { + fn from(s: Option) -> RawOrigin { + match s { + Some(who) => RawOrigin::Signed(who), + None => RawOrigin::Inherent, + } + } + } + + pub type Origin = RawOrigin<::AccountId>; + } + + mod origin_without_generic { + #[derive(Clone, PartialEq, Eq, Debug)] + pub struct Origin; + } + + mod origin_with_generic { + #[derive(Clone, PartialEq, Eq, Debug)] + pub struct Origin { + t: T + } + } + + #[derive(Clone, PartialEq, Eq, Debug)] + pub struct TestRuntime; + + impl system::Trait for TestRuntime { + type AccountId = u32; + } + + impl_outer_origin!( + pub enum OriginWithoutSystem for TestRuntime { + origin_without_generic, + origin_with_generic, + } + ); + + impl_outer_origin!( + pub enum OriginWithoutSystem2 for TestRuntime { + origin_with_generic, + origin_without_generic + } + ); + + impl_outer_origin!( + pub enum OriginWithSystem for TestRuntime where system = system { + origin_without_generic, + origin_with_generic + } + ); + + impl_outer_origin!( + pub enum OriginWithSystem2 for TestRuntime where system = system { + origin_with_generic, + origin_without_generic, + } + ); + + impl_outer_origin!( + pub enum OriginEmpty for TestRuntime where system = system {} + ); +}