Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Commit

Permalink
Make impl_outer_origin! support generic Origins (#732)
Browse files Browse the repository at this point in the history
* Make `impl_outer_origin!` support generic `Origin`s

* Support empty outer origin
  • Loading branch information
bkchr authored and gavofyork committed Sep 13, 2018
1 parent 1102f84 commit 2e9704c
Show file tree
Hide file tree
Showing 2 changed files with 262 additions and 70 deletions.
72 changes: 2 additions & 70 deletions srml/support/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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<Option<$system::Origin<$trait>>> for $name {
fn into(self) -> Option<$system::Origin<$trait>> {
if let $name::system(l) = self {
Some(l)
} else {
None
}
}
}
impl From<Option<<$trait as $system::Trait>::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<Option<$module::Origin>> 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 ),*
}
}
}
}
260 changes: 260 additions & 0 deletions srml/support/src/origin.rs
Original file line number Diff line number Diff line change
@@ -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 <http://www.gnu.org/licenses/>.

#[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<T>,
$( $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<T>,
$( $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<Option<$system::Origin<$runtime>>> for $name {
fn into(self) -> Option<$system::Origin<$runtime>> {
if let $name::system(l) = self {
Some(l)
} else {
None
}
}
}
impl From<Option<<$runtime as $system::Trait>::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<Option<$module::Origin $( <$generic_param> )*>> 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<AccountId> {
Root,
Signed(AccountId),
Inherent,
}

impl<AccountId> From<Option<AccountId>> for RawOrigin<AccountId> {
fn from(s: Option<AccountId>) -> RawOrigin<AccountId> {
match s {
Some(who) => RawOrigin::Signed(who),
None => RawOrigin::Inherent,
}
}
}

pub type Origin<T> = RawOrigin<<T as Trait>::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: 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<T>,
}
);

impl_outer_origin!(
pub enum OriginWithoutSystem2 for TestRuntime {
origin_with_generic<T>,
origin_without_generic
}
);

impl_outer_origin!(
pub enum OriginWithSystem for TestRuntime where system = system {
origin_without_generic,
origin_with_generic<T>
}
);

impl_outer_origin!(
pub enum OriginWithSystem2 for TestRuntime where system = system {
origin_with_generic<T>,
origin_without_generic,
}
);

impl_outer_origin!(
pub enum OriginEmpty for TestRuntime where system = system {}
);
}

0 comments on commit 2e9704c

Please sign in to comment.