Allow usage of path in construct_runtime! (#8801)

* Allow usage of path in construct_runtime!

* Fix whitespace

* Fix whitespace

* Make expand_runtime_metadata accept slice instead of Iterator

* Include Call and Event in construct_runtime for testing

* Migrate impl_outer_event to proc macro

* Fix integrity_test_works

* Update UI test expectations

* Factor in module path while generating enum variant or fn names

* Use ParseStream::lookahead for more helpful error messages

* Remove generating outer_event_metadata

* Ensure pallets with different paths but same last path segment can coexist

* Remove unnecessary generated function

* Migrate decl_outer_config to proc macro

* Add default_filter test for expand_outer_origin

* Allow crate, self and super keywords to appear in pallet path

* Add UI test for specifying empty pallet paths in construct_runtime
This commit is contained in:
Keith Yeung
2021-06-01 02:23:41 -07:00
committed by GitHub
parent f85492dcbf
commit 3b1c2f55b2
11 changed files with 1179 additions and 201 deletions
@@ -0,0 +1,123 @@
// This file is part of Substrate.
// Copyright (C) 2021 Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License
use crate::construct_runtime::Pallet;
use proc_macro2::TokenStream;
use quote::{format_ident, quote};
use syn::Ident;
pub fn expand_outer_config(
runtime: &Ident,
pallet_decls: &[Pallet],
scrate: &TokenStream,
) -> TokenStream {
let mut types = TokenStream::new();
let mut fields = TokenStream::new();
let mut build_storage_calls = TokenStream::new();
for decl in pallet_decls {
if let Some(pallet_entry) = decl.find_part("Config") {
let config = format_ident!("{}Config", decl.name);
let mod_name = decl.pallet.mod_name();
let field_name = if let Some(inst) = decl.instance.as_ref() {
format_ident!("{}_{}", mod_name, inst)
} else {
mod_name
};
let part_is_generic = !pallet_entry.generics.params.is_empty();
types.extend(expand_config_types(runtime, decl, &config, part_is_generic));
fields.extend(quote!(pub #field_name: #config,));
build_storage_calls.extend(expand_config_build_storage_call(scrate, runtime, decl, &field_name));
}
}
quote!{
#types
#[cfg(any(feature = "std", test))]
use #scrate::serde as __genesis_config_serde_import__;
#[cfg(any(feature = "std", test))]
#[derive(#scrate::serde::Serialize, #scrate::serde::Deserialize, Default)]
#[serde(rename_all = "camelCase")]
#[serde(deny_unknown_fields)]
#[serde(crate = "__genesis_config_serde_import__")]
#[allow(non_snake_case)]
pub struct GenesisConfig {
#fields
}
#[cfg(any(feature = "std", test))]
impl #scrate::sp_runtime::BuildStorage for GenesisConfig {
fn assimilate_storage(
&self,
storage: &mut #scrate::sp_runtime::Storage,
) -> std::result::Result<(), String> {
#build_storage_calls
#scrate::BasicExternalities::execute_with_storage(storage, || {
<AllPalletsWithSystem as #scrate::traits::OnGenesis>::on_genesis();
});
Ok(())
}
}
}
}
fn expand_config_types(
runtime: &Ident,
decl: &Pallet,
config: &Ident,
part_is_generic: bool,
) -> TokenStream {
let path = &decl.pallet;
match (decl.instance.as_ref(), part_is_generic) {
(Some(inst), true) => quote!{
#[cfg(any(feature = "std", test))]
pub type #config = #path::GenesisConfig<#runtime, #path::#inst>;
},
(None, true) => quote!{
#[cfg(any(feature = "std", test))]
pub type #config = #path::GenesisConfig<#runtime>;
},
(_, false) => quote!{
#[cfg(any(feature = "std", test))]
pub type #config = #path::GenesisConfig;
},
}
}
fn expand_config_build_storage_call(
scrate: &TokenStream,
runtime: &Ident,
decl: &Pallet,
field_name: &Ident,
) -> TokenStream {
let path = &decl.pallet;
let instance = if let Some(inst) = decl.instance.as_ref() {
quote!(#path::#inst)
} else {
quote!(#path::__InherentHiddenInstance)
};
quote!{
#scrate::sp_runtime::BuildModuleGenesisStorage::
<#runtime, #instance>::build_module_genesis_storage(&self.#field_name, storage)?;
}
}
@@ -0,0 +1,146 @@
// This file is part of Substrate.
// Copyright (C) 2021 Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License
use crate::construct_runtime::{Pallet, parse::PalletPath};
use proc_macro2::TokenStream;
use quote::{format_ident, quote};
use syn::{Generics, Ident};
pub fn expand_outer_event(
runtime: &Ident,
pallet_decls: &[Pallet],
scrate: &TokenStream,
) -> syn::Result<TokenStream> {
let mut event_variants = TokenStream::new();
let mut event_conversions = TokenStream::new();
let mut events_metadata = TokenStream::new();
for pallet_decl in pallet_decls {
if let Some(pallet_entry) = pallet_decl.find_part("Event") {
let path = &pallet_decl.pallet;
let index = pallet_decl.index;
let instance = pallet_decl.instance.as_ref();
let generics = &pallet_entry.generics;
if instance.is_some() && generics.params.is_empty() {
let msg = format!(
"Instantiable pallet with no generic `Event` cannot \
be constructed: pallet `{}` must have generic `Event`",
pallet_decl.name,
);
return Err(syn::Error::new(pallet_decl.name.span(), msg));
}
let part_is_generic = !generics.params.is_empty();
let pallet_event = match (instance, part_is_generic) {
(Some(inst), true) => quote!(#path::Event::<#runtime, #path::#inst>),
(Some(inst), false) => quote!(#path::Event::<#path::#inst>),
(None, true) => quote!(#path::Event::<#runtime>),
(None, false) => quote!(#path::Event),
};
event_variants.extend(expand_event_variant(runtime, path, index, instance, generics));
event_conversions.extend(expand_event_conversion(scrate, path, instance, &pallet_event));
events_metadata.extend(expand_event_metadata(scrate, path, &pallet_event));
}
}
Ok(quote!{
#[derive(
Clone, PartialEq, Eq,
#scrate::codec::Encode,
#scrate::codec::Decode,
#scrate::RuntimeDebug,
)]
#[allow(non_camel_case_types)]
pub enum Event {
#event_variants
}
#event_conversions
})
}
fn expand_event_variant(
runtime: &Ident,
path: &PalletPath,
index: u8,
instance: Option<&Ident>,
generics: &Generics,
) -> TokenStream {
let part_is_generic = !generics.params.is_empty();
let mod_name = &path.mod_name();
match (instance, part_is_generic) {
(Some(inst), true) => {
let variant = format_ident!("{}_{}", mod_name, inst);
quote!(#[codec(index = #index)] #variant(#path::Event<#runtime, #path::#inst>),)
}
(Some(inst), false) => {
let variant = format_ident!("{}_{}", mod_name, inst);
quote!(#[codec(index = #index)] #variant(#path::Event<#path::#inst>),)
}
(None, true) => {
quote!(#[codec(index = #index)] #mod_name(#path::Event<#runtime>),)
}
(None, false) => {
quote!(#[codec(index = #index)] #mod_name(#path::Event),)
}
}
}
fn expand_event_conversion(
scrate: &TokenStream,
path: &PalletPath,
instance: Option<&Ident>,
pallet_event: &TokenStream,
) -> TokenStream {
let mod_name = path.mod_name();
let variant = if let Some(inst) = instance {
format_ident!("{}_{}", mod_name, inst)
} else {
mod_name
};
quote!{
impl From<#pallet_event> for Event {
fn from(x: #pallet_event) -> Self {
Event::#variant(x)
}
}
impl #scrate::sp_std::convert::TryInto<#pallet_event> for Event {
type Error = ();
fn try_into(self) -> #scrate::sp_std::result::Result<#pallet_event, Self::Error> {
match self {
Self::#variant(evt) => Ok(evt),
_ => Err(()),
}
}
}
}
}
fn expand_event_metadata(
scrate: &TokenStream,
path: &PalletPath,
pallet_event: &TokenStream,
) -> TokenStream {
let mod_name = path.mod_name();
quote!{(stringify!(#mod_name), #scrate::event::FnEncode(#pallet_event::metadata)),}
}
@@ -0,0 +1,190 @@
// This file is part of Substrate.
// Copyright (C) 2021 Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License
use proc_macro2::TokenStream;
use crate::construct_runtime::Pallet;
use syn::{Ident, TypePath};
use quote::quote;
pub fn expand_runtime_metadata(
runtime: &Ident,
pallet_declarations: &[Pallet],
scrate: &TokenStream,
extrinsic: &TypePath,
) -> TokenStream {
let modules = pallet_declarations
.iter()
.filter_map(|pallet_declaration| {
pallet_declaration.find_part("Pallet").map(|_| {
let filtered_names: Vec<_> = pallet_declaration
.pallet_parts()
.iter()
.filter(|part| part.name() != "Pallet")
.map(|part| part.name())
.collect();
(pallet_declaration, filtered_names)
})
})
.map(|(decl, filtered_names)| {
let name = &decl.name;
let index = &decl.index;
let storage = expand_pallet_metadata_storage(&filtered_names, runtime, scrate, decl);
let calls = expand_pallet_metadata_calls(&filtered_names, runtime, scrate, decl);
let event = expand_pallet_metadata_events(&filtered_names, runtime, scrate, decl);
let constants = expand_pallet_metadata_constants(runtime, scrate, decl);
let errors = expand_pallet_metadata_errors(runtime, scrate, decl);
quote!{
#scrate::metadata::ModuleMetadata {
name: #scrate::metadata::DecodeDifferent::Encode(stringify!(#name)),
index: #index,
storage: #storage,
calls: #calls,
event: #event,
constants: #constants,
errors: #errors,
}
}
})
.collect::<Vec<_>>();
quote!{
impl #runtime {
pub fn metadata() -> #scrate::metadata::RuntimeMetadataPrefixed {
#scrate::metadata::RuntimeMetadataLastVersion {
modules: #scrate::metadata::DecodeDifferent::Encode(&[ #(#modules),* ]),
extrinsic: #scrate::metadata::ExtrinsicMetadata {
version: <#extrinsic as #scrate::sp_runtime::traits::ExtrinsicMetadata>::VERSION,
signed_extensions: <
<
#extrinsic as #scrate::sp_runtime::traits::ExtrinsicMetadata
>::SignedExtensions as #scrate::sp_runtime::traits::SignedExtension
>::identifier()
.into_iter()
.map(#scrate::metadata::DecodeDifferent::Encode)
.collect(),
},
}.into()
}
}
}
}
fn expand_pallet_metadata_storage(
filtered_names: &[&'static str],
runtime: &Ident,
scrate: &TokenStream,
decl: &Pallet,
) -> TokenStream {
if filtered_names.contains(&"Storage") {
let instance = decl.instance.as_ref().into_iter();
let path = &decl.pallet;
quote!{
Some(#scrate::metadata::DecodeDifferent::Encode(
#scrate::metadata::FnEncode(
#path::Pallet::<#runtime #(, #path::#instance)*>::storage_metadata
)
))
}
} else {
quote!(None)
}
}
fn expand_pallet_metadata_calls(
filtered_names: &[&'static str],
runtime: &Ident,
scrate: &TokenStream,
decl: &Pallet,
) -> TokenStream {
if filtered_names.contains(&"Call") {
let instance = decl.instance.as_ref().into_iter();
let path = &decl.pallet;
quote!{
Some(#scrate::metadata::DecodeDifferent::Encode(
#scrate::metadata::FnEncode(
#path::Pallet::<#runtime #(, #path::#instance)*>::call_functions
)
))
}
} else {
quote!(None)
}
}
fn expand_pallet_metadata_events(
filtered_names: &[&'static str],
runtime: &Ident,
scrate: &TokenStream,
decl: &Pallet,
) -> TokenStream {
if filtered_names.contains(&"Event") {
let path = &decl.pallet;
let part_is_generic =
!decl.find_part("Event").expect("Event part exists; qed").generics.params.is_empty();
let pallet_event = match (decl.instance.as_ref(), part_is_generic) {
(Some(inst), true) => quote!(#path::Event::<#runtime, #path::#inst>),
(Some(inst), false) => quote!(#path::Event::<#path::#inst>),
(None, true) => quote!(#path::Event::<#runtime>),
(None, false) => quote!(#path::Event),
};
quote!{
Some(#scrate::metadata::DecodeDifferent::Encode(
#scrate::metadata::FnEncode(#pallet_event::metadata)
))
}
} else {
quote!(None)
}
}
fn expand_pallet_metadata_constants(
runtime: &Ident,
scrate: &TokenStream,
decl: &Pallet,
) -> TokenStream {
let path = &decl.pallet;
let instance = decl.instance.as_ref().into_iter();
quote!{
#scrate::metadata::DecodeDifferent::Encode(
#scrate::metadata::FnEncode(
#path::Pallet::<#runtime #(, #path::#instance)*>::module_constants_metadata
)
)
}
}
fn expand_pallet_metadata_errors(
runtime: &Ident,
scrate: &TokenStream,
decl: &Pallet,
) -> TokenStream {
let path = &decl.pallet;
let instance = decl.instance.as_ref().into_iter();
quote!{
#scrate::metadata::DecodeDifferent::Encode(
#scrate::metadata::FnEncode(
<#path::Pallet::<#runtime #(, #path::#instance)*> as #scrate::metadata::ModuleErrorMetadata>::metadata
)
)
}
}
@@ -0,0 +1,26 @@
// This file is part of Substrate.
// Copyright (C) 2021 Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License
mod config;
mod event;
mod metadata;
mod origin;
pub use config::expand_outer_config;
pub use event::expand_outer_event;
pub use metadata::expand_runtime_metadata;
pub use origin::expand_outer_origin;
@@ -0,0 +1,341 @@
// This file is part of Substrate.
// Copyright (C) 2021 Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License
use crate::construct_runtime::{parse::PalletPath, Pallet, SYSTEM_PALLET_NAME};
use proc_macro2::TokenStream;
use quote::{format_ident, quote};
use syn::{token, Ident, Generics};
pub fn expand_outer_origin(
runtime: &Ident,
pallets: &[Pallet],
pallets_token: token::Brace,
scrate: &TokenStream,
) -> syn::Result<TokenStream> {
let system_pallet = pallets.iter()
.find(|decl| decl.name == SYSTEM_PALLET_NAME)
.ok_or_else(|| syn::Error::new(
pallets_token.span,
"`System` pallet declaration is missing. \
Please add this line: `System: frame_system::{Pallet, Call, Storage, Config, Event<T>},`",
))?;
let mut caller_variants = TokenStream::new();
let mut pallet_conversions = TokenStream::new();
for pallet_decl in pallets.iter().filter(|pallet| pallet.name != SYSTEM_PALLET_NAME) {
if let Some(pallet_entry) = pallet_decl.find_part("Origin") {
let path = &pallet_decl.pallet;
let instance = pallet_decl.instance.as_ref();
let index = pallet_decl.index;
let generics = &pallet_entry.generics;
if instance.is_some() && generics.params.is_empty() {
let msg = format!(
"Instantiable pallet with no generic `Origin` cannot \
be constructed: pallet `{}` must have generic `Origin`",
pallet_decl.name
);
return Err(syn::Error::new(pallet_decl.name.span(), msg));
}
caller_variants.extend(
expand_origin_caller_variant(runtime, path, index, instance, generics),
);
pallet_conversions.extend(
expand_origin_pallet_conversions(scrate, runtime, path, instance, generics),
);
}
}
let system_path = &system_pallet.pallet;
let system_index = system_pallet.index;
Ok(quote!{
// WARNING: All instance must hold the filter `frame_system::Config::BaseCallFilter`, except
// when caller is system Root. One can use `OriginTrait::reset_filter` to do so.
#[derive(Clone)]
pub struct Origin {
caller: OriginCaller,
filter: #scrate::sp_std::rc::Rc<Box<dyn Fn(&<#runtime as #system_path::Config>::Call) -> bool>>,
}
#[cfg(not(feature = "std"))]
impl #scrate::sp_std::fmt::Debug for Origin {
fn fmt(
&self,
fmt: &mut #scrate::sp_std::fmt::Formatter,
) -> #scrate::sp_std::result::Result<(), #scrate::sp_std::fmt::Error> {
fmt.write_str("<wasm:stripped>")
}
}
#[cfg(feature = "std")]
impl #scrate::sp_std::fmt::Debug for Origin {
fn fmt(
&self,
fmt: &mut #scrate::sp_std::fmt::Formatter,
) -> #scrate::sp_std::result::Result<(), #scrate::sp_std::fmt::Error> {
fmt.debug_struct("Origin")
.field("caller", &self.caller)
.field("filter", &"[function ptr]")
.finish()
}
}
impl #scrate::traits::OriginTrait for Origin {
type Call = <#runtime as #system_path::Config>::Call;
type PalletsOrigin = OriginCaller;
type AccountId = <#runtime as #system_path::Config>::AccountId;
fn add_filter(&mut self, filter: impl Fn(&Self::Call) -> bool + 'static) {
let f = self.filter.clone();
self.filter = #scrate::sp_std::rc::Rc::new(Box::new(move |call| {
f(call) && filter(call)
}));
}
fn reset_filter(&mut self) {
let filter = <
<#runtime as #system_path::Config>::BaseCallFilter
as #scrate::traits::Filter<<#runtime as #system_path::Config>::Call>
>::filter;
self.filter = #scrate::sp_std::rc::Rc::new(Box::new(filter));
}
fn set_caller_from(&mut self, other: impl Into<Self>) {
self.caller = other.into().caller;
}
fn filter_call(&self, call: &Self::Call) -> bool {
(self.filter)(call)
}
fn caller(&self) -> &Self::PalletsOrigin {
&self.caller
}
fn try_with_caller<R>(
mut self,
f: impl FnOnce(Self::PalletsOrigin) -> Result<R, Self::PalletsOrigin>,
) -> Result<R, Self> {
match f(self.caller) {
Ok(r) => Ok(r),
Err(caller) => { self.caller = caller; Err(self) }
}
}
/// Create with system none origin and `frame-system::Config::BaseCallFilter`.
fn none() -> Self {
#system_path::RawOrigin::None.into()
}
/// Create with system root origin and no filter.
fn root() -> Self {
#system_path::RawOrigin::Root.into()
}
/// Create with system signed origin and `frame-system::Config::BaseCallFilter`.
fn signed(by: <#runtime as #system_path::Config>::AccountId) -> Self {
#system_path::RawOrigin::Signed(by).into()
}
}
#[derive(Clone, PartialEq, Eq, #scrate::RuntimeDebug, #scrate::codec::Encode, #scrate::codec::Decode)]
#[allow(non_camel_case_types)]
pub enum OriginCaller {
#[codec(index = #system_index)]
system(#system_path::Origin<#runtime>),
#caller_variants
#[allow(dead_code)]
Void(#scrate::Void)
}
// For backwards compatibility and ease of accessing these functions.
#[allow(dead_code)]
impl Origin {
/// Create with system none origin and `frame-system::Config::BaseCallFilter`.
pub fn none() -> Self {
<Origin as #scrate::traits::OriginTrait>::none()
}
/// Create with system root origin and no filter.
pub fn root() -> Self {
<Origin as #scrate::traits::OriginTrait>::root()
}
/// Create with system signed origin and `frame-system::Config::BaseCallFilter`.
pub fn signed(by: <#runtime as #system_path::Config>::AccountId) -> Self {
<Origin as #scrate::traits::OriginTrait>::signed(by)
}
}
impl From<#system_path::Origin<#runtime>> for OriginCaller {
fn from(x: #system_path::Origin<#runtime>) -> Self {
OriginCaller::system(x)
}
}
impl #scrate::sp_std::convert::TryFrom<OriginCaller> for #system_path::Origin<#runtime> {
type Error = OriginCaller;
fn try_from(x: OriginCaller)
-> #scrate::sp_std::result::Result<#system_path::Origin<#runtime>, OriginCaller>
{
if let OriginCaller::system(l) = x {
Ok(l)
} else {
Err(x)
}
}
}
impl From<#system_path::Origin<#runtime>> for Origin {
/// Convert to runtime origin:
/// * root origin is built with no filter
/// * others use `frame-system::Config::BaseCallFilter`
fn from(x: #system_path::Origin<#runtime>) -> Self {
let o: OriginCaller = x.into();
o.into()
}
}
impl From<OriginCaller> for Origin {
fn from(x: OriginCaller) -> Self {
let mut o = Origin {
caller: x,
filter: #scrate::sp_std::rc::Rc::new(Box::new(|_| true)),
};
// Root has no filter
if !matches!(o.caller, OriginCaller::system(#system_path::Origin::<#runtime>::Root)) {
#scrate::traits::OriginTrait::reset_filter(&mut o);
}
o
}
}
impl Into<#scrate::sp_std::result::Result<#system_path::Origin<#runtime>, Origin>> for Origin {
/// NOTE: converting to pallet origin loses the origin filter information.
fn into(self) -> #scrate::sp_std::result::Result<#system_path::Origin<#runtime>, Self> {
if let OriginCaller::system(l) = self.caller {
Ok(l)
} else {
Err(self)
}
}
}
impl From<Option<<#runtime as #system_path::Config>::AccountId>> for Origin {
/// Convert to runtime origin with caller being system signed or none and use filter
/// `frame-system::Config::BaseCallFilter`.
fn from(x: Option<<#runtime as #system_path::Config>::AccountId>) -> Self {
<#system_path::Origin<#runtime>>::from(x).into()
}
}
#pallet_conversions
})
}
fn expand_origin_caller_variant(
runtime: &Ident,
path: &PalletPath,
index: u8,
instance: Option<&Ident>,
generics: &Generics,
) -> TokenStream {
let part_is_generic = !generics.params.is_empty();
let mod_name = &path.mod_name();
match (instance, part_is_generic) {
(Some(inst), true) => {
let variant = format_ident!("{}_{}", mod_name, inst);
quote!(#[codec(index = #index)] #variant(#path::Origin<#runtime, #path::#inst>),)
}
(Some(inst), false) => {
let variant = format_ident!("{}_{}", mod_name, inst);
quote!(#[codec(index = #index)] #variant(#path::Origin<#path::#inst>),)
}
(None, true) => {
quote!(#[codec(index = #index)] #mod_name(#path::Origin<#runtime>),)
}
(None, false) => {
quote!(#[codec(index = #index)] #mod_name(#path::Origin),)
}
}
}
fn expand_origin_pallet_conversions(
scrate: &TokenStream,
runtime: &Ident,
path: &PalletPath,
instance: Option<&Ident>,
generics: &Generics,
) -> TokenStream {
let mod_name = path.mod_name();
let variant = if let Some(inst) = instance {
format_ident!("{}_{}", mod_name, inst)
} else {
mod_name
};
let part_is_generic = !generics.params.is_empty();
let pallet_origin = match (instance, part_is_generic) {
(Some(inst), true) => quote!(#path::Origin<#runtime, #path::#inst>),
(Some(inst), false) => quote!(#path::Origin<#path::#inst>),
(None, true) => quote!(#path::Origin<#runtime>),
(None, false) => quote!(#path::Origin),
};
quote!{
impl From<#pallet_origin> for OriginCaller {
fn from(x: #pallet_origin) -> Self {
OriginCaller::#variant(x)
}
}
impl From<#pallet_origin> for Origin {
/// Convert to runtime origin using `frame-system::Config::BaseCallFilter`.
fn from(x: #pallet_origin) -> Self {
let x: OriginCaller = x.into();
x.into()
}
}
impl Into<#scrate::sp_std::result::Result<#pallet_origin, Origin>> for Origin {
/// NOTE: converting to pallet origin loses the origin filter information.
fn into(self) -> #scrate::sp_std::result::Result<#pallet_origin, Self> {
if let OriginCaller::#variant(l) = self.caller {
Ok(l)
} else {
Err(self)
}
}
}
impl #scrate::sp_std::convert::TryFrom<OriginCaller> for #pallet_origin {
type Error = OriginCaller;
fn try_from(
x: OriginCaller,
) -> #scrate::sp_std::result::Result<#pallet_origin, OriginCaller> {
if let OriginCaller::#variant(l) = x {
Ok(l)
} else {
Err(x)
}
}
}
}
}