// This file is part of Substrate. // Copyright (C) 2020-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::pallet::Def; use frame_support_procedural_tools::clean_type_string; use quote::ToTokens; struct ConstDef { /// Name of the associated type. pub ident: syn::Ident, /// The type in Get, e.g. `u32` in `type Foo: Get;`, but `Self` is replaced by `T` pub type_: syn::Type, /// The doc associated pub doc: Vec, /// default_byte implementation pub default_byte_impl: proc_macro2::TokenStream, } /// * Impl fn module_constant_metadata for pallet. pub fn expand_constants(def: &mut Def) -> proc_macro2::TokenStream { let frame_support = &def.frame_support; let type_impl_gen = &def.type_impl_generics(proc_macro2::Span::call_site()); let type_decl_gen = &def.type_decl_generics(proc_macro2::Span::call_site()); let type_use_gen = &def.type_use_generics(proc_macro2::Span::call_site()); let pallet_ident = &def.pallet_struct.pallet; let mut where_clauses = vec![&def.config.where_clause]; where_clauses.extend(def.extra_constants.iter().map(|d| &d.where_clause)); let completed_where_clause = super::merge_where_clauses(&where_clauses); let config_consts = def.config.consts_metadata.iter().map(|const_| { let ident = &const_.ident; let const_type = &const_.type_; ConstDef { ident: const_.ident.clone(), type_: const_.type_.clone(), doc: const_.doc.clone(), default_byte_impl: quote::quote!( let value = >::get(); #frame_support::codec::Encode::encode(&value) ), } }); let extra_consts = def.extra_constants.iter().flat_map(|d| &d.extra_constants).map(|const_| { let ident = &const_.ident; ConstDef { ident: const_.ident.clone(), type_: const_.type_.clone(), doc: const_.doc.clone(), default_byte_impl: quote::quote!( let value = >::#ident(); #frame_support::codec::Encode::encode(&value) ), } }); let consts = config_consts.chain(extra_consts) .map(|const_| { let const_type = &const_.type_; let const_type_str = clean_type_string(&const_type.to_token_stream().to_string()); let ident = &const_.ident; let ident_str = format!("{}", ident); let doc = const_.doc.clone().into_iter(); let default_byte_impl = &const_.default_byte_impl; let default_byte_getter = syn::Ident::new( &format!("{}DefaultByteGetter", ident), ident.span() ); quote::quote!({ #[allow(non_upper_case_types)] #[allow(non_camel_case_types)] struct #default_byte_getter<#type_decl_gen>( #frame_support::sp_std::marker::PhantomData<(#type_use_gen)> ); impl<#type_impl_gen> #frame_support::dispatch::DefaultByte for #default_byte_getter<#type_use_gen> #completed_where_clause { fn default_byte(&self) -> #frame_support::sp_std::vec::Vec { #default_byte_impl } } unsafe impl<#type_impl_gen> Send for #default_byte_getter<#type_use_gen> #completed_where_clause {} unsafe impl<#type_impl_gen> Sync for #default_byte_getter<#type_use_gen> #completed_where_clause {} #frame_support::dispatch::ModuleConstantMetadata { name: #frame_support::dispatch::DecodeDifferent::Encode(#ident_str), ty: #frame_support::dispatch::DecodeDifferent::Encode(#const_type_str), value: #frame_support::dispatch::DecodeDifferent::Encode( #frame_support::dispatch::DefaultByteGetter( &#default_byte_getter::<#type_use_gen>( #frame_support::sp_std::marker::PhantomData ) ) ), documentation: #frame_support::dispatch::DecodeDifferent::Encode( &[ #( #doc ),* ] ), } }) }); quote::quote!( impl<#type_impl_gen> #pallet_ident<#type_use_gen> #completed_where_clause{ #[doc(hidden)] pub fn module_constants_metadata() -> &'static [#frame_support::dispatch::ModuleConstantMetadata] { &[ #( #consts ),* ] } } ) }