mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-14 13:21:10 +00:00
Run cargo fmt on the whole code base (#9394)
* Run cargo fmt on the whole code base * Second run * Add CI check * Fix compilation * More unnecessary braces * Handle weights * Use --all * Use correct attributes... * Fix UI tests * AHHHHHHHHH * 🤦 * Docs * Fix compilation * 🤷 * Please stop * 🤦 x 2 * More * make rustfmt.toml consistent with polkadot Co-authored-by: André Silva <andrerfosilva@gmail.com>
This commit is contained in:
@@ -30,56 +30,61 @@ pub fn derive_clone_no_bound(input: proc_macro::TokenStream) -> proc_macro::Toke
|
||||
let impl_ = match input.data {
|
||||
syn::Data::Struct(struct_) => match struct_.fields {
|
||||
syn::Fields::Named(named) => {
|
||||
let fields = named.named.iter()
|
||||
.map(|i| &i.ident)
|
||||
.map(|i| quote::quote_spanned!(i.span() =>
|
||||
let fields = named.named.iter().map(|i| &i.ident).map(|i| {
|
||||
quote::quote_spanned!(i.span() =>
|
||||
#i: core::clone::Clone::clone(&self.#i)
|
||||
));
|
||||
)
|
||||
});
|
||||
|
||||
quote::quote!( Self { #( #fields, )* } )
|
||||
},
|
||||
syn::Fields::Unnamed(unnamed) => {
|
||||
let fields = unnamed.unnamed.iter().enumerate()
|
||||
.map(|(i, _)| syn::Index::from(i))
|
||||
.map(|i| quote::quote_spanned!(i.span() =>
|
||||
core::clone::Clone::clone(&self.#i)
|
||||
));
|
||||
let fields =
|
||||
unnamed.unnamed.iter().enumerate().map(|(i, _)| syn::Index::from(i)).map(|i| {
|
||||
quote::quote_spanned!(i.span() =>
|
||||
core::clone::Clone::clone(&self.#i)
|
||||
)
|
||||
});
|
||||
|
||||
quote::quote!( Self ( #( #fields, )* ) )
|
||||
},
|
||||
syn::Fields::Unit => {
|
||||
quote::quote!( Self )
|
||||
}
|
||||
quote::quote!(Self)
|
||||
},
|
||||
},
|
||||
syn::Data::Enum(enum_) => {
|
||||
let variants = enum_.variants.iter()
|
||||
.map(|variant| {
|
||||
let ident = &variant.ident;
|
||||
match &variant.fields {
|
||||
syn::Fields::Named(named) => {
|
||||
let captured = named.named.iter().map(|i| &i.ident);
|
||||
let cloned = captured.clone()
|
||||
.map(|i| quote::quote_spanned!(i.span() =>
|
||||
#i: core::clone::Clone::clone(#i)
|
||||
));
|
||||
quote::quote!(
|
||||
Self::#ident { #( ref #captured, )* } => Self::#ident { #( #cloned, )*}
|
||||
let variants = enum_.variants.iter().map(|variant| {
|
||||
let ident = &variant.ident;
|
||||
match &variant.fields {
|
||||
syn::Fields::Named(named) => {
|
||||
let captured = named.named.iter().map(|i| &i.ident);
|
||||
let cloned = captured.clone().map(|i| {
|
||||
quote::quote_spanned!(i.span() =>
|
||||
#i: core::clone::Clone::clone(#i)
|
||||
)
|
||||
},
|
||||
syn::Fields::Unnamed(unnamed) => {
|
||||
let captured = unnamed.unnamed.iter().enumerate()
|
||||
.map(|(i, f)| syn::Ident::new(&format!("_{}", i), f.span()));
|
||||
let cloned = captured.clone()
|
||||
.map(|i| quote::quote_spanned!(i.span() =>
|
||||
core::clone::Clone::clone(#i)
|
||||
));
|
||||
quote::quote!(
|
||||
Self::#ident ( #( ref #captured, )* ) => Self::#ident ( #( #cloned, )*)
|
||||
});
|
||||
quote::quote!(
|
||||
Self::#ident { #( ref #captured, )* } => Self::#ident { #( #cloned, )*}
|
||||
)
|
||||
},
|
||||
syn::Fields::Unnamed(unnamed) => {
|
||||
let captured = unnamed
|
||||
.unnamed
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, f)| syn::Ident::new(&format!("_{}", i), f.span()));
|
||||
let cloned = captured.clone().map(|i| {
|
||||
quote::quote_spanned!(i.span() =>
|
||||
core::clone::Clone::clone(#i)
|
||||
)
|
||||
},
|
||||
syn::Fields::Unit => quote::quote!( Self::#ident => Self::#ident ),
|
||||
}
|
||||
});
|
||||
});
|
||||
quote::quote!(
|
||||
Self::#ident ( #( ref #captured, )* ) => Self::#ident ( #( #cloned, )*)
|
||||
)
|
||||
},
|
||||
syn::Fields::Unit => quote::quote!( Self::#ident => Self::#ident ),
|
||||
}
|
||||
});
|
||||
|
||||
quote::quote!(match self {
|
||||
#( #variants, )*
|
||||
@@ -99,5 +104,6 @@ pub fn derive_clone_no_bound(input: proc_macro::TokenStream) -> proc_macro::Toke
|
||||
}
|
||||
}
|
||||
};
|
||||
).into()
|
||||
)
|
||||
.into()
|
||||
}
|
||||
|
||||
@@ -30,16 +30,16 @@ pub fn expand_outer_dispatch(
|
||||
let mut query_call_part_macros = Vec::new();
|
||||
let mut pallet_names = Vec::new();
|
||||
|
||||
let pallets_with_call = pallet_decls
|
||||
.iter()
|
||||
.filter(|decl| decl.exists_part("Call"));
|
||||
let pallets_with_call = pallet_decls.iter().filter(|decl| decl.exists_part("Call"));
|
||||
|
||||
for pallet_declaration in pallets_with_call {
|
||||
let name = &pallet_declaration.name;
|
||||
let path = &pallet_declaration.path;
|
||||
let index = pallet_declaration.index;
|
||||
|
||||
variant_defs.extend(quote!(#[codec(index = #index)] #name( #scrate::dispatch::CallableCallFor<#name, #runtime> ),));
|
||||
variant_defs.extend(
|
||||
quote!(#[codec(index = #index)] #name( #scrate::dispatch::CallableCallFor<#name, #runtime> ),),
|
||||
);
|
||||
variant_patterns.push(quote!(Call::#name(call)));
|
||||
pallet_names.push(name);
|
||||
query_call_part_macros.push(quote! {
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
use crate::construct_runtime::Pallet;
|
||||
use inflector::Inflector;
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::{ToTokens, format_ident, quote};
|
||||
use quote::{format_ident, quote, ToTokens};
|
||||
use syn::Ident;
|
||||
|
||||
pub fn expand_outer_config(
|
||||
@@ -37,15 +37,18 @@ pub fn expand_outer_config(
|
||||
let pallet_name = &decl.name;
|
||||
let path_str = path.into_token_stream().to_string();
|
||||
let config = format_ident!("{}Config", pallet_name);
|
||||
let field_name = &Ident::new(
|
||||
&pallet_name.to_string().to_snake_case(),
|
||||
decl.name.span(),
|
||||
);
|
||||
let field_name =
|
||||
&Ident::new(&pallet_name.to_string().to_snake_case(), decl.name.span());
|
||||
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));
|
||||
build_storage_calls.extend(expand_config_build_storage_call(
|
||||
scrate,
|
||||
runtime,
|
||||
decl,
|
||||
&field_name,
|
||||
));
|
||||
query_genesis_config_part_macros.push(quote! {
|
||||
#path::__substrate_genesis_config_check::is_genesis_config_defined!(#pallet_name);
|
||||
#[cfg(feature = "std")]
|
||||
@@ -97,15 +100,15 @@ fn expand_config_types(
|
||||
let path = &decl.path;
|
||||
|
||||
match (decl.instance.as_ref(), part_is_generic) {
|
||||
(Some(inst), true) => quote!{
|
||||
(Some(inst), true) => quote! {
|
||||
#[cfg(any(feature = "std", test))]
|
||||
pub type #config = #path::GenesisConfig<#runtime, #path::#inst>;
|
||||
},
|
||||
(None, true) => quote!{
|
||||
(None, true) => quote! {
|
||||
#[cfg(any(feature = "std", test))]
|
||||
pub type #config = #path::GenesisConfig<#runtime>;
|
||||
},
|
||||
(_, false) => quote!{
|
||||
(_, false) => quote! {
|
||||
#[cfg(any(feature = "std", test))]
|
||||
pub type #config = #path::GenesisConfig;
|
||||
},
|
||||
@@ -125,7 +128,7 @@ fn expand_config_build_storage_call(
|
||||
quote!(#path::__InherentHiddenInstance)
|
||||
};
|
||||
|
||||
quote!{
|
||||
quote! {
|
||||
#scrate::sp_runtime::BuildModuleGenesisStorage::
|
||||
<#runtime, #instance>::build_module_genesis_storage(&self.#field_name, storage)?;
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ pub fn expand_outer_event(
|
||||
be constructed: pallet `{}` must have generic `Event`",
|
||||
pallet_name,
|
||||
);
|
||||
return Err(syn::Error::new(pallet_name.span(), msg));
|
||||
return Err(syn::Error::new(pallet_name.span(), msg))
|
||||
}
|
||||
|
||||
let part_is_generic = !generics.params.is_empty();
|
||||
@@ -54,7 +54,13 @@ pub fn expand_outer_event(
|
||||
(None, false) => quote!(#path::Event),
|
||||
};
|
||||
|
||||
event_variants.extend(expand_event_variant(runtime, pallet_decl, index, instance, generics));
|
||||
event_variants.extend(expand_event_variant(
|
||||
runtime,
|
||||
pallet_decl,
|
||||
index,
|
||||
instance,
|
||||
generics,
|
||||
));
|
||||
event_conversions.extend(expand_event_conversion(scrate, pallet_decl, &pallet_event));
|
||||
query_event_part_macros.push(quote! {
|
||||
#path::__substrate_event_check::is_event_part_defined!(#pallet_name);
|
||||
@@ -94,16 +100,16 @@ fn expand_event_variant(
|
||||
match instance {
|
||||
Some(inst) if part_is_generic => {
|
||||
quote!(#[codec(index = #index)] #variant_name(#path::Event<#runtime, #path::#inst>),)
|
||||
}
|
||||
},
|
||||
Some(inst) => {
|
||||
quote!(#[codec(index = #index)] #variant_name(#path::Event<#path::#inst>),)
|
||||
}
|
||||
},
|
||||
None if part_is_generic => {
|
||||
quote!(#[codec(index = #index)] #variant_name(#path::Event<#runtime>),)
|
||||
}
|
||||
},
|
||||
None => {
|
||||
quote!(#[codec(index = #index)] #variant_name(#path::Event),)
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,7 +120,7 @@ fn expand_event_conversion(
|
||||
) -> TokenStream {
|
||||
let variant_name = &pallet.name;
|
||||
|
||||
quote!{
|
||||
quote! {
|
||||
impl From<#pallet_event> for Event {
|
||||
fn from(x: #pallet_event) -> Self {
|
||||
Event::#variant_name(x)
|
||||
|
||||
@@ -15,10 +15,10 @@
|
||||
// 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 proc_macro2::TokenStream;
|
||||
use quote::quote;
|
||||
use syn::{Ident, TypePath};
|
||||
|
||||
pub fn expand_runtime_metadata(
|
||||
runtime: &Ident,
|
||||
@@ -48,7 +48,7 @@ pub fn expand_runtime_metadata(
|
||||
let constants = expand_pallet_metadata_constants(runtime, scrate, decl);
|
||||
let errors = expand_pallet_metadata_errors(runtime, scrate, decl);
|
||||
|
||||
quote!{
|
||||
quote! {
|
||||
#scrate::metadata::ModuleMetadata {
|
||||
name: #scrate::metadata::DecodeDifferent::Encode(stringify!(#name)),
|
||||
index: #index,
|
||||
@@ -62,7 +62,7 @@ pub fn expand_runtime_metadata(
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
quote!{
|
||||
quote! {
|
||||
impl #runtime {
|
||||
pub fn metadata() -> #scrate::metadata::RuntimeMetadataPrefixed {
|
||||
#scrate::metadata::RuntimeMetadataLastVersion {
|
||||
@@ -94,7 +94,7 @@ fn expand_pallet_metadata_storage(
|
||||
let instance = decl.instance.as_ref().into_iter();
|
||||
let path = &decl.path;
|
||||
|
||||
quote!{
|
||||
quote! {
|
||||
Some(#scrate::metadata::DecodeDifferent::Encode(
|
||||
#scrate::metadata::FnEncode(
|
||||
#path::Pallet::<#runtime #(, #path::#instance)*>::storage_metadata
|
||||
@@ -116,7 +116,7 @@ fn expand_pallet_metadata_calls(
|
||||
let instance = decl.instance.as_ref().into_iter();
|
||||
let path = &decl.path;
|
||||
|
||||
quote!{
|
||||
quote! {
|
||||
Some(#scrate::metadata::DecodeDifferent::Encode(
|
||||
#scrate::metadata::FnEncode(
|
||||
#path::Pallet::<#runtime #(, #path::#instance)*>::call_functions
|
||||
@@ -136,8 +136,12 @@ fn expand_pallet_metadata_events(
|
||||
) -> TokenStream {
|
||||
if filtered_names.contains(&"Event") {
|
||||
let path = &decl.path;
|
||||
let part_is_generic =
|
||||
!decl.find_part("Event").expect("Event part exists; qed").generics.params.is_empty();
|
||||
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>),
|
||||
@@ -145,7 +149,7 @@ fn expand_pallet_metadata_events(
|
||||
(None, false) => quote!(#path::Event),
|
||||
};
|
||||
|
||||
quote!{
|
||||
quote! {
|
||||
Some(#scrate::metadata::DecodeDifferent::Encode(
|
||||
#scrate::metadata::FnEncode(#pallet_event::metadata)
|
||||
))
|
||||
@@ -163,7 +167,7 @@ fn expand_pallet_metadata_constants(
|
||||
let path = &decl.path;
|
||||
let instance = decl.instance.as_ref().into_iter();
|
||||
|
||||
quote!{
|
||||
quote! {
|
||||
#scrate::metadata::DecodeDifferent::Encode(
|
||||
#scrate::metadata::FnEncode(
|
||||
#path::Pallet::<#runtime #(, #path::#instance)*>::module_constants_metadata
|
||||
@@ -180,7 +184,7 @@ fn expand_pallet_metadata_errors(
|
||||
let path = &decl.path;
|
||||
let instance = decl.instance.as_ref().into_iter();
|
||||
|
||||
quote!{
|
||||
quote! {
|
||||
#scrate::metadata::DecodeDifferent::Encode(
|
||||
#scrate::metadata::FnEncode(
|
||||
<#path::Pallet::<#runtime #(, #path::#instance)*> as #scrate::metadata::ModuleErrorMetadata>::metadata
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
use crate::construct_runtime::{Pallet, SYSTEM_PALLET_NAME};
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::quote;
|
||||
use syn::{token, Ident, Generics};
|
||||
use syn::{token, Generics, Ident};
|
||||
|
||||
pub fn expand_outer_origin(
|
||||
runtime: &Ident,
|
||||
@@ -26,13 +26,14 @@ pub fn expand_outer_origin(
|
||||
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. \
|
||||
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();
|
||||
@@ -52,15 +53,23 @@ pub fn expand_outer_origin(
|
||||
be constructed: pallet `{}` must have generic `Origin`",
|
||||
name
|
||||
);
|
||||
return Err(syn::Error::new(name.span(), msg));
|
||||
return Err(syn::Error::new(name.span(), msg))
|
||||
}
|
||||
|
||||
caller_variants.extend(
|
||||
expand_origin_caller_variant(runtime, pallet_decl, index, instance, generics),
|
||||
);
|
||||
pallet_conversions.extend(
|
||||
expand_origin_pallet_conversions(scrate, runtime, pallet_decl, instance, generics),
|
||||
);
|
||||
caller_variants.extend(expand_origin_caller_variant(
|
||||
runtime,
|
||||
pallet_decl,
|
||||
index,
|
||||
instance,
|
||||
generics,
|
||||
));
|
||||
pallet_conversions.extend(expand_origin_pallet_conversions(
|
||||
scrate,
|
||||
runtime,
|
||||
pallet_decl,
|
||||
instance,
|
||||
generics,
|
||||
));
|
||||
query_origin_part_macros.push(quote! {
|
||||
#path::__substrate_origin_check::is_origin_part_defined!(#name);
|
||||
});
|
||||
@@ -270,16 +279,16 @@ fn expand_origin_caller_variant(
|
||||
match instance {
|
||||
Some(inst) if part_is_generic => {
|
||||
quote!(#[codec(index = #index)] #variant_name(#path::Origin<#runtime, #path::#inst>),)
|
||||
}
|
||||
},
|
||||
Some(inst) => {
|
||||
quote!(#[codec(index = #index)] #variant_name(#path::Origin<#path::#inst>),)
|
||||
}
|
||||
},
|
||||
None if part_is_generic => {
|
||||
quote!(#[codec(index = #index)] #variant_name(#path::Origin<#runtime>),)
|
||||
}
|
||||
},
|
||||
None => {
|
||||
quote!(#[codec(index = #index)] #variant_name(#path::Origin),)
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -301,7 +310,7 @@ fn expand_origin_pallet_conversions(
|
||||
None => quote!(#path::Origin),
|
||||
};
|
||||
|
||||
quote!{
|
||||
quote! {
|
||||
impl From<#pallet_origin> for OriginCaller {
|
||||
fn from(x: #pallet_origin) -> Self {
|
||||
OriginCaller::#variant_name(x)
|
||||
|
||||
@@ -18,14 +18,15 @@
|
||||
mod expand;
|
||||
mod parse;
|
||||
|
||||
use frame_support_procedural_tools::syn_ext as ext;
|
||||
use frame_support_procedural_tools::{generate_crate_access, generate_hidden_includes};
|
||||
use frame_support_procedural_tools::{
|
||||
generate_crate_access, generate_hidden_includes, syn_ext as ext,
|
||||
};
|
||||
use parse::{PalletDeclaration, PalletPart, PalletPath, RuntimeDefinition, WhereSection};
|
||||
use proc_macro::TokenStream;
|
||||
use proc_macro2::TokenStream as TokenStream2;
|
||||
use quote::quote;
|
||||
use syn::{Ident, Result};
|
||||
use std::collections::HashMap;
|
||||
use syn::{Ident, Result};
|
||||
|
||||
/// The fixed name of the system pallet.
|
||||
const SYSTEM_PALLET_NAME: &str = "System";
|
||||
@@ -65,48 +66,44 @@ fn complete_pallets(decl: impl Iterator<Item = PalletDeclaration>) -> syn::Resul
|
||||
let mut last_index: Option<u8> = None;
|
||||
let mut names = HashMap::new();
|
||||
|
||||
decl
|
||||
.map(|pallet| {
|
||||
let final_index = match pallet.index {
|
||||
Some(i) => i,
|
||||
None => last_index.map_or(Some(0), |i| i.checked_add(1))
|
||||
.ok_or_else(|| {
|
||||
let msg = "Pallet index doesn't fit into u8, index is 256";
|
||||
syn::Error::new(pallet.name.span(), msg)
|
||||
})?,
|
||||
};
|
||||
decl.map(|pallet| {
|
||||
let final_index = match pallet.index {
|
||||
Some(i) => i,
|
||||
None => last_index.map_or(Some(0), |i| i.checked_add(1)).ok_or_else(|| {
|
||||
let msg = "Pallet index doesn't fit into u8, index is 256";
|
||||
syn::Error::new(pallet.name.span(), msg)
|
||||
})?,
|
||||
};
|
||||
|
||||
last_index = Some(final_index);
|
||||
last_index = Some(final_index);
|
||||
|
||||
if let Some(used_pallet) = indices.insert(final_index, pallet.name.clone()) {
|
||||
let msg = format!(
|
||||
"Pallet indices are conflicting: Both pallets {} and {} are at index {}",
|
||||
used_pallet,
|
||||
pallet.name,
|
||||
final_index,
|
||||
);
|
||||
let mut err = syn::Error::new(used_pallet.span(), &msg);
|
||||
err.combine(syn::Error::new(pallet.name.span(), msg));
|
||||
return Err(err);
|
||||
}
|
||||
if let Some(used_pallet) = indices.insert(final_index, pallet.name.clone()) {
|
||||
let msg = format!(
|
||||
"Pallet indices are conflicting: Both pallets {} and {} are at index {}",
|
||||
used_pallet, pallet.name, final_index,
|
||||
);
|
||||
let mut err = syn::Error::new(used_pallet.span(), &msg);
|
||||
err.combine(syn::Error::new(pallet.name.span(), msg));
|
||||
return Err(err)
|
||||
}
|
||||
|
||||
if let Some(used_pallet) = names.insert(pallet.name.clone(), pallet.name.span()) {
|
||||
let msg = "Two pallets with the same name!";
|
||||
if let Some(used_pallet) = names.insert(pallet.name.clone(), pallet.name.span()) {
|
||||
let msg = "Two pallets with the same name!";
|
||||
|
||||
let mut err = syn::Error::new(used_pallet, &msg);
|
||||
err.combine(syn::Error::new(pallet.name.span(), &msg));
|
||||
return Err(err);
|
||||
}
|
||||
let mut err = syn::Error::new(used_pallet, &msg);
|
||||
err.combine(syn::Error::new(pallet.name.span(), &msg));
|
||||
return Err(err)
|
||||
}
|
||||
|
||||
Ok(Pallet {
|
||||
name: pallet.name,
|
||||
index: final_index,
|
||||
path: pallet.path,
|
||||
instance: pallet.instance,
|
||||
pallet_parts: pallet.pallet_parts,
|
||||
})
|
||||
Ok(Pallet {
|
||||
name: pallet.name,
|
||||
index: final_index,
|
||||
path: pallet.path,
|
||||
instance: pallet.instance,
|
||||
pallet_parts: pallet.pallet_parts,
|
||||
})
|
||||
.collect()
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn construct_runtime(input: TokenStream) -> TokenStream {
|
||||
@@ -119,17 +116,9 @@ pub fn construct_runtime(input: TokenStream) -> TokenStream {
|
||||
fn construct_runtime_parsed(definition: RuntimeDefinition) -> Result<TokenStream2> {
|
||||
let RuntimeDefinition {
|
||||
name,
|
||||
where_section: WhereSection {
|
||||
block,
|
||||
node_block,
|
||||
unchecked_extrinsic,
|
||||
..
|
||||
},
|
||||
where_section: WhereSection { block, node_block, unchecked_extrinsic, .. },
|
||||
pallets:
|
||||
ext::Braces {
|
||||
content: ext::Punctuated { inner: pallets, .. },
|
||||
token: pallets_token,
|
||||
},
|
||||
ext::Braces { content: ext::Punctuated { inner: pallets, .. }, token: pallets_token },
|
||||
..
|
||||
} = definition;
|
||||
|
||||
@@ -148,13 +137,8 @@ fn construct_runtime_parsed(definition: RuntimeDefinition) -> Result<TokenStream
|
||||
let dispatch = expand::expand_outer_dispatch(&name, &pallets, &scrate);
|
||||
let metadata = expand::expand_runtime_metadata(&name, &pallets, &scrate, &unchecked_extrinsic);
|
||||
let outer_config = expand::expand_outer_config(&name, &pallets, &scrate);
|
||||
let inherent = expand::expand_outer_inherent(
|
||||
&name,
|
||||
&block,
|
||||
&unchecked_extrinsic,
|
||||
&pallets,
|
||||
&scrate,
|
||||
);
|
||||
let inherent =
|
||||
expand::expand_outer_inherent(&name, &block, &unchecked_extrinsic, &pallets, &scrate);
|
||||
let validate_unsigned = expand::expand_outer_validate_unsigned(&name, &pallets, &scrate);
|
||||
let integrity_test = decl_integrity_test(&scrate);
|
||||
|
||||
@@ -210,12 +194,7 @@ fn decl_all_pallets<'a>(
|
||||
let type_name = &pallet_declaration.name;
|
||||
let pallet = &pallet_declaration.path;
|
||||
let mut generics = vec![quote!(#runtime)];
|
||||
generics.extend(
|
||||
pallet_declaration
|
||||
.instance
|
||||
.iter()
|
||||
.map(|name| quote!(#pallet::#name)),
|
||||
);
|
||||
generics.extend(pallet_declaration.instance.iter().map(|name| quote!(#pallet::#name)));
|
||||
let type_decl = quote!(
|
||||
pub type #type_name = #pallet::Pallet <#(#generics),*>;
|
||||
);
|
||||
@@ -224,11 +203,13 @@ fn decl_all_pallets<'a>(
|
||||
}
|
||||
// Make nested tuple structure like (((Babe, Consensus), Grandpa), ...)
|
||||
// But ignore the system pallet.
|
||||
let all_pallets = names.iter()
|
||||
let all_pallets = names
|
||||
.iter()
|
||||
.filter(|n| **n != SYSTEM_PALLET_NAME)
|
||||
.fold(TokenStream2::default(), |combined, name| quote!((#name, #combined)));
|
||||
|
||||
let all_pallets_with_system = names.iter()
|
||||
let all_pallets_with_system = names
|
||||
.iter()
|
||||
.fold(TokenStream2::default(), |combined, name| quote!((#name, #combined)));
|
||||
|
||||
quote!(
|
||||
@@ -258,8 +239,7 @@ fn decl_pallet_runtime_setup(
|
||||
let names = pallet_declarations.iter().map(|d| &d.name);
|
||||
let names2 = pallet_declarations.iter().map(|d| &d.name);
|
||||
let name_strings = pallet_declarations.iter().map(|d| d.name.to_string());
|
||||
let indices = pallet_declarations.iter()
|
||||
.map(|pallet| pallet.index as usize);
|
||||
let indices = pallet_declarations.iter().map(|pallet| pallet.index as usize);
|
||||
|
||||
quote!(
|
||||
/// Provides an implementation of `PalletInfo` to provide information
|
||||
|
||||
@@ -77,9 +77,9 @@ impl Parse for WhereSection {
|
||||
definitions.push(definition);
|
||||
if !input.peek(Token![,]) {
|
||||
if !input.peek(token::Brace) {
|
||||
return Err(input.error("Expected `,` or `{`"));
|
||||
return Err(input.error("Expected `,` or `{`"))
|
||||
}
|
||||
break;
|
||||
break
|
||||
}
|
||||
input.parse::<Token![,]>()?;
|
||||
}
|
||||
@@ -87,23 +87,14 @@ impl Parse for WhereSection {
|
||||
let node_block = remove_kind(input, WhereKind::NodeBlock, &mut definitions)?.value;
|
||||
let unchecked_extrinsic =
|
||||
remove_kind(input, WhereKind::UncheckedExtrinsic, &mut definitions)?.value;
|
||||
if let Some(WhereDefinition {
|
||||
ref kind_span,
|
||||
ref kind,
|
||||
..
|
||||
}) = definitions.first()
|
||||
{
|
||||
if let Some(WhereDefinition { ref kind_span, ref kind, .. }) = definitions.first() {
|
||||
let msg = format!(
|
||||
"`{:?}` was declared above. Please use exactly one declaration for `{:?}`.",
|
||||
kind, kind
|
||||
);
|
||||
return Err(Error::new(*kind_span, msg));
|
||||
return Err(Error::new(*kind_span, msg))
|
||||
}
|
||||
Ok(Self {
|
||||
block,
|
||||
node_block,
|
||||
unchecked_extrinsic,
|
||||
})
|
||||
Ok(Self { block, node_block, unchecked_extrinsic })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,17 +118,11 @@ impl Parse for WhereDefinition {
|
||||
let (kind_span, kind) = if lookahead.peek(keyword::Block) {
|
||||
(input.parse::<keyword::Block>()?.span(), WhereKind::Block)
|
||||
} else if lookahead.peek(keyword::NodeBlock) {
|
||||
(
|
||||
input.parse::<keyword::NodeBlock>()?.span(),
|
||||
WhereKind::NodeBlock,
|
||||
)
|
||||
(input.parse::<keyword::NodeBlock>()?.span(), WhereKind::NodeBlock)
|
||||
} else if lookahead.peek(keyword::UncheckedExtrinsic) {
|
||||
(
|
||||
input.parse::<keyword::UncheckedExtrinsic>()?.span(),
|
||||
WhereKind::UncheckedExtrinsic,
|
||||
)
|
||||
(input.parse::<keyword::UncheckedExtrinsic>()?.span(), WhereKind::UncheckedExtrinsic)
|
||||
} else {
|
||||
return Err(lookahead.error());
|
||||
return Err(lookahead.error())
|
||||
};
|
||||
|
||||
Ok(Self {
|
||||
@@ -187,13 +172,7 @@ impl Parse for PalletDeclaration {
|
||||
None
|
||||
};
|
||||
|
||||
let parsed = Self {
|
||||
name,
|
||||
path,
|
||||
instance,
|
||||
pallet_parts,
|
||||
index,
|
||||
};
|
||||
let parsed = Self { name, path, instance, pallet_parts, index };
|
||||
|
||||
Ok(parsed)
|
||||
}
|
||||
@@ -214,17 +193,17 @@ impl Parse for PalletPath {
|
||||
let mut lookahead = input.lookahead1();
|
||||
let mut segments = Punctuated::new();
|
||||
|
||||
if lookahead.peek(Token![crate])
|
||||
|| lookahead.peek(Token![self])
|
||||
|| lookahead.peek(Token![super])
|
||||
|| lookahead.peek(Ident)
|
||||
if lookahead.peek(Token![crate]) ||
|
||||
lookahead.peek(Token![self]) ||
|
||||
lookahead.peek(Token![super]) ||
|
||||
lookahead.peek(Ident)
|
||||
{
|
||||
let ident = input.call(Ident::parse_any)?;
|
||||
segments.push(PathSegment { ident, arguments: PathArguments::None });
|
||||
let _: Token![::] = input.parse()?;
|
||||
lookahead = input.lookahead1();
|
||||
} else {
|
||||
return Err(lookahead.error());
|
||||
return Err(lookahead.error())
|
||||
}
|
||||
|
||||
while lookahead.peek(Ident) {
|
||||
@@ -235,15 +214,10 @@ impl Parse for PalletPath {
|
||||
}
|
||||
|
||||
if !lookahead.peek(token::Brace) && !lookahead.peek(Token![<]) {
|
||||
return Err(lookahead.error());
|
||||
return Err(lookahead.error())
|
||||
}
|
||||
|
||||
Ok(Self {
|
||||
inner: Path {
|
||||
leading_colon: None,
|
||||
segments,
|
||||
}
|
||||
})
|
||||
Ok(Self { inner: Path { leading_colon: None, segments } })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -257,7 +231,7 @@ impl quote::ToTokens for PalletPath {
|
||||
///
|
||||
/// `{ Call, Event }`
|
||||
fn parse_pallet_parts(input: ParseStream) -> Result<Vec<PalletPart>> {
|
||||
let pallet_parts :ext::Braces<ext::Punctuated<PalletPart, Token![,]>> = input.parse()?;
|
||||
let pallet_parts: ext::Braces<ext::Punctuated<PalletPart, Token![,]>> = input.parse()?;
|
||||
|
||||
let mut resolved = HashSet::new();
|
||||
for part in pallet_parts.content.inner.iter() {
|
||||
@@ -266,7 +240,7 @@ fn parse_pallet_parts(input: ParseStream) -> Result<Vec<PalletPart>> {
|
||||
"`{}` was already declared before. Please remove the duplicate declaration",
|
||||
part.name(),
|
||||
);
|
||||
return Err(Error::new(part.keyword.span(), msg));
|
||||
return Err(Error::new(part.keyword.span(), msg))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -371,13 +345,10 @@ impl Parse for PalletPart {
|
||||
keyword.name(),
|
||||
valid_generics,
|
||||
);
|
||||
return Err(syn::Error::new(keyword.span(), msg));
|
||||
return Err(syn::Error::new(keyword.span(), msg))
|
||||
}
|
||||
|
||||
Ok(Self {
|
||||
keyword,
|
||||
generics,
|
||||
})
|
||||
Ok(Self { keyword, generics })
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -30,9 +30,10 @@ pub fn derive_debug_no_bound(input: proc_macro::TokenStream) -> proc_macro::Toke
|
||||
let impl_ = match input.data {
|
||||
syn::Data::Struct(struct_) => match struct_.fields {
|
||||
syn::Fields::Named(named) => {
|
||||
let fields = named.named.iter()
|
||||
.map(|i| &i.ident)
|
||||
.map(|i| quote::quote_spanned!(i.span() => .field(stringify!(#i), &self.#i) ));
|
||||
let fields =
|
||||
named.named.iter().map(|i| &i.ident).map(
|
||||
|i| quote::quote_spanned!(i.span() => .field(stringify!(#i), &self.#i) ),
|
||||
);
|
||||
|
||||
quote::quote!(
|
||||
fmt.debug_struct(stringify!(#input_ident))
|
||||
@@ -41,7 +42,10 @@ pub fn derive_debug_no_bound(input: proc_macro::TokenStream) -> proc_macro::Toke
|
||||
)
|
||||
},
|
||||
syn::Fields::Unnamed(unnamed) => {
|
||||
let fields = unnamed.unnamed.iter().enumerate()
|
||||
let fields = unnamed
|
||||
.unnamed
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, _)| syn::Index::from(i))
|
||||
.map(|i| quote::quote_spanned!(i.span() => .field(&self.#i) ));
|
||||
|
||||
@@ -51,46 +55,50 @@ pub fn derive_debug_no_bound(input: proc_macro::TokenStream) -> proc_macro::Toke
|
||||
.finish()
|
||||
)
|
||||
},
|
||||
syn::Fields::Unit => quote::quote!( fmt.write_str(stringify!(#input_ident)) ),
|
||||
syn::Fields::Unit => quote::quote!(fmt.write_str(stringify!(#input_ident))),
|
||||
},
|
||||
syn::Data::Enum(enum_) => {
|
||||
let variants = enum_.variants.iter()
|
||||
.map(|variant| {
|
||||
let ident = &variant.ident;
|
||||
let full_variant_str = format!("{}::{}", input_ident, ident);
|
||||
match &variant.fields {
|
||||
syn::Fields::Named(named) => {
|
||||
let captured = named.named.iter().map(|i| &i.ident);
|
||||
let debugged = captured.clone()
|
||||
.map(|i| quote::quote_spanned!(i.span() =>
|
||||
.field(stringify!(#i), &#i)
|
||||
));
|
||||
quote::quote!(
|
||||
Self::#ident { #( ref #captured, )* } => {
|
||||
fmt.debug_struct(#full_variant_str)
|
||||
#( #debugged )*
|
||||
.finish()
|
||||
}
|
||||
let variants = enum_.variants.iter().map(|variant| {
|
||||
let ident = &variant.ident;
|
||||
let full_variant_str = format!("{}::{}", input_ident, ident);
|
||||
match &variant.fields {
|
||||
syn::Fields::Named(named) => {
|
||||
let captured = named.named.iter().map(|i| &i.ident);
|
||||
let debugged = captured.clone().map(|i| {
|
||||
quote::quote_spanned!(i.span() =>
|
||||
.field(stringify!(#i), &#i)
|
||||
)
|
||||
},
|
||||
syn::Fields::Unnamed(unnamed) => {
|
||||
let captured = unnamed.unnamed.iter().enumerate()
|
||||
.map(|(i, f)| syn::Ident::new(&format!("_{}", i), f.span()));
|
||||
let debugged = captured.clone()
|
||||
.map(|i| quote::quote_spanned!(i.span() => .field(&#i)));
|
||||
quote::quote!(
|
||||
Self::#ident ( #( ref #captured, )* ) => {
|
||||
fmt.debug_tuple(#full_variant_str)
|
||||
#( #debugged )*
|
||||
.finish()
|
||||
}
|
||||
)
|
||||
},
|
||||
syn::Fields::Unit => quote::quote!(
|
||||
Self::#ident => fmt.write_str(#full_variant_str)
|
||||
),
|
||||
}
|
||||
});
|
||||
});
|
||||
quote::quote!(
|
||||
Self::#ident { #( ref #captured, )* } => {
|
||||
fmt.debug_struct(#full_variant_str)
|
||||
#( #debugged )*
|
||||
.finish()
|
||||
}
|
||||
)
|
||||
},
|
||||
syn::Fields::Unnamed(unnamed) => {
|
||||
let captured = unnamed
|
||||
.unnamed
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, f)| syn::Ident::new(&format!("_{}", i), f.span()));
|
||||
let debugged = captured
|
||||
.clone()
|
||||
.map(|i| quote::quote_spanned!(i.span() => .field(&#i)));
|
||||
quote::quote!(
|
||||
Self::#ident ( #( ref #captured, )* ) => {
|
||||
fmt.debug_tuple(#full_variant_str)
|
||||
#( #debugged )*
|
||||
.finish()
|
||||
}
|
||||
)
|
||||
},
|
||||
syn::Fields::Unit => quote::quote!(
|
||||
Self::#ident => fmt.write_str(#full_variant_str)
|
||||
),
|
||||
}
|
||||
});
|
||||
|
||||
quote::quote!(match *self {
|
||||
#( #variants, )*
|
||||
@@ -110,5 +118,6 @@ pub fn derive_debug_no_bound(input: proc_macro::TokenStream) -> proc_macro::Toke
|
||||
}
|
||||
}
|
||||
};
|
||||
).into()
|
||||
)
|
||||
.into()
|
||||
}
|
||||
|
||||
@@ -30,56 +30,60 @@ pub fn derive_default_no_bound(input: proc_macro::TokenStream) -> proc_macro::To
|
||||
let impl_ = match input.data {
|
||||
syn::Data::Struct(struct_) => match struct_.fields {
|
||||
syn::Fields::Named(named) => {
|
||||
let fields = named.named.iter()
|
||||
.map(|i| &i.ident)
|
||||
.map(|i| quote::quote_spanned!(i.span() =>
|
||||
let fields = named.named.iter().map(|i| &i.ident).map(|i| {
|
||||
quote::quote_spanned!(i.span() =>
|
||||
#i: core::default::Default::default()
|
||||
));
|
||||
)
|
||||
});
|
||||
|
||||
quote::quote!( Self { #( #fields, )* } )
|
||||
},
|
||||
syn::Fields::Unnamed(unnamed) => {
|
||||
let fields = unnamed.unnamed.iter().enumerate()
|
||||
.map(|(i, _)| syn::Index::from(i))
|
||||
.map(|i| quote::quote_spanned!(i.span() =>
|
||||
core::default::Default::default()
|
||||
));
|
||||
let fields =
|
||||
unnamed.unnamed.iter().enumerate().map(|(i, _)| syn::Index::from(i)).map(|i| {
|
||||
quote::quote_spanned!(i.span() =>
|
||||
core::default::Default::default()
|
||||
)
|
||||
});
|
||||
|
||||
quote::quote!( Self ( #( #fields, )* ) )
|
||||
},
|
||||
syn::Fields::Unit => {
|
||||
quote::quote!( Self )
|
||||
}
|
||||
quote::quote!(Self)
|
||||
},
|
||||
},
|
||||
syn::Data::Enum(enum_) => {
|
||||
syn::Data::Enum(enum_) =>
|
||||
if let Some(first_variant) = enum_.variants.first() {
|
||||
let variant_ident = &first_variant.ident;
|
||||
match &first_variant.fields {
|
||||
syn::Fields::Named(named) => {
|
||||
let fields = named.named.iter()
|
||||
.map(|i| &i.ident)
|
||||
.map(|i| quote::quote_spanned!(i.span() =>
|
||||
let fields = named.named.iter().map(|i| &i.ident).map(|i| {
|
||||
quote::quote_spanned!(i.span() =>
|
||||
#i: core::default::Default::default()
|
||||
));
|
||||
)
|
||||
});
|
||||
|
||||
quote::quote!( #name :: #ty_generics :: #variant_ident { #( #fields, )* } )
|
||||
},
|
||||
syn::Fields::Unnamed(unnamed) => {
|
||||
let fields = unnamed.unnamed.iter().enumerate()
|
||||
let fields = unnamed
|
||||
.unnamed
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, _)| syn::Index::from(i))
|
||||
.map(|i| quote::quote_spanned!(i.span() =>
|
||||
core::default::Default::default()
|
||||
));
|
||||
.map(|i| {
|
||||
quote::quote_spanned!(i.span() =>
|
||||
core::default::Default::default()
|
||||
)
|
||||
});
|
||||
|
||||
quote::quote!( #name :: #ty_generics :: #variant_ident ( #( #fields, )* ) )
|
||||
},
|
||||
syn::Fields::Unit => quote::quote!( #name :: #ty_generics :: #variant_ident ),
|
||||
}
|
||||
} else {
|
||||
quote::quote!( Self )
|
||||
}
|
||||
|
||||
},
|
||||
quote::quote!(Self)
|
||||
},
|
||||
syn::Data::Union(_) => {
|
||||
let msg = "Union type not supported by `derive(CloneNoBound)`";
|
||||
return syn::Error::new(input.span(), msg).to_compile_error().into()
|
||||
@@ -94,5 +98,6 @@ pub fn derive_default_no_bound(input: proc_macro::TokenStream) -> proc_macro::To
|
||||
}
|
||||
}
|
||||
};
|
||||
).into()
|
||||
)
|
||||
.into()
|
||||
}
|
||||
|
||||
@@ -1,18 +1,17 @@
|
||||
use proc_macro::TokenStream;
|
||||
use crate::COUNTER;
|
||||
use proc_macro::TokenStream;
|
||||
|
||||
pub fn generate_dummy_part_checker(input: TokenStream) -> TokenStream {
|
||||
if !input.is_empty() {
|
||||
return syn::Error::new(proc_macro2::Span::call_site(), "No arguments expected")
|
||||
.to_compile_error().into()
|
||||
.to_compile_error()
|
||||
.into()
|
||||
}
|
||||
|
||||
let count = COUNTER.with(|counter| counter.borrow_mut().inc());
|
||||
|
||||
let no_op_macro_ident = syn::Ident::new(
|
||||
&format!("__dummy_part_checker_{}", count),
|
||||
proc_macro2::Span::call_site(),
|
||||
);
|
||||
let no_op_macro_ident =
|
||||
syn::Ident::new(&format!("__dummy_part_checker_{}", count), proc_macro2::Span::call_site());
|
||||
|
||||
quote::quote!(
|
||||
#[macro_export]
|
||||
@@ -58,5 +57,6 @@ pub fn generate_dummy_part_checker(input: TokenStream) -> TokenStream {
|
||||
#[doc(hidden)]
|
||||
pub use #no_op_macro_ident as is_origin_part_defined;
|
||||
}
|
||||
).into()
|
||||
)
|
||||
.into()
|
||||
}
|
||||
|
||||
@@ -16,14 +16,14 @@
|
||||
// limitations under the License.
|
||||
|
||||
use proc_macro2::{Span, TokenStream};
|
||||
use quote::{ToTokens, format_ident, quote};
|
||||
use quote::{format_ident, quote, ToTokens};
|
||||
use syn::{Ident, Result};
|
||||
|
||||
const MAX_IDENTS: usize = 18;
|
||||
|
||||
pub fn impl_key_prefix_for_tuples(input: proc_macro::TokenStream) -> Result<TokenStream> {
|
||||
if !input.is_empty() {
|
||||
return Err(syn::Error::new(Span::call_site(), "No arguments expected"));
|
||||
return Err(syn::Error::new(Span::call_site(), "No arguments expected"))
|
||||
}
|
||||
|
||||
let mut all_trait_impls = TokenStream::new();
|
||||
@@ -36,13 +36,17 @@ pub fn impl_key_prefix_for_tuples(input: proc_macro::TokenStream) -> Result<Toke
|
||||
for prefix_count in 1..i {
|
||||
let (prefixes, suffixes) = current_tuple.split_at(prefix_count);
|
||||
|
||||
let hashers = current_tuple.iter().map(|ident| format_ident!("Hasher{}", ident)).collect::<Vec<_>>();
|
||||
let kargs = prefixes.iter().map(|ident| format_ident!("KArg{}", ident)).collect::<Vec<_>>();
|
||||
let hashers = current_tuple
|
||||
.iter()
|
||||
.map(|ident| format_ident!("Hasher{}", ident))
|
||||
.collect::<Vec<_>>();
|
||||
let kargs =
|
||||
prefixes.iter().map(|ident| format_ident!("KArg{}", ident)).collect::<Vec<_>>();
|
||||
let partial_keygen = generate_keygen(prefixes);
|
||||
let suffix_keygen = generate_keygen(suffixes);
|
||||
let suffix_tuple = generate_tuple(suffixes);
|
||||
|
||||
let trait_impls = quote!{
|
||||
let trait_impls = quote! {
|
||||
impl<
|
||||
#(#current_tuple: FullCodec,)*
|
||||
#(#hashers: StorageHasher,)*
|
||||
|
||||
@@ -19,21 +19,21 @@
|
||||
|
||||
#![recursion_limit = "512"]
|
||||
|
||||
mod storage;
|
||||
mod clone_no_bound;
|
||||
mod construct_runtime;
|
||||
mod debug_no_bound;
|
||||
mod default_no_bound;
|
||||
mod dummy_part_checker;
|
||||
mod key_prefix;
|
||||
mod pallet;
|
||||
mod pallet_version;
|
||||
mod transactional;
|
||||
mod debug_no_bound;
|
||||
mod clone_no_bound;
|
||||
mod partial_eq_no_bound;
|
||||
mod default_no_bound;
|
||||
mod key_prefix;
|
||||
mod dummy_part_checker;
|
||||
mod storage;
|
||||
mod transactional;
|
||||
|
||||
pub(crate) use storage::INHERENT_INSTANCE_NAME;
|
||||
use proc_macro::TokenStream;
|
||||
use std::cell::RefCell;
|
||||
pub(crate) use storage::INHERENT_INSTANCE_NAME;
|
||||
|
||||
thread_local! {
|
||||
/// A global counter, can be used to generate a relatively unique identifier.
|
||||
@@ -200,14 +200,14 @@ impl Counter {
|
||||
///
|
||||
/// // Your storage items
|
||||
/// }
|
||||
/// add_extra_genesis {
|
||||
/// config(genesis_field): GenesisFieldType;
|
||||
/// config(genesis_field2): GenesisFieldType;
|
||||
/// ...
|
||||
/// build(|_: &Self| {
|
||||
/// // Modification of storage
|
||||
/// })
|
||||
/// }
|
||||
/// add_extra_genesis {
|
||||
/// config(genesis_field): GenesisFieldType;
|
||||
/// config(genesis_field2): GenesisFieldType;
|
||||
/// ...
|
||||
/// build(|_: &Self| {
|
||||
/// // Modification of storage
|
||||
/// })
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
@@ -219,7 +219,7 @@ impl Counter {
|
||||
/// ...,
|
||||
/// Example: example::{Pallet, Storage, ..., Config<T>},
|
||||
/// ...,
|
||||
/// }
|
||||
/// }
|
||||
/// );
|
||||
/// ```
|
||||
///
|
||||
@@ -413,7 +413,8 @@ pub fn derive_runtime_debug_no_bound(input: TokenStream) -> TokenStream {
|
||||
}
|
||||
}
|
||||
};
|
||||
).into()
|
||||
)
|
||||
.into()
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
@@ -444,7 +445,8 @@ pub fn derive_eq_no_bound(input: TokenStream) -> TokenStream {
|
||||
const _: () = {
|
||||
impl #impl_generics core::cmp::Eq for #name #ty_generics #where_clause {}
|
||||
};
|
||||
).into()
|
||||
)
|
||||
.into()
|
||||
}
|
||||
|
||||
/// derive `Default` but do no bound any generic. Docs are at `frame_support::DefaultNoBound`.
|
||||
@@ -455,12 +457,15 @@ pub fn derive_default_no_bound(input: TokenStream) -> TokenStream {
|
||||
|
||||
#[proc_macro_attribute]
|
||||
pub fn require_transactional(attr: TokenStream, input: TokenStream) -> TokenStream {
|
||||
transactional::require_transactional(attr, input).unwrap_or_else(|e| e.to_compile_error().into())
|
||||
transactional::require_transactional(attr, input)
|
||||
.unwrap_or_else(|e| e.to_compile_error().into())
|
||||
}
|
||||
|
||||
#[proc_macro]
|
||||
pub fn crate_to_pallet_version(input: TokenStream) -> TokenStream {
|
||||
pallet_version::crate_to_pallet_version(input).unwrap_or_else(|e| e.to_compile_error()).into()
|
||||
pallet_version::crate_to_pallet_version(input)
|
||||
.unwrap_or_else(|e| e.to_compile_error())
|
||||
.into()
|
||||
}
|
||||
|
||||
/// The number of module instances supported by the runtime, starting at index 1,
|
||||
@@ -471,7 +476,9 @@ pub(crate) const NUMBER_OF_INSTANCE: u8 = 16;
|
||||
/// It implements the trait `HasKeyPrefix` and `HasReversibleKeyPrefix` for tuple of `Key`.
|
||||
#[proc_macro]
|
||||
pub fn impl_key_prefix_for_tuples(input: TokenStream) -> TokenStream {
|
||||
key_prefix::impl_key_prefix_for_tuples(input).unwrap_or_else(syn::Error::into_compile_error).into()
|
||||
key_prefix::impl_key_prefix_for_tuples(input)
|
||||
.unwrap_or_else(syn::Error::into_compile_error)
|
||||
.into()
|
||||
}
|
||||
|
||||
/// Internal macro use by frame_support to generate dummy part checker for old pallet declaration
|
||||
|
||||
@@ -15,9 +15,8 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use crate::pallet::Def;
|
||||
use crate::{pallet::Def, COUNTER};
|
||||
use frame_support_procedural_tools::clean_type_string;
|
||||
use crate::COUNTER;
|
||||
use syn::spanned::Spanned;
|
||||
|
||||
/// * Generate enum call and implement various trait on it.
|
||||
@@ -31,7 +30,7 @@ pub fn expand_call(def: &mut Def) -> proc_macro2::TokenStream {
|
||||
let docs = call.docs.clone();
|
||||
|
||||
(span, where_clause, methods, docs)
|
||||
}
|
||||
},
|
||||
None => (def.item.span(), None, Vec::new(), Vec::new()),
|
||||
};
|
||||
let frame_support = &def.frame_support;
|
||||
@@ -48,16 +47,20 @@ pub fn expand_call(def: &mut Def) -> proc_macro2::TokenStream {
|
||||
|
||||
let fn_doc = methods.iter().map(|method| &method.docs).collect::<Vec<_>>();
|
||||
|
||||
let args_name = methods.iter()
|
||||
let args_name = methods
|
||||
.iter()
|
||||
.map(|method| method.args.iter().map(|(_, name, _)| name.clone()).collect::<Vec<_>>())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let args_type = methods.iter()
|
||||
let args_type = methods
|
||||
.iter()
|
||||
.map(|method| method.args.iter().map(|(_, _, type_)| type_.clone()).collect::<Vec<_>>())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let args_compact_attr = methods.iter().map(|method| {
|
||||
method.args.iter()
|
||||
method
|
||||
.args
|
||||
.iter()
|
||||
.map(|(is_compact, _, type_)| {
|
||||
if *is_compact {
|
||||
quote::quote_spanned!(type_.span() => #[codec(compact)] )
|
||||
@@ -69,7 +72,9 @@ pub fn expand_call(def: &mut Def) -> proc_macro2::TokenStream {
|
||||
});
|
||||
|
||||
let args_metadata_type = methods.iter().map(|method| {
|
||||
method.args.iter()
|
||||
method
|
||||
.args
|
||||
.iter()
|
||||
.map(|(is_compact, _, type_)| {
|
||||
let final_type = if *is_compact {
|
||||
quote::quote_spanned!(type_.span() => Compact<#type_>)
|
||||
@@ -84,14 +89,10 @@ pub fn expand_call(def: &mut Def) -> proc_macro2::TokenStream {
|
||||
let default_docs = [syn::parse_quote!(
|
||||
r"Contains one variant per dispatchable that can be called by an extrinsic."
|
||||
)];
|
||||
let docs = if docs.is_empty() {
|
||||
&default_docs[..]
|
||||
} else {
|
||||
&docs[..]
|
||||
};
|
||||
let docs = if docs.is_empty() { &default_docs[..] } else { &docs[..] };
|
||||
|
||||
let maybe_compile_error = if def.call.is_none() {
|
||||
quote::quote!{
|
||||
quote::quote! {
|
||||
compile_error!(concat!(
|
||||
"`",
|
||||
stringify!($pallet_name),
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use crate::pallet::{Def, parse::helper::get_doc_literals};
|
||||
use crate::pallet::{parse::helper::get_doc_literals, Def};
|
||||
|
||||
/// * Generate default rust doc
|
||||
pub fn expand_config(def: &mut Def) -> proc_macro2::TokenStream {
|
||||
|
||||
@@ -71,58 +71,55 @@ pub fn expand_constants(def: &mut Def) -> proc_macro2::TokenStream {
|
||||
}
|
||||
});
|
||||
|
||||
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()
|
||||
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)>
|
||||
);
|
||||
|
||||
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<u8> {
|
||||
#default_byte_impl
|
||||
}
|
||||
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<u8> {
|
||||
#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
|
||||
{}
|
||||
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
|
||||
)
|
||||
#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 ),* ]
|
||||
),
|
||||
}
|
||||
})
|
||||
});
|
||||
)
|
||||
),
|
||||
documentation: #frame_support::dispatch::DecodeDifferent::Encode(
|
||||
&[ #( #doc ),* ]
|
||||
),
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
quote::quote!(
|
||||
impl<#type_impl_gen> #pallet_ident<#type_use_gen> #completed_where_clause{
|
||||
|
||||
@@ -15,16 +15,12 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use crate::pallet::{Def, parse::helper::get_doc_literals};
|
||||
use crate::pallet::{parse::helper::get_doc_literals, Def};
|
||||
|
||||
/// * impl various trait on Error
|
||||
/// * impl ModuleErrorMetadata for Error
|
||||
pub fn expand_error(def: &mut Def) -> proc_macro2::TokenStream {
|
||||
let error = if let Some(error) = &def.error {
|
||||
error
|
||||
} else {
|
||||
return Default::default()
|
||||
};
|
||||
let error = if let Some(error) = &def.error { error } else { return Default::default() };
|
||||
|
||||
let error_ident = &error.error;
|
||||
let frame_support = &def.frame_support;
|
||||
@@ -41,27 +37,24 @@ pub fn expand_error(def: &mut Def) -> proc_macro2::TokenStream {
|
||||
)
|
||||
);
|
||||
|
||||
let as_u8_matches = error.variants.iter().enumerate()
|
||||
.map(|(i, (variant, _))| {
|
||||
quote::quote_spanned!(error.attr_span => Self::#variant => #i as u8,)
|
||||
});
|
||||
let as_u8_matches = error.variants.iter().enumerate().map(
|
||||
|(i, (variant, _))| quote::quote_spanned!(error.attr_span => Self::#variant => #i as u8,),
|
||||
);
|
||||
|
||||
let as_str_matches = error.variants.iter()
|
||||
.map(|(variant, _)| {
|
||||
let variant_str = format!("{}", variant);
|
||||
quote::quote_spanned!(error.attr_span => Self::#variant => #variant_str,)
|
||||
});
|
||||
let as_str_matches = error.variants.iter().map(|(variant, _)| {
|
||||
let variant_str = format!("{}", variant);
|
||||
quote::quote_spanned!(error.attr_span => Self::#variant => #variant_str,)
|
||||
});
|
||||
|
||||
let metadata = error.variants.iter()
|
||||
.map(|(variant, doc)| {
|
||||
let variant_str = format!("{}", variant);
|
||||
quote::quote_spanned!(error.attr_span =>
|
||||
#frame_support::error::ErrorMetadata {
|
||||
name: #frame_support::error::DecodeDifferent::Encode(#variant_str),
|
||||
documentation: #frame_support::error::DecodeDifferent::Encode(&[ #( #doc, )* ]),
|
||||
},
|
||||
)
|
||||
});
|
||||
let metadata = error.variants.iter().map(|(variant, doc)| {
|
||||
let variant_str = format!("{}", variant);
|
||||
quote::quote_spanned!(error.attr_span =>
|
||||
#frame_support::error::ErrorMetadata {
|
||||
name: #frame_support::error::DecodeDifferent::Encode(#variant_str),
|
||||
documentation: #frame_support::error::DecodeDifferent::Encode(&[ #( #doc, )* ]),
|
||||
},
|
||||
)
|
||||
});
|
||||
|
||||
let error_item = {
|
||||
let item = &mut def.item.content.as_mut().expect("Checked by def parser").1[error.index];
|
||||
|
||||
@@ -15,8 +15,10 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use crate::pallet::{Def, parse::helper::get_doc_literals};
|
||||
use crate::COUNTER;
|
||||
use crate::{
|
||||
pallet::{parse::helper::get_doc_literals, Def},
|
||||
COUNTER,
|
||||
};
|
||||
use syn::{spanned::Spanned, Ident};
|
||||
|
||||
/// * Add __Ignore variant on Event
|
||||
@@ -29,10 +31,8 @@ pub fn expand_event(def: &mut Def) -> proc_macro2::TokenStream {
|
||||
let ident = Ident::new(&format!("__is_event_part_defined_{}", count), event.attr_span);
|
||||
(event, ident)
|
||||
} else {
|
||||
let macro_ident = Ident::new(
|
||||
&format!("__is_event_part_defined_{}", count),
|
||||
def.item.span(),
|
||||
);
|
||||
let macro_ident =
|
||||
Ident::new(&format!("__is_event_part_defined_{}", count), def.item.span());
|
||||
|
||||
return quote::quote! {
|
||||
#[doc(hidden)]
|
||||
@@ -49,42 +49,39 @@ pub fn expand_event(def: &mut Def) -> proc_macro2::TokenStream {
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[doc(hidden)]
|
||||
pub use #macro_ident as is_event_part_defined;
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
let event_where_clause = &event.where_clause;
|
||||
|
||||
// NOTE: actually event where clause must be a subset of config where clause because of
|
||||
// `type Event: From<Event<Self>>`. But we merge either way for potential better error message
|
||||
let completed_where_clause = super::merge_where_clauses(&[
|
||||
&event.where_clause,
|
||||
&def.config.where_clause,
|
||||
]);
|
||||
let completed_where_clause =
|
||||
super::merge_where_clauses(&[&event.where_clause, &def.config.where_clause]);
|
||||
|
||||
let event_ident = &event.event;
|
||||
let frame_system = &def.frame_system;
|
||||
let frame_support = &def.frame_support;
|
||||
let event_use_gen = &event.gen_kind.type_use_gen(event.attr_span);
|
||||
let event_impl_gen= &event.gen_kind.type_impl_gen(event.attr_span);
|
||||
let metadata = event.metadata.iter()
|
||||
.map(|(ident, args, docs)| {
|
||||
let name = format!("{}", ident);
|
||||
quote::quote_spanned!(event.attr_span =>
|
||||
#frame_support::event::EventMetadata {
|
||||
name: #frame_support::event::DecodeDifferent::Encode(#name),
|
||||
arguments: #frame_support::event::DecodeDifferent::Encode(&[
|
||||
#( #args, )*
|
||||
]),
|
||||
documentation: #frame_support::event::DecodeDifferent::Encode(&[
|
||||
#( #docs, )*
|
||||
]),
|
||||
},
|
||||
)
|
||||
});
|
||||
let event_impl_gen = &event.gen_kind.type_impl_gen(event.attr_span);
|
||||
let metadata = event.metadata.iter().map(|(ident, args, docs)| {
|
||||
let name = format!("{}", ident);
|
||||
quote::quote_spanned!(event.attr_span =>
|
||||
#frame_support::event::EventMetadata {
|
||||
name: #frame_support::event::DecodeDifferent::Encode(#name),
|
||||
arguments: #frame_support::event::DecodeDifferent::Encode(&[
|
||||
#( #args, )*
|
||||
]),
|
||||
documentation: #frame_support::event::DecodeDifferent::Encode(&[
|
||||
#( #docs, )*
|
||||
]),
|
||||
},
|
||||
)
|
||||
});
|
||||
|
||||
let event_item = {
|
||||
let item = &mut def.item.content.as_mut().expect("Checked by def parser").1[event.index];
|
||||
@@ -166,7 +163,7 @@ pub fn expand_event(def: &mut Def) -> proc_macro2::TokenStream {
|
||||
macro_rules! #macro_ident {
|
||||
($pallet_name:ident) => {};
|
||||
}
|
||||
|
||||
|
||||
#[doc(hidden)]
|
||||
pub use #macro_ident as is_event_part_defined;
|
||||
}
|
||||
|
||||
@@ -40,8 +40,8 @@ pub fn expand_genesis_build(def: &mut Def) -> proc_macro2::TokenStream {
|
||||
|
||||
let gen_cfg_use_gen = genesis_config.gen_kind.type_use_gen(genesis_build.attr_span);
|
||||
|
||||
let genesis_build_item = &mut def.item.content.as_mut()
|
||||
.expect("Checked by def parser").1[genesis_build.index];
|
||||
let genesis_build_item =
|
||||
&mut def.item.content.as_mut().expect("Checked by def parser").1[genesis_build.index];
|
||||
|
||||
let genesis_build_item_impl = if let syn::Item::Impl(impl_) = genesis_build_item {
|
||||
impl_
|
||||
|
||||
@@ -15,9 +15,11 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use crate::pallet::{Def, parse::helper::get_doc_literals};
|
||||
use crate::COUNTER;
|
||||
use syn::{Ident, spanned::Spanned};
|
||||
use crate::{
|
||||
pallet::{parse::helper::get_doc_literals, Def},
|
||||
COUNTER,
|
||||
};
|
||||
use syn::{spanned::Spanned, Ident};
|
||||
|
||||
/// * add various derive trait on GenesisConfig struct.
|
||||
pub fn expand_genesis_config(def: &mut Def) -> proc_macro2::TokenStream {
|
||||
@@ -37,15 +39,11 @@ pub fn expand_genesis_config(def: &mut Def) -> proc_macro2::TokenStream {
|
||||
|
||||
(genesis_config, def_macro_ident, std_macro_ident)
|
||||
} else {
|
||||
let def_macro_ident = Ident::new(
|
||||
&format!("__is_genesis_config_defined_{}", count),
|
||||
def.item.span(),
|
||||
);
|
||||
let def_macro_ident =
|
||||
Ident::new(&format!("__is_genesis_config_defined_{}", count), def.item.span());
|
||||
|
||||
let std_macro_ident = Ident::new(
|
||||
&format!("__is_std_enabled_for_genesis_{}", count),
|
||||
def.item.span(),
|
||||
);
|
||||
let std_macro_ident =
|
||||
Ident::new(&format!("__is_std_enabled_for_genesis_{}", count), def.item.span());
|
||||
|
||||
return quote::quote! {
|
||||
#[doc(hidden)]
|
||||
@@ -74,18 +72,18 @@ pub fn expand_genesis_config(def: &mut Def) -> proc_macro2::TokenStream {
|
||||
#[doc(hidden)]
|
||||
pub use #std_macro_ident as is_std_enabled_for_genesis;
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
let frame_support = &def.frame_support;
|
||||
|
||||
let genesis_config_item = &mut def.item.content.as_mut()
|
||||
.expect("Checked by def parser").1[genesis_config.index];
|
||||
let genesis_config_item =
|
||||
&mut def.item.content.as_mut().expect("Checked by def parser").1[genesis_config.index];
|
||||
|
||||
let serde_crate = format!("{}::serde", frame_support);
|
||||
|
||||
match genesis_config_item {
|
||||
syn::Item::Enum(syn::ItemEnum { attrs, ..}) |
|
||||
syn::Item::Enum(syn::ItemEnum { attrs, .. }) |
|
||||
syn::Item::Struct(syn::ItemStruct { attrs, .. }) |
|
||||
syn::Item::Type(syn::ItemType { attrs, .. }) => {
|
||||
if get_doc_literals(&attrs).is_empty() {
|
||||
|
||||
@@ -59,7 +59,7 @@ pub fn expand_hooks(def: &mut Def) -> proc_macro2::TokenStream {
|
||||
|
||||
let hooks_impl = if def.hooks.is_none() {
|
||||
let frame_system = &def.frame_system;
|
||||
quote::quote!{
|
||||
quote::quote! {
|
||||
impl<#type_impl_gen>
|
||||
#frame_support::traits::Hooks<<T as #frame_system::Config>::BlockNumber>
|
||||
for Pallet<#type_use_gen> {}
|
||||
|
||||
@@ -15,11 +15,10 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use crate::pallet::Def;
|
||||
use crate::{pallet::Def, COUNTER};
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::quote;
|
||||
use crate::COUNTER;
|
||||
use syn::{Ident, spanned::Spanned};
|
||||
use syn::{spanned::Spanned, Ident};
|
||||
|
||||
pub fn expand_inherents(def: &mut Def) -> TokenStream {
|
||||
let count = COUNTER.with(|counter| counter.borrow_mut().inc());
|
||||
@@ -48,7 +47,7 @@ pub fn expand_inherents(def: &mut Def) -> TokenStream {
|
||||
#maybe_compile_error
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[doc(hidden)]
|
||||
pub use #macro_ident as is_inherent_part_defined;
|
||||
}
|
||||
|
||||
@@ -15,9 +15,8 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use crate::{pallet::Def, NUMBER_OF_INSTANCE};
|
||||
use proc_macro2::Span;
|
||||
use crate::pallet::Def;
|
||||
use crate::NUMBER_OF_INSTANCE;
|
||||
|
||||
/// * Provide inherent instance to be used by construct_runtime
|
||||
/// * Provide Instance1 ..= Instance16 for instantiable pallet
|
||||
@@ -25,7 +24,9 @@ pub fn expand_instances(def: &mut Def) -> proc_macro2::TokenStream {
|
||||
let frame_support = &def.frame_support;
|
||||
let inherent_ident = syn::Ident::new(crate::INHERENT_INSTANCE_NAME, Span::call_site());
|
||||
let instances = if def.config.has_instance {
|
||||
(1..=NUMBER_OF_INSTANCE).map(|i| syn::Ident::new(&format!("Instance{}", i), Span::call_site())).collect()
|
||||
(1..=NUMBER_OF_INSTANCE)
|
||||
.map(|i| syn::Ident::new(&format!("Instance{}", i), Span::call_site()))
|
||||
.collect()
|
||||
} else {
|
||||
vec![]
|
||||
};
|
||||
|
||||
@@ -15,24 +15,24 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
mod constants;
|
||||
mod pallet_struct;
|
||||
mod call;
|
||||
mod config;
|
||||
mod constants;
|
||||
mod error;
|
||||
mod event;
|
||||
mod storage;
|
||||
mod hooks;
|
||||
mod store_trait;
|
||||
mod inherent;
|
||||
mod instances;
|
||||
mod genesis_build;
|
||||
mod genesis_config;
|
||||
mod type_value;
|
||||
mod hooks;
|
||||
mod inherent;
|
||||
mod instances;
|
||||
mod origin;
|
||||
mod pallet_struct;
|
||||
mod storage;
|
||||
mod store_trait;
|
||||
mod type_value;
|
||||
mod validate_unsigned;
|
||||
|
||||
use crate::pallet::{Def, parse::helper::get_doc_literals};
|
||||
use crate::pallet::{parse::helper::get_doc_literals, Def};
|
||||
use quote::ToTokens;
|
||||
|
||||
/// Merge where clause together, `where` token span is taken from the first not none one.
|
||||
@@ -97,7 +97,11 @@ pub fn expand(mut def: Def) -> proc_macro2::TokenStream {
|
||||
#validate_unsigned
|
||||
);
|
||||
|
||||
def.item.content.as_mut().expect("This is checked by parsing").1
|
||||
def.item
|
||||
.content
|
||||
.as_mut()
|
||||
.expect("This is checked by parsing")
|
||||
.1
|
||||
.push(syn::Item::Verbatim(new_items));
|
||||
|
||||
def.item.into_token_stream()
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
use crate::{pallet::Def, COUNTER};
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::quote;
|
||||
use syn::{Ident, spanned::Spanned};
|
||||
use syn::{spanned::Spanned, Ident};
|
||||
|
||||
pub fn expand_origins(def: &mut Def) -> TokenStream {
|
||||
let count = COUNTER.with(|counter| counter.borrow_mut().inc());
|
||||
@@ -47,7 +47,7 @@ pub fn expand_origins(def: &mut Def) -> TokenStream {
|
||||
#maybe_compile_error
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[doc(hidden)]
|
||||
pub use #macro_ident as is_origin_part_defined;
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use crate::pallet::{Def, expand::merge_where_clauses, parse::helper::get_doc_literals};
|
||||
use crate::pallet::{expand::merge_where_clauses, parse::helper::get_doc_literals, Def};
|
||||
|
||||
/// * Add derive trait on Pallet
|
||||
/// * Implement GetPalletVersion on Pallet
|
||||
@@ -104,29 +104,25 @@ pub fn expand_pallet_struct(def: &mut Def) -> proc_macro2::TokenStream {
|
||||
|
||||
// Depending on the flag `generate_storage_info` we use partial or full storage info from
|
||||
// storage.
|
||||
let (
|
||||
storage_info_span,
|
||||
storage_info_trait,
|
||||
storage_info_method,
|
||||
) = if let Some(span) = def.pallet_struct.generate_storage_info {
|
||||
(
|
||||
span,
|
||||
quote::quote_spanned!(span => StorageInfoTrait),
|
||||
quote::quote_spanned!(span => storage_info),
|
||||
)
|
||||
} else {
|
||||
let span = def.pallet_struct.attr_span;
|
||||
(
|
||||
span,
|
||||
quote::quote_spanned!(span => PartialStorageInfoTrait),
|
||||
quote::quote_spanned!(span => partial_storage_info),
|
||||
)
|
||||
};
|
||||
let (storage_info_span, storage_info_trait, storage_info_method) =
|
||||
if let Some(span) = def.pallet_struct.generate_storage_info {
|
||||
(
|
||||
span,
|
||||
quote::quote_spanned!(span => StorageInfoTrait),
|
||||
quote::quote_spanned!(span => storage_info),
|
||||
)
|
||||
} else {
|
||||
let span = def.pallet_struct.attr_span;
|
||||
(
|
||||
span,
|
||||
quote::quote_spanned!(span => PartialStorageInfoTrait),
|
||||
quote::quote_spanned!(span => partial_storage_info),
|
||||
)
|
||||
};
|
||||
|
||||
let storage_names = &def.storages.iter().map(|storage| &storage.ident).collect::<Vec<_>>();
|
||||
let storage_cfg_attrs = &def.storages.iter()
|
||||
.map(|storage| &storage.cfg_attrs)
|
||||
.collect::<Vec<_>>();
|
||||
let storage_cfg_attrs =
|
||||
&def.storages.iter().map(|storage| &storage.cfg_attrs).collect::<Vec<_>>();
|
||||
|
||||
let storage_info = quote::quote_spanned!(storage_info_span =>
|
||||
impl<#type_impl_gen> #frame_support::traits::StorageInfoTrait
|
||||
|
||||
@@ -15,8 +15,10 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use crate::pallet::{Def, parse::storage::StorageDef};
|
||||
use crate::pallet::parse::storage::{Metadata, QueryKind, StorageGenerics};
|
||||
use crate::pallet::{
|
||||
parse::storage::{Metadata, QueryKind, StorageDef, StorageGenerics},
|
||||
Def,
|
||||
};
|
||||
use frame_support_procedural_tools::clean_type_string;
|
||||
use std::collections::HashSet;
|
||||
|
||||
@@ -30,10 +32,7 @@ fn prefix_ident(storage: &StorageDef) -> syn::Ident {
|
||||
/// Check for duplicated storage prefixes. This step is necessary since users can specify an
|
||||
/// alternative storage prefix using the #[pallet::storage_prefix] syntax, and we need to ensure
|
||||
/// that the prefix specified by the user is not a duplicate of an existing one.
|
||||
fn check_prefix_duplicates(
|
||||
storage_def: &StorageDef,
|
||||
set: &mut HashSet<String>,
|
||||
) -> syn::Result<()> {
|
||||
fn check_prefix_duplicates(storage_def: &StorageDef, set: &mut HashSet<String>) -> syn::Result<()> {
|
||||
let prefix = storage_def.prefix();
|
||||
|
||||
if !set.insert(prefix.clone()) {
|
||||
@@ -41,7 +40,7 @@ fn check_prefix_duplicates(
|
||||
storage_def.prefix_span(),
|
||||
format!("Duplicate storage prefixes found for `{}`", prefix),
|
||||
);
|
||||
return Err(err);
|
||||
return Err(err)
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@@ -85,10 +84,8 @@ pub fn process_generics(def: &mut Def) -> syn::Result<()> {
|
||||
|
||||
let default_query_kind: syn::Type =
|
||||
syn::parse_quote!(#frame_support::storage::types::OptionQuery);
|
||||
let default_on_empty: syn::Type =
|
||||
syn::parse_quote!(#frame_support::traits::GetDefault);
|
||||
let default_max_values: syn::Type =
|
||||
syn::parse_quote!(#frame_support::traits::GetDefault);
|
||||
let default_on_empty: syn::Type = syn::parse_quote!(#frame_support::traits::GetDefault);
|
||||
let default_max_values: syn::Type = syn::parse_quote!(#frame_support::traits::GetDefault);
|
||||
|
||||
if let Some(named_generics) = storage_def.named_generics.clone() {
|
||||
args.args.clear();
|
||||
@@ -100,7 +97,7 @@ pub fn process_generics(def: &mut Def) -> syn::Result<()> {
|
||||
args.args.push(syn::GenericArgument::Type(query_kind));
|
||||
let on_empty = on_empty.unwrap_or_else(|| default_on_empty.clone());
|
||||
args.args.push(syn::GenericArgument::Type(on_empty));
|
||||
}
|
||||
},
|
||||
StorageGenerics::Map { hasher, key, value, query_kind, on_empty, max_values } => {
|
||||
args.args.push(syn::GenericArgument::Type(hasher));
|
||||
args.args.push(syn::GenericArgument::Type(key));
|
||||
@@ -111,9 +108,16 @@ pub fn process_generics(def: &mut Def) -> syn::Result<()> {
|
||||
args.args.push(syn::GenericArgument::Type(on_empty));
|
||||
let max_values = max_values.unwrap_or_else(|| default_max_values.clone());
|
||||
args.args.push(syn::GenericArgument::Type(max_values));
|
||||
}
|
||||
},
|
||||
StorageGenerics::DoubleMap {
|
||||
hasher1, key1, hasher2, key2, value, query_kind, on_empty, max_values,
|
||||
hasher1,
|
||||
key1,
|
||||
hasher2,
|
||||
key2,
|
||||
value,
|
||||
query_kind,
|
||||
on_empty,
|
||||
max_values,
|
||||
} => {
|
||||
args.args.push(syn::GenericArgument::Type(hasher1));
|
||||
args.args.push(syn::GenericArgument::Type(key1));
|
||||
@@ -126,8 +130,8 @@ pub fn process_generics(def: &mut Def) -> syn::Result<()> {
|
||||
args.args.push(syn::GenericArgument::Type(on_empty));
|
||||
let max_values = max_values.unwrap_or_else(|| default_max_values.clone());
|
||||
args.args.push(syn::GenericArgument::Type(max_values));
|
||||
}
|
||||
StorageGenerics::NMap { keygen, value, query_kind, on_empty, max_values, } => {
|
||||
},
|
||||
StorageGenerics::NMap { keygen, value, query_kind, on_empty, max_values } => {
|
||||
args.args.push(syn::GenericArgument::Type(keygen));
|
||||
args.args.push(syn::GenericArgument::Type(value));
|
||||
let query_kind = query_kind.unwrap_or_else(|| default_query_kind.clone());
|
||||
@@ -136,7 +140,7 @@ pub fn process_generics(def: &mut Def) -> syn::Result<()> {
|
||||
args.args.push(syn::GenericArgument::Type(on_empty));
|
||||
let max_values = max_values.unwrap_or_else(|| default_max_values.clone());
|
||||
args.args.push(syn::GenericArgument::Type(max_values));
|
||||
}
|
||||
},
|
||||
}
|
||||
} else {
|
||||
args.args[0] = syn::parse_quote!( #prefix_ident<#type_use_gen> );
|
||||
@@ -154,118 +158,116 @@ pub fn process_generics(def: &mut Def) -> syn::Result<()> {
|
||||
/// * generate metadatas
|
||||
pub fn expand_storages(def: &mut Def) -> proc_macro2::TokenStream {
|
||||
if let Err(e) = process_generics(def) {
|
||||
return e.into_compile_error().into();
|
||||
return e.into_compile_error().into()
|
||||
}
|
||||
|
||||
let frame_support = &def.frame_support;
|
||||
let frame_system = &def.frame_system;
|
||||
let pallet_ident = &def.pallet_struct.pallet;
|
||||
|
||||
let entries = def.storages.iter().map(|storage| {
|
||||
let docs = &storage.docs;
|
||||
|
||||
let entries = def.storages.iter()
|
||||
.map(|storage| {
|
||||
let docs = &storage.docs;
|
||||
let ident = &storage.ident;
|
||||
let gen = &def.type_use_generics(storage.attr_span);
|
||||
let full_ident = quote::quote_spanned!(storage.attr_span => #ident<#gen> );
|
||||
|
||||
let ident = &storage.ident;
|
||||
let gen = &def.type_use_generics(storage.attr_span);
|
||||
let full_ident = quote::quote_spanned!(storage.attr_span => #ident<#gen> );
|
||||
let cfg_attrs = &storage.cfg_attrs;
|
||||
|
||||
let cfg_attrs = &storage.cfg_attrs;
|
||||
let metadata_trait = match &storage.metadata {
|
||||
Metadata::Value { .. } => quote::quote_spanned!(storage.attr_span =>
|
||||
#frame_support::storage::types::StorageValueMetadata
|
||||
),
|
||||
Metadata::Map { .. } => quote::quote_spanned!(storage.attr_span =>
|
||||
#frame_support::storage::types::StorageMapMetadata
|
||||
),
|
||||
Metadata::DoubleMap { .. } => quote::quote_spanned!(storage.attr_span =>
|
||||
#frame_support::storage::types::StorageDoubleMapMetadata
|
||||
),
|
||||
Metadata::NMap { .. } => quote::quote_spanned!(storage.attr_span =>
|
||||
#frame_support::storage::types::StorageNMapMetadata
|
||||
),
|
||||
};
|
||||
|
||||
let metadata_trait = match &storage.metadata {
|
||||
Metadata::Value { .. } => quote::quote_spanned!(storage.attr_span =>
|
||||
#frame_support::storage::types::StorageValueMetadata
|
||||
),
|
||||
Metadata::Map { .. } => quote::quote_spanned!(storage.attr_span =>
|
||||
#frame_support::storage::types::StorageMapMetadata
|
||||
),
|
||||
Metadata::DoubleMap { .. } => quote::quote_spanned!(storage.attr_span =>
|
||||
#frame_support::storage::types::StorageDoubleMapMetadata
|
||||
),
|
||||
Metadata::NMap { .. } => quote::quote_spanned!(storage.attr_span =>
|
||||
#frame_support::storage::types::StorageNMapMetadata
|
||||
),
|
||||
};
|
||||
|
||||
let ty = match &storage.metadata {
|
||||
Metadata::Value { value } => {
|
||||
let value = clean_type_string("e::quote!(#value).to_string());
|
||||
quote::quote_spanned!(storage.attr_span =>
|
||||
#frame_support::metadata::StorageEntryType::Plain(
|
||||
#frame_support::metadata::DecodeDifferent::Encode(#value)
|
||||
)
|
||||
let ty = match &storage.metadata {
|
||||
Metadata::Value { value } => {
|
||||
let value = clean_type_string("e::quote!(#value).to_string());
|
||||
quote::quote_spanned!(storage.attr_span =>
|
||||
#frame_support::metadata::StorageEntryType::Plain(
|
||||
#frame_support::metadata::DecodeDifferent::Encode(#value)
|
||||
)
|
||||
},
|
||||
Metadata::Map { key, value } => {
|
||||
let value = clean_type_string("e::quote!(#value).to_string());
|
||||
let key = clean_type_string("e::quote!(#key).to_string());
|
||||
quote::quote_spanned!(storage.attr_span =>
|
||||
#frame_support::metadata::StorageEntryType::Map {
|
||||
hasher: <#full_ident as #metadata_trait>::HASHER,
|
||||
key: #frame_support::metadata::DecodeDifferent::Encode(#key),
|
||||
value: #frame_support::metadata::DecodeDifferent::Encode(#value),
|
||||
unused: false,
|
||||
}
|
||||
)
|
||||
},
|
||||
Metadata::DoubleMap { key1, key2, value } => {
|
||||
let value = clean_type_string("e::quote!(#value).to_string());
|
||||
let key1 = clean_type_string("e::quote!(#key1).to_string());
|
||||
let key2 = clean_type_string("e::quote!(#key2).to_string());
|
||||
quote::quote_spanned!(storage.attr_span =>
|
||||
#frame_support::metadata::StorageEntryType::DoubleMap {
|
||||
hasher: <#full_ident as #metadata_trait>::HASHER1,
|
||||
key2_hasher: <#full_ident as #metadata_trait>::HASHER2,
|
||||
key1: #frame_support::metadata::DecodeDifferent::Encode(#key1),
|
||||
key2: #frame_support::metadata::DecodeDifferent::Encode(#key2),
|
||||
value: #frame_support::metadata::DecodeDifferent::Encode(#value),
|
||||
}
|
||||
)
|
||||
},
|
||||
Metadata::NMap { keys, value, .. } => {
|
||||
let keys = keys
|
||||
.iter()
|
||||
.map(|key| clean_type_string("e::quote!(#key).to_string()))
|
||||
.collect::<Vec<_>>();
|
||||
let value = clean_type_string("e::quote!(#value).to_string());
|
||||
quote::quote_spanned!(storage.attr_span =>
|
||||
#frame_support::metadata::StorageEntryType::NMap {
|
||||
keys: #frame_support::metadata::DecodeDifferent::Encode(&[
|
||||
#( #keys, )*
|
||||
]),
|
||||
hashers: #frame_support::metadata::DecodeDifferent::Encode(
|
||||
<#full_ident as #metadata_trait>::HASHERS,
|
||||
),
|
||||
value: #frame_support::metadata::DecodeDifferent::Encode(#value),
|
||||
}
|
||||
)
|
||||
}
|
||||
};
|
||||
)
|
||||
},
|
||||
Metadata::Map { key, value } => {
|
||||
let value = clean_type_string("e::quote!(#value).to_string());
|
||||
let key = clean_type_string("e::quote!(#key).to_string());
|
||||
quote::quote_spanned!(storage.attr_span =>
|
||||
#frame_support::metadata::StorageEntryType::Map {
|
||||
hasher: <#full_ident as #metadata_trait>::HASHER,
|
||||
key: #frame_support::metadata::DecodeDifferent::Encode(#key),
|
||||
value: #frame_support::metadata::DecodeDifferent::Encode(#value),
|
||||
unused: false,
|
||||
}
|
||||
)
|
||||
},
|
||||
Metadata::DoubleMap { key1, key2, value } => {
|
||||
let value = clean_type_string("e::quote!(#value).to_string());
|
||||
let key1 = clean_type_string("e::quote!(#key1).to_string());
|
||||
let key2 = clean_type_string("e::quote!(#key2).to_string());
|
||||
quote::quote_spanned!(storage.attr_span =>
|
||||
#frame_support::metadata::StorageEntryType::DoubleMap {
|
||||
hasher: <#full_ident as #metadata_trait>::HASHER1,
|
||||
key2_hasher: <#full_ident as #metadata_trait>::HASHER2,
|
||||
key1: #frame_support::metadata::DecodeDifferent::Encode(#key1),
|
||||
key2: #frame_support::metadata::DecodeDifferent::Encode(#key2),
|
||||
value: #frame_support::metadata::DecodeDifferent::Encode(#value),
|
||||
}
|
||||
)
|
||||
},
|
||||
Metadata::NMap { keys, value, .. } => {
|
||||
let keys = keys
|
||||
.iter()
|
||||
.map(|key| clean_type_string("e::quote!(#key).to_string()))
|
||||
.collect::<Vec<_>>();
|
||||
let value = clean_type_string("e::quote!(#value).to_string());
|
||||
quote::quote_spanned!(storage.attr_span =>
|
||||
#frame_support::metadata::StorageEntryType::NMap {
|
||||
keys: #frame_support::metadata::DecodeDifferent::Encode(&[
|
||||
#( #keys, )*
|
||||
]),
|
||||
hashers: #frame_support::metadata::DecodeDifferent::Encode(
|
||||
<#full_ident as #metadata_trait>::HASHERS,
|
||||
),
|
||||
value: #frame_support::metadata::DecodeDifferent::Encode(#value),
|
||||
}
|
||||
)
|
||||
},
|
||||
};
|
||||
|
||||
quote::quote_spanned!(storage.attr_span =>
|
||||
#(#cfg_attrs)* #frame_support::metadata::StorageEntryMetadata {
|
||||
name: #frame_support::metadata::DecodeDifferent::Encode(
|
||||
<#full_ident as #metadata_trait>::NAME
|
||||
),
|
||||
modifier: <#full_ident as #metadata_trait>::MODIFIER,
|
||||
ty: #ty,
|
||||
default: #frame_support::metadata::DecodeDifferent::Encode(
|
||||
<#full_ident as #metadata_trait>::DEFAULT
|
||||
),
|
||||
documentation: #frame_support::metadata::DecodeDifferent::Encode(&[
|
||||
#( #docs, )*
|
||||
]),
|
||||
}
|
||||
)
|
||||
});
|
||||
quote::quote_spanned!(storage.attr_span =>
|
||||
#(#cfg_attrs)* #frame_support::metadata::StorageEntryMetadata {
|
||||
name: #frame_support::metadata::DecodeDifferent::Encode(
|
||||
<#full_ident as #metadata_trait>::NAME
|
||||
),
|
||||
modifier: <#full_ident as #metadata_trait>::MODIFIER,
|
||||
ty: #ty,
|
||||
default: #frame_support::metadata::DecodeDifferent::Encode(
|
||||
<#full_ident as #metadata_trait>::DEFAULT
|
||||
),
|
||||
documentation: #frame_support::metadata::DecodeDifferent::Encode(&[
|
||||
#( #docs, )*
|
||||
]),
|
||||
}
|
||||
)
|
||||
});
|
||||
|
||||
let getters = def.storages.iter()
|
||||
.map(|storage| if let Some(getter) = &storage.getter {
|
||||
let completed_where_clause = super::merge_where_clauses(&[
|
||||
&storage.where_clause,
|
||||
&def.config.where_clause,
|
||||
]);
|
||||
let docs = storage.docs.iter()
|
||||
let getters = def.storages.iter().map(|storage| {
|
||||
if let Some(getter) = &storage.getter {
|
||||
let completed_where_clause =
|
||||
super::merge_where_clauses(&[&storage.where_clause, &def.config.where_clause]);
|
||||
let docs = storage
|
||||
.docs
|
||||
.iter()
|
||||
.map(|d| quote::quote_spanned!(storage.attr_span => #[doc = #d]));
|
||||
|
||||
let ident = &storage.ident;
|
||||
@@ -365,11 +367,12 @@ pub fn expand_storages(def: &mut Def) -> proc_macro2::TokenStream {
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
},
|
||||
}
|
||||
} else {
|
||||
Default::default()
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
let prefix_structs = def.storages.iter().map(|storage_def| {
|
||||
let type_impl_gen = &def.type_impl_generics(storage_def.attr_span);
|
||||
|
||||
@@ -22,11 +22,8 @@ use syn::spanned::Spanned;
|
||||
/// * generate Store trait with all storages,
|
||||
/// * implement Store trait for Pallet.
|
||||
pub fn expand_store_trait(def: &mut Def) -> proc_macro2::TokenStream {
|
||||
let (trait_vis, trait_store) = if let Some(store) = &def.pallet_struct.store {
|
||||
store
|
||||
} else {
|
||||
return Default::default()
|
||||
};
|
||||
let (trait_vis, trait_store) =
|
||||
if let Some(store) = &def.pallet_struct.store { store } else { return Default::default() };
|
||||
|
||||
let type_impl_gen = &def.type_impl_generics(trait_store.span());
|
||||
let type_use_gen = &def.type_use_generics(trait_store.span());
|
||||
@@ -37,7 +34,8 @@ pub fn expand_store_trait(def: &mut Def) -> proc_macro2::TokenStream {
|
||||
let completed_where_clause = super::merge_where_clauses(&where_clauses);
|
||||
|
||||
let storage_names = &def.storages.iter().map(|storage| &storage.ident).collect::<Vec<_>>();
|
||||
let storage_cfg_attrs = &def.storages.iter().map(|storage| &storage.cfg_attrs).collect::<Vec<_>>();
|
||||
let storage_cfg_attrs =
|
||||
&def.storages.iter().map(|storage| &storage.cfg_attrs).collect::<Vec<_>>();
|
||||
|
||||
quote::quote_spanned!(trait_store.span() =>
|
||||
#trait_vis trait #trait_store {
|
||||
|
||||
@@ -15,15 +15,15 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use crate::pallet::Def;
|
||||
use crate::{pallet::Def, COUNTER};
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::quote;
|
||||
use crate::COUNTER;
|
||||
use syn::{Ident, spanned::Spanned};
|
||||
use syn::{spanned::Spanned, Ident};
|
||||
|
||||
pub fn expand_validate_unsigned(def: &mut Def) -> TokenStream {
|
||||
let count = COUNTER.with(|counter| counter.borrow_mut().inc());
|
||||
let macro_ident = Ident::new(&format!("__is_validate_unsigned_part_defined_{}", count), def.item.span());
|
||||
let macro_ident =
|
||||
Ident::new(&format!("__is_validate_unsigned_part_defined_{}", count), def.item.span());
|
||||
|
||||
let maybe_compile_error = if def.validate_unsigned.is_none() {
|
||||
quote! {
|
||||
@@ -48,7 +48,7 @@ pub fn expand_validate_unsigned(def: &mut Def) -> TokenStream {
|
||||
#maybe_compile_error
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[doc(hidden)]
|
||||
pub use #macro_ident as is_validate_unsigned_part_defined;
|
||||
}
|
||||
|
||||
@@ -25,21 +25,22 @@
|
||||
//! This step will modify the ItemMod by adding some derive attributes or phantom data variants
|
||||
//! to user defined types. And also crate new types and implement block.
|
||||
|
||||
mod parse;
|
||||
mod expand;
|
||||
mod parse;
|
||||
|
||||
pub use parse::Def;
|
||||
use syn::spanned::Spanned;
|
||||
|
||||
pub fn pallet(
|
||||
attr: proc_macro::TokenStream,
|
||||
item: proc_macro::TokenStream
|
||||
item: proc_macro::TokenStream,
|
||||
) -> proc_macro::TokenStream {
|
||||
if !attr.is_empty() {
|
||||
let msg = "Invalid pallet macro call: expected no attributes, e.g. macro call must be just \
|
||||
let msg =
|
||||
"Invalid pallet macro call: expected no attributes, e.g. macro call must be just \
|
||||
`#[frame_support::pallet]` or `#[pallet]`";
|
||||
let span = proc_macro2::TokenStream::from(attr).span();
|
||||
return syn::Error::new(span, msg).to_compile_error().into();
|
||||
return syn::Error::new(span, msg).to_compile_error().into()
|
||||
}
|
||||
|
||||
let item = syn::parse_macro_input!(item as syn::ItemMod);
|
||||
|
||||
@@ -75,9 +75,7 @@ impl syn::parse::Parse for FunctionAttr {
|
||||
|
||||
let weight_content;
|
||||
syn::parenthesized!(weight_content in content);
|
||||
Ok(FunctionAttr {
|
||||
weight: weight_content.parse::<syn::Expr>()?,
|
||||
})
|
||||
Ok(FunctionAttr { weight: weight_content.parse::<syn::Expr>()? })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,7 +98,6 @@ impl syn::parse::Parse for ArgAttrIsCompact {
|
||||
|
||||
/// Check the syntax is `OriginFor<T>`
|
||||
pub fn check_dispatchable_first_arg_type(ty: &syn::Type) -> syn::Result<()> {
|
||||
|
||||
pub struct CheckDispatchableFirstArg;
|
||||
impl syn::parse::Parse for CheckDispatchableFirstArg {
|
||||
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
|
||||
@@ -113,13 +110,12 @@ pub fn check_dispatchable_first_arg_type(ty: &syn::Type) -> syn::Result<()> {
|
||||
}
|
||||
}
|
||||
|
||||
syn::parse2::<CheckDispatchableFirstArg>(ty.to_token_stream())
|
||||
.map_err(|e| {
|
||||
let msg = "Invalid type: expected `OriginFor<T>`";
|
||||
let mut err = syn::Error::new(ty.span(), msg);
|
||||
err.combine(e);
|
||||
err
|
||||
})?;
|
||||
syn::parse2::<CheckDispatchableFirstArg>(ty.to_token_stream()).map_err(|e| {
|
||||
let msg = "Invalid type: expected `OriginFor<T>`";
|
||||
let mut err = syn::Error::new(ty.span(), msg);
|
||||
err.combine(e);
|
||||
err
|
||||
})?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -128,12 +124,12 @@ impl CallDef {
|
||||
pub fn try_from(
|
||||
attr_span: proc_macro2::Span,
|
||||
index: usize,
|
||||
item: &mut syn::Item
|
||||
item: &mut syn::Item,
|
||||
) -> syn::Result<Self> {
|
||||
let item = if let syn::Item::Impl(item) = item {
|
||||
item
|
||||
} else {
|
||||
return Err(syn::Error::new(item.span(), "Invalid pallet::call, expected item impl"));
|
||||
return Err(syn::Error::new(item.span(), "Invalid pallet::call, expected item impl"))
|
||||
};
|
||||
|
||||
let mut instances = vec![];
|
||||
@@ -158,18 +154,18 @@ impl CallDef {
|
||||
_ => method.vis.span(),
|
||||
};
|
||||
|
||||
return Err(syn::Error::new(span, msg));
|
||||
return Err(syn::Error::new(span, msg))
|
||||
}
|
||||
|
||||
match method.sig.inputs.first() {
|
||||
None => {
|
||||
let msg = "Invalid pallet::call, must have at least origin arg";
|
||||
return Err(syn::Error::new(method.sig.span(), msg));
|
||||
return Err(syn::Error::new(method.sig.span(), msg))
|
||||
},
|
||||
Some(syn::FnArg::Receiver(_)) => {
|
||||
let msg = "Invalid pallet::call, first argument must be a typed argument, \
|
||||
e.g. `origin: OriginFor<T>`";
|
||||
return Err(syn::Error::new(method.sig.span(), msg));
|
||||
return Err(syn::Error::new(method.sig.span(), msg))
|
||||
},
|
||||
Some(syn::FnArg::Typed(arg)) => {
|
||||
check_dispatchable_first_arg_type(&*arg.ty)?;
|
||||
@@ -181,7 +177,7 @@ impl CallDef {
|
||||
} else {
|
||||
let msg = "Invalid pallet::call, require return type \
|
||||
DispatchResultWithPostInfo";
|
||||
return Err(syn::Error::new(method.sig.span(), msg));
|
||||
return Err(syn::Error::new(method.sig.span(), msg))
|
||||
}
|
||||
|
||||
let mut call_var_attrs: Vec<FunctionAttr> =
|
||||
@@ -193,7 +189,7 @@ impl CallDef {
|
||||
} else {
|
||||
"Invalid pallet::call, too many weight attributes given"
|
||||
};
|
||||
return Err(syn::Error::new(method.sig.span(), msg));
|
||||
return Err(syn::Error::new(method.sig.span(), msg))
|
||||
}
|
||||
let weight = call_var_attrs.pop().unwrap().weight;
|
||||
|
||||
@@ -210,14 +206,14 @@ impl CallDef {
|
||||
|
||||
if arg_attrs.len() > 1 {
|
||||
let msg = "Invalid pallet::call, argument has too many attributes";
|
||||
return Err(syn::Error::new(arg.span(), msg));
|
||||
return Err(syn::Error::new(arg.span(), msg))
|
||||
}
|
||||
|
||||
let arg_ident = if let syn::Pat::Ident(pat) = &*arg.pat {
|
||||
pat.ident.clone()
|
||||
} else {
|
||||
let msg = "Invalid pallet::call, argument must be ident";
|
||||
return Err(syn::Error::new(arg.pat.span(), msg));
|
||||
return Err(syn::Error::new(arg.pat.span(), msg))
|
||||
};
|
||||
|
||||
args.push((!arg_attrs.is_empty(), arg_ident, arg.ty.clone()));
|
||||
@@ -225,15 +221,10 @@ impl CallDef {
|
||||
|
||||
let docs = helper::get_doc_literals(&method.attrs);
|
||||
|
||||
methods.push(CallVariantDef {
|
||||
name: method.sig.ident.clone(),
|
||||
weight,
|
||||
args,
|
||||
docs,
|
||||
});
|
||||
methods.push(CallVariantDef { name: method.sig.ident.clone(), weight, args, docs });
|
||||
} else {
|
||||
let msg = "Invalid pallet::call, only method accepted";
|
||||
return Err(syn::Error::new(impl_item.span(), msg));
|
||||
return Err(syn::Error::new(impl_item.span(), msg))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
|
||||
use super::helper;
|
||||
use core::convert::TryFrom;
|
||||
use syn::spanned::Spanned;
|
||||
use quote::ToTokens;
|
||||
use syn::spanned::Spanned;
|
||||
|
||||
/// List of additional token to be used for parsing.
|
||||
mod keyword {
|
||||
@@ -66,23 +66,26 @@ impl TryFrom<&syn::TraitItemType> for ConstMetadataDef {
|
||||
type Error = syn::Error;
|
||||
|
||||
fn try_from(trait_ty: &syn::TraitItemType) -> Result<Self, Self::Error> {
|
||||
let err = |span, msg|
|
||||
syn::Error::new(span, format!("Invalid usage of `#[pallet::constant]`: {}", msg));
|
||||
let err = |span, msg| {
|
||||
syn::Error::new(span, format!("Invalid usage of `#[pallet::constant]`: {}", msg))
|
||||
};
|
||||
let doc = helper::get_doc_literals(&trait_ty.attrs);
|
||||
let ident = trait_ty.ident.clone();
|
||||
let bound = trait_ty.bounds
|
||||
let bound = trait_ty
|
||||
.bounds
|
||||
.iter()
|
||||
.find_map(|b|
|
||||
.find_map(|b| {
|
||||
if let syn::TypeParamBound::Trait(tb) = b {
|
||||
tb.path.segments
|
||||
tb.path
|
||||
.segments
|
||||
.last()
|
||||
.and_then(|s| if s.ident == "Get" { Some(s) } else { None } )
|
||||
.and_then(|s| if s.ident == "Get" { Some(s) } else { None })
|
||||
} else {
|
||||
None
|
||||
}
|
||||
)
|
||||
})
|
||||
.ok_or_else(|| err(trait_ty.span(), "`Get<T>` trait bound not found"))?;
|
||||
let type_arg = if let syn::PathArguments::AngleBracketed (ref ab) = bound.arguments {
|
||||
let type_arg = if let syn::PathArguments::AngleBracketed(ref ab) = bound.arguments {
|
||||
if ab.args.len() == 1 {
|
||||
if let syn::GenericArgument::Type(ref ty) = ab.args[0] {
|
||||
Ok(ty)
|
||||
@@ -214,15 +217,15 @@ impl syn::parse::Parse for FromEventParse {
|
||||
fn check_event_type(
|
||||
frame_system: &syn::Ident,
|
||||
trait_item: &syn::TraitItem,
|
||||
trait_has_instance: bool
|
||||
) -> syn::Result<bool> {
|
||||
trait_has_instance: bool,
|
||||
) -> syn::Result<bool> {
|
||||
if let syn::TraitItem::Type(type_) = trait_item {
|
||||
if type_.ident == "Event" {
|
||||
// Check event has no generics
|
||||
if !type_.generics.params.is_empty() || type_.generics.where_clause.is_some() {
|
||||
let msg = "Invalid `type Event`, associated type `Event` is reserved and must have\
|
||||
no generics nor where_clause";
|
||||
return Err(syn::Error::new(trait_item.span(), msg));
|
||||
return Err(syn::Error::new(trait_item.span(), msg))
|
||||
}
|
||||
// Check bound contains IsType and From
|
||||
|
||||
@@ -237,28 +240,28 @@ fn check_event_type(
|
||||
bound: `IsType<<Self as {}::Config>::Event>`",
|
||||
frame_system,
|
||||
);
|
||||
return Err(syn::Error::new(type_.span(), msg));
|
||||
return Err(syn::Error::new(type_.span(), msg))
|
||||
}
|
||||
|
||||
let from_event_bound = type_.bounds.iter().find_map(|s| {
|
||||
syn::parse2::<FromEventParse>(s.to_token_stream()).ok()
|
||||
});
|
||||
let from_event_bound = type_
|
||||
.bounds
|
||||
.iter()
|
||||
.find_map(|s| syn::parse2::<FromEventParse>(s.to_token_stream()).ok());
|
||||
|
||||
let from_event_bound = if let Some(b) = from_event_bound {
|
||||
b
|
||||
} else {
|
||||
let msg = "Invalid `type Event`, associated type `Event` is reserved and must \
|
||||
bound: `From<Event>` or `From<Event<Self>>` or `From<Event<Self, I>>`";
|
||||
return Err(syn::Error::new(type_.span(), msg));
|
||||
return Err(syn::Error::new(type_.span(), msg))
|
||||
};
|
||||
|
||||
if from_event_bound.is_generic
|
||||
&& (from_event_bound.has_instance != trait_has_instance)
|
||||
if from_event_bound.is_generic && (from_event_bound.has_instance != trait_has_instance)
|
||||
{
|
||||
let msg = "Invalid `type Event`, associated type `Event` bounds inconsistent \
|
||||
`From<Event..>`. Config and generic Event must be both with instance or \
|
||||
without instance";
|
||||
return Err(syn::Error::new(type_.span(), msg));
|
||||
return Err(syn::Error::new(type_.span(), msg))
|
||||
}
|
||||
|
||||
Ok(true)
|
||||
@@ -272,16 +275,14 @@ fn check_event_type(
|
||||
|
||||
/// Replace ident `Self` by `T`
|
||||
pub fn replace_self_by_t(input: proc_macro2::TokenStream) -> proc_macro2::TokenStream {
|
||||
input.into_iter()
|
||||
input
|
||||
.into_iter()
|
||||
.map(|token_tree| match token_tree {
|
||||
proc_macro2::TokenTree::Group(group) =>
|
||||
proc_macro2::Group::new(
|
||||
group.delimiter(),
|
||||
replace_self_by_t(group.stream())
|
||||
).into(),
|
||||
proc_macro2::Group::new(group.delimiter(), replace_self_by_t(group.stream())).into(),
|
||||
proc_macro2::TokenTree::Ident(ident) if ident == "Self" =>
|
||||
proc_macro2::Ident::new("T", ident.span()).into(),
|
||||
other => other
|
||||
other => other,
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
@@ -297,27 +298,27 @@ impl ConfigDef {
|
||||
item
|
||||
} else {
|
||||
let msg = "Invalid pallet::config, expected trait definition";
|
||||
return Err(syn::Error::new(item.span(), msg));
|
||||
return Err(syn::Error::new(item.span(), msg))
|
||||
};
|
||||
|
||||
if !matches!(item.vis, syn::Visibility::Public(_)) {
|
||||
let msg = "Invalid pallet::config, trait must be public";
|
||||
return Err(syn::Error::new(item.span(), msg));
|
||||
return Err(syn::Error::new(item.span(), msg))
|
||||
}
|
||||
|
||||
syn::parse2::<keyword::Config>(item.ident.to_token_stream())?;
|
||||
|
||||
|
||||
let where_clause = {
|
||||
let stream = replace_self_by_t(item.generics.where_clause.to_token_stream());
|
||||
syn::parse2::<Option<syn::WhereClause>>(stream)
|
||||
.expect("Internal error: replacing `Self` by `T` should result in valid where
|
||||
clause")
|
||||
syn::parse2::<Option<syn::WhereClause>>(stream).expect(
|
||||
"Internal error: replacing `Self` by `T` should result in valid where
|
||||
clause",
|
||||
)
|
||||
};
|
||||
|
||||
if item.generics.params.len() > 1 {
|
||||
let msg = "Invalid pallet::config, expected no more than one generic";
|
||||
return Err(syn::Error::new(item.generics.params[2].span(), msg));
|
||||
return Err(syn::Error::new(item.generics.params[2].span(), msg))
|
||||
}
|
||||
|
||||
let has_instance = if item.generics.params.first().is_some() {
|
||||
@@ -331,15 +332,15 @@ impl ConfigDef {
|
||||
let mut consts_metadata = vec![];
|
||||
for trait_item in &mut item.items {
|
||||
// Parse for event
|
||||
has_event_type = has_event_type
|
||||
|| check_event_type(frame_system, trait_item, has_instance)?;
|
||||
has_event_type =
|
||||
has_event_type || check_event_type(frame_system, trait_item, has_instance)?;
|
||||
|
||||
// Parse for constant
|
||||
let type_attrs_const: Vec<TypeAttrConst> = helper::take_item_pallet_attrs(trait_item)?;
|
||||
|
||||
if type_attrs_const.len() > 1 {
|
||||
let msg = "Invalid attribute in pallet::config, only one attribute is expected";
|
||||
return Err(syn::Error::new(type_attrs_const[1].span(), msg));
|
||||
return Err(syn::Error::new(type_attrs_const[1].span(), msg))
|
||||
}
|
||||
|
||||
if type_attrs_const.len() == 1 {
|
||||
@@ -349,17 +350,17 @@ impl ConfigDef {
|
||||
consts_metadata.push(constant);
|
||||
},
|
||||
_ => {
|
||||
let msg = "Invalid pallet::constant in pallet::config, expected type trait \
|
||||
let msg =
|
||||
"Invalid pallet::constant in pallet::config, expected type trait \
|
||||
item";
|
||||
return Err(syn::Error::new(trait_item.span(), msg));
|
||||
return Err(syn::Error::new(trait_item.span(), msg))
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let attr: Option<DisableFrameSystemSupertraitCheck> = helper::take_first_item_pallet_attr(
|
||||
&mut item.attrs
|
||||
)?;
|
||||
let attr: Option<DisableFrameSystemSupertraitCheck> =
|
||||
helper::take_first_item_pallet_attr(&mut item.attrs)?;
|
||||
|
||||
let disable_system_supertrait_check = attr.is_some();
|
||||
|
||||
@@ -372,10 +373,9 @@ impl ConfigDef {
|
||||
let found = if item.supertraits.is_empty() {
|
||||
"none".to_string()
|
||||
} else {
|
||||
let mut found = item.supertraits.iter()
|
||||
.fold(String::new(), |acc, s| {
|
||||
format!("{}`{}`, ", acc, quote::quote!(#s).to_string())
|
||||
});
|
||||
let mut found = item.supertraits.iter().fold(String::new(), |acc, s| {
|
||||
format!("{}`{}`, ", acc, quote::quote!(#s).to_string())
|
||||
});
|
||||
found.pop();
|
||||
found.pop();
|
||||
found
|
||||
@@ -387,19 +387,11 @@ impl ConfigDef {
|
||||
(try `pub trait Config: frame_system::Config {{ ...` or \
|
||||
`pub trait Config<I: 'static>: frame_system::Config {{ ...`). \
|
||||
To disable this check, use `#[pallet::disable_frame_system_supertrait_check]`",
|
||||
frame_system,
|
||||
found,
|
||||
frame_system, found,
|
||||
);
|
||||
return Err(syn::Error::new(item.span(), msg));
|
||||
return Err(syn::Error::new(item.span(), msg))
|
||||
}
|
||||
|
||||
Ok(Self {
|
||||
index,
|
||||
has_instance,
|
||||
consts_metadata,
|
||||
has_event_type,
|
||||
where_clause,
|
||||
attr_span,
|
||||
})
|
||||
Ok(Self { index, has_instance, consts_metadata, has_event_type, where_clause, attr_span })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
// limitations under the License.
|
||||
|
||||
use super::helper;
|
||||
use syn::spanned::Spanned;
|
||||
use quote::ToTokens;
|
||||
use syn::spanned::Spanned;
|
||||
|
||||
/// List of additional token to be used for parsing.
|
||||
mod keyword {
|
||||
@@ -48,11 +48,11 @@ impl ErrorDef {
|
||||
let item = if let syn::Item::Enum(item) = item {
|
||||
item
|
||||
} else {
|
||||
return Err(syn::Error::new(item.span(), "Invalid pallet::error, expected item enum"));
|
||||
return Err(syn::Error::new(item.span(), "Invalid pallet::error, expected item enum"))
|
||||
};
|
||||
if !matches!(item.vis, syn::Visibility::Public(_)) {
|
||||
let msg = "Invalid pallet::error, `Error` must be public";
|
||||
return Err(syn::Error::new(item.span(), msg));
|
||||
return Err(syn::Error::new(item.span(), msg))
|
||||
}
|
||||
|
||||
let mut instances = vec![];
|
||||
@@ -60,34 +60,30 @@ impl ErrorDef {
|
||||
|
||||
if item.generics.where_clause.is_some() {
|
||||
let msg = "Invalid pallet::error, where clause is not allowed on pallet error item";
|
||||
return Err(syn::Error::new(item.generics.where_clause.as_ref().unwrap().span(), msg));
|
||||
return Err(syn::Error::new(item.generics.where_clause.as_ref().unwrap().span(), msg))
|
||||
}
|
||||
|
||||
let error = syn::parse2::<keyword::Error>(item.ident.to_token_stream())?;
|
||||
|
||||
let variants = item.variants.iter()
|
||||
let variants = item
|
||||
.variants
|
||||
.iter()
|
||||
.map(|variant| {
|
||||
if !matches!(variant.fields, syn::Fields::Unit) {
|
||||
let msg = "Invalid pallet::error, unexpected fields, must be `Unit`";
|
||||
return Err(syn::Error::new(variant.fields.span(), msg));
|
||||
return Err(syn::Error::new(variant.fields.span(), msg))
|
||||
}
|
||||
if variant.discriminant.is_some() {
|
||||
let msg = "Invalid pallet::error, unexpected discriminant, discriminant \
|
||||
are not supported";
|
||||
let span = variant.discriminant.as_ref().unwrap().0.span();
|
||||
return Err(syn::Error::new(span, msg));
|
||||
return Err(syn::Error::new(span, msg))
|
||||
}
|
||||
|
||||
Ok((variant.ident.clone(), helper::get_doc_literals(&variant.attrs)))
|
||||
})
|
||||
.collect::<Result<_, _>>()?;
|
||||
|
||||
Ok(ErrorDef {
|
||||
attr_span,
|
||||
index,
|
||||
variants,
|
||||
instances,
|
||||
error,
|
||||
})
|
||||
Ok(ErrorDef { attr_span, index, variants, instances, error })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,9 +16,9 @@
|
||||
// limitations under the License.
|
||||
|
||||
use super::helper;
|
||||
use syn::spanned::Spanned;
|
||||
use quote::ToTokens;
|
||||
use frame_support_procedural_tools::clean_type_string;
|
||||
use quote::ToTokens;
|
||||
use syn::spanned::Spanned;
|
||||
|
||||
/// List of additional token to be used for parsing.
|
||||
mod keyword {
|
||||
@@ -80,7 +80,7 @@ impl PalletEventAttr {
|
||||
|
||||
/// Parse for syntax `$Type = "$SomeString"`.
|
||||
fn parse_event_metadata_element(
|
||||
input: syn::parse::ParseStream
|
||||
input: syn::parse::ParseStream,
|
||||
) -> syn::Result<(syn::Type, String)> {
|
||||
let typ = input.parse::<syn::Type>()?;
|
||||
input.parse::<syn::Token![=]>()?;
|
||||
@@ -118,7 +118,6 @@ impl syn::parse::Parse for PalletEventAttr {
|
||||
generate_content.parse::<syn::Token![fn]>()?;
|
||||
let fn_span = generate_content.parse::<keyword::deposit_event>()?.span();
|
||||
|
||||
|
||||
Ok(PalletEventAttr::DepositEvent { fn_vis, span, fn_span })
|
||||
} else {
|
||||
Err(lookahead.error())
|
||||
@@ -139,11 +138,10 @@ impl PalletEventAttrInfo {
|
||||
match attr {
|
||||
PalletEventAttr::Metadata { metadata: m, .. } if metadata.is_none() =>
|
||||
metadata = Some(m),
|
||||
PalletEventAttr::DepositEvent { fn_vis, fn_span, .. } if deposit_event.is_none() =>
|
||||
PalletEventAttr::DepositEvent { fn_vis, fn_span, .. }
|
||||
if deposit_event.is_none() =>
|
||||
deposit_event = Some((fn_vis, fn_span)),
|
||||
attr => {
|
||||
return Err(syn::Error::new(attr.span(), "Duplicate attribute"));
|
||||
}
|
||||
attr => return Err(syn::Error::new(attr.span(), "Duplicate attribute")),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -170,7 +168,7 @@ impl EventDef {
|
||||
|
||||
if !matches!(item.vis, syn::Visibility::Public(_)) {
|
||||
let msg = "Invalid pallet::event, `Error` must be public";
|
||||
return Err(syn::Error::new(item.span(), msg));
|
||||
return Err(syn::Error::new(item.span(), msg))
|
||||
}
|
||||
|
||||
let where_clause = item.generics.where_clause.clone();
|
||||
@@ -182,10 +180,7 @@ impl EventDef {
|
||||
instances.push(u);
|
||||
} else {
|
||||
// construct_runtime only allow non generic event for non instantiable pallet.
|
||||
instances.push(helper::InstanceUsage {
|
||||
has_instance: false,
|
||||
span: item.ident.span(),
|
||||
})
|
||||
instances.push(helper::InstanceUsage { has_instance: false, span: item.ident.span() })
|
||||
}
|
||||
|
||||
let has_instance = item.generics.type_params().any(|t| t.ident == "I");
|
||||
@@ -195,13 +190,19 @@ impl EventDef {
|
||||
|
||||
let event = syn::parse2::<keyword::Event>(item.ident.to_token_stream())?;
|
||||
|
||||
let metadata = item.variants.iter()
|
||||
let metadata = item
|
||||
.variants
|
||||
.iter()
|
||||
.map(|variant| {
|
||||
let name = variant.ident.clone();
|
||||
let docs = helper::get_doc_literals(&variant.attrs);
|
||||
let args = variant.fields.iter()
|
||||
let args = variant
|
||||
.fields
|
||||
.iter()
|
||||
.map(|field| {
|
||||
metadata.iter().find(|m| m.0 == field.ty)
|
||||
metadata
|
||||
.iter()
|
||||
.find(|m| m.0 == field.ty)
|
||||
.map(|m| m.1.clone())
|
||||
.unwrap_or_else(|| {
|
||||
clean_type_string(&field.ty.to_token_stream().to_string())
|
||||
|
||||
@@ -52,14 +52,11 @@ pub struct ExtraConstantDef {
|
||||
}
|
||||
|
||||
impl ExtraConstantsDef {
|
||||
pub fn try_from(
|
||||
index: usize,
|
||||
item: &mut syn::Item
|
||||
) -> syn::Result<Self> {
|
||||
pub fn try_from(index: usize, item: &mut syn::Item) -> syn::Result<Self> {
|
||||
let item = if let syn::Item::Impl(item) = item {
|
||||
item
|
||||
} else {
|
||||
return Err(syn::Error::new(item.span(), "Invalid pallet::call, expected item impl"));
|
||||
return Err(syn::Error::new(item.span(), "Invalid pallet::call, expected item impl"))
|
||||
};
|
||||
|
||||
let mut instances = vec![];
|
||||
@@ -78,28 +75,28 @@ impl ExtraConstantsDef {
|
||||
method
|
||||
} else {
|
||||
let msg = "Invalid pallet::call, only method accepted";
|
||||
return Err(syn::Error::new(impl_item.span(), msg));
|
||||
return Err(syn::Error::new(impl_item.span(), msg))
|
||||
};
|
||||
|
||||
if !method.sig.inputs.is_empty() {
|
||||
let msg = "Invalid pallet::extra_constants, method must have 0 args";
|
||||
return Err(syn::Error::new(method.sig.span(), msg));
|
||||
return Err(syn::Error::new(method.sig.span(), msg))
|
||||
}
|
||||
|
||||
if !method.sig.generics.params.is_empty() {
|
||||
let msg = "Invalid pallet::extra_constants, method must have 0 generics";
|
||||
return Err(syn::Error::new(method.sig.generics.params[0].span(), msg));
|
||||
return Err(syn::Error::new(method.sig.generics.params[0].span(), msg))
|
||||
}
|
||||
|
||||
if method.sig.generics.where_clause.is_some() {
|
||||
let msg = "Invalid pallet::extra_constants, method must have no where clause";
|
||||
return Err(syn::Error::new(method.sig.generics.where_clause.span(), msg));
|
||||
return Err(syn::Error::new(method.sig.generics.where_clause.span(), msg))
|
||||
}
|
||||
|
||||
let type_ = match &method.sig.output {
|
||||
syn::ReturnType::Default => {
|
||||
let msg = "Invalid pallet::extra_constants, method must have a return type";
|
||||
return Err(syn::Error::new(method.span(), msg));
|
||||
return Err(syn::Error::new(method.span(), msg))
|
||||
},
|
||||
syn::ReturnType::Type(_, type_) => *type_.clone(),
|
||||
};
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use syn::spanned::Spanned;
|
||||
use super::helper;
|
||||
use syn::spanned::Spanned;
|
||||
|
||||
/// Definition for pallet genesis build implementation.
|
||||
pub struct GenesisBuildDef {
|
||||
@@ -40,24 +40,22 @@ impl GenesisBuildDef {
|
||||
item
|
||||
} else {
|
||||
let msg = "Invalid pallet::genesis_build, expected item impl";
|
||||
return Err(syn::Error::new(item.span(), msg));
|
||||
return Err(syn::Error::new(item.span(), msg))
|
||||
};
|
||||
|
||||
let item_trait = &item.trait_.as_ref()
|
||||
let item_trait = &item
|
||||
.trait_
|
||||
.as_ref()
|
||||
.ok_or_else(|| {
|
||||
let msg = "Invalid pallet::genesis_build, expected impl<..> GenesisBuild<..> \
|
||||
for GenesisConfig<..>";
|
||||
syn::Error::new(item.span(), msg)
|
||||
})?.1;
|
||||
})?
|
||||
.1;
|
||||
|
||||
let mut instances = vec![];
|
||||
instances.push(helper::check_genesis_builder_usage(&item_trait)?);
|
||||
|
||||
Ok(Self {
|
||||
attr_span,
|
||||
index,
|
||||
instances,
|
||||
where_clause: item.generics.where_clause.clone(),
|
||||
})
|
||||
Ok(Self { attr_span, index, instances, where_clause: item.generics.where_clause.clone() })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use syn::spanned::Spanned;
|
||||
use super::helper;
|
||||
use syn::spanned::Spanned;
|
||||
|
||||
/// Definition for pallet genesis config type.
|
||||
///
|
||||
@@ -42,7 +42,7 @@ impl GenesisConfigDef {
|
||||
syn::Item::Struct(item) => (&item.vis, &item.ident, &item.generics),
|
||||
_ => {
|
||||
let msg = "Invalid pallet::genesis_config, expected enum or struct";
|
||||
return Err(syn::Error::new(item.span(), msg));
|
||||
return Err(syn::Error::new(item.span(), msg))
|
||||
},
|
||||
};
|
||||
|
||||
@@ -60,19 +60,14 @@ impl GenesisConfigDef {
|
||||
|
||||
if !matches!(vis, syn::Visibility::Public(_)) {
|
||||
let msg = "Invalid pallet::genesis_config, GenesisConfig must be public";
|
||||
return Err(syn::Error::new(item_span, msg));
|
||||
return Err(syn::Error::new(item_span, msg))
|
||||
}
|
||||
|
||||
if ident != "GenesisConfig" {
|
||||
let msg = "Invalid pallet::genesis_config, ident must `GenesisConfig`";
|
||||
return Err(syn::Error::new(ident.span(), msg));
|
||||
return Err(syn::Error::new(ident.span(), msg))
|
||||
}
|
||||
|
||||
Ok(GenesisConfigDef {
|
||||
index,
|
||||
genesis_config: ident.clone(),
|
||||
instances,
|
||||
gen_kind,
|
||||
})
|
||||
Ok(GenesisConfigDef { index, genesis_config: ident.clone(), instances, gen_kind })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use syn::spanned::Spanned;
|
||||
use quote::ToTokens;
|
||||
use syn::spanned::Spanned;
|
||||
|
||||
/// List of additional token to be used for parsing.
|
||||
mod keyword {
|
||||
@@ -47,20 +47,15 @@ pub trait MutItemAttrs {
|
||||
}
|
||||
|
||||
/// Take the first pallet attribute (e.g. attribute like `#[pallet..]`) and decode it to `Attr`
|
||||
pub fn take_first_item_pallet_attr<Attr>(item: &mut impl MutItemAttrs) -> syn::Result<Option<Attr>> where
|
||||
pub fn take_first_item_pallet_attr<Attr>(item: &mut impl MutItemAttrs) -> syn::Result<Option<Attr>>
|
||||
where
|
||||
Attr: syn::parse::Parse,
|
||||
{
|
||||
let attrs = if let Some(attrs) = item.mut_item_attrs() {
|
||||
attrs
|
||||
} else {
|
||||
return Ok(None)
|
||||
};
|
||||
let attrs = if let Some(attrs) = item.mut_item_attrs() { attrs } else { return Ok(None) };
|
||||
|
||||
if let Some(index) = attrs.iter()
|
||||
.position(|attr|
|
||||
attr.path.segments.first().map_or(false, |segment| segment.ident == "pallet")
|
||||
)
|
||||
{
|
||||
if let Some(index) = attrs.iter().position(|attr| {
|
||||
attr.path.segments.first().map_or(false, |segment| segment.ident == "pallet")
|
||||
}) {
|
||||
let pallet_attr = attrs.remove(index);
|
||||
Ok(Some(syn::parse2(pallet_attr.into_token_stream())?))
|
||||
} else {
|
||||
@@ -69,7 +64,8 @@ pub fn take_first_item_pallet_attr<Attr>(item: &mut impl MutItemAttrs) -> syn::R
|
||||
}
|
||||
|
||||
/// Take all the pallet attributes (e.g. attribute like `#[pallet..]`) and decode them to `Attr`
|
||||
pub fn take_item_pallet_attrs<Attr>(item: &mut impl MutItemAttrs) -> syn::Result<Vec<Attr>> where
|
||||
pub fn take_item_pallet_attrs<Attr>(item: &mut impl MutItemAttrs) -> syn::Result<Vec<Attr>>
|
||||
where
|
||||
Attr: syn::parse::Parse,
|
||||
{
|
||||
let mut pallet_attrs = Vec::new();
|
||||
@@ -83,13 +79,16 @@ pub fn take_item_pallet_attrs<Attr>(item: &mut impl MutItemAttrs) -> syn::Result
|
||||
|
||||
/// Get all the cfg attributes (e.g. attribute like `#[cfg..]`) and decode them to `Attr`
|
||||
pub fn get_item_cfg_attrs(attrs: &[syn::Attribute]) -> Vec<syn::Attribute> {
|
||||
attrs.iter().filter_map(|attr| {
|
||||
if attr.path.segments.first().map_or(false, |segment| segment.ident == "cfg") {
|
||||
Some(attr.clone())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}).collect::<Vec<_>>()
|
||||
attrs
|
||||
.iter()
|
||||
.filter_map(|attr| {
|
||||
if attr.path.segments.first().map_or(false, |segment| segment.ident == "cfg") {
|
||||
Some(attr.clone())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
|
||||
impl MutItemAttrs for syn::Item {
|
||||
@@ -116,7 +115,6 @@ impl MutItemAttrs for syn::Item {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl MutItemAttrs for syn::TraitItem {
|
||||
fn mut_item_attrs(&mut self) -> Option<&mut Vec<syn::Attribute>> {
|
||||
match self {
|
||||
@@ -143,7 +141,8 @@ impl MutItemAttrs for syn::ItemMod {
|
||||
|
||||
/// Return all doc attributes literals found.
|
||||
pub fn get_doc_literals(attrs: &Vec<syn::Attribute>) -> Vec<syn::Lit> {
|
||||
attrs.iter()
|
||||
attrs
|
||||
.iter()
|
||||
.filter_map(|attr| {
|
||||
if let Ok(syn::Meta::NameValue(meta)) = attr.parse_meta() {
|
||||
if meta.path.get_ident().map_or(false, |ident| ident == "doc") {
|
||||
@@ -166,7 +165,7 @@ impl syn::parse::Parse for Unit {
|
||||
syn::parenthesized!(content in input);
|
||||
if !content.is_empty() {
|
||||
let msg = "unexpected tokens, expected nothing inside parenthesis as `()`";
|
||||
return Err(syn::Error::new(content.span(), msg));
|
||||
return Err(syn::Error::new(content.span(), msg))
|
||||
}
|
||||
Ok(Self)
|
||||
}
|
||||
@@ -179,7 +178,7 @@ impl syn::parse::Parse for StaticLifetime {
|
||||
let lifetime = input.parse::<syn::Lifetime>()?;
|
||||
if lifetime.ident != "static" {
|
||||
let msg = "unexpected tokens, expected `static`";
|
||||
return Err(syn::Error::new(lifetime.ident.span(), msg));
|
||||
return Err(syn::Error::new(lifetime.ident.span(), msg))
|
||||
}
|
||||
Ok(Self)
|
||||
}
|
||||
@@ -190,10 +189,7 @@ impl syn::parse::Parse for StaticLifetime {
|
||||
/// `span` is used in case generics is empty (empty generics has span == call_site).
|
||||
///
|
||||
/// return the instance if found.
|
||||
pub fn check_config_def_gen(
|
||||
gen: &syn::Generics,
|
||||
span: proc_macro2::Span,
|
||||
) -> syn::Result<()> {
|
||||
pub fn check_config_def_gen(gen: &syn::Generics, span: proc_macro2::Span) -> syn::Result<()> {
|
||||
let expected = "expected `I: 'static = ()`";
|
||||
pub struct CheckTraitDefGenerics;
|
||||
impl syn::parse::Parse for CheckTraitDefGenerics {
|
||||
@@ -208,13 +204,12 @@ pub fn check_config_def_gen(
|
||||
}
|
||||
}
|
||||
|
||||
syn::parse2::<CheckTraitDefGenerics>(gen.params.to_token_stream())
|
||||
.map_err(|e| {
|
||||
let msg = format!("Invalid generics: {}", expected);
|
||||
let mut err = syn::Error::new(span, msg);
|
||||
err.combine(e);
|
||||
err
|
||||
})?;
|
||||
syn::parse2::<CheckTraitDefGenerics>(gen.params.to_token_stream()).map_err(|e| {
|
||||
let msg = format!("Invalid generics: {}", expected);
|
||||
let mut err = syn::Error::new(span, msg);
|
||||
err.combine(e);
|
||||
err
|
||||
})?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -234,10 +229,7 @@ pub fn check_type_def_gen_no_bounds(
|
||||
pub struct Checker(InstanceUsage);
|
||||
impl syn::parse::Parse for Checker {
|
||||
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
|
||||
let mut instance_usage = InstanceUsage {
|
||||
has_instance: false,
|
||||
span: input.span(),
|
||||
};
|
||||
let mut instance_usage = InstanceUsage { has_instance: false, span: input.span() };
|
||||
|
||||
input.parse::<keyword::T>()?;
|
||||
if input.peek(syn::Token![,]) {
|
||||
@@ -258,7 +250,8 @@ pub fn check_type_def_gen_no_bounds(
|
||||
let mut err = syn::Error::new(span, msg);
|
||||
err.combine(e);
|
||||
err
|
||||
})?.0;
|
||||
})?
|
||||
.0;
|
||||
|
||||
Ok(i)
|
||||
}
|
||||
@@ -286,10 +279,7 @@ pub fn check_type_def_optional_gen(
|
||||
return Ok(Self(None))
|
||||
}
|
||||
|
||||
let mut instance_usage = InstanceUsage {
|
||||
span: input.span(),
|
||||
has_instance: false,
|
||||
};
|
||||
let mut instance_usage = InstanceUsage { span: input.span(), has_instance: false };
|
||||
|
||||
input.parse::<keyword::T>()?;
|
||||
|
||||
@@ -338,9 +328,13 @@ pub fn check_type_def_optional_gen(
|
||||
let mut err = syn::Error::new(span, msg);
|
||||
err.combine(e);
|
||||
err
|
||||
})?.0
|
||||
})?
|
||||
.0
|
||||
// Span can be call_site if generic is empty. Thus we replace it.
|
||||
.map(|mut i| { i.span = span; i });
|
||||
.map(|mut i| {
|
||||
i.span = span;
|
||||
i
|
||||
});
|
||||
|
||||
Ok(i)
|
||||
}
|
||||
@@ -355,10 +349,7 @@ pub fn check_pallet_struct_usage(type_: &Box<syn::Type>) -> syn::Result<Instance
|
||||
pub struct Checker(InstanceUsage);
|
||||
impl syn::parse::Parse for Checker {
|
||||
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
|
||||
let mut instance_usage = InstanceUsage {
|
||||
span: input.span(),
|
||||
has_instance: false,
|
||||
};
|
||||
let mut instance_usage = InstanceUsage { span: input.span(), has_instance: false };
|
||||
|
||||
input.parse::<keyword::Pallet>()?;
|
||||
input.parse::<syn::Token![<]>()?;
|
||||
@@ -380,7 +371,8 @@ pub fn check_pallet_struct_usage(type_: &Box<syn::Type>) -> syn::Result<Instance
|
||||
let mut err = syn::Error::new(type_.span(), msg);
|
||||
err.combine(e);
|
||||
err
|
||||
})?.0;
|
||||
})?
|
||||
.0;
|
||||
|
||||
Ok(i)
|
||||
}
|
||||
@@ -392,18 +384,12 @@ pub fn check_pallet_struct_usage(type_: &Box<syn::Type>) -> syn::Result<Instance
|
||||
/// `span` is used in case generics is empty (empty generics has span == call_site).
|
||||
///
|
||||
/// return whether it contains instance.
|
||||
pub fn check_impl_gen(
|
||||
gen: &syn::Generics,
|
||||
span: proc_macro2::Span
|
||||
) -> syn::Result<InstanceUsage> {
|
||||
pub fn check_impl_gen(gen: &syn::Generics, span: proc_macro2::Span) -> syn::Result<InstanceUsage> {
|
||||
let expected = "expected `impl<T: Config>` or `impl<T: Config<I>, I: 'static>`";
|
||||
pub struct Checker(InstanceUsage);
|
||||
impl syn::parse::Parse for Checker {
|
||||
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
|
||||
let mut instance_usage = InstanceUsage {
|
||||
span: input.span(),
|
||||
has_instance: false,
|
||||
};
|
||||
let mut instance_usage = InstanceUsage { span: input.span(), has_instance: false };
|
||||
|
||||
input.parse::<keyword::T>()?;
|
||||
input.parse::<syn::Token![:]>()?;
|
||||
@@ -428,7 +414,8 @@ pub fn check_impl_gen(
|
||||
let mut err = syn::Error::new(span, format!("Invalid generics: {}", expected));
|
||||
err.combine(e);
|
||||
err
|
||||
})?.0;
|
||||
})?
|
||||
.0;
|
||||
|
||||
Ok(i)
|
||||
}
|
||||
@@ -451,10 +438,7 @@ pub fn check_type_def_gen(
|
||||
pub struct Checker(InstanceUsage);
|
||||
impl syn::parse::Parse for Checker {
|
||||
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
|
||||
let mut instance_usage = InstanceUsage {
|
||||
span: input.span(),
|
||||
has_instance: false,
|
||||
};
|
||||
let mut instance_usage = InstanceUsage { span: input.span(), has_instance: false };
|
||||
|
||||
input.parse::<keyword::T>()?;
|
||||
|
||||
@@ -503,7 +487,8 @@ pub fn check_type_def_gen(
|
||||
let mut err = syn::Error::new(span, msg);
|
||||
err.combine(e);
|
||||
err
|
||||
})?.0;
|
||||
})?
|
||||
.0;
|
||||
|
||||
// Span can be call_site if generic is empty. Thus we replace it.
|
||||
i.span = span;
|
||||
@@ -521,10 +506,7 @@ pub fn check_genesis_builder_usage(type_: &syn::Path) -> syn::Result<InstanceUsa
|
||||
pub struct Checker(InstanceUsage);
|
||||
impl syn::parse::Parse for Checker {
|
||||
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
|
||||
let mut instance_usage = InstanceUsage {
|
||||
span: input.span(),
|
||||
has_instance: false,
|
||||
};
|
||||
let mut instance_usage = InstanceUsage { span: input.span(), has_instance: false };
|
||||
|
||||
input.parse::<keyword::GenesisBuild>()?;
|
||||
input.parse::<syn::Token![<]>()?;
|
||||
@@ -546,7 +528,8 @@ pub fn check_genesis_builder_usage(type_: &syn::Path) -> syn::Result<InstanceUsa
|
||||
let mut err = syn::Error::new(type_.span(), msg);
|
||||
err.combine(e);
|
||||
err
|
||||
})?.0;
|
||||
})?
|
||||
.0;
|
||||
|
||||
Ok(i)
|
||||
}
|
||||
@@ -575,10 +558,7 @@ pub fn check_type_value_gen(
|
||||
input.parse::<syn::Token![:]>()?;
|
||||
input.parse::<keyword::Config>()?;
|
||||
|
||||
let mut instance_usage = InstanceUsage {
|
||||
span: input.span(),
|
||||
has_instance: false,
|
||||
};
|
||||
let mut instance_usage = InstanceUsage { span: input.span(), has_instance: false };
|
||||
|
||||
if input.is_empty() {
|
||||
return Ok(Self(Some(instance_usage)))
|
||||
@@ -603,17 +583,19 @@ pub fn check_type_value_gen(
|
||||
let mut err = syn::Error::new(span, msg);
|
||||
err.combine(e);
|
||||
err
|
||||
})?.0
|
||||
})?
|
||||
.0
|
||||
// Span can be call_site if generic is empty. Thus we replace it.
|
||||
.map(|mut i| { i.span = span; i });
|
||||
.map(|mut i| {
|
||||
i.span = span;
|
||||
i
|
||||
});
|
||||
|
||||
Ok(i)
|
||||
}
|
||||
|
||||
/// Check the keyword `DispatchResultWithPostInfo` or `DispatchResult`.
|
||||
pub fn check_pallet_call_return_type(
|
||||
type_: &syn::Type,
|
||||
) -> syn::Result<()> {
|
||||
pub fn check_pallet_call_return_type(type_: &syn::Type) -> syn::Result<()> {
|
||||
pub struct Checker;
|
||||
impl syn::parse::Parse for Checker {
|
||||
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use syn::spanned::Spanned;
|
||||
use super::helper;
|
||||
use syn::spanned::Spanned;
|
||||
|
||||
/// Implementation of the pallet hooks.
|
||||
pub struct HooksDef {
|
||||
@@ -42,30 +42,31 @@ impl HooksDef {
|
||||
item
|
||||
} else {
|
||||
let msg = "Invalid pallet::hooks, expected item impl";
|
||||
return Err(syn::Error::new(item.span(), msg));
|
||||
return Err(syn::Error::new(item.span(), msg))
|
||||
};
|
||||
|
||||
let mut instances = vec![];
|
||||
instances.push(helper::check_pallet_struct_usage(&item.self_ty)?);
|
||||
instances.push(helper::check_impl_gen(&item.generics, item.impl_token.span())?);
|
||||
|
||||
let item_trait = &item.trait_.as_ref()
|
||||
let item_trait = &item
|
||||
.trait_
|
||||
.as_ref()
|
||||
.ok_or_else(|| {
|
||||
let msg = "Invalid pallet::hooks, expected impl<..> Hooks \
|
||||
for Pallet<..>";
|
||||
syn::Error::new(item.span(), msg)
|
||||
})?.1;
|
||||
})?
|
||||
.1;
|
||||
|
||||
if item_trait.segments.len() != 1
|
||||
|| item_trait.segments[0].ident != "Hooks"
|
||||
{
|
||||
if item_trait.segments.len() != 1 || item_trait.segments[0].ident != "Hooks" {
|
||||
let msg = format!(
|
||||
"Invalid pallet::hooks, expected trait to be `Hooks` found `{}`\
|
||||
, you can import from `frame_support::pallet_prelude`",
|
||||
quote::quote!(#item_trait)
|
||||
);
|
||||
|
||||
return Err(syn::Error::new(item_trait.span(), msg));
|
||||
return Err(syn::Error::new(item_trait.span(), msg))
|
||||
}
|
||||
|
||||
let has_runtime_upgrade = item.items.iter().any(|i| match i {
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use syn::spanned::Spanned;
|
||||
use super::helper;
|
||||
use syn::spanned::Spanned;
|
||||
|
||||
/// The definition of the pallet inherent implementation.
|
||||
pub struct InherentDef {
|
||||
@@ -32,22 +32,22 @@ impl InherentDef {
|
||||
item
|
||||
} else {
|
||||
let msg = "Invalid pallet::inherent, expected item impl";
|
||||
return Err(syn::Error::new(item.span(), msg));
|
||||
return Err(syn::Error::new(item.span(), msg))
|
||||
};
|
||||
|
||||
if item.trait_.is_none() {
|
||||
let msg = "Invalid pallet::inherent, expected impl<..> ProvideInherent for Pallet<..>";
|
||||
return Err(syn::Error::new(item.span(), msg));
|
||||
return Err(syn::Error::new(item.span(), msg))
|
||||
}
|
||||
|
||||
if let Some(last) = item.trait_.as_ref().unwrap().1.segments.last() {
|
||||
if last.ident != "ProvideInherent" {
|
||||
let msg = "Invalid pallet::inherent, expected trait ProvideInherent";
|
||||
return Err(syn::Error::new(last.span(), msg));
|
||||
return Err(syn::Error::new(last.span(), msg))
|
||||
}
|
||||
} else {
|
||||
let msg = "Invalid pallet::inherent, expected impl<..> ProvideInherent for Pallet<..>";
|
||||
return Err(syn::Error::new(item.span(), msg));
|
||||
return Err(syn::Error::new(item.span(), msg))
|
||||
}
|
||||
|
||||
let mut instances = vec![];
|
||||
|
||||
@@ -19,24 +19,24 @@
|
||||
//!
|
||||
//! Parse the module into `Def` struct through `Def::try_from` function.
|
||||
|
||||
pub mod config;
|
||||
pub mod pallet_struct;
|
||||
pub mod hooks;
|
||||
pub mod call;
|
||||
pub mod config;
|
||||
pub mod error;
|
||||
pub mod origin;
|
||||
pub mod inherent;
|
||||
pub mod storage;
|
||||
pub mod event;
|
||||
pub mod helper;
|
||||
pub mod genesis_config;
|
||||
pub mod genesis_build;
|
||||
pub mod validate_unsigned;
|
||||
pub mod type_value;
|
||||
pub mod extra_constants;
|
||||
pub mod genesis_build;
|
||||
pub mod genesis_config;
|
||||
pub mod helper;
|
||||
pub mod hooks;
|
||||
pub mod inherent;
|
||||
pub mod origin;
|
||||
pub mod pallet_struct;
|
||||
pub mod storage;
|
||||
pub mod type_value;
|
||||
pub mod validate_unsigned;
|
||||
|
||||
use syn::spanned::Spanned;
|
||||
use frame_support_procedural_tools::generate_crate_access_2018;
|
||||
use syn::spanned::Spanned;
|
||||
|
||||
/// Parsed definition of a pallet.
|
||||
pub struct Def {
|
||||
@@ -67,11 +67,14 @@ impl Def {
|
||||
let frame_support = generate_crate_access_2018("frame-support")?;
|
||||
|
||||
let item_span = item.span();
|
||||
let items = &mut item.content.as_mut()
|
||||
let items = &mut item
|
||||
.content
|
||||
.as_mut()
|
||||
.ok_or_else(|| {
|
||||
let msg = "Invalid pallet definition, expected mod to be inlined.";
|
||||
syn::Error::new(item_span, msg)
|
||||
})?.1;
|
||||
})?
|
||||
.1;
|
||||
|
||||
let mut config = None;
|
||||
let mut pallet_struct = None;
|
||||
@@ -128,13 +131,12 @@ impl Def {
|
||||
},
|
||||
Some(PalletAttr::TypeValue(span)) =>
|
||||
type_values.push(type_value::TypeValueDef::try_from(span, index, item)?),
|
||||
Some(PalletAttr::ExtraConstants(_)) => {
|
||||
Some(PalletAttr::ExtraConstants(_)) =>
|
||||
extra_constants =
|
||||
Some(extra_constants::ExtraConstantsDef::try_from(index, item)?)
|
||||
},
|
||||
Some(extra_constants::ExtraConstantsDef::try_from(index, item)?),
|
||||
Some(attr) => {
|
||||
let msg = "Invalid duplicated attribute";
|
||||
return Err(syn::Error::new(attr.span(), msg));
|
||||
return Err(syn::Error::new(attr.span(), msg))
|
||||
},
|
||||
None => (),
|
||||
}
|
||||
@@ -148,12 +150,13 @@ impl Def {
|
||||
genesis_config.as_ref().map_or("unused", |_| "used"),
|
||||
genesis_build.as_ref().map_or("unused", |_| "used"),
|
||||
);
|
||||
return Err(syn::Error::new(item_span, msg));
|
||||
return Err(syn::Error::new(item_span, msg))
|
||||
}
|
||||
|
||||
let def = Def {
|
||||
item,
|
||||
config: config.ok_or_else(|| syn::Error::new(item_span, "Missing `#[pallet::config]`"))?,
|
||||
config: config
|
||||
.ok_or_else(|| syn::Error::new(item_span, "Missing `#[pallet::config]`"))?,
|
||||
pallet_struct: pallet_struct
|
||||
.ok_or_else(|| syn::Error::new(item_span, "Missing `#[pallet::pallet]`"))?,
|
||||
hooks,
|
||||
@@ -181,10 +184,7 @@ impl Def {
|
||||
/// Check that usage of trait `Event` is consistent with the definition, i.e. it is declared
|
||||
/// and trait defines type Event, or not declared and no trait associated type.
|
||||
fn check_event_usage(&self) -> syn::Result<()> {
|
||||
match (
|
||||
self.config.has_event_type,
|
||||
self.event.is_some(),
|
||||
) {
|
||||
match (self.config.has_event_type, self.event.is_some()) {
|
||||
(true, false) => {
|
||||
let msg = "Invalid usage of Event, `Config` contains associated type `Event`, \
|
||||
but enum `Event` is not declared (i.e. no use of `#[pallet::event]`). \
|
||||
@@ -197,7 +197,7 @@ impl Def {
|
||||
An Event associated type must be declare on trait `Config`.";
|
||||
Err(syn::Error::new(proc_macro2::Span::call_site(), msg))
|
||||
},
|
||||
_ => Ok(())
|
||||
_ => Ok(()),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -235,19 +235,18 @@ impl Def {
|
||||
instances.extend_from_slice(&extra_constants.instances[..]);
|
||||
}
|
||||
|
||||
let mut errors = instances.into_iter()
|
||||
.filter_map(|instances| {
|
||||
if instances.has_instance == self.config.has_instance {
|
||||
return None
|
||||
}
|
||||
let msg = if self.config.has_instance {
|
||||
"Invalid generic declaration, trait is defined with instance but generic use none"
|
||||
} else {
|
||||
"Invalid generic declaration, trait is defined without instance but generic use \
|
||||
let mut errors = instances.into_iter().filter_map(|instances| {
|
||||
if instances.has_instance == self.config.has_instance {
|
||||
return None
|
||||
}
|
||||
let msg = if self.config.has_instance {
|
||||
"Invalid generic declaration, trait is defined with instance but generic use none"
|
||||
} else {
|
||||
"Invalid generic declaration, trait is defined without instance but generic use \
|
||||
some"
|
||||
};
|
||||
Some(syn::Error::new(instances.span, msg))
|
||||
});
|
||||
};
|
||||
Some(syn::Error::new(instances.span, msg))
|
||||
});
|
||||
|
||||
if let Some(mut first_error) = errors.next() {
|
||||
for error in errors {
|
||||
@@ -351,7 +350,8 @@ impl GenericKind {
|
||||
match self {
|
||||
GenericKind::None => quote::quote!(),
|
||||
GenericKind::Config => quote::quote_spanned!(span => T: Config),
|
||||
GenericKind::ConfigAndInstance => quote::quote_spanned!(span => T: Config<I>, I: 'static),
|
||||
GenericKind::ConfigAndInstance =>
|
||||
quote::quote_spanned!(span => T: Config<I>, I: 'static),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use syn::spanned::Spanned;
|
||||
use super::helper;
|
||||
use syn::spanned::Spanned;
|
||||
|
||||
/// Definition of the pallet origin type.
|
||||
///
|
||||
@@ -42,7 +42,7 @@ impl OriginDef {
|
||||
syn::Item::Type(item) => (&item.vis, &item.ident, &item.generics),
|
||||
_ => {
|
||||
let msg = "Invalid pallet::origin, expected enum or struct or type";
|
||||
return Err(syn::Error::new(item.span(), msg));
|
||||
return Err(syn::Error::new(item.span(), msg))
|
||||
},
|
||||
};
|
||||
|
||||
@@ -54,27 +54,19 @@ impl OriginDef {
|
||||
instances.push(u);
|
||||
} else {
|
||||
// construct_runtime only allow generic event for instantiable pallet.
|
||||
instances.push(helper::InstanceUsage {
|
||||
has_instance: false,
|
||||
span: ident.span(),
|
||||
})
|
||||
instances.push(helper::InstanceUsage { has_instance: false, span: ident.span() })
|
||||
}
|
||||
|
||||
if !matches!(vis, syn::Visibility::Public(_)) {
|
||||
let msg = "Invalid pallet::origin, Origin must be public";
|
||||
return Err(syn::Error::new(item_span, msg));
|
||||
return Err(syn::Error::new(item_span, msg))
|
||||
}
|
||||
|
||||
if ident != "Origin" {
|
||||
let msg = "Invalid pallet::origin, ident must `Origin`";
|
||||
return Err(syn::Error::new(ident.span(), msg));
|
||||
return Err(syn::Error::new(ident.span(), msg))
|
||||
}
|
||||
|
||||
Ok(OriginDef {
|
||||
index,
|
||||
has_instance,
|
||||
is_generic,
|
||||
instances,
|
||||
})
|
||||
Ok(OriginDef { index, has_instance, is_generic, instances })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
// limitations under the License.
|
||||
|
||||
use super::helper;
|
||||
use syn::spanned::Spanned;
|
||||
use quote::ToTokens;
|
||||
use syn::spanned::Spanned;
|
||||
|
||||
/// List of additional token to be used for parsing.
|
||||
mod keyword {
|
||||
@@ -49,11 +49,7 @@ pub struct PalletStructDef {
|
||||
/// * `#[pallet::generate_store($vis trait Store)]`
|
||||
/// * `#[pallet::generate_storage_info]`
|
||||
pub enum PalletStructAttr {
|
||||
GenerateStore {
|
||||
span: proc_macro2::Span,
|
||||
vis: syn::Visibility,
|
||||
keyword: keyword::Store,
|
||||
},
|
||||
GenerateStore { span: proc_macro2::Span, vis: syn::Visibility, keyword: keyword::Store },
|
||||
GenerateStorageInfoTrait(proc_macro2::Span),
|
||||
}
|
||||
|
||||
@@ -103,7 +99,7 @@ impl PalletStructDef {
|
||||
item
|
||||
} else {
|
||||
let msg = "Invalid pallet::pallet, expected struct definition";
|
||||
return Err(syn::Error::new(item.span(), msg));
|
||||
return Err(syn::Error::new(item.span(), msg))
|
||||
};
|
||||
|
||||
let mut store = None;
|
||||
@@ -115,12 +111,14 @@ impl PalletStructDef {
|
||||
PalletStructAttr::GenerateStore { vis, keyword, .. } if store.is_none() => {
|
||||
store = Some((vis, keyword));
|
||||
},
|
||||
PalletStructAttr::GenerateStorageInfoTrait(span) if generate_storage_info.is_none() => {
|
||||
PalletStructAttr::GenerateStorageInfoTrait(span)
|
||||
if generate_storage_info.is_none() =>
|
||||
{
|
||||
generate_storage_info = Some(span);
|
||||
},
|
||||
}
|
||||
attr => {
|
||||
let msg = "Unexpected duplicated attribute";
|
||||
return Err(syn::Error::new(attr.span(), msg));
|
||||
return Err(syn::Error::new(attr.span(), msg))
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -129,12 +127,12 @@ impl PalletStructDef {
|
||||
|
||||
if !matches!(item.vis, syn::Visibility::Public(_)) {
|
||||
let msg = "Invalid pallet::pallet, Pallet must be public";
|
||||
return Err(syn::Error::new(item.span(), msg));
|
||||
return Err(syn::Error::new(item.span(), msg))
|
||||
}
|
||||
|
||||
if item.generics.where_clause.is_some() {
|
||||
let msg = "Invalid pallet::pallet, where clause not supported on Pallet declaration";
|
||||
return Err(syn::Error::new(item.generics.where_clause.span(), msg));
|
||||
return Err(syn::Error::new(item.generics.where_clause.span(), msg))
|
||||
}
|
||||
|
||||
let mut instances = vec![];
|
||||
|
||||
@@ -16,9 +16,9 @@
|
||||
// limitations under the License.
|
||||
|
||||
use super::helper;
|
||||
use syn::spanned::Spanned;
|
||||
use quote::ToTokens;
|
||||
use std::collections::HashMap;
|
||||
use syn::spanned::Spanned;
|
||||
|
||||
/// List of additional token to be used for parsing.
|
||||
mod keyword {
|
||||
@@ -69,11 +69,10 @@ impl syn::parse::Parse for PalletStorageAttr {
|
||||
|
||||
let renamed_prefix = content.parse::<syn::LitStr>()?;
|
||||
// Ensure the renamed prefix is a proper Rust identifier
|
||||
syn::parse_str::<syn::Ident>(&renamed_prefix.value())
|
||||
.map_err(|_| {
|
||||
let msg = format!("`{}` is not a valid identifier", renamed_prefix.value());
|
||||
syn::Error::new(renamed_prefix.span(), msg)
|
||||
})?;
|
||||
syn::parse_str::<syn::Ident>(&renamed_prefix.value()).map_err(|_| {
|
||||
let msg = format!("`{}` is not a valid identifier", renamed_prefix.value());
|
||||
syn::Error::new(renamed_prefix.span(), msg)
|
||||
})?;
|
||||
|
||||
Ok(Self::StorageName(renamed_prefix, attr_span))
|
||||
} else {
|
||||
@@ -86,16 +85,8 @@ impl syn::parse::Parse for PalletStorageAttr {
|
||||
pub enum Metadata {
|
||||
Value { value: syn::Type },
|
||||
Map { value: syn::Type, key: syn::Type },
|
||||
DoubleMap {
|
||||
value: syn::Type,
|
||||
key1: syn::Type,
|
||||
key2: syn::Type
|
||||
},
|
||||
NMap {
|
||||
keys: Vec<syn::Type>,
|
||||
keygen: syn::Type,
|
||||
value: syn::Type,
|
||||
},
|
||||
DoubleMap { value: syn::Type, key1: syn::Type, key2: syn::Type },
|
||||
NMap { keys: Vec<syn::Type>, keygen: syn::Type, value: syn::Type },
|
||||
}
|
||||
|
||||
pub enum QueryKind {
|
||||
@@ -181,11 +172,8 @@ impl StorageGenerics {
|
||||
Self::DoubleMap { value, key1, key2, .. } => Metadata::DoubleMap { value, key1, key2 },
|
||||
Self::Map { value, key, .. } => Metadata::Map { value, key },
|
||||
Self::Value { value, .. } => Metadata::Value { value },
|
||||
Self::NMap { keygen, value, .. } => Metadata::NMap {
|
||||
keys: collect_keys(&keygen)?,
|
||||
keygen,
|
||||
value,
|
||||
},
|
||||
Self::NMap { keygen, value, .. } =>
|
||||
Metadata::NMap { keys: collect_keys(&keygen)?, keygen, value },
|
||||
};
|
||||
|
||||
Ok(res)
|
||||
@@ -194,11 +182,10 @@ impl StorageGenerics {
|
||||
/// Return the query kind from the defined generics
|
||||
fn query_kind(&self) -> Option<syn::Type> {
|
||||
match &self {
|
||||
Self::DoubleMap { query_kind, .. }
|
||||
| Self::Map { query_kind, .. }
|
||||
| Self::Value { query_kind, .. }
|
||||
| Self::NMap { query_kind, .. }
|
||||
=> query_kind.clone(),
|
||||
Self::DoubleMap { query_kind, .. } |
|
||||
Self::Map { query_kind, .. } |
|
||||
Self::Value { query_kind, .. } |
|
||||
Self::NMap { query_kind, .. } => query_kind.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -225,7 +212,10 @@ fn check_generics(
|
||||
let mut e = format!(
|
||||
"`{}` expect generics {}and optional generics {}",
|
||||
storage_type_name,
|
||||
mandatory_generics.iter().map(|name| format!("`{}`, ", name)).collect::<String>(),
|
||||
mandatory_generics
|
||||
.iter()
|
||||
.map(|name| format!("`{}`, ", name))
|
||||
.collect::<String>(),
|
||||
&optional_generics.iter().map(|name| format!("`{}`, ", name)).collect::<String>(),
|
||||
);
|
||||
e.pop();
|
||||
@@ -235,14 +225,12 @@ fn check_generics(
|
||||
};
|
||||
|
||||
for (gen_name, gen_binding) in map {
|
||||
if !mandatory_generics.contains(&gen_name.as_str())
|
||||
&& !optional_generics.contains(&gen_name.as_str())
|
||||
if !mandatory_generics.contains(&gen_name.as_str()) &&
|
||||
!optional_generics.contains(&gen_name.as_str())
|
||||
{
|
||||
let msg = format!(
|
||||
"Invalid pallet::storage, Unexpected generic `{}` for `{}`. {}",
|
||||
gen_name,
|
||||
storage_type_name,
|
||||
expectation,
|
||||
gen_name, storage_type_name, expectation,
|
||||
);
|
||||
errors.push(syn::Error::new(gen_binding.span(), msg));
|
||||
}
|
||||
@@ -252,8 +240,7 @@ fn check_generics(
|
||||
if !map.contains_key(&mandatory_generic.to_string()) {
|
||||
let msg = format!(
|
||||
"Invalid pallet::storage, cannot find `{}` generic, required for `{}`.",
|
||||
mandatory_generic,
|
||||
storage_type_name
|
||||
mandatory_generic, storage_type_name
|
||||
);
|
||||
errors.push(syn::Error::new(args_span, msg));
|
||||
}
|
||||
@@ -284,7 +271,7 @@ fn process_named_generics(
|
||||
let msg = "Invalid pallet::storage, Duplicated named generic";
|
||||
let mut err = syn::Error::new(arg.ident.span(), msg);
|
||||
err.combine(syn::Error::new(other.ident.span(), msg));
|
||||
return Err(err);
|
||||
return Err(err)
|
||||
}
|
||||
parsed.insert(arg.ident.to_string(), arg.clone());
|
||||
}
|
||||
@@ -300,15 +287,14 @@ fn process_named_generics(
|
||||
)?;
|
||||
|
||||
StorageGenerics::Value {
|
||||
value: parsed.remove("Value")
|
||||
value: parsed
|
||||
.remove("Value")
|
||||
.map(|binding| binding.ty)
|
||||
.expect("checked above as mandatory generic"),
|
||||
query_kind: parsed.remove("QueryKind")
|
||||
.map(|binding| binding.ty),
|
||||
on_empty: parsed.remove("OnEmpty")
|
||||
.map(|binding| binding.ty),
|
||||
query_kind: parsed.remove("QueryKind").map(|binding| binding.ty),
|
||||
on_empty: parsed.remove("OnEmpty").map(|binding| binding.ty),
|
||||
}
|
||||
}
|
||||
},
|
||||
StorageKind::Map => {
|
||||
check_generics(
|
||||
&parsed,
|
||||
@@ -319,20 +305,23 @@ fn process_named_generics(
|
||||
)?;
|
||||
|
||||
StorageGenerics::Map {
|
||||
hasher: parsed.remove("Hasher")
|
||||
hasher: parsed
|
||||
.remove("Hasher")
|
||||
.map(|binding| binding.ty)
|
||||
.expect("checked above as mandatory generic"),
|
||||
key: parsed.remove("Key")
|
||||
key: parsed
|
||||
.remove("Key")
|
||||
.map(|binding| binding.ty)
|
||||
.expect("checked above as mandatory generic"),
|
||||
value: parsed.remove("Value")
|
||||
value: parsed
|
||||
.remove("Value")
|
||||
.map(|binding| binding.ty)
|
||||
.expect("checked above as mandatory generic"),
|
||||
query_kind: parsed.remove("QueryKind").map(|binding| binding.ty),
|
||||
on_empty: parsed.remove("OnEmpty").map(|binding| binding.ty),
|
||||
max_values: parsed.remove("MaxValues").map(|binding| binding.ty),
|
||||
}
|
||||
}
|
||||
},
|
||||
StorageKind::DoubleMap => {
|
||||
check_generics(
|
||||
&parsed,
|
||||
@@ -343,26 +332,31 @@ fn process_named_generics(
|
||||
)?;
|
||||
|
||||
StorageGenerics::DoubleMap {
|
||||
hasher1: parsed.remove("Hasher1")
|
||||
hasher1: parsed
|
||||
.remove("Hasher1")
|
||||
.map(|binding| binding.ty)
|
||||
.expect("checked above as mandatory generic"),
|
||||
key1: parsed.remove("Key1")
|
||||
key1: parsed
|
||||
.remove("Key1")
|
||||
.map(|binding| binding.ty)
|
||||
.expect("checked above as mandatory generic"),
|
||||
hasher2: parsed.remove("Hasher2")
|
||||
hasher2: parsed
|
||||
.remove("Hasher2")
|
||||
.map(|binding| binding.ty)
|
||||
.expect("checked above as mandatory generic"),
|
||||
key2: parsed.remove("Key2")
|
||||
key2: parsed
|
||||
.remove("Key2")
|
||||
.map(|binding| binding.ty)
|
||||
.expect("checked above as mandatory generic"),
|
||||
value: parsed.remove("Value")
|
||||
value: parsed
|
||||
.remove("Value")
|
||||
.map(|binding| binding.ty)
|
||||
.expect("checked above as mandatory generic"),
|
||||
query_kind: parsed.remove("QueryKind").map(|binding| binding.ty),
|
||||
on_empty: parsed.remove("OnEmpty").map(|binding| binding.ty),
|
||||
max_values: parsed.remove("MaxValues").map(|binding| binding.ty),
|
||||
}
|
||||
}
|
||||
},
|
||||
StorageKind::NMap => {
|
||||
check_generics(
|
||||
&parsed,
|
||||
@@ -373,17 +367,19 @@ fn process_named_generics(
|
||||
)?;
|
||||
|
||||
StorageGenerics::NMap {
|
||||
keygen: parsed.remove("Key")
|
||||
keygen: parsed
|
||||
.remove("Key")
|
||||
.map(|binding| binding.ty)
|
||||
.expect("checked above as mandatory generic"),
|
||||
value: parsed.remove("Value")
|
||||
value: parsed
|
||||
.remove("Value")
|
||||
.map(|binding| binding.ty)
|
||||
.expect("checked above as mandatory generic"),
|
||||
query_kind: parsed.remove("QueryKind").map(|binding| binding.ty),
|
||||
on_empty: parsed.remove("OnEmpty").map(|binding| binding.ty),
|
||||
max_values: parsed.remove("MaxValues").map(|binding| binding.ty),
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
let metadata = generics.metadata()?;
|
||||
@@ -399,41 +395,32 @@ fn process_unnamed_generics(
|
||||
args: &[syn::Type],
|
||||
) -> syn::Result<(Option<StorageGenerics>, Metadata, Option<syn::Type>)> {
|
||||
let retrieve_arg = |arg_pos| {
|
||||
args.get(arg_pos)
|
||||
.cloned()
|
||||
.ok_or_else(|| {
|
||||
let msg = format!(
|
||||
"Invalid pallet::storage, unexpected number of generic argument, \
|
||||
args.get(arg_pos).cloned().ok_or_else(|| {
|
||||
let msg = format!(
|
||||
"Invalid pallet::storage, unexpected number of generic argument, \
|
||||
expect at least {} args, found {}.",
|
||||
arg_pos + 1,
|
||||
args.len(),
|
||||
);
|
||||
syn::Error::new(args_span, msg)
|
||||
})
|
||||
arg_pos + 1,
|
||||
args.len(),
|
||||
);
|
||||
syn::Error::new(args_span, msg)
|
||||
})
|
||||
};
|
||||
|
||||
let prefix_arg = retrieve_arg(0)?;
|
||||
syn::parse2::<syn::Token![_]>(prefix_arg.to_token_stream())
|
||||
.map_err(|e| {
|
||||
let msg = "Invalid pallet::storage, for unnamed generic arguments the type \
|
||||
syn::parse2::<syn::Token![_]>(prefix_arg.to_token_stream()).map_err(|e| {
|
||||
let msg = "Invalid pallet::storage, for unnamed generic arguments the type \
|
||||
first generic argument must be `_`, the argument is then replaced by macro.";
|
||||
let mut err = syn::Error::new(prefix_arg.span(), msg);
|
||||
err.combine(e);
|
||||
err
|
||||
})?;
|
||||
let mut err = syn::Error::new(prefix_arg.span(), msg);
|
||||
err.combine(e);
|
||||
err
|
||||
})?;
|
||||
|
||||
let res = match storage {
|
||||
StorageKind::Value => (
|
||||
None,
|
||||
Metadata::Value { value: retrieve_arg(1)? },
|
||||
retrieve_arg(2).ok(),
|
||||
),
|
||||
StorageKind::Value =>
|
||||
(None, Metadata::Value { value: retrieve_arg(1)? }, retrieve_arg(2).ok()),
|
||||
StorageKind::Map => (
|
||||
None,
|
||||
Metadata::Map {
|
||||
key: retrieve_arg(2)?,
|
||||
value: retrieve_arg(3)?,
|
||||
},
|
||||
Metadata::Map { key: retrieve_arg(2)?, value: retrieve_arg(3)? },
|
||||
retrieve_arg(4).ok(),
|
||||
),
|
||||
StorageKind::DoubleMap => (
|
||||
@@ -448,15 +435,7 @@ fn process_unnamed_generics(
|
||||
StorageKind::NMap => {
|
||||
let keygen = retrieve_arg(1)?;
|
||||
let keys = collect_keys(&keygen)?;
|
||||
(
|
||||
None,
|
||||
Metadata::NMap {
|
||||
keys,
|
||||
keygen,
|
||||
value: retrieve_arg(2)?,
|
||||
},
|
||||
retrieve_arg(3).ok(),
|
||||
)
|
||||
(None, Metadata::NMap { keys, keygen, value: retrieve_arg(2)? }, retrieve_arg(3).ok())
|
||||
},
|
||||
};
|
||||
|
||||
@@ -479,8 +458,8 @@ fn process_generics(
|
||||
found `{}`.",
|
||||
found,
|
||||
);
|
||||
return Err(syn::Error::new(segment.ident.span(), msg));
|
||||
}
|
||||
return Err(syn::Error::new(segment.ident.span(), msg))
|
||||
},
|
||||
};
|
||||
|
||||
let args_span = segment.arguments.span();
|
||||
@@ -490,12 +469,14 @@ fn process_generics(
|
||||
_ => {
|
||||
let msg = "Invalid pallet::storage, invalid number of generic generic arguments, \
|
||||
expect more that 0 generic arguments.";
|
||||
return Err(syn::Error::new(segment.span(), msg));
|
||||
}
|
||||
return Err(syn::Error::new(segment.span(), msg))
|
||||
},
|
||||
};
|
||||
|
||||
if args.args.iter().all(|gen| matches!(gen, syn::GenericArgument::Type(_))) {
|
||||
let args = args.args.iter()
|
||||
let args = args
|
||||
.args
|
||||
.iter()
|
||||
.map(|gen| match gen {
|
||||
syn::GenericArgument::Type(gen) => gen.clone(),
|
||||
_ => unreachable!("It is asserted above that all generics are types"),
|
||||
@@ -503,7 +484,9 @@ fn process_generics(
|
||||
.collect::<Vec<_>>();
|
||||
process_unnamed_generics(&storage_kind, args_span, &args)
|
||||
} else if args.args.iter().all(|gen| matches!(gen, syn::GenericArgument::Binding(_))) {
|
||||
let args = args.args.iter()
|
||||
let args = args
|
||||
.args
|
||||
.iter()
|
||||
.map(|gen| match gen {
|
||||
syn::GenericArgument::Binding(gen) => gen.clone(),
|
||||
_ => unreachable!("It is asserted above that all generics are bindings"),
|
||||
@@ -521,11 +504,7 @@ fn process_generics(
|
||||
/// Parse the 2nd type argument to `StorageNMap` and return its keys.
|
||||
fn collect_keys(keygen: &syn::Type) -> syn::Result<Vec<syn::Type>> {
|
||||
if let syn::Type::Tuple(tup) = keygen {
|
||||
tup
|
||||
.elems
|
||||
.iter()
|
||||
.map(extract_key)
|
||||
.collect::<syn::Result<Vec<_>>>()
|
||||
tup.elems.iter().map(extract_key).collect::<syn::Result<Vec<_>>>()
|
||||
} else {
|
||||
Ok(vec![extract_key(keygen)?])
|
||||
}
|
||||
@@ -537,7 +516,7 @@ fn extract_key(ty: &syn::Type) -> syn::Result<syn::Type> {
|
||||
typ
|
||||
} else {
|
||||
let msg = "Invalid pallet::storage, expected type path";
|
||||
return Err(syn::Error::new(ty.span(), msg));
|
||||
return Err(syn::Error::new(ty.span(), msg))
|
||||
};
|
||||
|
||||
let key_struct = typ.path.segments.last().ok_or_else(|| {
|
||||
@@ -546,28 +525,31 @@ fn extract_key(ty: &syn::Type) -> syn::Result<syn::Type> {
|
||||
})?;
|
||||
if key_struct.ident != "Key" && key_struct.ident != "NMapKey" {
|
||||
let msg = "Invalid pallet::storage, expected Key or NMapKey struct";
|
||||
return Err(syn::Error::new(key_struct.ident.span(), msg));
|
||||
return Err(syn::Error::new(key_struct.ident.span(), msg))
|
||||
}
|
||||
|
||||
let ty_params = if let syn::PathArguments::AngleBracketed(args) = &key_struct.arguments {
|
||||
args
|
||||
} else {
|
||||
let msg = "Invalid pallet::storage, expected angle bracketed arguments";
|
||||
return Err(syn::Error::new(key_struct.arguments.span(), msg));
|
||||
return Err(syn::Error::new(key_struct.arguments.span(), msg))
|
||||
};
|
||||
|
||||
if ty_params.args.len() != 2 {
|
||||
let msg = format!("Invalid pallet::storage, unexpected number of generic arguments \
|
||||
for Key struct, expected 2 args, found {}", ty_params.args.len());
|
||||
return Err(syn::Error::new(ty_params.span(), msg));
|
||||
let msg = format!(
|
||||
"Invalid pallet::storage, unexpected number of generic arguments \
|
||||
for Key struct, expected 2 args, found {}",
|
||||
ty_params.args.len()
|
||||
);
|
||||
return Err(syn::Error::new(ty_params.span(), msg))
|
||||
}
|
||||
|
||||
let key = match &ty_params.args[1] {
|
||||
syn::GenericArgument::Type(key_ty) => key_ty.clone(),
|
||||
_ => {
|
||||
let msg = "Invalid pallet::storage, expected type";
|
||||
return Err(syn::Error::new(ty_params.args[1].span(), msg));
|
||||
}
|
||||
return Err(syn::Error::new(ty_params.args[1].span(), msg))
|
||||
},
|
||||
};
|
||||
|
||||
Ok(key)
|
||||
@@ -576,8 +558,7 @@ fn extract_key(ty: &syn::Type) -> syn::Result<syn::Type> {
|
||||
impl StorageDef {
|
||||
/// Return the storage prefix for this storage item
|
||||
pub fn prefix(&self) -> String {
|
||||
self
|
||||
.rename_as
|
||||
self.rename_as
|
||||
.as_ref()
|
||||
.map(syn::LitStr::value)
|
||||
.unwrap_or(self.ident.to_string())
|
||||
@@ -586,11 +567,7 @@ impl StorageDef {
|
||||
/// Return either the span of the ident or the span of the literal in the
|
||||
/// #[storage_prefix] attribute
|
||||
pub fn prefix_span(&self) -> proc_macro2::Span {
|
||||
self
|
||||
.rename_as
|
||||
.as_ref()
|
||||
.map(syn::LitStr::span)
|
||||
.unwrap_or(self.ident.span())
|
||||
self.rename_as.as_ref().map(syn::LitStr::span).unwrap_or(self.ident.span())
|
||||
}
|
||||
|
||||
pub fn try_from(
|
||||
@@ -601,7 +578,7 @@ impl StorageDef {
|
||||
let item = if let syn::Item::Type(item) = item {
|
||||
item
|
||||
} else {
|
||||
return Err(syn::Error::new(item.span(), "Invalid pallet::storage, expect item type."));
|
||||
return Err(syn::Error::new(item.span(), "Invalid pallet::storage, expect item type."))
|
||||
};
|
||||
|
||||
let attrs: Vec<PalletStorageAttr> = helper::take_item_pallet_attrs(&mut item.attrs)?;
|
||||
@@ -610,23 +587,19 @@ impl StorageDef {
|
||||
.partition::<Vec<_>, _>(|attr| matches!(attr, PalletStorageAttr::Getter(..)));
|
||||
if getters.len() > 1 {
|
||||
let msg = "Invalid pallet::storage, multiple argument pallet::getter found";
|
||||
return Err(syn::Error::new(getters[1].attr_span(), msg));
|
||||
return Err(syn::Error::new(getters[1].attr_span(), msg))
|
||||
}
|
||||
if names.len() > 1 {
|
||||
let msg = "Invalid pallet::storage, multiple argument pallet::storage_prefix found";
|
||||
return Err(syn::Error::new(names[1].attr_span(), msg));
|
||||
return Err(syn::Error::new(names[1].attr_span(), msg))
|
||||
}
|
||||
let getter = getters.pop().map(|attr| {
|
||||
match attr {
|
||||
PalletStorageAttr::Getter(ident, _) => ident,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
let getter = getters.pop().map(|attr| match attr {
|
||||
PalletStorageAttr::Getter(ident, _) => ident,
|
||||
_ => unreachable!(),
|
||||
});
|
||||
let rename_as = names.pop().map(|attr| {
|
||||
match attr {
|
||||
PalletStorageAttr::StorageName(lit, _) => lit,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
let rename_as = names.pop().map(|attr| match attr {
|
||||
PalletStorageAttr::StorageName(lit, _) => lit,
|
||||
_ => unreachable!(),
|
||||
});
|
||||
|
||||
let cfg_attrs = helper::get_item_cfg_attrs(&item.attrs);
|
||||
@@ -641,12 +614,12 @@ impl StorageDef {
|
||||
typ
|
||||
} else {
|
||||
let msg = "Invalid pallet::storage, expected type path";
|
||||
return Err(syn::Error::new(item.ty.span(), msg));
|
||||
return Err(syn::Error::new(item.ty.span(), msg))
|
||||
};
|
||||
|
||||
if typ.path.segments.len() != 1 {
|
||||
let msg = "Invalid pallet::storage, expected type path with one segment";
|
||||
return Err(syn::Error::new(item.ty.span(), msg));
|
||||
return Err(syn::Error::new(item.ty.span(), msg))
|
||||
}
|
||||
|
||||
let (named_generics, metadata, query_kind) = process_generics(&typ.path.segments[0])?;
|
||||
@@ -654,11 +627,11 @@ impl StorageDef {
|
||||
let query_kind = query_kind
|
||||
.map(|query_kind| match query_kind {
|
||||
syn::Type::Path(path)
|
||||
if path.path.segments.last().map_or(false, |s| s.ident == "OptionQuery")
|
||||
=> Some(QueryKind::OptionQuery),
|
||||
if path.path.segments.last().map_or(false, |s| s.ident == "OptionQuery") =>
|
||||
Some(QueryKind::OptionQuery),
|
||||
syn::Type::Path(path)
|
||||
if path.path.segments.last().map_or(false, |s| s.ident == "ValueQuery")
|
||||
=> Some(QueryKind::ValueQuery),
|
||||
if path.path.segments.last().map_or(false, |s| s.ident == "ValueQuery") =>
|
||||
Some(QueryKind::ValueQuery),
|
||||
_ => None,
|
||||
})
|
||||
.unwrap_or(Some(QueryKind::OptionQuery)); // This value must match the default generic.
|
||||
@@ -667,7 +640,7 @@ impl StorageDef {
|
||||
let msg = "Invalid pallet::storage, cannot generate getter because QueryKind is not \
|
||||
identifiable. QueryKind must be `OptionQuery`, `ValueQuery`, or default one to be \
|
||||
identifiable.";
|
||||
return Err(syn::Error::new(getter.unwrap().span(), msg));
|
||||
return Err(syn::Error::new(getter.unwrap().span(), msg))
|
||||
}
|
||||
|
||||
Ok(StorageDef {
|
||||
|
||||
@@ -50,28 +50,31 @@ impl TypeValueDef {
|
||||
item
|
||||
} else {
|
||||
let msg = "Invalid pallet::type_value, expected item fn";
|
||||
return Err(syn::Error::new(item.span(), msg));
|
||||
return Err(syn::Error::new(item.span(), msg))
|
||||
};
|
||||
|
||||
|
||||
if !item.attrs.is_empty() {
|
||||
let msg = "Invalid pallet::type_value, unexpected attribute";
|
||||
return Err(syn::Error::new(item.attrs[0].span(), msg));
|
||||
return Err(syn::Error::new(item.attrs[0].span(), msg))
|
||||
}
|
||||
|
||||
if let Some(span) = item.sig.constness.as_ref().map(|t| t.span())
|
||||
if let Some(span) = item
|
||||
.sig
|
||||
.constness
|
||||
.as_ref()
|
||||
.map(|t| t.span())
|
||||
.or_else(|| item.sig.asyncness.as_ref().map(|t| t.span()))
|
||||
.or_else(|| item.sig.unsafety.as_ref().map(|t| t.span()))
|
||||
.or_else(|| item.sig.abi.as_ref().map(|t| t.span()))
|
||||
.or_else(|| item.sig.variadic.as_ref().map(|t| t.span()))
|
||||
{
|
||||
let msg = "Invalid pallet::type_value, unexpected token";
|
||||
return Err(syn::Error::new(span, msg));
|
||||
return Err(syn::Error::new(span, msg))
|
||||
}
|
||||
|
||||
if !item.sig.inputs.is_empty() {
|
||||
let msg = "Invalid pallet::type_value, unexpected argument";
|
||||
return Err(syn::Error::new(item.sig.inputs[0].span(), msg));
|
||||
return Err(syn::Error::new(item.sig.inputs[0].span(), msg))
|
||||
}
|
||||
|
||||
let vis = item.vis.clone();
|
||||
@@ -81,7 +84,7 @@ impl TypeValueDef {
|
||||
syn::ReturnType::Type(_, type_) => type_,
|
||||
syn::ReturnType::Default => {
|
||||
let msg = "Invalid pallet::type_value, expected return type";
|
||||
return Err(syn::Error::new(item.sig.span(), msg));
|
||||
return Err(syn::Error::new(item.sig.span(), msg))
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use syn::spanned::Spanned;
|
||||
use super::helper;
|
||||
use syn::spanned::Spanned;
|
||||
|
||||
/// The definition of the pallet validate unsigned implementation.
|
||||
pub struct ValidateUnsignedDef {
|
||||
@@ -32,24 +32,24 @@ impl ValidateUnsignedDef {
|
||||
item
|
||||
} else {
|
||||
let msg = "Invalid pallet::validate_unsigned, expected item impl";
|
||||
return Err(syn::Error::new(item.span(), msg));
|
||||
return Err(syn::Error::new(item.span(), msg))
|
||||
};
|
||||
|
||||
if item.trait_.is_none() {
|
||||
let msg = "Invalid pallet::validate_unsigned, expected impl<..> ValidateUnsigned for \
|
||||
Pallet<..>";
|
||||
return Err(syn::Error::new(item.span(), msg));
|
||||
return Err(syn::Error::new(item.span(), msg))
|
||||
}
|
||||
|
||||
if let Some(last) = item.trait_.as_ref().unwrap().1.segments.last() {
|
||||
if last.ident != "ValidateUnsigned" {
|
||||
let msg = "Invalid pallet::validate_unsigned, expected trait ValidateUnsigned";
|
||||
return Err(syn::Error::new(last.span(), msg));
|
||||
return Err(syn::Error::new(last.span(), msg))
|
||||
}
|
||||
} else {
|
||||
let msg = "Invalid pallet::validate_unsigned, expected impl<..> ValidateUnsigned for \
|
||||
Pallet<..>";
|
||||
return Err(syn::Error::new(item.span(), msg));
|
||||
return Err(syn::Error::new(item.span(), msg))
|
||||
}
|
||||
|
||||
let mut instances = vec![];
|
||||
|
||||
@@ -17,10 +17,10 @@
|
||||
|
||||
//! Implementation of macros related to pallet versioning.
|
||||
|
||||
use proc_macro2::{TokenStream, Span};
|
||||
use syn::{Result, Error};
|
||||
use std::{env, str::FromStr};
|
||||
use frame_support_procedural_tools::generate_crate_access_2018;
|
||||
use proc_macro2::{Span, TokenStream};
|
||||
use std::{env, str::FromStr};
|
||||
use syn::{Error, Result};
|
||||
|
||||
/// Get the version from the given version environment variable.
|
||||
///
|
||||
|
||||
@@ -30,41 +30,47 @@ pub fn derive_partial_eq_no_bound(input: proc_macro::TokenStream) -> proc_macro:
|
||||
let impl_ = match input.data {
|
||||
syn::Data::Struct(struct_) => match struct_.fields {
|
||||
syn::Fields::Named(named) => {
|
||||
let fields = named.named.iter()
|
||||
let fields = named
|
||||
.named
|
||||
.iter()
|
||||
.map(|i| &i.ident)
|
||||
.map(|i| quote::quote_spanned!(i.span() => self.#i == other.#i ));
|
||||
|
||||
quote::quote!( true #( && #fields )* )
|
||||
},
|
||||
syn::Fields::Unnamed(unnamed) => {
|
||||
let fields = unnamed.unnamed.iter().enumerate()
|
||||
let fields = unnamed
|
||||
.unnamed
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, _)| syn::Index::from(i))
|
||||
.map(|i| quote::quote_spanned!(i.span() => self.#i == other.#i ));
|
||||
|
||||
quote::quote!( true #( && #fields )* )
|
||||
},
|
||||
syn::Fields::Unit => {
|
||||
quote::quote!( true )
|
||||
}
|
||||
quote::quote!(true)
|
||||
},
|
||||
},
|
||||
syn::Data::Enum(enum_) => {
|
||||
let variants = enum_.variants.iter()
|
||||
.map(|variant| {
|
||||
let variants =
|
||||
enum_.variants.iter().map(|variant| {
|
||||
let ident = &variant.ident;
|
||||
match &variant.fields {
|
||||
syn::Fields::Named(named) => {
|
||||
let names = named.named.iter().map(|i| &i.ident);
|
||||
let other_names = names.clone()
|
||||
.enumerate()
|
||||
.map(|(n, ident)|
|
||||
syn::Ident::new(&format!("_{}", n), ident.span())
|
||||
);
|
||||
let other_names = names.clone().enumerate().map(|(n, ident)| {
|
||||
syn::Ident::new(&format!("_{}", n), ident.span())
|
||||
});
|
||||
|
||||
let capture = names.clone();
|
||||
let other_capture = names.clone().zip(other_names.clone())
|
||||
let other_capture = names
|
||||
.clone()
|
||||
.zip(other_names.clone())
|
||||
.map(|(i, other_i)| quote::quote!(#i: #other_i));
|
||||
let eq = names.zip(other_names)
|
||||
.map(|(i, other_i)| quote::quote_spanned!(i.span() => #i == #other_i));
|
||||
let eq = names.zip(other_names).map(
|
||||
|(i, other_i)| quote::quote_spanned!(i.span() => #i == #other_i),
|
||||
);
|
||||
quote::quote!(
|
||||
(
|
||||
Self::#ident { #( #capture, )* },
|
||||
@@ -73,12 +79,18 @@ pub fn derive_partial_eq_no_bound(input: proc_macro::TokenStream) -> proc_macro:
|
||||
)
|
||||
},
|
||||
syn::Fields::Unnamed(unnamed) => {
|
||||
let names = unnamed.unnamed.iter().enumerate()
|
||||
let names = unnamed
|
||||
.unnamed
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, f)| syn::Ident::new(&format!("_{}", i), f.span()));
|
||||
let other_names = unnamed.unnamed.iter().enumerate()
|
||||
.map(|(i, f)| syn::Ident::new(&format!("_{}_other", i), f.span()));
|
||||
let eq = names.clone().zip(other_names.clone())
|
||||
.map(|(i, other_i)| quote::quote_spanned!(i.span() => #i == #other_i));
|
||||
let other_names =
|
||||
unnamed.unnamed.iter().enumerate().map(|(i, f)| {
|
||||
syn::Ident::new(&format!("_{}_other", i), f.span())
|
||||
});
|
||||
let eq = names.clone().zip(other_names.clone()).map(
|
||||
|(i, other_i)| quote::quote_spanned!(i.span() => #i == #other_i),
|
||||
);
|
||||
quote::quote!(
|
||||
(
|
||||
Self::#ident ( #( #names, )* ),
|
||||
@@ -122,5 +134,6 @@ pub fn derive_partial_eq_no_bound(input: proc_macro::TokenStream) -> proc_macro:
|
||||
}
|
||||
}
|
||||
};
|
||||
).into()
|
||||
)
|
||||
.into()
|
||||
}
|
||||
|
||||
@@ -17,11 +17,11 @@
|
||||
|
||||
//! Builder logic definition used to build genesis storage.
|
||||
|
||||
use super::super::{DeclStorageDefExt, StorageLineTypeDef};
|
||||
use frame_support_procedural_tools::syn_ext as ext;
|
||||
use proc_macro2::TokenStream;
|
||||
use syn::spanned::Spanned;
|
||||
use quote::{quote, quote_spanned};
|
||||
use super::super::{DeclStorageDefExt, StorageLineTypeDef};
|
||||
use syn::spanned::Spanned;
|
||||
|
||||
/// Definition of builder blocks, each block insert some value in the storage.
|
||||
/// They must be called inside externalities, and with `self` being the genesis config.
|
||||
@@ -79,7 +79,7 @@ impl BuilderDef {
|
||||
if let Some(data) = data {
|
||||
blocks.push(match &line.storage_type {
|
||||
StorageLineTypeDef::Simple(_) if line.is_option => {
|
||||
quote!{{
|
||||
quote! {{
|
||||
#data
|
||||
let v: Option<&#value_type>= data;
|
||||
if let Some(v) = v {
|
||||
@@ -88,7 +88,7 @@ impl BuilderDef {
|
||||
}}
|
||||
},
|
||||
StorageLineTypeDef::Simple(_) if !line.is_option => {
|
||||
quote!{{
|
||||
quote! {{
|
||||
#data
|
||||
let v: &#value_type = data;
|
||||
<#storage_struct as #scrate::#storage_trait>::put::<&#value_type>(v);
|
||||
@@ -97,7 +97,7 @@ impl BuilderDef {
|
||||
StorageLineTypeDef::Simple(_) => unreachable!(),
|
||||
StorageLineTypeDef::Map(map) => {
|
||||
let key = &map.key;
|
||||
quote!{{
|
||||
quote! {{
|
||||
#data
|
||||
let data: &#scrate::sp_std::vec::Vec<(#key, #value_type)> = data;
|
||||
data.iter().for_each(|(k, v)| {
|
||||
@@ -110,7 +110,7 @@ impl BuilderDef {
|
||||
StorageLineTypeDef::DoubleMap(map) => {
|
||||
let key1 = &map.key1;
|
||||
let key2 = &map.key2;
|
||||
quote!{{
|
||||
quote! {{
|
||||
#data
|
||||
let data: &#scrate::sp_std::vec::Vec<(#key1, #key2, #value_type)> = data;
|
||||
data.iter().for_each(|(k1, k2, v)| {
|
||||
@@ -122,12 +122,8 @@ impl BuilderDef {
|
||||
},
|
||||
StorageLineTypeDef::NMap(map) => {
|
||||
let key_tuple = map.to_key_tuple();
|
||||
let key_arg = if map.keys.len() == 1 {
|
||||
quote!((k,))
|
||||
} else {
|
||||
quote!(k)
|
||||
};
|
||||
quote!{{
|
||||
let key_arg = if map.keys.len() == 1 { quote!((k,)) } else { quote!(k) };
|
||||
quote! {{
|
||||
#data
|
||||
let data: &#scrate::sp_std::vec::Vec<(#key_tuple, #value_type)> = data;
|
||||
data.iter().for_each(|(k, v)| {
|
||||
@@ -148,10 +144,6 @@ impl BuilderDef {
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Self {
|
||||
blocks,
|
||||
is_generic,
|
||||
}
|
||||
Self { blocks, is_generic }
|
||||
}
|
||||
}
|
||||
|
||||
+50
-46
@@ -17,11 +17,11 @@
|
||||
|
||||
//! Genesis config definition.
|
||||
|
||||
use super::super::{DeclStorageDefExt, StorageLineTypeDef};
|
||||
use frame_support_procedural_tools::syn_ext as ext;
|
||||
use proc_macro2::TokenStream;
|
||||
use syn::{spanned::Spanned, parse_quote};
|
||||
use quote::quote;
|
||||
use super::super::{DeclStorageDefExt, StorageLineTypeDef};
|
||||
use syn::{parse_quote, spanned::Spanned};
|
||||
|
||||
pub struct GenesisConfigFieldDef {
|
||||
pub name: syn::Ident,
|
||||
@@ -47,30 +47,28 @@ impl GenesisConfigDef {
|
||||
pub fn from_def(def: &DeclStorageDefExt) -> syn::Result<Self> {
|
||||
let fields = Self::get_genesis_config_field_defs(def)?;
|
||||
|
||||
let is_generic = fields.iter()
|
||||
let is_generic = fields
|
||||
.iter()
|
||||
.any(|field| ext::type_contains_ident(&field.typ, &def.module_runtime_generic));
|
||||
|
||||
let (
|
||||
genesis_struct_decl,
|
||||
genesis_impl,
|
||||
genesis_struct,
|
||||
genesis_where_clause
|
||||
) = if is_generic {
|
||||
let runtime_generic = &def.module_runtime_generic;
|
||||
let runtime_trait = &def.module_runtime_trait;
|
||||
let optional_instance = &def.optional_instance;
|
||||
let optional_instance_bound = &def.optional_instance_bound;
|
||||
let optional_instance_bound_optional_default = &def.optional_instance_bound_optional_default;
|
||||
let where_clause = &def.where_clause;
|
||||
(
|
||||
quote!(<#runtime_generic: #runtime_trait, #optional_instance_bound_optional_default>),
|
||||
quote!(<#runtime_generic: #runtime_trait, #optional_instance_bound>),
|
||||
quote!(<#runtime_generic, #optional_instance>),
|
||||
where_clause.clone(),
|
||||
)
|
||||
} else {
|
||||
(quote!(), quote!(), quote!(), None)
|
||||
};
|
||||
let (genesis_struct_decl, genesis_impl, genesis_struct, genesis_where_clause) =
|
||||
if is_generic {
|
||||
let runtime_generic = &def.module_runtime_generic;
|
||||
let runtime_trait = &def.module_runtime_trait;
|
||||
let optional_instance = &def.optional_instance;
|
||||
let optional_instance_bound = &def.optional_instance_bound;
|
||||
let optional_instance_bound_optional_default =
|
||||
&def.optional_instance_bound_optional_default;
|
||||
let where_clause = &def.where_clause;
|
||||
(
|
||||
quote!(<#runtime_generic: #runtime_trait, #optional_instance_bound_optional_default>),
|
||||
quote!(<#runtime_generic: #runtime_trait, #optional_instance_bound>),
|
||||
quote!(<#runtime_generic, #optional_instance>),
|
||||
where_clause.clone(),
|
||||
)
|
||||
} else {
|
||||
(quote!(), quote!(), quote!(), None)
|
||||
};
|
||||
|
||||
Ok(Self {
|
||||
is_generic,
|
||||
@@ -82,14 +80,14 @@ impl GenesisConfigDef {
|
||||
})
|
||||
}
|
||||
|
||||
fn get_genesis_config_field_defs(def: &DeclStorageDefExt)
|
||||
-> syn::Result<Vec<GenesisConfigFieldDef>>
|
||||
{
|
||||
fn get_genesis_config_field_defs(
|
||||
def: &DeclStorageDefExt,
|
||||
) -> syn::Result<Vec<GenesisConfigFieldDef>> {
|
||||
let mut config_field_defs = Vec::new();
|
||||
|
||||
for (config_field, line) in def.storage_lines.iter()
|
||||
.filter_map(|line| line.config.as_ref().map(|config_field| (config_field.clone(), line)))
|
||||
{
|
||||
for (config_field, line) in def.storage_lines.iter().filter_map(|line| {
|
||||
line.config.as_ref().map(|config_field| (config_field.clone(), line))
|
||||
}) {
|
||||
let value_type = &line.value_type;
|
||||
|
||||
let typ = match &line.storage_type {
|
||||
@@ -107,18 +105,20 @@ impl GenesisConfigDef {
|
||||
StorageLineTypeDef::NMap(map) => {
|
||||
let key_tuple = map.to_key_tuple();
|
||||
parse_quote!( Vec<(#key_tuple, #value_type)> )
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
let default = line.default_value.as_ref()
|
||||
.map(|d| {
|
||||
if line.is_option {
|
||||
quote!( #d.unwrap_or_default() )
|
||||
} else {
|
||||
quote!( #d )
|
||||
}
|
||||
})
|
||||
.unwrap_or_else(|| quote!( Default::default() ));
|
||||
let default =
|
||||
line.default_value
|
||||
.as_ref()
|
||||
.map(|d| {
|
||||
if line.is_option {
|
||||
quote!( #d.unwrap_or_default() )
|
||||
} else {
|
||||
quote!( #d )
|
||||
}
|
||||
})
|
||||
.unwrap_or_else(|| quote!(Default::default()));
|
||||
|
||||
config_field_defs.push(GenesisConfigFieldDef {
|
||||
name: config_field,
|
||||
@@ -129,22 +129,26 @@ impl GenesisConfigDef {
|
||||
}
|
||||
|
||||
for line in &def.extra_genesis_config_lines {
|
||||
let attrs = line.attrs.iter()
|
||||
let attrs = line
|
||||
.attrs
|
||||
.iter()
|
||||
.map(|attr| {
|
||||
let meta = attr.parse_meta()?;
|
||||
if meta.path().is_ident("cfg") {
|
||||
return Err(syn::Error::new(
|
||||
meta.span(),
|
||||
"extra genesis config items do not support `cfg` attribute"
|
||||
));
|
||||
"extra genesis config items do not support `cfg` attribute",
|
||||
))
|
||||
}
|
||||
Ok(meta)
|
||||
})
|
||||
.collect::<syn::Result<_>>()?;
|
||||
|
||||
let default = line.default.as_ref().map(|e| quote!( #e ))
|
||||
.unwrap_or_else(|| quote!( Default::default() ));
|
||||
|
||||
let default = line
|
||||
.default
|
||||
.as_ref()
|
||||
.map(|e| quote!( #e ))
|
||||
.unwrap_or_else(|| quote!(Default::default()));
|
||||
|
||||
config_field_defs.push(GenesisConfigFieldDef {
|
||||
name: line.name.clone(),
|
||||
|
||||
@@ -18,14 +18,14 @@
|
||||
//! Declaration of genesis config structure and implementation of build storage trait and
|
||||
//! functions.
|
||||
|
||||
use proc_macro2::{TokenStream, Span};
|
||||
use quote::quote;
|
||||
use super::DeclStorageDefExt;
|
||||
pub use genesis_config_def::GenesisConfigDef;
|
||||
pub use builder_def::BuilderDef;
|
||||
pub use genesis_config_def::GenesisConfigDef;
|
||||
use proc_macro2::{Span, TokenStream};
|
||||
use quote::quote;
|
||||
|
||||
mod genesis_config_def;
|
||||
mod builder_def;
|
||||
mod genesis_config_def;
|
||||
|
||||
const DEFAULT_INSTANCE_NAME: &str = "__GeneratedInstance";
|
||||
|
||||
@@ -118,19 +118,16 @@ fn impl_build_storage(
|
||||
let genesis_impl = &genesis_config.genesis_impl;
|
||||
let genesis_where_clause = &genesis_config.genesis_where_clause;
|
||||
|
||||
let (
|
||||
fn_generic,
|
||||
fn_traitinstance,
|
||||
fn_where_clause
|
||||
) = if !genesis_config.is_generic && builders.is_generic {
|
||||
(
|
||||
quote!( <#runtime_generic: #runtime_trait, #optional_instance_bound> ),
|
||||
quote!( #runtime_generic, #optional_instance ),
|
||||
Some(&def.where_clause),
|
||||
)
|
||||
} else {
|
||||
(quote!(), quote!(), None)
|
||||
};
|
||||
let (fn_generic, fn_traitinstance, fn_where_clause) =
|
||||
if !genesis_config.is_generic && builders.is_generic {
|
||||
(
|
||||
quote!( <#runtime_generic: #runtime_trait, #optional_instance_bound> ),
|
||||
quote!( #runtime_generic, #optional_instance ),
|
||||
Some(&def.where_clause),
|
||||
)
|
||||
} else {
|
||||
(quote!(), quote!(), None)
|
||||
};
|
||||
|
||||
let builder_blocks = &builders.blocks;
|
||||
|
||||
@@ -138,7 +135,7 @@ fn impl_build_storage(
|
||||
#scrate::sp_runtime::BuildModuleGenesisStorage<#runtime_generic, #inherent_instance>
|
||||
);
|
||||
|
||||
quote!{
|
||||
quote! {
|
||||
#[cfg(feature = "std")]
|
||||
impl#genesis_impl GenesisConfig#genesis_struct #genesis_where_clause {
|
||||
/// Build the storage for this module.
|
||||
@@ -189,7 +186,7 @@ pub fn genesis_config_and_build_storage(def: &DeclStorageDefExt) -> TokenStream
|
||||
decl_genesis_config_and_impl_default(scrate, &genesis_config);
|
||||
let impl_build_storage = impl_build_storage(scrate, def, &genesis_config, &builders);
|
||||
|
||||
quote!{
|
||||
quote! {
|
||||
#decl_genesis_config_and_impl_default
|
||||
#impl_build_storage
|
||||
}
|
||||
|
||||
@@ -17,15 +17,17 @@
|
||||
|
||||
//! Implementation of getters on module structure.
|
||||
|
||||
use super::{DeclStorageDefExt, StorageLineTypeDef};
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::quote;
|
||||
use super::{DeclStorageDefExt, StorageLineTypeDef};
|
||||
|
||||
pub fn impl_getters(def: &DeclStorageDefExt) -> TokenStream {
|
||||
let scrate = &def.hidden_crate;
|
||||
let mut getters = TokenStream::new();
|
||||
|
||||
for (get_fn, line) in def.storage_lines.iter()
|
||||
for (get_fn, line) in def
|
||||
.storage_lines
|
||||
.iter()
|
||||
.filter_map(|line| line.getter.as_ref().map(|get_fn| (get_fn, line)))
|
||||
{
|
||||
let attrs = &line.doc_attrs;
|
||||
@@ -35,7 +37,7 @@ pub fn impl_getters(def: &DeclStorageDefExt) -> TokenStream {
|
||||
|
||||
let getter = match &line.storage_type {
|
||||
StorageLineTypeDef::Simple(value) => {
|
||||
quote!{
|
||||
quote! {
|
||||
#( #[ #attrs ] )*
|
||||
pub fn #get_fn() -> #value {
|
||||
<#storage_struct as #scrate::#storage_trait>::get()
|
||||
@@ -45,7 +47,7 @@ pub fn impl_getters(def: &DeclStorageDefExt) -> TokenStream {
|
||||
StorageLineTypeDef::Map(map) => {
|
||||
let key = &map.key;
|
||||
let value = &map.value;
|
||||
quote!{
|
||||
quote! {
|
||||
#( #[ #attrs ] )*
|
||||
pub fn #get_fn<K: #scrate::codec::EncodeLike<#key>>(key: K) -> #value {
|
||||
<#storage_struct as #scrate::#storage_trait>::get(key)
|
||||
@@ -56,7 +58,7 @@ pub fn impl_getters(def: &DeclStorageDefExt) -> TokenStream {
|
||||
let key1 = &map.key1;
|
||||
let key2 = &map.key2;
|
||||
let value = &map.value;
|
||||
quote!{
|
||||
quote! {
|
||||
pub fn #get_fn<KArg1, KArg2>(k1: KArg1, k2: KArg2) -> #value
|
||||
where
|
||||
KArg1: #scrate::codec::EncodeLike<#key1>,
|
||||
@@ -69,7 +71,7 @@ pub fn impl_getters(def: &DeclStorageDefExt) -> TokenStream {
|
||||
StorageLineTypeDef::NMap(map) => {
|
||||
let keygen = map.to_keygen_struct(&def.hidden_crate);
|
||||
let value = &map.value;
|
||||
quote!{
|
||||
quote! {
|
||||
pub fn #get_fn<KArg>(key: KArg) -> #value
|
||||
where
|
||||
KArg: #scrate::storage::types::EncodeLikeTuple<
|
||||
@@ -80,7 +82,7 @@ pub fn impl_getters(def: &DeclStorageDefExt) -> TokenStream {
|
||||
<#storage_struct as #scrate::#storage_trait>::get(key)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
getters.extend(getter);
|
||||
}
|
||||
|
||||
@@ -18,10 +18,10 @@
|
||||
//! Implementation of the trait instance and the instance structures implementing it.
|
||||
//! (For not instantiable traits there is still the inherent instance implemented).
|
||||
|
||||
use proc_macro2::{TokenStream, Span};
|
||||
use quote::quote;
|
||||
use super::DeclStorageDefExt;
|
||||
use crate::NUMBER_OF_INSTANCE;
|
||||
use proc_macro2::{Span, TokenStream};
|
||||
use quote::quote;
|
||||
|
||||
pub(crate) const INHERENT_INSTANCE_NAME: &str = "__InherentHiddenInstance";
|
||||
|
||||
@@ -52,14 +52,12 @@ pub fn decl_and_impl(def: &DeclStorageDefExt) -> TokenStream {
|
||||
index: i,
|
||||
}
|
||||
})
|
||||
.chain(
|
||||
module_instance.instance_default.as_ref().map(|ident| InstanceDef {
|
||||
prefix: String::new(),
|
||||
instance_struct: ident.clone(),
|
||||
doc: quote!(#[doc=r"Default module instance"]),
|
||||
index: 0,
|
||||
})
|
||||
);
|
||||
.chain(module_instance.instance_default.as_ref().map(|ident| InstanceDef {
|
||||
prefix: String::new(),
|
||||
instance_struct: ident.clone(),
|
||||
doc: quote!(#[doc=r"Default module instance"]),
|
||||
index: 0,
|
||||
}));
|
||||
|
||||
for instance_def in instance_defs {
|
||||
impls.extend(create_and_impl_instance_struct(scrate, &instance_def, def));
|
||||
@@ -70,8 +68,8 @@ pub fn decl_and_impl(def: &DeclStorageDefExt) -> TokenStream {
|
||||
let inherent_instance = syn::Ident::new(INHERENT_INSTANCE_NAME, Span::call_site());
|
||||
|
||||
// Implementation of inherent instance.
|
||||
if let Some(default_instance) = def.module_instance.as_ref()
|
||||
.and_then(|i| i.instance_default.as_ref())
|
||||
if let Some(default_instance) =
|
||||
def.module_instance.as_ref().and_then(|i| i.instance_default.as_ref())
|
||||
{
|
||||
impls.extend(quote! {
|
||||
/// Hidden instance generated to be internally used when module is used without
|
||||
@@ -97,10 +95,7 @@ pub fn decl_and_impl(def: &DeclStorageDefExt) -> TokenStream {
|
||||
impls
|
||||
}
|
||||
|
||||
fn reexport_instance_trait(
|
||||
scrate: &TokenStream,
|
||||
def: &DeclStorageDefExt,
|
||||
) -> TokenStream {
|
||||
fn reexport_instance_trait(scrate: &TokenStream, def: &DeclStorageDefExt) -> TokenStream {
|
||||
if let Some(i) = def.module_instance.as_ref() {
|
||||
let instance_trait = &i.instance_trait;
|
||||
quote!(
|
||||
|
||||
@@ -17,17 +17,17 @@
|
||||
|
||||
//! Implementation of `storage_metadata` on module structure, used by construct_runtime.
|
||||
|
||||
use super::{DeclStorageDefExt, StorageLineDefExt, StorageLineTypeDef};
|
||||
use frame_support_procedural_tools::clean_type_string;
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::quote;
|
||||
use super::{DeclStorageDefExt, StorageLineDefExt, StorageLineTypeDef};
|
||||
|
||||
fn storage_line_metadata_type(scrate: &TokenStream, line: &StorageLineDefExt) -> TokenStream {
|
||||
let value_type = &line.value_type;
|
||||
let value_type = clean_type_string("e!( #value_type ).to_string());
|
||||
match &line.storage_type {
|
||||
StorageLineTypeDef::Simple(_) => {
|
||||
quote!{
|
||||
quote! {
|
||||
#scrate::metadata::StorageEntryType::Plain(
|
||||
#scrate::metadata::DecodeDifferent::Encode(#value_type),
|
||||
)
|
||||
@@ -37,7 +37,7 @@ fn storage_line_metadata_type(scrate: &TokenStream, line: &StorageLineDefExt) ->
|
||||
let hasher = map.hasher.into_metadata();
|
||||
let key = &map.key;
|
||||
let key = clean_type_string("e!(#key).to_string());
|
||||
quote!{
|
||||
quote! {
|
||||
#scrate::metadata::StorageEntryType::Map {
|
||||
hasher: #scrate::metadata::#hasher,
|
||||
key: #scrate::metadata::DecodeDifferent::Encode(#key),
|
||||
@@ -53,7 +53,7 @@ fn storage_line_metadata_type(scrate: &TokenStream, line: &StorageLineDefExt) ->
|
||||
let key1 = clean_type_string("e!(#key1).to_string());
|
||||
let key2 = &map.key2;
|
||||
let key2 = clean_type_string("e!(#key2).to_string());
|
||||
quote!{
|
||||
quote! {
|
||||
#scrate::metadata::StorageEntryType::DoubleMap {
|
||||
hasher: #scrate::metadata::#hasher1,
|
||||
key1: #scrate::metadata::DecodeDifferent::Encode(#key1),
|
||||
@@ -64,15 +64,17 @@ fn storage_line_metadata_type(scrate: &TokenStream, line: &StorageLineDefExt) ->
|
||||
}
|
||||
},
|
||||
StorageLineTypeDef::NMap(map) => {
|
||||
let keys = map.keys
|
||||
let keys = map
|
||||
.keys
|
||||
.iter()
|
||||
.map(|key| clean_type_string("e!(#key).to_string()))
|
||||
.collect::<Vec<_>>();
|
||||
let hashers = map.hashers
|
||||
let hashers = map
|
||||
.hashers
|
||||
.iter()
|
||||
.map(|hasher| hasher.to_storage_hasher_struct())
|
||||
.collect::<Vec<_>>();
|
||||
quote!{
|
||||
quote! {
|
||||
#scrate::metadata::StorageEntryType::NMap {
|
||||
keys: #scrate::metadata::DecodeDifferent::Encode(&[
|
||||
#( #keys, )*
|
||||
@@ -83,7 +85,7 @@ fn storage_line_metadata_type(scrate: &TokenStream, line: &StorageLineDefExt) ->
|
||||
value: #scrate::metadata::DecodeDifferent::Encode(#value_type),
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,12 +94,17 @@ fn default_byte_getter(
|
||||
line: &StorageLineDefExt,
|
||||
def: &DeclStorageDefExt,
|
||||
) -> (TokenStream, TokenStream) {
|
||||
let default = line.default_value.as_ref().map(|d| quote!( #d ))
|
||||
.unwrap_or_else(|| quote!( Default::default() ));
|
||||
let default = line
|
||||
.default_value
|
||||
.as_ref()
|
||||
.map(|d| quote!( #d ))
|
||||
.unwrap_or_else(|| quote!(Default::default()));
|
||||
|
||||
let str_name = line.name.to_string();
|
||||
let struct_name = syn::Ident::new(&("__GetByteStruct".to_string() + &str_name), line.name.span());
|
||||
let cache_name = syn::Ident::new(&("__CACHE_GET_BYTE_STRUCT_".to_string() + &str_name), line.name.span());
|
||||
let struct_name =
|
||||
syn::Ident::new(&("__GetByteStruct".to_string() + &str_name), line.name.span());
|
||||
let cache_name =
|
||||
syn::Ident::new(&("__CACHE_GET_BYTE_STRUCT_".to_string() + &str_name), line.name.span());
|
||||
|
||||
let runtime_generic = &def.module_runtime_generic;
|
||||
let runtime_trait = &def.module_runtime_trait;
|
||||
@@ -177,10 +184,8 @@ pub fn impl_metadata(def: &DeclStorageDefExt) -> TokenStream {
|
||||
|
||||
let ty = storage_line_metadata_type(scrate, line);
|
||||
|
||||
let (
|
||||
default_byte_getter_struct_def,
|
||||
default_byte_getter_struct_instance,
|
||||
) = default_byte_getter(scrate, line, def);
|
||||
let (default_byte_getter_struct_def, default_byte_getter_struct_instance) =
|
||||
default_byte_getter(scrate, line, def);
|
||||
|
||||
let mut docs = TokenStream::new();
|
||||
for attr in line.attrs.iter().filter_map(|v| v.parse_meta().ok()) {
|
||||
|
||||
@@ -17,22 +17,22 @@
|
||||
|
||||
//! `decl_storage` input definition and expansion.
|
||||
|
||||
mod storage_struct;
|
||||
mod storage_info;
|
||||
mod parse;
|
||||
mod store_trait;
|
||||
mod getters;
|
||||
mod metadata;
|
||||
mod instance_trait;
|
||||
mod genesis_config;
|
||||
mod getters;
|
||||
mod instance_trait;
|
||||
mod metadata;
|
||||
mod parse;
|
||||
mod print_pallet_upgrade;
|
||||
mod storage_info;
|
||||
mod storage_struct;
|
||||
mod store_trait;
|
||||
|
||||
pub(crate) use instance_trait::INHERENT_INSTANCE_NAME;
|
||||
|
||||
use quote::quote;
|
||||
use frame_support_procedural_tools::{
|
||||
generate_crate_access, generate_hidden_includes, syn_ext as ext
|
||||
generate_crate_access, generate_hidden_includes, syn_ext as ext,
|
||||
};
|
||||
use quote::quote;
|
||||
|
||||
/// All information contained in input of decl_storage
|
||||
pub struct DeclStorageDef {
|
||||
@@ -115,34 +115,37 @@ pub struct DeclStorageDefExt {
|
||||
|
||||
impl From<DeclStorageDef> for DeclStorageDefExt {
|
||||
fn from(mut def: DeclStorageDef) -> Self {
|
||||
let hidden_crate_name = def.hidden_crate.as_ref().map(|i| i.to_string())
|
||||
let hidden_crate_name = def
|
||||
.hidden_crate
|
||||
.as_ref()
|
||||
.map(|i| i.to_string())
|
||||
.unwrap_or_else(|| "decl_storage".to_string());
|
||||
|
||||
let hidden_crate = generate_crate_access(&hidden_crate_name, "frame-support");
|
||||
let hidden_imports = generate_hidden_includes(&hidden_crate_name, "frame-support");
|
||||
|
||||
let storage_lines = def.storage_lines.drain(..).collect::<Vec<_>>();
|
||||
let storage_lines = storage_lines.into_iter()
|
||||
let storage_lines = storage_lines
|
||||
.into_iter()
|
||||
.map(|line| StorageLineDefExt::from_def(line, &def, &hidden_crate))
|
||||
.collect();
|
||||
|
||||
let (
|
||||
optional_instance,
|
||||
optional_instance_bound,
|
||||
optional_instance_bound_optional_default,
|
||||
) = if let Some(instance) = def.module_instance.as_ref() {
|
||||
let instance_generic = &instance.instance_generic;
|
||||
let instance_trait= &instance.instance_trait;
|
||||
let optional_equal_instance_default = instance.instance_default.as_ref()
|
||||
.map(|d| quote!( = #d ));
|
||||
(
|
||||
Some(quote!(#instance_generic)),
|
||||
Some(quote!(#instance_generic: #instance_trait)),
|
||||
Some(quote!(#instance_generic: #instance_trait #optional_equal_instance_default)),
|
||||
)
|
||||
} else {
|
||||
(None, None, None)
|
||||
};
|
||||
let (optional_instance, optional_instance_bound, optional_instance_bound_optional_default) =
|
||||
if let Some(instance) = def.module_instance.as_ref() {
|
||||
let instance_generic = &instance.instance_generic;
|
||||
let instance_trait = &instance.instance_trait;
|
||||
let optional_equal_instance_default =
|
||||
instance.instance_default.as_ref().map(|d| quote!( = #d ));
|
||||
(
|
||||
Some(quote!(#instance_generic)),
|
||||
Some(quote!(#instance_generic: #instance_trait)),
|
||||
Some(
|
||||
quote!(#instance_generic: #instance_trait #optional_equal_instance_default),
|
||||
),
|
||||
)
|
||||
} else {
|
||||
(None, None, None)
|
||||
};
|
||||
|
||||
let module_runtime_generic = &def.module_runtime_generic;
|
||||
let module_runtime_trait = &def.module_runtime_trait;
|
||||
@@ -255,22 +258,20 @@ impl StorageLineDefExt {
|
||||
hidden_crate: &proc_macro2::TokenStream,
|
||||
) -> Self {
|
||||
let is_generic = match &storage_def.storage_type {
|
||||
StorageLineTypeDef::Simple(value) => {
|
||||
ext::type_contains_ident(&value, &def.module_runtime_generic)
|
||||
},
|
||||
StorageLineTypeDef::Map(map) => {
|
||||
ext::type_contains_ident(&map.key, &def.module_runtime_generic)
|
||||
|| ext::type_contains_ident(&map.value, &def.module_runtime_generic)
|
||||
}
|
||||
StorageLineTypeDef::DoubleMap(map) => {
|
||||
ext::type_contains_ident(&map.key1, &def.module_runtime_generic)
|
||||
|| ext::type_contains_ident(&map.key2, &def.module_runtime_generic)
|
||||
|| ext::type_contains_ident(&map.value, &def.module_runtime_generic)
|
||||
}
|
||||
StorageLineTypeDef::NMap(map) => {
|
||||
map.keys.iter().any(|key| ext::type_contains_ident(key, &def.module_runtime_generic))
|
||||
|| ext::type_contains_ident(&map.value, &def.module_runtime_generic)
|
||||
}
|
||||
StorageLineTypeDef::Simple(value) =>
|
||||
ext::type_contains_ident(&value, &def.module_runtime_generic),
|
||||
StorageLineTypeDef::Map(map) =>
|
||||
ext::type_contains_ident(&map.key, &def.module_runtime_generic) ||
|
||||
ext::type_contains_ident(&map.value, &def.module_runtime_generic),
|
||||
StorageLineTypeDef::DoubleMap(map) =>
|
||||
ext::type_contains_ident(&map.key1, &def.module_runtime_generic) ||
|
||||
ext::type_contains_ident(&map.key2, &def.module_runtime_generic) ||
|
||||
ext::type_contains_ident(&map.value, &def.module_runtime_generic),
|
||||
StorageLineTypeDef::NMap(map) =>
|
||||
map.keys
|
||||
.iter()
|
||||
.any(|key| ext::type_contains_ident(key, &def.module_runtime_generic)) ||
|
||||
ext::type_contains_ident(&map.value, &def.module_runtime_generic),
|
||||
};
|
||||
|
||||
let query_type = match &storage_def.storage_type {
|
||||
@@ -280,15 +281,13 @@ impl StorageLineDefExt {
|
||||
StorageLineTypeDef::NMap(map) => map.value.clone(),
|
||||
};
|
||||
let is_option = ext::extract_type_option(&query_type).is_some();
|
||||
let value_type = ext::extract_type_option(&query_type).unwrap_or_else(|| query_type.clone());
|
||||
let value_type =
|
||||
ext::extract_type_option(&query_type).unwrap_or_else(|| query_type.clone());
|
||||
|
||||
let module_runtime_generic = &def.module_runtime_generic;
|
||||
let module_runtime_trait = &def.module_runtime_trait;
|
||||
let optional_storage_runtime_comma = if is_generic {
|
||||
Some(quote!( #module_runtime_generic, ))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let optional_storage_runtime_comma =
|
||||
if is_generic { Some(quote!( #module_runtime_generic, )) } else { None };
|
||||
let optional_storage_runtime_bound_comma = if is_generic {
|
||||
Some(quote!( #module_runtime_generic: #module_runtime_trait, ))
|
||||
} else {
|
||||
@@ -304,11 +303,8 @@ impl StorageLineDefExt {
|
||||
#storage_name<#optional_storage_runtime_comma #optional_instance_generic>
|
||||
);
|
||||
|
||||
let optional_storage_where_clause = if is_generic {
|
||||
def.where_clause.as_ref().map(|w| quote!( #w ))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let optional_storage_where_clause =
|
||||
if is_generic { def.where_clause.as_ref().map(|w| quote!( #w )) } else { None };
|
||||
|
||||
let storage_trait_truncated = match &storage_def.storage_type {
|
||||
StorageLineTypeDef::Simple(_) => {
|
||||
@@ -326,13 +322,15 @@ impl StorageLineDefExt {
|
||||
StorageLineTypeDef::NMap(map) => {
|
||||
let keygen = map.to_keygen_struct(hidden_crate);
|
||||
quote!( StorageNMap<#keygen, #value_type> )
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
let storage_trait = quote!( storage::#storage_trait_truncated );
|
||||
let storage_generator_trait = quote!( storage::generator::#storage_trait_truncated );
|
||||
|
||||
let doc_attrs = storage_def.attrs.iter()
|
||||
let doc_attrs = storage_def
|
||||
.attrs
|
||||
.iter()
|
||||
.filter_map(|a| a.parse_meta().ok())
|
||||
.filter(|m| m.path().is_ident("doc"))
|
||||
.collect();
|
||||
@@ -396,27 +394,28 @@ impl NMapDef {
|
||||
if self.keys.len() == 1 {
|
||||
let hasher = &self.hashers[0].to_storage_hasher_struct();
|
||||
let key = &self.keys[0];
|
||||
return quote!( #scrate::storage::types::Key<#scrate::#hasher, #key> );
|
||||
return quote!( #scrate::storage::types::Key<#scrate::#hasher, #key> )
|
||||
}
|
||||
|
||||
let key_hasher = self.keys.iter().zip(&self.hashers).map(|(key, hasher)| {
|
||||
let hasher = hasher.to_storage_hasher_struct();
|
||||
quote!( #scrate::storage::types::Key<#scrate::#hasher, #key> )
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
let key_hasher = self
|
||||
.keys
|
||||
.iter()
|
||||
.zip(&self.hashers)
|
||||
.map(|(key, hasher)| {
|
||||
let hasher = hasher.to_storage_hasher_struct();
|
||||
quote!( #scrate::storage::types::Key<#scrate::#hasher, #key> )
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
quote!(( #(#key_hasher,)* ))
|
||||
}
|
||||
|
||||
fn to_key_tuple(&self) -> proc_macro2::TokenStream {
|
||||
if self.keys.len() == 1 {
|
||||
let key = &self.keys[0];
|
||||
return quote!(#key);
|
||||
return quote!(#key)
|
||||
}
|
||||
|
||||
let tuple = self.keys.iter().map(|key| {
|
||||
quote!(#key)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
let tuple = self.keys.iter().map(|key| quote!(#key)).collect::<Vec<_>>();
|
||||
quote!(( #(#tuple,)* ))
|
||||
}
|
||||
}
|
||||
@@ -442,25 +441,25 @@ pub enum HasherKind {
|
||||
impl HasherKind {
|
||||
fn to_storage_hasher_struct(&self) -> proc_macro2::TokenStream {
|
||||
match self {
|
||||
HasherKind::Blake2_256 => quote!( Blake2_256 ),
|
||||
HasherKind::Blake2_128 => quote!( Blake2_128 ),
|
||||
HasherKind::Blake2_128Concat => quote!( Blake2_128Concat ),
|
||||
HasherKind::Twox256 => quote!( Twox256 ),
|
||||
HasherKind::Twox128 => quote!( Twox128 ),
|
||||
HasherKind::Twox64Concat => quote!( Twox64Concat ),
|
||||
HasherKind::Identity => quote!( Identity ),
|
||||
HasherKind::Blake2_256 => quote!(Blake2_256),
|
||||
HasherKind::Blake2_128 => quote!(Blake2_128),
|
||||
HasherKind::Blake2_128Concat => quote!(Blake2_128Concat),
|
||||
HasherKind::Twox256 => quote!(Twox256),
|
||||
HasherKind::Twox128 => quote!(Twox128),
|
||||
HasherKind::Twox64Concat => quote!(Twox64Concat),
|
||||
HasherKind::Identity => quote!(Identity),
|
||||
}
|
||||
}
|
||||
|
||||
fn into_metadata(&self) -> proc_macro2::TokenStream {
|
||||
match self {
|
||||
HasherKind::Blake2_256 => quote!( StorageHasher::Blake2_256 ),
|
||||
HasherKind::Blake2_128 => quote!( StorageHasher::Blake2_128 ),
|
||||
HasherKind::Blake2_128Concat => quote!( StorageHasher::Blake2_128Concat ),
|
||||
HasherKind::Twox256 => quote!( StorageHasher::Twox256 ),
|
||||
HasherKind::Twox128 => quote!( StorageHasher::Twox128 ),
|
||||
HasherKind::Twox64Concat => quote!( StorageHasher::Twox64Concat ),
|
||||
HasherKind::Identity => quote!( StorageHasher::Identity ),
|
||||
HasherKind::Blake2_256 => quote!(StorageHasher::Blake2_256),
|
||||
HasherKind::Blake2_128 => quote!(StorageHasher::Blake2_128),
|
||||
HasherKind::Blake2_128Concat => quote!(StorageHasher::Blake2_128Concat),
|
||||
HasherKind::Twox256 => quote!(StorageHasher::Twox256),
|
||||
HasherKind::Twox128 => quote!(StorageHasher::Twox128),
|
||||
HasherKind::Twox64Concat => quote!(StorageHasher::Twox64Concat),
|
||||
HasherKind::Identity => quote!(StorageHasher::Identity),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -502,5 +501,6 @@ pub fn decl_storage_impl(input: proc_macro::TokenStream) -> proc_macro::TokenStr
|
||||
#genesis_config
|
||||
#storage_struct
|
||||
#storage_info
|
||||
).into()
|
||||
)
|
||||
.into()
|
||||
}
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
|
||||
//! Parsing of decl_storage input.
|
||||
|
||||
use frame_support_procedural_tools::{ToTokens, Parse, syn_ext as ext};
|
||||
use syn::{Ident, Token, spanned::Spanned};
|
||||
use frame_support_procedural_tools::{syn_ext as ext, Parse, ToTokens};
|
||||
use syn::{spanned::Spanned, Ident, Token};
|
||||
|
||||
mod keyword {
|
||||
syn::custom_keyword!(generate_storage_info);
|
||||
@@ -367,48 +367,35 @@ fn get_module_instance(
|
||||
it is now defined at frame_support::traits::Instance. Expect `Instance` found `{}`",
|
||||
instantiable.as_ref().unwrap(),
|
||||
);
|
||||
return Err(syn::Error::new(instantiable.span(), msg));
|
||||
return Err(syn::Error::new(instantiable.span(), msg))
|
||||
}
|
||||
|
||||
match (instance, instantiable, default_instance) {
|
||||
(Some(instance), Some(instantiable), default_instance) => {
|
||||
(Some(instance), Some(instantiable), default_instance) =>
|
||||
Ok(Some(super::ModuleInstanceDef {
|
||||
instance_generic: instance,
|
||||
instance_trait: instantiable,
|
||||
instance_default: default_instance,
|
||||
}))
|
||||
},
|
||||
})),
|
||||
(None, None, None) => Ok(None),
|
||||
(Some(instance), None, _) => Err(
|
||||
syn::Error::new(
|
||||
instance.span(),
|
||||
format!(
|
||||
"Expect instantiable trait bound for instance: {}. {}",
|
||||
instance,
|
||||
right_syntax,
|
||||
)
|
||||
)
|
||||
),
|
||||
(None, Some(instantiable), _) => Err(
|
||||
syn::Error::new(
|
||||
instantiable.span(),
|
||||
format!(
|
||||
"Expect instance generic for bound instantiable: {}. {}",
|
||||
instantiable,
|
||||
right_syntax,
|
||||
)
|
||||
)
|
||||
),
|
||||
(None, _, Some(default_instance)) => Err(
|
||||
syn::Error::new(
|
||||
default_instance.span(),
|
||||
format!(
|
||||
"Expect instance generic for default instance: {}. {}",
|
||||
default_instance,
|
||||
right_syntax,
|
||||
)
|
||||
)
|
||||
),
|
||||
(Some(instance), None, _) => Err(syn::Error::new(
|
||||
instance.span(),
|
||||
format!("Expect instantiable trait bound for instance: {}. {}", instance, right_syntax,),
|
||||
)),
|
||||
(None, Some(instantiable), _) => Err(syn::Error::new(
|
||||
instantiable.span(),
|
||||
format!(
|
||||
"Expect instance generic for bound instantiable: {}. {}",
|
||||
instantiable, right_syntax,
|
||||
),
|
||||
)),
|
||||
(None, _, Some(default_instance)) => Err(syn::Error::new(
|
||||
default_instance.span(),
|
||||
format!(
|
||||
"Expect instance generic for default instance: {}. {}",
|
||||
default_instance, right_syntax,
|
||||
),
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -417,37 +404,37 @@ pub fn parse(input: syn::parse::ParseStream) -> syn::Result<super::DeclStorageDe
|
||||
|
||||
let def = StorageDefinition::parse(input)?;
|
||||
|
||||
let module_instance = get_module_instance(
|
||||
def.mod_instance,
|
||||
def.mod_instantiable,
|
||||
def.mod_default_instance,
|
||||
)?;
|
||||
let module_instance =
|
||||
get_module_instance(def.mod_instance, def.mod_instantiable, def.mod_default_instance)?;
|
||||
|
||||
let mut extra_genesis_config_lines = vec![];
|
||||
let mut extra_genesis_build = None;
|
||||
|
||||
for line in def.extra_genesis.inner.into_iter()
|
||||
for line in def
|
||||
.extra_genesis
|
||||
.inner
|
||||
.into_iter()
|
||||
.flat_map(|o| o.content.content.lines.inner.into_iter())
|
||||
{
|
||||
match line {
|
||||
AddExtraGenesisLineEnum::AddExtraGenesisLine(def) => {
|
||||
extra_genesis_config_lines.push(super::ExtraGenesisLineDef{
|
||||
extra_genesis_config_lines.push(super::ExtraGenesisLineDef {
|
||||
attrs: def.attrs.inner,
|
||||
name: def.extra_field.content,
|
||||
typ: def.extra_type,
|
||||
default: def.default_value.inner.map(|o| o.expr),
|
||||
});
|
||||
}
|
||||
},
|
||||
AddExtraGenesisLineEnum::AddExtraGenesisBuild(def) => {
|
||||
if extra_genesis_build.is_some() {
|
||||
return Err(syn::Error::new(
|
||||
def.span(),
|
||||
"Only one build expression allowed for extra genesis"
|
||||
"Only one build expression allowed for extra genesis",
|
||||
))
|
||||
}
|
||||
|
||||
extra_genesis_build = Some(def.expr.content);
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -496,68 +483,65 @@ fn parse_storage_line_defs(
|
||||
};
|
||||
|
||||
if let Some(ref config) = config {
|
||||
storage_lines.iter().filter_map(|sl| sl.config.as_ref()).try_for_each(|other_config| {
|
||||
if other_config == config {
|
||||
Err(syn::Error::new(
|
||||
config.span(),
|
||||
"`config()`/`get()` with the same name already defined.",
|
||||
))
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
})?;
|
||||
storage_lines.iter().filter_map(|sl| sl.config.as_ref()).try_for_each(
|
||||
|other_config| {
|
||||
if other_config == config {
|
||||
Err(syn::Error::new(
|
||||
config.span(),
|
||||
"`config()`/`get()` with the same name already defined.",
|
||||
))
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
},
|
||||
)?;
|
||||
}
|
||||
|
||||
let max_values = match &line.storage_type {
|
||||
DeclStorageType::Map(_) | DeclStorageType::DoubleMap(_) | DeclStorageType::NMap(_) => {
|
||||
line.max_values.inner.map(|i| i.expr.content)
|
||||
},
|
||||
DeclStorageType::Simple(_) => {
|
||||
DeclStorageType::Map(_) | DeclStorageType::DoubleMap(_) | DeclStorageType::NMap(_) =>
|
||||
line.max_values.inner.map(|i| i.expr.content),
|
||||
DeclStorageType::Simple(_) =>
|
||||
if let Some(max_values) = line.max_values.inner {
|
||||
let msg = "unexpected max_values attribute for storage value.";
|
||||
let span = max_values.max_values_keyword.span();
|
||||
return Err(syn::Error::new(span, msg));
|
||||
return Err(syn::Error::new(span, msg))
|
||||
} else {
|
||||
Some(syn::parse_quote!(1u32))
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
let span = line.storage_type.span();
|
||||
let no_hasher_error = || syn::Error::new(
|
||||
span,
|
||||
"Default hasher has been removed, use explicit hasher(blake2_128_concat) instead."
|
||||
);
|
||||
let no_hasher_error = || {
|
||||
syn::Error::new(
|
||||
span,
|
||||
"Default hasher has been removed, use explicit hasher(blake2_128_concat) instead.",
|
||||
)
|
||||
};
|
||||
|
||||
let storage_type = match line.storage_type {
|
||||
DeclStorageType::Map(map) => super::StorageLineTypeDef::Map(
|
||||
super::MapDef {
|
||||
hasher: map.hasher.inner.ok_or_else(no_hasher_error)?.into(),
|
||||
key: map.key,
|
||||
value: map.value,
|
||||
}
|
||||
),
|
||||
DeclStorageType::DoubleMap(map) => super::StorageLineTypeDef::DoubleMap(
|
||||
Box::new(super::DoubleMapDef {
|
||||
DeclStorageType::Map(map) => super::StorageLineTypeDef::Map(super::MapDef {
|
||||
hasher: map.hasher.inner.ok_or_else(no_hasher_error)?.into(),
|
||||
key: map.key,
|
||||
value: map.value,
|
||||
}),
|
||||
DeclStorageType::DoubleMap(map) =>
|
||||
super::StorageLineTypeDef::DoubleMap(Box::new(super::DoubleMapDef {
|
||||
hasher1: map.hasher1.inner.ok_or_else(no_hasher_error)?.into(),
|
||||
hasher2: map.hasher2.inner.ok_or_else(no_hasher_error)?.into(),
|
||||
key1: map.key1,
|
||||
key2: map.key2,
|
||||
value: map.value,
|
||||
})
|
||||
),
|
||||
DeclStorageType::NMap(map) => super::StorageLineTypeDef::NMap(
|
||||
super::NMapDef {
|
||||
hashers: map
|
||||
.storage_keys
|
||||
.inner
|
||||
.iter()
|
||||
.map(|pair| Ok(pair.hasher.inner.clone().ok_or_else(no_hasher_error)?.into()))
|
||||
.collect::<Result<Vec<_>, syn::Error>>()?,
|
||||
keys: map.storage_keys.inner.iter().map(|pair| pair.key.clone()).collect(),
|
||||
value: map.value,
|
||||
}
|
||||
),
|
||||
})),
|
||||
DeclStorageType::NMap(map) => super::StorageLineTypeDef::NMap(super::NMapDef {
|
||||
hashers: map
|
||||
.storage_keys
|
||||
.inner
|
||||
.iter()
|
||||
.map(|pair| Ok(pair.hasher.inner.clone().ok_or_else(no_hasher_error)?.into()))
|
||||
.collect::<Result<Vec<_>, syn::Error>>()?,
|
||||
keys: map.storage_keys.inner.iter().map(|pair| pair.key.clone()).collect(),
|
||||
value: map.value,
|
||||
}),
|
||||
DeclStorageType::Simple(expr) => super::StorageLineTypeDef::Simple(expr),
|
||||
};
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use super::StorageLineTypeDef;
|
||||
use quote::ToTokens;
|
||||
use frame_support_procedural_tools::clean_type_string;
|
||||
use quote::ToTokens;
|
||||
|
||||
/// Environment variable that tells us to print pallet upgrade helper.
|
||||
const PRINT_PALLET_UPGRADE: &str = "PRINT_PALLET_UPGRADE";
|
||||
@@ -10,7 +10,7 @@ fn check_print_pallet_upgrade() -> bool {
|
||||
}
|
||||
|
||||
/// Convert visibilty as now objects are defined in a module.
|
||||
fn convert_vis(vis: &syn::Visibility) -> &'static str{
|
||||
fn convert_vis(vis: &syn::Visibility) -> &'static str {
|
||||
match vis {
|
||||
syn::Visibility::Inherited => "pub(super)",
|
||||
syn::Visibility::Public(_) => "pub",
|
||||
@@ -31,23 +31,13 @@ pub fn maybe_print_pallet_upgrade(def: &super::DeclStorageDefExt) {
|
||||
|
||||
let scrate = "e::quote!(frame_support);
|
||||
|
||||
let config_gen = if def.optional_instance.is_some() {
|
||||
"<I: 'static = ()>"
|
||||
} else {
|
||||
Default::default()
|
||||
};
|
||||
let config_gen =
|
||||
if def.optional_instance.is_some() { "<I: 'static = ()>" } else { Default::default() };
|
||||
|
||||
let impl_gen = if def.optional_instance.is_some() {
|
||||
"<T: Config<I>, I: 'static>"
|
||||
} else {
|
||||
"<T: Config>"
|
||||
};
|
||||
let impl_gen =
|
||||
if def.optional_instance.is_some() { "<T: Config<I>, I: 'static>" } else { "<T: Config>" };
|
||||
|
||||
let decl_gen = if def.optional_instance.is_some() {
|
||||
"<T, I=()>"
|
||||
} else {
|
||||
"<T>"
|
||||
};
|
||||
let decl_gen = if def.optional_instance.is_some() { "<T, I=()>" } else { "<T>" };
|
||||
|
||||
let full_decl_gen = if def.optional_instance.is_some() {
|
||||
"<T: Config<I>, I: 'static = ()>"
|
||||
@@ -55,17 +45,9 @@ pub fn maybe_print_pallet_upgrade(def: &super::DeclStorageDefExt) {
|
||||
"<T: Config>"
|
||||
};
|
||||
|
||||
let use_gen = if def.optional_instance.is_some() {
|
||||
"<T, I>"
|
||||
} else {
|
||||
"<T>"
|
||||
};
|
||||
let use_gen = if def.optional_instance.is_some() { "<T, I>" } else { "<T>" };
|
||||
|
||||
let use_gen_tuple = if def.optional_instance.is_some() {
|
||||
"<(T, I)>"
|
||||
} else {
|
||||
"<T>"
|
||||
};
|
||||
let use_gen_tuple = if def.optional_instance.is_some() { "<(T, I)>" } else { "<T>" };
|
||||
|
||||
let mut genesis_config = String::new();
|
||||
let mut genesis_build = String::new();
|
||||
@@ -80,17 +62,11 @@ pub fn maybe_print_pallet_upgrade(def: &super::DeclStorageDefExt) {
|
||||
},
|
||||
};
|
||||
|
||||
let genesis_config_impl_gen = if genesis_config_def.is_generic {
|
||||
impl_gen
|
||||
} else {
|
||||
Default::default()
|
||||
};
|
||||
let genesis_config_impl_gen =
|
||||
if genesis_config_def.is_generic { impl_gen } else { Default::default() };
|
||||
|
||||
let genesis_config_use_gen = if genesis_config_def.is_generic {
|
||||
use_gen
|
||||
} else {
|
||||
Default::default()
|
||||
};
|
||||
let genesis_config_use_gen =
|
||||
if genesis_config_def.is_generic { use_gen } else { Default::default() };
|
||||
|
||||
let genesis_config_decl_gen = if genesis_config_def.is_generic {
|
||||
if def.optional_instance.is_some() {
|
||||
@@ -105,26 +81,31 @@ pub fn maybe_print_pallet_upgrade(def: &super::DeclStorageDefExt) {
|
||||
let mut genesis_config_decl_fields = String::new();
|
||||
let mut genesis_config_default_fields = String::new();
|
||||
for field in &genesis_config_def.fields {
|
||||
genesis_config_decl_fields.push_str(&format!("
|
||||
genesis_config_decl_fields.push_str(&format!(
|
||||
"
|
||||
{attrs}pub {name}: {typ},",
|
||||
attrs = field.attrs.iter()
|
||||
.fold(String::new(), |res, attr| {
|
||||
format!("{}#[{}]
|
||||
attrs = field.attrs.iter().fold(String::new(), |res, attr| {
|
||||
format!(
|
||||
"{}#[{}]
|
||||
",
|
||||
res, attr.to_token_stream())
|
||||
}),
|
||||
res,
|
||||
attr.to_token_stream()
|
||||
)
|
||||
}),
|
||||
name = field.name,
|
||||
typ = to_cleaned_string(&field.typ),
|
||||
));
|
||||
|
||||
genesis_config_default_fields.push_str(&format!("
|
||||
genesis_config_default_fields.push_str(&format!(
|
||||
"
|
||||
{name}: {default},",
|
||||
name = field.name,
|
||||
default = to_cleaned_string(&field.default),
|
||||
));
|
||||
}
|
||||
|
||||
genesis_config = format!("
|
||||
genesis_config = format!(
|
||||
"
|
||||
#[pallet::genesis_config]
|
||||
pub struct GenesisConfig{genesis_config_decl_gen}
|
||||
// TODO_MAYBE_WHERE_CLAUSE
|
||||
@@ -147,16 +128,18 @@ pub fn maybe_print_pallet_upgrade(def: &super::DeclStorageDefExt) {
|
||||
genesis_config_use_gen = genesis_config_use_gen,
|
||||
);
|
||||
|
||||
let genesis_config_build = genesis_config_builder_def.blocks.iter()
|
||||
.fold(String::new(), |res, block| {
|
||||
format!("{}
|
||||
let genesis_config_build =
|
||||
genesis_config_builder_def.blocks.iter().fold(String::new(), |res, block| {
|
||||
format!(
|
||||
"{}
|
||||
{}",
|
||||
res,
|
||||
to_cleaned_string(block),
|
||||
)
|
||||
});
|
||||
|
||||
genesis_build = format!("
|
||||
genesis_build = format!(
|
||||
"
|
||||
#[pallet::genesis_build]
|
||||
impl{impl_gen} GenesisBuild{use_gen} for GenesisConfig{genesis_config_use_gen}
|
||||
// TODO_MAYBE_WHERE_CLAUSE
|
||||
@@ -176,7 +159,8 @@ pub fn maybe_print_pallet_upgrade(def: &super::DeclStorageDefExt) {
|
||||
let storage_vis = convert_vis(&line.visibility);
|
||||
|
||||
let getter = if let Some(getter) = &line.getter {
|
||||
format!("
|
||||
format!(
|
||||
"
|
||||
#[pallet::getter(fn {getter})]",
|
||||
getter = getter
|
||||
)
|
||||
@@ -186,9 +170,12 @@ pub fn maybe_print_pallet_upgrade(def: &super::DeclStorageDefExt) {
|
||||
|
||||
let value_type = &line.value_type;
|
||||
|
||||
let default_value_type_value = line.default_value.as_ref()
|
||||
let default_value_type_value = line
|
||||
.default_value
|
||||
.as_ref()
|
||||
.map(|default_expr| {
|
||||
format!("
|
||||
format!(
|
||||
"
|
||||
#[pallet::type_value]
|
||||
{storage_vis} fn DefaultFor{name} /* TODO_MAYBE_GENERICS */ () -> {value_type} {{
|
||||
{default_expr}
|
||||
@@ -212,13 +199,16 @@ pub fn maybe_print_pallet_upgrade(def: &super::DeclStorageDefExt) {
|
||||
", ValueQuery"
|
||||
};
|
||||
|
||||
let comma_default_value_getter_name = line.default_value.as_ref()
|
||||
let comma_default_value_getter_name = line
|
||||
.default_value
|
||||
.as_ref()
|
||||
.map(|_| format!(", DefaultFor{}", line.name))
|
||||
.unwrap_or_else(String::new);
|
||||
|
||||
let typ = match &line.storage_type {
|
||||
StorageLineTypeDef::Map(map) => {
|
||||
format!("StorageMap<_, {hasher}, {key}, {value_type}{comma_query_kind}\
|
||||
format!(
|
||||
"StorageMap<_, {hasher}, {key}, {value_type}{comma_query_kind}\
|
||||
{comma_default_value_getter_name}>",
|
||||
hasher = &map.hasher.to_storage_hasher_struct(),
|
||||
key = to_cleaned_string(&map.key),
|
||||
@@ -228,7 +218,8 @@ pub fn maybe_print_pallet_upgrade(def: &super::DeclStorageDefExt) {
|
||||
)
|
||||
},
|
||||
StorageLineTypeDef::DoubleMap(double_map) => {
|
||||
format!("StorageDoubleMap<_, {hasher1}, {key1}, {hasher2}, {key2}, {value_type}\
|
||||
format!(
|
||||
"StorageDoubleMap<_, {hasher1}, {key1}, {hasher2}, {key2}, {value_type}\
|
||||
{comma_query_kind}{comma_default_value_getter_name}>",
|
||||
hasher1 = double_map.hasher1.to_storage_hasher_struct(),
|
||||
key1 = to_cleaned_string(&double_map.key1),
|
||||
@@ -240,16 +231,18 @@ pub fn maybe_print_pallet_upgrade(def: &super::DeclStorageDefExt) {
|
||||
)
|
||||
},
|
||||
StorageLineTypeDef::NMap(map) => {
|
||||
format!("StorageNMap<_, {keygen}, {value_type}{comma_query_kind}\
|
||||
format!(
|
||||
"StorageNMap<_, {keygen}, {value_type}{comma_query_kind}\
|
||||
{comma_default_value_getter_name}>",
|
||||
keygen = map.to_keygen_struct(&def.hidden_crate),
|
||||
value_type = to_cleaned_string(&value_type),
|
||||
comma_query_kind = comma_query_kind,
|
||||
comma_default_value_getter_name = comma_default_value_getter_name,
|
||||
)
|
||||
}
|
||||
},
|
||||
StorageLineTypeDef::Simple(_) => {
|
||||
format!("StorageValue<_, {value_type}{comma_query_kind}\
|
||||
format!(
|
||||
"StorageValue<_, {value_type}{comma_query_kind}\
|
||||
{comma_default_value_getter_name}>",
|
||||
value_type = to_cleaned_string(&value_type),
|
||||
comma_query_kind = comma_query_kind,
|
||||
@@ -265,7 +258,8 @@ pub fn maybe_print_pallet_upgrade(def: &super::DeclStorageDefExt) {
|
||||
""
|
||||
};
|
||||
|
||||
storages.push_str(&format!("
|
||||
storages.push_str(&format!(
|
||||
"
|
||||
{default_value_type_value}{doc}
|
||||
#[pallet::storage]{getter}
|
||||
{storage_vis} type {name}{full_decl_gen} = {typ};{additional_comment}",
|
||||
@@ -276,21 +270,21 @@ pub fn maybe_print_pallet_upgrade(def: &super::DeclStorageDefExt) {
|
||||
full_decl_gen = full_decl_gen,
|
||||
typ = typ,
|
||||
additional_comment = additional_comment,
|
||||
doc = line.doc_attrs.iter()
|
||||
.fold(String::new(), |mut res, attr| {
|
||||
if let syn::Meta::NameValue(name_value) = attr {
|
||||
if name_value.path.is_ident("doc") {
|
||||
if let syn::Lit::Str(string) = &name_value.lit {
|
||||
res = format!("{}
|
||||
doc = line.doc_attrs.iter().fold(String::new(), |mut res, attr| {
|
||||
if let syn::Meta::NameValue(name_value) = attr {
|
||||
if name_value.path.is_ident("doc") {
|
||||
if let syn::Lit::Str(string) = &name_value.lit {
|
||||
res = format!(
|
||||
"{}
|
||||
///{}",
|
||||
res,
|
||||
string.value(),
|
||||
);
|
||||
}
|
||||
res,
|
||||
string.value(),
|
||||
);
|
||||
}
|
||||
}
|
||||
res
|
||||
}),
|
||||
}
|
||||
res
|
||||
}),
|
||||
));
|
||||
}
|
||||
|
||||
@@ -308,7 +302,8 @@ pub fn maybe_print_pallet_upgrade(def: &super::DeclStorageDefExt) {
|
||||
""
|
||||
};
|
||||
|
||||
println!("
|
||||
println!(
|
||||
"
|
||||
// Template for pallet upgrade for {pallet_name}
|
||||
|
||||
pub use pallet::*;
|
||||
|
||||
@@ -17,9 +17,9 @@
|
||||
|
||||
//! Implementation of trait `StorageInfoTrait` on module structure.
|
||||
|
||||
use super::DeclStorageDefExt;
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::quote;
|
||||
use super::DeclStorageDefExt;
|
||||
|
||||
pub fn impl_storage_info(def: &DeclStorageDefExt) -> TokenStream {
|
||||
let scrate = &def.hidden_crate;
|
||||
|
||||
@@ -17,16 +17,15 @@
|
||||
|
||||
//! Implementation of storage structures and implementation of storage traits on them.
|
||||
|
||||
use proc_macro2::{TokenStream, Ident, Span};
|
||||
use super::{instance_trait::INHERENT_INSTANCE_NAME, DeclStorageDefExt, StorageLineTypeDef};
|
||||
use proc_macro2::{Ident, Span, TokenStream};
|
||||
use quote::quote;
|
||||
use super::{
|
||||
DeclStorageDefExt, StorageLineTypeDef,
|
||||
instance_trait::INHERENT_INSTANCE_NAME,
|
||||
};
|
||||
|
||||
fn from_optional_value_to_query(is_option: bool, default: &Option<syn::Expr>) -> TokenStream {
|
||||
let default = default.as_ref().map(|d| quote!( #d ))
|
||||
.unwrap_or_else(|| quote!( Default::default() ));
|
||||
let default = default
|
||||
.as_ref()
|
||||
.map(|d| quote!( #d ))
|
||||
.unwrap_or_else(|| quote!(Default::default()));
|
||||
|
||||
if !is_option {
|
||||
// raw type case
|
||||
@@ -40,10 +39,10 @@ fn from_optional_value_to_query(is_option: bool, default: &Option<syn::Expr>) ->
|
||||
fn from_query_to_optional_value(is_option: bool) -> TokenStream {
|
||||
if !is_option {
|
||||
// raw type case
|
||||
quote!( Some(v) )
|
||||
quote!(Some(v))
|
||||
} else {
|
||||
// Option<> type case
|
||||
quote!( v )
|
||||
quote!(v)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,7 +51,6 @@ pub fn decl_and_impl(def: &DeclStorageDefExt) -> TokenStream {
|
||||
let mut impls = TokenStream::new();
|
||||
|
||||
for line in &def.storage_lines {
|
||||
|
||||
// Propagate doc attributes.
|
||||
let attrs = &line.doc_attrs;
|
||||
|
||||
@@ -60,7 +58,8 @@ pub fn decl_and_impl(def: &DeclStorageDefExt) -> TokenStream {
|
||||
let optional_storage_runtime_comma = &line.optional_storage_runtime_comma;
|
||||
let optional_storage_runtime_bound_comma = &line.optional_storage_runtime_bound_comma;
|
||||
let optional_storage_where_clause = &line.optional_storage_where_clause;
|
||||
let optional_instance_bound_optional_default = &def.optional_instance_bound_optional_default;
|
||||
let optional_instance_bound_optional_default =
|
||||
&def.optional_instance_bound_optional_default;
|
||||
let optional_instance_bound = &def.optional_instance_bound;
|
||||
let optional_instance = &def.optional_instance;
|
||||
let name = &line.name;
|
||||
@@ -87,10 +86,8 @@ pub fn decl_and_impl(def: &DeclStorageDefExt) -> TokenStream {
|
||||
Ident::new(INHERENT_INSTANCE_NAME, Span::call_site())
|
||||
};
|
||||
|
||||
let storage_name_bstr = syn::LitByteStr::new(
|
||||
line.name.to_string().as_ref(),
|
||||
line.name.span()
|
||||
);
|
||||
let storage_name_bstr =
|
||||
syn::LitByteStr::new(line.name.to_string().as_ref(), line.name.span());
|
||||
|
||||
let storage_generator_trait = &line.storage_generator_trait;
|
||||
let storage_struct = &line.storage_struct;
|
||||
@@ -242,7 +239,7 @@ pub fn decl_and_impl(def: &DeclStorageDefExt) -> TokenStream {
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
let max_values = if let Some(max_values) = &line.max_values {
|
||||
|
||||
@@ -17,26 +17,26 @@
|
||||
|
||||
//! Declaration of store trait and implementation on module structure.
|
||||
|
||||
use super::DeclStorageDefExt;
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::quote;
|
||||
use super::DeclStorageDefExt;
|
||||
|
||||
pub fn decl_and_impl(def: &DeclStorageDefExt) -> TokenStream {
|
||||
let decl_store_items = def.storage_lines.iter()
|
||||
.map(|sline| &sline.name)
|
||||
.fold(TokenStream::new(), |mut items, name| {
|
||||
let decl_store_items = def.storage_lines.iter().map(|sline| &sline.name).fold(
|
||||
TokenStream::new(),
|
||||
|mut items, name| {
|
||||
items.extend(quote!(type #name;));
|
||||
items
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
let impl_store_items = def.storage_lines.iter()
|
||||
.fold(TokenStream::new(), |mut items, line| {
|
||||
let name = &line.name;
|
||||
let storage_struct = &line.storage_struct;
|
||||
let impl_store_items = def.storage_lines.iter().fold(TokenStream::new(), |mut items, line| {
|
||||
let name = &line.name;
|
||||
let storage_struct = &line.storage_struct;
|
||||
|
||||
items.extend(quote!(type #name = #storage_struct;));
|
||||
items
|
||||
});
|
||||
items.extend(quote!(type #name = #storage_struct;));
|
||||
items
|
||||
});
|
||||
|
||||
let visibility = &def.visibility;
|
||||
let store_trait = &def.store_trait;
|
||||
|
||||
@@ -15,10 +15,10 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use frame_support_procedural_tools::generate_crate_access_2018;
|
||||
use proc_macro::TokenStream;
|
||||
use quote::quote;
|
||||
use syn::{ItemFn, Result};
|
||||
use frame_support_procedural_tools::generate_crate_access_2018;
|
||||
|
||||
pub fn transactional(_attr: TokenStream, input: TokenStream) -> Result<TokenStream> {
|
||||
let ItemFn { attrs, vis, sig, block } = syn::parse(input)?;
|
||||
|
||||
@@ -23,14 +23,14 @@
|
||||
|
||||
use proc_macro::TokenStream;
|
||||
use proc_macro2::Span;
|
||||
use syn::parse_macro_input;
|
||||
use quote::quote;
|
||||
use syn::parse_macro_input;
|
||||
|
||||
pub(crate) fn fields_idents(
|
||||
fields: impl Iterator<Item = syn::Field>,
|
||||
) -> impl Iterator<Item = proc_macro2::TokenStream> {
|
||||
fields.enumerate().map(|(ix, field)| {
|
||||
field.ident.map(|i| quote!{#i}).unwrap_or_else(|| {
|
||||
field.ident.map(|i| quote! {#i}).unwrap_or_else(|| {
|
||||
let f_ix: syn::Ident = syn::Ident::new(&format!("f_{}", ix), Span::call_site());
|
||||
quote!( #f_ix )
|
||||
})
|
||||
@@ -42,10 +42,7 @@ pub(crate) fn fields_access(
|
||||
) -> impl Iterator<Item = proc_macro2::TokenStream> {
|
||||
fields.enumerate().map(|(ix, field)| {
|
||||
field.ident.map(|i| quote!( #i )).unwrap_or_else(|| {
|
||||
let f_ix: syn::Index = syn::Index {
|
||||
index: ix as u32,
|
||||
span: Span::call_site(),
|
||||
};
|
||||
let f_ix: syn::Index = syn::Index { index: ix as u32, span: Span::call_site() };
|
||||
quote!( #f_ix )
|
||||
})
|
||||
})
|
||||
@@ -64,15 +61,10 @@ pub fn derive_parse(input: TokenStream) -> TokenStream {
|
||||
}
|
||||
|
||||
fn derive_parse_struct(input: syn::ItemStruct) -> TokenStream {
|
||||
let syn::ItemStruct {
|
||||
ident,
|
||||
generics,
|
||||
fields,
|
||||
..
|
||||
} = input;
|
||||
let syn::ItemStruct { ident, generics, fields, .. } = input;
|
||||
let field_names = {
|
||||
let name = fields_idents(fields.iter().map(Clone::clone));
|
||||
quote!{
|
||||
quote! {
|
||||
#(
|
||||
#name,
|
||||
)*
|
||||
@@ -110,12 +102,7 @@ pub fn derive_totokens(input: TokenStream) -> TokenStream {
|
||||
}
|
||||
|
||||
fn derive_totokens_struct(input: syn::ItemStruct) -> TokenStream {
|
||||
let syn::ItemStruct {
|
||||
ident,
|
||||
generics,
|
||||
fields,
|
||||
..
|
||||
} = input;
|
||||
let syn::ItemStruct { ident, generics, fields, .. } = input;
|
||||
|
||||
let fields = fields_access(fields.iter().map(Clone::clone));
|
||||
let tokens = quote! {
|
||||
@@ -133,12 +120,7 @@ fn derive_totokens_struct(input: syn::ItemStruct) -> TokenStream {
|
||||
}
|
||||
|
||||
fn derive_totokens_enum(input: syn::ItemEnum) -> TokenStream {
|
||||
let syn::ItemEnum {
|
||||
ident,
|
||||
generics,
|
||||
variants,
|
||||
..
|
||||
} = input;
|
||||
let syn::ItemEnum { ident, generics, variants, .. } = input;
|
||||
let variants = variants.iter().map(|v| {
|
||||
let v_ident = v.ident.clone();
|
||||
let fields_build = if v.fields.iter().count() > 0 {
|
||||
|
||||
@@ -23,13 +23,13 @@
|
||||
pub use frame_support_procedural_tools_derive::*;
|
||||
|
||||
use proc_macro_crate::{crate_name, FoundCrate};
|
||||
use syn::parse::Error;
|
||||
use quote::quote;
|
||||
use syn::parse::Error;
|
||||
|
||||
pub mod syn_ext;
|
||||
|
||||
// FIXME #1569, remove the following functions, which are copied from sp-api-macros
|
||||
use proc_macro2::{TokenStream, Span};
|
||||
use proc_macro2::{Span, TokenStream};
|
||||
use syn::Ident;
|
||||
|
||||
fn generate_hidden_includes_mod_name(unique_id: &str) -> Ident {
|
||||
@@ -39,7 +39,7 @@ fn generate_hidden_includes_mod_name(unique_id: &str) -> Ident {
|
||||
/// Generates the access to the `frame-support` crate.
|
||||
pub fn generate_crate_access(unique_id: &str, def_crate: &str) -> TokenStream {
|
||||
if std::env::var("CARGO_PKG_NAME").unwrap() == def_crate {
|
||||
quote::quote!( frame_support )
|
||||
quote::quote!(frame_support)
|
||||
} else {
|
||||
let mod_name = generate_hidden_includes_mod_name(unique_id);
|
||||
quote::quote!( self::#mod_name::hidden_include )
|
||||
@@ -55,12 +55,8 @@ pub fn generate_crate_access_2018(def_crate: &str) -> Result<syn::Ident, Error>
|
||||
let name = def_crate.to_string().replace("-", "_");
|
||||
Ok(syn::Ident::new(&name, Span::call_site()))
|
||||
},
|
||||
Ok(FoundCrate::Name(name)) => {
|
||||
Ok(Ident::new(&name, Span::call_site()))
|
||||
},
|
||||
Err(e) => {
|
||||
Err(Error::new(Span::call_site(), e))
|
||||
}
|
||||
Ok(FoundCrate::Name(name)) => Ok(Ident::new(&name, Span::call_site())),
|
||||
Err(e) => Err(Error::new(Span::call_site(), e)),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,7 +78,7 @@ pub fn generate_hidden_includes(unique_id: &str, def_crate: &str) -> TokenStream
|
||||
Err(e) => {
|
||||
let err = Error::new(Span::call_site(), e).to_compile_error();
|
||||
quote!( #err )
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,11 +19,15 @@
|
||||
//! Extension to syn types, mainly for parsing
|
||||
// end::description[]
|
||||
|
||||
use syn::{visit::{Visit, self}, parse::{Parse, ParseStream, Result}, Ident};
|
||||
use frame_support_procedural_tools_derive::{Parse, ToTokens};
|
||||
use proc_macro2::{TokenStream, TokenTree};
|
||||
use quote::ToTokens;
|
||||
use std::iter::once;
|
||||
use frame_support_procedural_tools_derive::{ToTokens, Parse};
|
||||
use syn::{
|
||||
parse::{Parse, ParseStream, Result},
|
||||
visit::{self, Visit},
|
||||
Ident,
|
||||
};
|
||||
|
||||
/// stop parsing here getting remaining token as content
|
||||
/// Warn duplicate stream (part of)
|
||||
@@ -35,7 +39,6 @@ pub struct StopParse {
|
||||
// inner macro really dependant on syn naming convention, do not export
|
||||
macro_rules! groups_impl {
|
||||
($name:ident, $tok:ident, $deli:ident, $parse:ident) => {
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct $name<P> {
|
||||
pub token: syn::token::$tok,
|
||||
@@ -46,7 +49,7 @@ macro_rules! groups_impl {
|
||||
fn parse(input: ParseStream) -> Result<Self> {
|
||||
let syn::group::$name { token, content } = syn::group::$parse(input)?;
|
||||
let content = content.parse()?;
|
||||
Ok($name { token, content, })
|
||||
Ok($name { token, content })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,12 +63,12 @@ macro_rules! groups_impl {
|
||||
}
|
||||
}
|
||||
|
||||
impl <P: Clone> Clone for $name<P> {
|
||||
impl<P: Clone> Clone for $name<P> {
|
||||
fn clone(&self) -> Self {
|
||||
Self { token: self.token.clone(), content: self.content.clone() }
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
groups_impl!(Braces, Brace, Brace, parse_braces);
|
||||
@@ -73,23 +76,22 @@ groups_impl!(Brackets, Bracket, Bracket, parse_brackets);
|
||||
groups_impl!(Parens, Paren, Parenthesis, parse_parens);
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct PunctuatedInner<P,T,V> {
|
||||
pub inner: syn::punctuated::Punctuated<P,T>,
|
||||
pub struct PunctuatedInner<P, T, V> {
|
||||
pub inner: syn::punctuated::Punctuated<P, T>,
|
||||
pub variant: V,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct NoTrailing;
|
||||
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Trailing;
|
||||
|
||||
pub type Punctuated<P,T> = PunctuatedInner<P,T,NoTrailing>;
|
||||
pub type Punctuated<P, T> = PunctuatedInner<P, T, NoTrailing>;
|
||||
|
||||
pub type PunctuatedTrailing<P,T> = PunctuatedInner<P,T,Trailing>;
|
||||
pub type PunctuatedTrailing<P, T> = PunctuatedInner<P, T, Trailing>;
|
||||
|
||||
impl<P: Parse, T: Parse + syn::token::Token> Parse for PunctuatedInner<P,T,Trailing> {
|
||||
impl<P: Parse, T: Parse + syn::token::Token> Parse for PunctuatedInner<P, T, Trailing> {
|
||||
fn parse(input: ParseStream) -> Result<Self> {
|
||||
Ok(PunctuatedInner {
|
||||
inner: syn::punctuated::Punctuated::parse_separated_nonempty(input)?,
|
||||
@@ -98,7 +100,7 @@ impl<P: Parse, T: Parse + syn::token::Token> Parse for PunctuatedInner<P,T,Trail
|
||||
}
|
||||
}
|
||||
|
||||
impl<P: Parse, T: Parse> Parse for PunctuatedInner<P,T,NoTrailing> {
|
||||
impl<P: Parse, T: Parse> Parse for PunctuatedInner<P, T, NoTrailing> {
|
||||
fn parse(input: ParseStream) -> Result<Self> {
|
||||
Ok(PunctuatedInner {
|
||||
inner: syn::punctuated::Punctuated::parse_terminated(input)?,
|
||||
@@ -107,13 +109,13 @@ impl<P: Parse, T: Parse> Parse for PunctuatedInner<P,T,NoTrailing> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<P: ToTokens, T: ToTokens, V> ToTokens for PunctuatedInner<P,T,V> {
|
||||
impl<P: ToTokens, T: ToTokens, V> ToTokens for PunctuatedInner<P, T, V> {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
self.inner.to_tokens(tokens)
|
||||
}
|
||||
}
|
||||
|
||||
impl <P: Clone, T: Clone, V: Clone> Clone for PunctuatedInner<P, T, V> {
|
||||
impl<P: Clone, T: Clone, V: Clone> Clone for PunctuatedInner<P, T, V> {
|
||||
fn clone(&self) -> Self {
|
||||
Self { inner: self.inner.clone(), variant: self.variant.clone() }
|
||||
}
|
||||
@@ -127,9 +129,7 @@ pub struct Meta {
|
||||
|
||||
impl Parse for Meta {
|
||||
fn parse(input: ParseStream) -> Result<Self> {
|
||||
Ok(Meta {
|
||||
inner: syn::Meta::parse(input)?,
|
||||
})
|
||||
Ok(Meta { inner: syn::Meta::parse(input)? })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,9 +151,7 @@ pub struct OuterAttributes {
|
||||
impl Parse for OuterAttributes {
|
||||
fn parse(input: ParseStream) -> Result<Self> {
|
||||
let inner = syn::Attribute::parse_outer(input)?;
|
||||
Ok(OuterAttributes {
|
||||
inner,
|
||||
})
|
||||
Ok(OuterAttributes { inner })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -189,13 +187,11 @@ struct ContainsIdent<'a> {
|
||||
|
||||
impl<'ast> ContainsIdent<'ast> {
|
||||
fn visit_tokenstream(&mut self, stream: TokenStream) {
|
||||
stream.into_iter().for_each(|tt|
|
||||
match tt {
|
||||
TokenTree::Ident(id) => self.visit_ident(&id),
|
||||
TokenTree::Group(ref group) => self.visit_tokenstream(group.stream()),
|
||||
_ => {}
|
||||
}
|
||||
)
|
||||
stream.into_iter().for_each(|tt| match tt {
|
||||
TokenTree::Ident(id) => self.visit_ident(&id),
|
||||
TokenTree::Group(ref group) => self.visit_tokenstream(group.stream()),
|
||||
_ => {},
|
||||
})
|
||||
}
|
||||
|
||||
fn visit_ident(&mut self, ident: &Ident) {
|
||||
@@ -218,10 +214,7 @@ impl<'ast> Visit<'ast> for ContainsIdent<'ast> {
|
||||
|
||||
/// Check if a `Type` contains the given `Ident`.
|
||||
pub fn type_contains_ident(typ: &syn::Type, ident: &Ident) -> bool {
|
||||
let mut visit = ContainsIdent {
|
||||
result: false,
|
||||
ident,
|
||||
};
|
||||
let mut visit = ContainsIdent { result: false, ident };
|
||||
|
||||
visit::visit_type(&mut visit, typ);
|
||||
visit.result
|
||||
@@ -229,10 +222,7 @@ pub fn type_contains_ident(typ: &syn::Type, ident: &Ident) -> bool {
|
||||
|
||||
/// Check if a `Expr` contains the given `Ident`.
|
||||
pub fn expr_contains_ident(expr: &syn::Expr, ident: &Ident) -> bool {
|
||||
let mut visit = ContainsIdent {
|
||||
result: false,
|
||||
ident,
|
||||
};
|
||||
let mut visit = ContainsIdent { result: false, ident };
|
||||
|
||||
visit::visit_expr(&mut visit, expr);
|
||||
visit.result
|
||||
|
||||
@@ -18,20 +18,26 @@
|
||||
//! Dispatch system. Contains a macro for defining runtime modules and
|
||||
//! generating values representing lazy module function calls.
|
||||
|
||||
pub use crate::sp_std::{result, fmt, prelude::{Vec, Clone, Eq, PartialEq}, marker};
|
||||
pub use crate::codec::{Codec, EncodeLike, Decode, Encode, Input, Output, HasCompact, EncodeAsRef};
|
||||
pub use frame_metadata::{
|
||||
FunctionMetadata, DecodeDifferent, DecodeDifferentArray, FunctionArgumentMetadata,
|
||||
ModuleConstantMetadata, DefaultByte, DefaultByteGetter, ModuleErrorMetadata, ErrorMetadata
|
||||
pub use crate::{
|
||||
codec::{Codec, Decode, Encode, EncodeAsRef, EncodeLike, HasCompact, Input, Output},
|
||||
sp_std::{
|
||||
fmt, marker,
|
||||
prelude::{Clone, Eq, PartialEq, Vec},
|
||||
result,
|
||||
},
|
||||
traits::{
|
||||
CallMetadata, GetCallMetadata, GetCallName, GetPalletVersion, UnfilteredDispatchable,
|
||||
},
|
||||
weights::{
|
||||
ClassifyDispatch, DispatchInfo, GetDispatchInfo, PaysFee, PostDispatchInfo,
|
||||
TransactionPriority, WeighData, Weight, WithPostDispatchInfo,
|
||||
},
|
||||
};
|
||||
pub use crate::weights::{
|
||||
GetDispatchInfo, DispatchInfo, WeighData, ClassifyDispatch, TransactionPriority, Weight,
|
||||
PaysFee, PostDispatchInfo, WithPostDispatchInfo,
|
||||
pub use frame_metadata::{
|
||||
DecodeDifferent, DecodeDifferentArray, DefaultByte, DefaultByteGetter, ErrorMetadata,
|
||||
FunctionArgumentMetadata, FunctionMetadata, ModuleConstantMetadata, ModuleErrorMetadata,
|
||||
};
|
||||
pub use sp_runtime::{traits::Dispatchable, DispatchError};
|
||||
pub use crate::traits::{
|
||||
CallMetadata, GetCallMetadata, GetCallName, UnfilteredDispatchable, GetPalletVersion,
|
||||
};
|
||||
|
||||
/// The return typ of a `Dispatchable` in frame. When returned explicitly from
|
||||
/// a dispatchable function it allows overriding the default `PostDispatchInfo`
|
||||
@@ -2331,7 +2337,6 @@ macro_rules! __call_to_functions {
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/// Convert a list of functions into a list of `FunctionMetadata` items.
|
||||
#[macro_export]
|
||||
#[doc(hidden)]
|
||||
@@ -2465,13 +2470,19 @@ macro_rules! __check_reserved_fn_name {
|
||||
#[allow(dead_code)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::weights::{DispatchInfo, DispatchClass, Pays, RuntimeDbWeight};
|
||||
use crate::traits::{
|
||||
GetCallName, OnInitialize, OnFinalize, OnIdle, OnRuntimeUpgrade,
|
||||
IntegrityTest, Get, PalletInfo,
|
||||
use crate::{
|
||||
traits::{
|
||||
Get, GetCallName, IntegrityTest, OnFinalize, OnIdle, OnInitialize, OnRuntimeUpgrade,
|
||||
PalletInfo,
|
||||
},
|
||||
weights::{DispatchClass, DispatchInfo, Pays, RuntimeDbWeight},
|
||||
};
|
||||
|
||||
pub trait Config: system::Config + Sized where Self::AccountId: From<u32> { }
|
||||
pub trait Config: system::Config + Sized
|
||||
where
|
||||
Self::AccountId: From<u32>,
|
||||
{
|
||||
}
|
||||
|
||||
pub mod system {
|
||||
use super::*;
|
||||
@@ -2546,18 +2557,14 @@ mod tests {
|
||||
FunctionMetadata {
|
||||
name: DecodeDifferent::Encode("aux_0"),
|
||||
arguments: DecodeDifferent::Encode(&[]),
|
||||
documentation: DecodeDifferent::Encode(&[
|
||||
" Hi, this is a comment."
|
||||
])
|
||||
documentation: DecodeDifferent::Encode(&[" Hi, this is a comment."]),
|
||||
},
|
||||
FunctionMetadata {
|
||||
name: DecodeDifferent::Encode("aux_1"),
|
||||
arguments: DecodeDifferent::Encode(&[
|
||||
FunctionArgumentMetadata {
|
||||
name: DecodeDifferent::Encode("_data"),
|
||||
ty: DecodeDifferent::Encode("Compact<u32>")
|
||||
}
|
||||
]),
|
||||
arguments: DecodeDifferent::Encode(&[FunctionArgumentMetadata {
|
||||
name: DecodeDifferent::Encode("_data"),
|
||||
ty: DecodeDifferent::Encode("Compact<u32>"),
|
||||
}]),
|
||||
documentation: DecodeDifferent::Encode(&[]),
|
||||
},
|
||||
FunctionMetadata {
|
||||
@@ -2570,7 +2577,7 @@ mod tests {
|
||||
FunctionArgumentMetadata {
|
||||
name: DecodeDifferent::Encode("_data2"),
|
||||
ty: DecodeDifferent::Encode("String"),
|
||||
}
|
||||
},
|
||||
]),
|
||||
documentation: DecodeDifferent::Encode(&[]),
|
||||
},
|
||||
@@ -2581,12 +2588,10 @@ mod tests {
|
||||
},
|
||||
FunctionMetadata {
|
||||
name: DecodeDifferent::Encode("aux_4"),
|
||||
arguments: DecodeDifferent::Encode(&[
|
||||
FunctionArgumentMetadata {
|
||||
name: DecodeDifferent::Encode("_data"),
|
||||
ty: DecodeDifferent::Encode("i32"),
|
||||
}
|
||||
]),
|
||||
arguments: DecodeDifferent::Encode(&[FunctionArgumentMetadata {
|
||||
name: DecodeDifferent::Encode("_data"),
|
||||
ty: DecodeDifferent::Encode("i32"),
|
||||
}]),
|
||||
documentation: DecodeDifferent::Encode(&[]),
|
||||
},
|
||||
FunctionMetadata {
|
||||
@@ -2598,8 +2603,8 @@ mod tests {
|
||||
},
|
||||
FunctionArgumentMetadata {
|
||||
name: DecodeDifferent::Encode("_data2"),
|
||||
ty: DecodeDifferent::Encode("Compact<u32>")
|
||||
}
|
||||
ty: DecodeDifferent::Encode("Compact<u32>"),
|
||||
},
|
||||
]),
|
||||
documentation: DecodeDifferent::Encode(&[]),
|
||||
},
|
||||
@@ -2611,7 +2616,7 @@ mod tests {
|
||||
];
|
||||
|
||||
pub struct TraitImpl {}
|
||||
impl Config for TraitImpl { }
|
||||
impl Config for TraitImpl {}
|
||||
|
||||
type Test = Module<TraitImpl>;
|
||||
|
||||
@@ -2679,7 +2684,6 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl system::Config for TraitImpl {
|
||||
type Origin = OuterOrigin;
|
||||
type AccountId = u32;
|
||||
@@ -2760,9 +2764,9 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn on_runtime_upgrade_should_work() {
|
||||
sp_io::TestExternalities::default().execute_with(||
|
||||
sp_io::TestExternalities::default().execute_with(|| {
|
||||
assert_eq!(<Module<TraitImpl> as OnRuntimeUpgrade>::on_runtime_upgrade(), 10)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -2788,7 +2792,10 @@ mod tests {
|
||||
#[test]
|
||||
fn get_call_names() {
|
||||
let call_names = Call::<TraitImpl>::get_call_names();
|
||||
assert_eq!(["aux_0", "aux_1", "aux_2", "aux_3", "aux_4", "aux_5", "operational"], call_names);
|
||||
assert_eq!(
|
||||
["aux_0", "aux_1", "aux_2", "aux_3", "aux_4", "aux_5", "operational"],
|
||||
call_names
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -18,9 +18,9 @@
|
||||
//! Macro for declaring a module error.
|
||||
|
||||
#[doc(hidden)]
|
||||
pub use sp_runtime::traits::{LookupError, BadOrigin};
|
||||
pub use frame_metadata::{DecodeDifferent, ErrorMetadata, ModuleErrorMetadata};
|
||||
#[doc(hidden)]
|
||||
pub use frame_metadata::{ModuleErrorMetadata, ErrorMetadata, DecodeDifferent};
|
||||
pub use sp_runtime::traits::{BadOrigin, LookupError};
|
||||
|
||||
/// Declare an error type for a runtime module.
|
||||
///
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
pub use frame_metadata::{EventMetadata, DecodeDifferent, OuterEventMetadata, FnEncode};
|
||||
pub use frame_metadata::{DecodeDifferent, EventMetadata, FnEncode, OuterEventMetadata};
|
||||
|
||||
/// Implement the `Event` for a module.
|
||||
///
|
||||
@@ -35,7 +35,7 @@ pub use frame_metadata::{EventMetadata, DecodeDifferent, OuterEventMetadata, FnE
|
||||
/// }
|
||||
/// );
|
||||
///
|
||||
///# fn main() {}
|
||||
/// # fn main() {}
|
||||
/// ```
|
||||
///
|
||||
/// # Generic Event Example:
|
||||
@@ -75,7 +75,7 @@ pub use frame_metadata::{EventMetadata, DecodeDifferent, OuterEventMetadata, FnE
|
||||
/// );
|
||||
/// }
|
||||
///
|
||||
///# fn main() {}
|
||||
/// # fn main() {}
|
||||
/// ```
|
||||
///
|
||||
/// The syntax for generic events requires the `where`.
|
||||
@@ -83,9 +83,9 @@ pub use frame_metadata::{EventMetadata, DecodeDifferent, OuterEventMetadata, FnE
|
||||
/// # Generic Event with Instance Example:
|
||||
///
|
||||
/// ```rust
|
||||
///# struct DefaultInstance;
|
||||
///# trait Instance {}
|
||||
///# impl Instance for DefaultInstance {}
|
||||
/// # struct DefaultInstance;
|
||||
/// # trait Instance {}
|
||||
/// # impl Instance for DefaultInstance {}
|
||||
/// trait Config<I: Instance=DefaultInstance> {
|
||||
/// type Balance;
|
||||
/// type Token;
|
||||
@@ -100,7 +100,7 @@ pub use frame_metadata::{EventMetadata, DecodeDifferent, OuterEventMetadata, FnE
|
||||
/// Message(Balance, Token),
|
||||
/// }
|
||||
/// );
|
||||
///# fn main() {}
|
||||
/// # fn main() {}
|
||||
/// ```
|
||||
#[macro_export]
|
||||
macro_rules! decl_event {
|
||||
@@ -337,8 +337,8 @@ macro_rules! __events_to_metadata {
|
||||
#[allow(dead_code)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use codec::{Decode, Encode};
|
||||
use serde::Serialize;
|
||||
use codec::{Encode, Decode};
|
||||
|
||||
mod system {
|
||||
pub trait Config: 'static {
|
||||
@@ -414,9 +414,10 @@ mod tests {
|
||||
|
||||
decl_event!(
|
||||
/// Event with renamed generic parameter
|
||||
pub enum Event<T> where
|
||||
pub enum Event<T>
|
||||
where
|
||||
BalanceRenamed = <T as Config>::Balance,
|
||||
OriginRenamed = <T as system::Config>::Origin
|
||||
OriginRenamed = <T as system::Config>::Origin,
|
||||
{
|
||||
TestEvent(BalanceRenamed),
|
||||
TestOrigin(OriginRenamed),
|
||||
@@ -467,15 +468,13 @@ mod tests {
|
||||
|
||||
decl_event!(
|
||||
/// Event finish formatting on an named one with trailing comma
|
||||
pub enum Event<T> where
|
||||
pub enum Event<T>
|
||||
where
|
||||
BalanceRenamed = <T as Config>::Balance,
|
||||
OriginRenamed = <T as system::Config>::Origin,
|
||||
{
|
||||
TestEvent(BalanceRenamed, OriginRenamed),
|
||||
TrailingCommaInArgs(
|
||||
u32,
|
||||
u32,
|
||||
),
|
||||
TrailingCommaInArgs(u32, u32),
|
||||
}
|
||||
);
|
||||
}
|
||||
@@ -505,26 +504,24 @@ mod tests {
|
||||
fn event_metadata() {
|
||||
assert_eq!(
|
||||
system_renamed::Event::metadata(),
|
||||
&[
|
||||
EventMetadata {
|
||||
name: DecodeDifferent::Encode("SystemEvent"),
|
||||
arguments: DecodeDifferent::Encode(&[]),
|
||||
documentation: DecodeDifferent::Encode(&[]),
|
||||
},
|
||||
]
|
||||
&[EventMetadata {
|
||||
name: DecodeDifferent::Encode("SystemEvent"),
|
||||
arguments: DecodeDifferent::Encode(&[]),
|
||||
documentation: DecodeDifferent::Encode(&[]),
|
||||
},]
|
||||
);
|
||||
assert_eq!(
|
||||
event_module::Event::<TestRuntime>::metadata(),
|
||||
&[
|
||||
EventMetadata {
|
||||
name: DecodeDifferent::Encode("TestEvent"),
|
||||
arguments: DecodeDifferent::Encode(&[ "Balance", "Origin" ]),
|
||||
documentation: DecodeDifferent::Encode(&[ " Hi, I am a comment." ])
|
||||
arguments: DecodeDifferent::Encode(&["Balance", "Origin"]),
|
||||
documentation: DecodeDifferent::Encode(&[" Hi, I am a comment."])
|
||||
},
|
||||
EventMetadata {
|
||||
name: DecodeDifferent::Encode("EventWithoutParams"),
|
||||
arguments: DecodeDifferent::Encode(&[]),
|
||||
documentation: DecodeDifferent::Encode(&[ " Dog" ]),
|
||||
documentation: DecodeDifferent::Encode(&[" Dog"]),
|
||||
},
|
||||
]
|
||||
);
|
||||
@@ -533,25 +530,23 @@ mod tests {
|
||||
&[
|
||||
EventMetadata {
|
||||
name: DecodeDifferent::Encode("TestEvent"),
|
||||
arguments: DecodeDifferent::Encode(&[ "BalanceRenamed" ]),
|
||||
arguments: DecodeDifferent::Encode(&["BalanceRenamed"]),
|
||||
documentation: DecodeDifferent::Encode(&[])
|
||||
},
|
||||
EventMetadata {
|
||||
name: DecodeDifferent::Encode("TestOrigin"),
|
||||
arguments: DecodeDifferent::Encode(&[ "OriginRenamed" ]),
|
||||
arguments: DecodeDifferent::Encode(&["OriginRenamed"]),
|
||||
documentation: DecodeDifferent::Encode(&[]),
|
||||
},
|
||||
]
|
||||
);
|
||||
assert_eq!(
|
||||
event_module3::Event::metadata(),
|
||||
&[
|
||||
EventMetadata {
|
||||
name: DecodeDifferent::Encode("HiEvent"),
|
||||
arguments: DecodeDifferent::Encode(&[]),
|
||||
documentation: DecodeDifferent::Encode(&[])
|
||||
}
|
||||
],
|
||||
&[EventMetadata {
|
||||
name: DecodeDifferent::Encode("HiEvent"),
|
||||
arguments: DecodeDifferent::Encode(&[]),
|
||||
documentation: DecodeDifferent::Encode(&[])
|
||||
}],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
//! Hash utilities.
|
||||
|
||||
use codec::{Codec, MaxEncodedLen};
|
||||
use sp_io::hashing::{blake2_128, blake2_256, twox_128, twox_256, twox_64};
|
||||
use sp_std::prelude::Vec;
|
||||
use sp_io::hashing::{blake2_128, blake2_256, twox_64, twox_128, twox_256};
|
||||
|
||||
// This trait must be kept coherent with frame-support-procedural HasherKind usage
|
||||
pub trait Hashable: Sized {
|
||||
@@ -51,7 +51,9 @@ impl<T: Codec> Hashable for T {
|
||||
fn twox_64_concat(&self) -> Vec<u8> {
|
||||
self.using_encoded(Twox64Concat::hash)
|
||||
}
|
||||
fn identity(&self) -> Vec<u8> { self.encode() }
|
||||
fn identity(&self) -> Vec<u8> {
|
||||
self.encode()
|
||||
}
|
||||
}
|
||||
|
||||
/// Hasher to use to hash keys to insert to storage.
|
||||
@@ -98,11 +100,7 @@ impl StorageHasher for Twox64Concat {
|
||||
const METADATA: frame_metadata::StorageHasher = frame_metadata::StorageHasher::Twox64Concat;
|
||||
type Output = Vec<u8>;
|
||||
fn hash(x: &[u8]) -> Vec<u8> {
|
||||
twox_64(x)
|
||||
.iter()
|
||||
.chain(x.into_iter())
|
||||
.cloned()
|
||||
.collect::<Vec<_>>()
|
||||
twox_64(x).iter().chain(x.into_iter()).cloned().collect::<Vec<_>>()
|
||||
}
|
||||
fn max_len<K: MaxEncodedLen>() -> usize {
|
||||
K::max_encoded_len().saturating_add(8)
|
||||
@@ -124,11 +122,7 @@ impl StorageHasher for Blake2_128Concat {
|
||||
const METADATA: frame_metadata::StorageHasher = frame_metadata::StorageHasher::Blake2_128Concat;
|
||||
type Output = Vec<u8>;
|
||||
fn hash(x: &[u8]) -> Vec<u8> {
|
||||
blake2_128(x)
|
||||
.iter()
|
||||
.chain(x.into_iter())
|
||||
.cloned()
|
||||
.collect::<Vec<_>>()
|
||||
blake2_128(x).iter().chain(x.into_iter()).cloned().collect::<Vec<_>>()
|
||||
}
|
||||
fn max_len<K: MaxEncodedLen>() -> usize {
|
||||
K::max_encoded_len().saturating_add(16)
|
||||
|
||||
@@ -15,13 +15,13 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#[doc(hidden)]
|
||||
pub use crate::sp_std::vec::Vec;
|
||||
#[doc(hidden)]
|
||||
pub use crate::sp_runtime::traits::{Block as BlockT, Extrinsic};
|
||||
#[doc(hidden)]
|
||||
pub use crate::sp_std::vec::Vec;
|
||||
|
||||
pub use sp_inherents::{
|
||||
InherentData, CheckInherentsResult, IsFatalError, InherentIdentifier, MakeFatalError,
|
||||
CheckInherentsResult, InherentData, InherentIdentifier, IsFatalError, MakeFatalError,
|
||||
};
|
||||
|
||||
/// A pallet that provides or verifies an inherent extrinsic.
|
||||
@@ -53,7 +53,9 @@ pub trait ProvideInherent {
|
||||
/// one inherent for which:
|
||||
/// * type is [`Self::Call`],
|
||||
/// * [`Self::is_inherent`] returns true.
|
||||
fn is_inherent_required(_: &InherentData) -> Result<Option<Self::Error>, Self::Error> { Ok(None) }
|
||||
fn is_inherent_required(_: &InherentData) -> Result<Option<Self::Error>, Self::Error> {
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
/// Check whether the given inherent is valid. Checking the inherent is optional and can be
|
||||
/// omitted by using the default implementation.
|
||||
|
||||
+222
-203
@@ -25,42 +25,42 @@ extern crate self as frame_support;
|
||||
#[doc(hidden)]
|
||||
pub use sp_tracing;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
pub use serde;
|
||||
pub use sp_core::Void;
|
||||
#[doc(hidden)]
|
||||
pub use sp_std;
|
||||
#[doc(hidden)]
|
||||
pub use codec;
|
||||
#[doc(hidden)]
|
||||
pub use frame_metadata as metadata;
|
||||
#[doc(hidden)]
|
||||
pub use log;
|
||||
#[cfg(feature = "std")]
|
||||
#[doc(hidden)]
|
||||
pub use once_cell;
|
||||
#[doc(hidden)]
|
||||
pub use paste;
|
||||
#[cfg(feature = "std")]
|
||||
pub use serde;
|
||||
pub use sp_core::Void;
|
||||
#[doc(hidden)]
|
||||
pub use sp_io::{self, storage::root as storage_root};
|
||||
#[doc(hidden)]
|
||||
pub use sp_runtime::RuntimeDebug;
|
||||
#[cfg(feature = "std")]
|
||||
#[doc(hidden)]
|
||||
pub use sp_state_machine::BasicExternalities;
|
||||
#[doc(hidden)]
|
||||
pub use sp_io::{storage::root as storage_root, self};
|
||||
#[doc(hidden)]
|
||||
pub use sp_runtime::RuntimeDebug;
|
||||
#[doc(hidden)]
|
||||
pub use log;
|
||||
#[doc(hidden)]
|
||||
pub use frame_metadata as metadata;
|
||||
pub use sp_std;
|
||||
|
||||
#[macro_use]
|
||||
pub mod dispatch;
|
||||
pub mod storage;
|
||||
mod hash;
|
||||
pub mod storage;
|
||||
#[macro_use]
|
||||
pub mod event;
|
||||
pub mod inherent;
|
||||
#[macro_use]
|
||||
pub mod error;
|
||||
pub mod instances;
|
||||
pub mod traits;
|
||||
pub mod weights;
|
||||
pub mod instances;
|
||||
|
||||
#[doc(hidden)]
|
||||
pub mod unsigned {
|
||||
@@ -68,23 +68,27 @@ pub mod unsigned {
|
||||
pub use crate::sp_runtime::traits::ValidateUnsigned;
|
||||
#[doc(hidden)]
|
||||
pub use crate::sp_runtime::transaction_validity::{
|
||||
TransactionValidity, UnknownTransaction, TransactionValidityError, TransactionSource,
|
||||
TransactionSource, TransactionValidity, TransactionValidityError, UnknownTransaction,
|
||||
};
|
||||
}
|
||||
|
||||
pub use self::hash::{
|
||||
Twox256, Twox128, Blake2_256, Blake2_128, Identity, Twox64Concat, Blake2_128Concat, Hashable,
|
||||
StorageHasher, ReversibleStorageHasher
|
||||
pub use self::{
|
||||
dispatch::{Callable, Parameter},
|
||||
hash::{
|
||||
Blake2_128, Blake2_128Concat, Blake2_256, Hashable, Identity, ReversibleStorageHasher,
|
||||
StorageHasher, Twox128, Twox256, Twox64Concat,
|
||||
},
|
||||
storage::{
|
||||
bounded_vec::{BoundedSlice, BoundedVec},
|
||||
migration,
|
||||
weak_bounded_vec::WeakBoundedVec,
|
||||
IterableStorageDoubleMap, IterableStorageMap, IterableStorageNMap, StorageDoubleMap,
|
||||
StorageMap, StorageNMap, StoragePrefixedMap, StorageValue,
|
||||
},
|
||||
};
|
||||
pub use self::storage::{
|
||||
StorageValue, StorageMap, StorageDoubleMap, StorageNMap, StoragePrefixedMap,
|
||||
IterableStorageMap, IterableStorageDoubleMap, IterableStorageNMap, migration,
|
||||
bounded_vec::{BoundedVec, BoundedSlice}, weak_bounded_vec::WeakBoundedVec,
|
||||
};
|
||||
pub use self::dispatch::{Parameter, Callable};
|
||||
pub use sp_runtime::{self, ConsensusEngineId, print, traits::Printable};
|
||||
pub use sp_runtime::{self, print, traits::Printable, ConsensusEngineId};
|
||||
|
||||
use codec::{Encode, Decode};
|
||||
use codec::{Decode, Encode};
|
||||
use sp_runtime::TypeId;
|
||||
|
||||
/// A unified log target for support operations.
|
||||
@@ -108,14 +112,14 @@ impl TypeId for PalletId {
|
||||
///
|
||||
/// Useful for creating a *storage-like* struct for test and migrations.
|
||||
///
|
||||
///```
|
||||
/// ```
|
||||
/// # use frame_support::generate_storage_alias;
|
||||
/// use frame_support::codec;
|
||||
/// use frame_support::Twox64Concat;
|
||||
/// // generate a storage value with type u32.
|
||||
/// generate_storage_alias!(Prefix, StorageName => Value<u32>);
|
||||
///
|
||||
/// // generate a double map from `(u32, u32)` (with hashers `Twox64Concat` for each key)
|
||||
/// // generate a double map from `(u32, u32)` (with hashers `Twox64Concat` for each key)
|
||||
/// // to `Vec<u8>`
|
||||
/// generate_storage_alias!(
|
||||
/// OtherPrefix, OtherStorageName => DoubleMap<
|
||||
@@ -534,7 +538,7 @@ pub fn debug(data: &impl sp_std::fmt::Debug) {
|
||||
|
||||
#[doc(inline)]
|
||||
pub use frame_support_procedural::{
|
||||
decl_storage, construct_runtime, transactional, RuntimeDebugNoBound,
|
||||
construct_runtime, decl_storage, transactional, RuntimeDebugNoBound,
|
||||
};
|
||||
|
||||
#[doc(hidden)]
|
||||
@@ -546,14 +550,14 @@ pub use frame_support_procedural::__generate_dummy_part_checker;
|
||||
/// ```
|
||||
/// # use frame_support::CloneNoBound;
|
||||
/// trait Config {
|
||||
/// type C: Clone;
|
||||
/// type C: Clone;
|
||||
/// }
|
||||
///
|
||||
/// // Foo implements [`Clone`] because `C` bounds [`Clone`].
|
||||
/// // Otherwise compilation will fail with an output telling `c` doesn't implement [`Clone`].
|
||||
/// #[derive(CloneNoBound)]
|
||||
/// struct Foo<T: Config> {
|
||||
/// c: T::C,
|
||||
/// c: T::C,
|
||||
/// }
|
||||
/// ```
|
||||
pub use frame_support_procedural::CloneNoBound;
|
||||
@@ -564,14 +568,14 @@ pub use frame_support_procedural::CloneNoBound;
|
||||
/// ```
|
||||
/// # use frame_support::{EqNoBound, PartialEqNoBound};
|
||||
/// trait Config {
|
||||
/// type C: Eq;
|
||||
/// type C: Eq;
|
||||
/// }
|
||||
///
|
||||
/// // Foo implements [`Eq`] because `C` bounds [`Eq`].
|
||||
/// // Otherwise compilation will fail with an output telling `c` doesn't implement [`Eq`].
|
||||
/// #[derive(PartialEqNoBound, EqNoBound)]
|
||||
/// struct Foo<T: Config> {
|
||||
/// c: T::C,
|
||||
/// c: T::C,
|
||||
/// }
|
||||
/// ```
|
||||
pub use frame_support_procedural::EqNoBound;
|
||||
@@ -582,14 +586,14 @@ pub use frame_support_procedural::EqNoBound;
|
||||
/// ```
|
||||
/// # use frame_support::PartialEqNoBound;
|
||||
/// trait Config {
|
||||
/// type C: PartialEq;
|
||||
/// type C: PartialEq;
|
||||
/// }
|
||||
///
|
||||
/// // Foo implements [`PartialEq`] because `C` bounds [`PartialEq`].
|
||||
/// // Otherwise compilation will fail with an output telling `c` doesn't implement [`PartialEq`].
|
||||
/// #[derive(PartialEqNoBound)]
|
||||
/// struct Foo<T: Config> {
|
||||
/// c: T::C,
|
||||
/// c: T::C,
|
||||
/// }
|
||||
/// ```
|
||||
pub use frame_support_procedural::PartialEqNoBound;
|
||||
@@ -601,14 +605,14 @@ pub use frame_support_procedural::PartialEqNoBound;
|
||||
/// # use frame_support::DebugNoBound;
|
||||
/// # use core::fmt::Debug;
|
||||
/// trait Config {
|
||||
/// type C: Debug;
|
||||
/// type C: Debug;
|
||||
/// }
|
||||
///
|
||||
/// // Foo implements [`Debug`] because `C` bounds [`Debug`].
|
||||
/// // Otherwise compilation will fail with an output telling `c` doesn't implement [`Debug`].
|
||||
/// #[derive(DebugNoBound)]
|
||||
/// struct Foo<T: Config> {
|
||||
/// c: T::C,
|
||||
/// c: T::C,
|
||||
/// }
|
||||
/// ```
|
||||
pub use frame_support_procedural::DebugNoBound;
|
||||
@@ -620,14 +624,14 @@ pub use frame_support_procedural::DebugNoBound;
|
||||
/// # use frame_support::DefaultNoBound;
|
||||
/// # use core::default::Default;
|
||||
/// trait Config {
|
||||
/// type C: Default;
|
||||
/// type C: Default;
|
||||
/// }
|
||||
///
|
||||
/// // Foo implements [`Default`] because `C` bounds [`Default`].
|
||||
/// // Otherwise compilation will fail with an output telling `c` doesn't implement [`Default`].
|
||||
/// #[derive(DefaultNoBound)]
|
||||
/// struct Foo<T: Config> {
|
||||
/// c: T::C,
|
||||
/// c: T::C,
|
||||
/// }
|
||||
/// ```
|
||||
pub use frame_support_procedural::DefaultNoBound;
|
||||
@@ -684,8 +688,8 @@ pub use frame_support_procedural::crate_to_pallet_version;
|
||||
#[macro_export]
|
||||
macro_rules! fail {
|
||||
( $y:expr ) => {{
|
||||
return Err($y.into());
|
||||
}}
|
||||
return Err($y.into())
|
||||
}};
|
||||
}
|
||||
|
||||
/// Evaluate `$x:expr` and if not true return `Err($y:expr)`.
|
||||
@@ -697,7 +701,7 @@ macro_rules! ensure {
|
||||
if !$x {
|
||||
$crate::fail!($y);
|
||||
}
|
||||
}}
|
||||
}};
|
||||
}
|
||||
|
||||
/// Evaluate an expression, assert it returns an expected `Err` value and that
|
||||
@@ -713,7 +717,7 @@ macro_rules! assert_noop {
|
||||
let h = $crate::storage_root();
|
||||
$crate::assert_err!($x, $y);
|
||||
assert_eq!(h, $crate::storage_root());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// Evaluate any expression and assert that runtime storage has not been mutated
|
||||
@@ -728,7 +732,7 @@ macro_rules! assert_storage_noop {
|
||||
let h = $crate::storage_root();
|
||||
$x;
|
||||
assert_eq!(h, $crate::storage_root());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// Assert an expression returns an error specified.
|
||||
@@ -738,7 +742,7 @@ macro_rules! assert_storage_noop {
|
||||
macro_rules! assert_err {
|
||||
( $x:expr , $y:expr $(,)? ) => {
|
||||
assert_eq!($x, Err($y.into()));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// Assert an expression returns an error specified.
|
||||
@@ -749,7 +753,7 @@ macro_rules! assert_err {
|
||||
macro_rules! assert_err_ignore_postinfo {
|
||||
( $x:expr , $y:expr $(,)? ) => {
|
||||
$crate::assert_err!($x.map(|_| ()).map_err(|e| e.error), $y);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// Assert an expression returns error with the given weight.
|
||||
@@ -762,7 +766,7 @@ macro_rules! assert_err_with_weight {
|
||||
} else {
|
||||
panic!("expected Err(_), got Ok(_).")
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// Panic if an expression doesn't evaluate to `Ok`.
|
||||
@@ -780,23 +784,23 @@ macro_rules! assert_ok {
|
||||
};
|
||||
( $x:expr, $y:expr $(,)? ) => {
|
||||
assert_eq!($x, Ok($y));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[doc(hidden)]
|
||||
pub use serde::{Serialize, Deserialize};
|
||||
pub use serde::{Deserialize, Serialize};
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod tests {
|
||||
use super::*;
|
||||
use codec::{Codec, EncodeLike};
|
||||
use frame_metadata::{
|
||||
DecodeDifferent, StorageEntryMetadata, StorageMetadata, StorageEntryType,
|
||||
StorageEntryModifier, DefaultByteGetter, StorageHasher,
|
||||
DecodeDifferent, DefaultByteGetter, StorageEntryMetadata, StorageEntryModifier,
|
||||
StorageEntryType, StorageHasher, StorageMetadata,
|
||||
};
|
||||
use sp_std::{marker::PhantomData, result};
|
||||
use sp_io::TestExternalities;
|
||||
use sp_std::{marker::PhantomData, result};
|
||||
|
||||
/// A PalletInfo implementation which just panics.
|
||||
pub struct PanicPalletInfo;
|
||||
@@ -864,7 +868,9 @@ pub mod tests {
|
||||
|
||||
type Map = Data;
|
||||
|
||||
trait Sorted { fn sorted(self) -> Self; }
|
||||
trait Sorted {
|
||||
fn sorted(self) -> Self;
|
||||
}
|
||||
impl<T: Ord> Sorted for Vec<T> {
|
||||
fn sorted(mut self) -> Self {
|
||||
self.sort();
|
||||
@@ -918,13 +924,15 @@ pub mod tests {
|
||||
DataDM::insert(1, 0, 2);
|
||||
DataDM::insert(1, 1, 3);
|
||||
|
||||
let get_all = || vec![
|
||||
DataDM::get(0, 1),
|
||||
DataDM::get(1, 0),
|
||||
DataDM::get(1, 1),
|
||||
DataDM::get(2, 0),
|
||||
DataDM::get(2, 1),
|
||||
];
|
||||
let get_all = || {
|
||||
vec![
|
||||
DataDM::get(0, 1),
|
||||
DataDM::get(1, 0),
|
||||
DataDM::get(1, 1),
|
||||
DataDM::get(2, 0),
|
||||
DataDM::get(2, 1),
|
||||
]
|
||||
};
|
||||
assert_eq!(get_all(), vec![1, 2, 3, 0, 0]);
|
||||
|
||||
// Two existing
|
||||
@@ -990,15 +998,24 @@ pub mod tests {
|
||||
Map::mutate(&key, |val| {
|
||||
*val = 15;
|
||||
});
|
||||
assert_eq!(Map::iter().collect::<Vec<_>>().sorted(), vec![(key - 2, 42), (key - 1, 43), (key, 15)]);
|
||||
assert_eq!(
|
||||
Map::iter().collect::<Vec<_>>().sorted(),
|
||||
vec![(key - 2, 42), (key - 1, 43), (key, 15)]
|
||||
);
|
||||
Map::mutate(&key, |val| {
|
||||
*val = 17;
|
||||
});
|
||||
assert_eq!(Map::iter().collect::<Vec<_>>().sorted(), vec![(key - 2, 42), (key - 1, 43), (key, 17)]);
|
||||
assert_eq!(
|
||||
Map::iter().collect::<Vec<_>>().sorted(),
|
||||
vec![(key - 2, 42), (key - 1, 43), (key, 17)]
|
||||
);
|
||||
|
||||
// remove first
|
||||
Map::remove(&key);
|
||||
assert_eq!(Map::iter().collect::<Vec<_>>().sorted(), vec![(key - 2, 42), (key - 1, 43)]);
|
||||
assert_eq!(
|
||||
Map::iter().collect::<Vec<_>>().sorted(),
|
||||
vec![(key - 2, 42), (key - 1, 43)]
|
||||
);
|
||||
|
||||
// remove last from the list
|
||||
Map::remove(&(key - 2));
|
||||
@@ -1049,7 +1066,6 @@ pub mod tests {
|
||||
assert_eq!(DoubleMap::get(&key1, &(key2 + 1)), 0u64);
|
||||
assert_eq!(DoubleMap::get(&(key1 + 1), &key2), 4u64);
|
||||
assert_eq!(DoubleMap::get(&(key1 + 1), &(key2 + 1)), 4u64);
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1100,10 +1116,13 @@ pub mod tests {
|
||||
assert_eq!(DoubleMap::get(&key1, key2), 1);
|
||||
|
||||
// no-op if `Err`
|
||||
assert_noop!(DoubleMap::try_mutate_exists(key1, key2, |v| -> TestResult {
|
||||
*v = Some(2);
|
||||
Err("nah")
|
||||
}), "nah");
|
||||
assert_noop!(
|
||||
DoubleMap::try_mutate_exists(key1, key2, |v| -> TestResult {
|
||||
*v = Some(2);
|
||||
Err("nah")
|
||||
}),
|
||||
"nah"
|
||||
);
|
||||
|
||||
// removed if mutated to`None`
|
||||
assert_ok!(DoubleMap::try_mutate_exists(key1, key2, |v| -> TestResult {
|
||||
@@ -1116,126 +1135,124 @@ pub mod tests {
|
||||
|
||||
const EXPECTED_METADATA: StorageMetadata = StorageMetadata {
|
||||
prefix: DecodeDifferent::Encode("Test"),
|
||||
entries: DecodeDifferent::Encode(
|
||||
&[
|
||||
StorageEntryMetadata {
|
||||
name: DecodeDifferent::Encode("Data"),
|
||||
modifier: StorageEntryModifier::Default,
|
||||
ty: StorageEntryType::Map{
|
||||
hasher: StorageHasher::Twox64Concat,
|
||||
key: DecodeDifferent::Encode("u32"),
|
||||
value: DecodeDifferent::Encode("u64"),
|
||||
unused: false,
|
||||
},
|
||||
default: DecodeDifferent::Encode(
|
||||
DefaultByteGetter(&__GetByteStructData(PhantomData::<Test>))
|
||||
),
|
||||
documentation: DecodeDifferent::Encode(&[]),
|
||||
entries: DecodeDifferent::Encode(&[
|
||||
StorageEntryMetadata {
|
||||
name: DecodeDifferent::Encode("Data"),
|
||||
modifier: StorageEntryModifier::Default,
|
||||
ty: StorageEntryType::Map {
|
||||
hasher: StorageHasher::Twox64Concat,
|
||||
key: DecodeDifferent::Encode("u32"),
|
||||
value: DecodeDifferent::Encode("u64"),
|
||||
unused: false,
|
||||
},
|
||||
StorageEntryMetadata {
|
||||
name: DecodeDifferent::Encode("OptionLinkedMap"),
|
||||
modifier: StorageEntryModifier::Optional,
|
||||
ty: StorageEntryType::Map {
|
||||
hasher: StorageHasher::Blake2_128Concat,
|
||||
key: DecodeDifferent::Encode("u32"),
|
||||
value: DecodeDifferent::Encode("u32"),
|
||||
unused: false,
|
||||
},
|
||||
default: DecodeDifferent::Encode(
|
||||
DefaultByteGetter(&__GetByteStructOptionLinkedMap(PhantomData::<Test>))
|
||||
),
|
||||
documentation: DecodeDifferent::Encode(&[]),
|
||||
default: DecodeDifferent::Encode(DefaultByteGetter(&__GetByteStructData(
|
||||
PhantomData::<Test>,
|
||||
))),
|
||||
documentation: DecodeDifferent::Encode(&[]),
|
||||
},
|
||||
StorageEntryMetadata {
|
||||
name: DecodeDifferent::Encode("OptionLinkedMap"),
|
||||
modifier: StorageEntryModifier::Optional,
|
||||
ty: StorageEntryType::Map {
|
||||
hasher: StorageHasher::Blake2_128Concat,
|
||||
key: DecodeDifferent::Encode("u32"),
|
||||
value: DecodeDifferent::Encode("u32"),
|
||||
unused: false,
|
||||
},
|
||||
StorageEntryMetadata {
|
||||
name: DecodeDifferent::Encode("GenericData"),
|
||||
modifier: StorageEntryModifier::Default,
|
||||
ty: StorageEntryType::Map{
|
||||
hasher: StorageHasher::Identity,
|
||||
key: DecodeDifferent::Encode("T::BlockNumber"),
|
||||
value: DecodeDifferent::Encode("T::BlockNumber"),
|
||||
unused: false
|
||||
},
|
||||
default: DecodeDifferent::Encode(
|
||||
DefaultByteGetter(&__GetByteStructGenericData(PhantomData::<Test>))
|
||||
),
|
||||
documentation: DecodeDifferent::Encode(&[]),
|
||||
default: DecodeDifferent::Encode(DefaultByteGetter(
|
||||
&__GetByteStructOptionLinkedMap(PhantomData::<Test>),
|
||||
)),
|
||||
documentation: DecodeDifferent::Encode(&[]),
|
||||
},
|
||||
StorageEntryMetadata {
|
||||
name: DecodeDifferent::Encode("GenericData"),
|
||||
modifier: StorageEntryModifier::Default,
|
||||
ty: StorageEntryType::Map {
|
||||
hasher: StorageHasher::Identity,
|
||||
key: DecodeDifferent::Encode("T::BlockNumber"),
|
||||
value: DecodeDifferent::Encode("T::BlockNumber"),
|
||||
unused: false,
|
||||
},
|
||||
StorageEntryMetadata {
|
||||
name: DecodeDifferent::Encode("GenericData2"),
|
||||
modifier: StorageEntryModifier::Optional,
|
||||
ty: StorageEntryType::Map{
|
||||
hasher: StorageHasher::Blake2_128Concat,
|
||||
key: DecodeDifferent::Encode("T::BlockNumber"),
|
||||
value: DecodeDifferent::Encode("T::BlockNumber"),
|
||||
unused: false
|
||||
},
|
||||
default: DecodeDifferent::Encode(
|
||||
DefaultByteGetter(&__GetByteStructGenericData2(PhantomData::<Test>))
|
||||
),
|
||||
documentation: DecodeDifferent::Encode(&[]),
|
||||
default: DecodeDifferent::Encode(DefaultByteGetter(&__GetByteStructGenericData(
|
||||
PhantomData::<Test>,
|
||||
))),
|
||||
documentation: DecodeDifferent::Encode(&[]),
|
||||
},
|
||||
StorageEntryMetadata {
|
||||
name: DecodeDifferent::Encode("GenericData2"),
|
||||
modifier: StorageEntryModifier::Optional,
|
||||
ty: StorageEntryType::Map {
|
||||
hasher: StorageHasher::Blake2_128Concat,
|
||||
key: DecodeDifferent::Encode("T::BlockNumber"),
|
||||
value: DecodeDifferent::Encode("T::BlockNumber"),
|
||||
unused: false,
|
||||
},
|
||||
StorageEntryMetadata {
|
||||
name: DecodeDifferent::Encode("DataDM"),
|
||||
modifier: StorageEntryModifier::Default,
|
||||
ty: StorageEntryType::DoubleMap{
|
||||
hasher: StorageHasher::Twox64Concat,
|
||||
key1: DecodeDifferent::Encode("u32"),
|
||||
key2: DecodeDifferent::Encode("u32"),
|
||||
value: DecodeDifferent::Encode("u64"),
|
||||
key2_hasher: StorageHasher::Blake2_128Concat,
|
||||
},
|
||||
default: DecodeDifferent::Encode(
|
||||
DefaultByteGetter(&__GetByteStructDataDM(PhantomData::<Test>))
|
||||
),
|
||||
documentation: DecodeDifferent::Encode(&[]),
|
||||
default: DecodeDifferent::Encode(DefaultByteGetter(&__GetByteStructGenericData2(
|
||||
PhantomData::<Test>,
|
||||
))),
|
||||
documentation: DecodeDifferent::Encode(&[]),
|
||||
},
|
||||
StorageEntryMetadata {
|
||||
name: DecodeDifferent::Encode("DataDM"),
|
||||
modifier: StorageEntryModifier::Default,
|
||||
ty: StorageEntryType::DoubleMap {
|
||||
hasher: StorageHasher::Twox64Concat,
|
||||
key1: DecodeDifferent::Encode("u32"),
|
||||
key2: DecodeDifferent::Encode("u32"),
|
||||
value: DecodeDifferent::Encode("u64"),
|
||||
key2_hasher: StorageHasher::Blake2_128Concat,
|
||||
},
|
||||
StorageEntryMetadata {
|
||||
name: DecodeDifferent::Encode("GenericDataDM"),
|
||||
modifier: StorageEntryModifier::Default,
|
||||
ty: StorageEntryType::DoubleMap{
|
||||
hasher: StorageHasher::Blake2_128Concat,
|
||||
key1: DecodeDifferent::Encode("T::BlockNumber"),
|
||||
key2: DecodeDifferent::Encode("T::BlockNumber"),
|
||||
value: DecodeDifferent::Encode("T::BlockNumber"),
|
||||
key2_hasher: StorageHasher::Identity,
|
||||
},
|
||||
default: DecodeDifferent::Encode(
|
||||
DefaultByteGetter(&__GetByteStructGenericDataDM(PhantomData::<Test>))
|
||||
),
|
||||
documentation: DecodeDifferent::Encode(&[]),
|
||||
default: DecodeDifferent::Encode(DefaultByteGetter(&__GetByteStructDataDM(
|
||||
PhantomData::<Test>,
|
||||
))),
|
||||
documentation: DecodeDifferent::Encode(&[]),
|
||||
},
|
||||
StorageEntryMetadata {
|
||||
name: DecodeDifferent::Encode("GenericDataDM"),
|
||||
modifier: StorageEntryModifier::Default,
|
||||
ty: StorageEntryType::DoubleMap {
|
||||
hasher: StorageHasher::Blake2_128Concat,
|
||||
key1: DecodeDifferent::Encode("T::BlockNumber"),
|
||||
key2: DecodeDifferent::Encode("T::BlockNumber"),
|
||||
value: DecodeDifferent::Encode("T::BlockNumber"),
|
||||
key2_hasher: StorageHasher::Identity,
|
||||
},
|
||||
StorageEntryMetadata {
|
||||
name: DecodeDifferent::Encode("GenericData2DM"),
|
||||
modifier: StorageEntryModifier::Optional,
|
||||
ty: StorageEntryType::DoubleMap{
|
||||
hasher: StorageHasher::Blake2_128Concat,
|
||||
key1: DecodeDifferent::Encode("T::BlockNumber"),
|
||||
key2: DecodeDifferent::Encode("T::BlockNumber"),
|
||||
value: DecodeDifferent::Encode("T::BlockNumber"),
|
||||
key2_hasher: StorageHasher::Twox64Concat,
|
||||
},
|
||||
default: DecodeDifferent::Encode(
|
||||
DefaultByteGetter(&__GetByteStructGenericData2DM(PhantomData::<Test>))
|
||||
),
|
||||
documentation: DecodeDifferent::Encode(&[]),
|
||||
default: DecodeDifferent::Encode(DefaultByteGetter(&__GetByteStructGenericDataDM(
|
||||
PhantomData::<Test>,
|
||||
))),
|
||||
documentation: DecodeDifferent::Encode(&[]),
|
||||
},
|
||||
StorageEntryMetadata {
|
||||
name: DecodeDifferent::Encode("GenericData2DM"),
|
||||
modifier: StorageEntryModifier::Optional,
|
||||
ty: StorageEntryType::DoubleMap {
|
||||
hasher: StorageHasher::Blake2_128Concat,
|
||||
key1: DecodeDifferent::Encode("T::BlockNumber"),
|
||||
key2: DecodeDifferent::Encode("T::BlockNumber"),
|
||||
value: DecodeDifferent::Encode("T::BlockNumber"),
|
||||
key2_hasher: StorageHasher::Twox64Concat,
|
||||
},
|
||||
StorageEntryMetadata {
|
||||
name: DecodeDifferent::Encode("AppendableDM"),
|
||||
modifier: StorageEntryModifier::Default,
|
||||
ty: StorageEntryType::DoubleMap{
|
||||
hasher: StorageHasher::Blake2_128Concat,
|
||||
key1: DecodeDifferent::Encode("u32"),
|
||||
key2: DecodeDifferent::Encode("T::BlockNumber"),
|
||||
value: DecodeDifferent::Encode("Vec<u32>"),
|
||||
key2_hasher: StorageHasher::Blake2_128Concat,
|
||||
},
|
||||
default: DecodeDifferent::Encode(
|
||||
DefaultByteGetter(&__GetByteStructGenericData2DM(PhantomData::<Test>))
|
||||
),
|
||||
documentation: DecodeDifferent::Encode(&[]),
|
||||
default: DecodeDifferent::Encode(DefaultByteGetter(
|
||||
&__GetByteStructGenericData2DM(PhantomData::<Test>),
|
||||
)),
|
||||
documentation: DecodeDifferent::Encode(&[]),
|
||||
},
|
||||
StorageEntryMetadata {
|
||||
name: DecodeDifferent::Encode("AppendableDM"),
|
||||
modifier: StorageEntryModifier::Default,
|
||||
ty: StorageEntryType::DoubleMap {
|
||||
hasher: StorageHasher::Blake2_128Concat,
|
||||
key1: DecodeDifferent::Encode("u32"),
|
||||
key2: DecodeDifferent::Encode("T::BlockNumber"),
|
||||
value: DecodeDifferent::Encode("Vec<u32>"),
|
||||
key2_hasher: StorageHasher::Blake2_128Concat,
|
||||
},
|
||||
]
|
||||
),
|
||||
default: DecodeDifferent::Encode(DefaultByteGetter(
|
||||
&__GetByteStructGenericData2DM(PhantomData::<Test>),
|
||||
)),
|
||||
documentation: DecodeDifferent::Encode(&[]),
|
||||
},
|
||||
]),
|
||||
};
|
||||
|
||||
#[test]
|
||||
@@ -1269,35 +1286,38 @@ pub mod tests {
|
||||
|
||||
/// Prelude to be used alongside pallet macro, for ease of use.
|
||||
pub mod pallet_prelude {
|
||||
pub use sp_std::marker::PhantomData;
|
||||
#[cfg(feature = "std")]
|
||||
pub use crate::traits::GenesisBuild;
|
||||
pub use crate::{
|
||||
EqNoBound, PartialEqNoBound, RuntimeDebugNoBound, DebugNoBound, CloneNoBound, Twox256,
|
||||
Twox128, Blake2_256, Blake2_128, Identity, Twox64Concat, Blake2_128Concat, ensure,
|
||||
RuntimeDebug, storage,
|
||||
dispatch::{DispatchError, DispatchResult, DispatchResultWithPostInfo, Parameter},
|
||||
ensure,
|
||||
inherent::{InherentData, InherentIdentifier, ProvideInherent},
|
||||
storage,
|
||||
storage::{
|
||||
bounded_vec::BoundedVec,
|
||||
types::{
|
||||
Key as NMapKey, OptionQuery, StorageDoubleMap, StorageMap, StorageNMap,
|
||||
StorageValue, ValueQuery,
|
||||
},
|
||||
},
|
||||
traits::{
|
||||
Get, Hooks, IsType, GetPalletVersion, EnsureOrigin, PalletInfoAccess, StorageInfoTrait,
|
||||
ConstU32, GetDefault,
|
||||
ConstU32, EnsureOrigin, Get, GetDefault, GetPalletVersion, Hooks, IsType,
|
||||
PalletInfoAccess, StorageInfoTrait,
|
||||
},
|
||||
dispatch::{DispatchResultWithPostInfo, Parameter, DispatchError, DispatchResult},
|
||||
weights::{DispatchClass, Pays, Weight},
|
||||
storage::types::{
|
||||
Key as NMapKey, StorageDoubleMap, StorageMap, StorageNMap, StorageValue, ValueQuery,
|
||||
OptionQuery,
|
||||
},
|
||||
storage::bounded_vec::BoundedVec,
|
||||
Blake2_128, Blake2_128Concat, Blake2_256, CloneNoBound, DebugNoBound, EqNoBound, Identity,
|
||||
PartialEqNoBound, RuntimeDebug, RuntimeDebugNoBound, Twox128, Twox256, Twox64Concat,
|
||||
};
|
||||
pub use codec::{Encode, Decode, MaxEncodedLen};
|
||||
pub use crate::inherent::{InherentData, InherentIdentifier, ProvideInherent};
|
||||
pub use codec::{Decode, Encode, MaxEncodedLen};
|
||||
pub use sp_runtime::{
|
||||
traits::{MaybeSerializeDeserialize, Member, ValidateUnsigned},
|
||||
transaction_validity::{
|
||||
TransactionSource, TransactionValidity, ValidTransaction, TransactionPriority,
|
||||
TransactionTag, TransactionLongevity, TransactionValidityError, InvalidTransaction,
|
||||
UnknownTransaction,
|
||||
InvalidTransaction, TransactionLongevity, TransactionPriority, TransactionSource,
|
||||
TransactionTag, TransactionValidity, TransactionValidityError, UnknownTransaction,
|
||||
ValidTransaction,
|
||||
},
|
||||
};
|
||||
pub use sp_std::marker::PhantomData;
|
||||
}
|
||||
|
||||
/// `pallet` attribute macro allows to define a pallet to be used in `construct_runtime!`.
|
||||
@@ -1321,9 +1341,9 @@ pub mod pallet_prelude {
|
||||
/// ```ignore
|
||||
/// #[pallet]
|
||||
/// pub mod pallet {
|
||||
/// use frame_support::pallet_prelude::*;
|
||||
/// use frame_system::pallet_prelude::*;
|
||||
/// ...
|
||||
/// use frame_support::pallet_prelude::*;
|
||||
/// use frame_system::pallet_prelude::*;
|
||||
/// ...
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
@@ -1350,8 +1370,8 @@ pub mod pallet_prelude {
|
||||
/// ```ignore
|
||||
/// #[pallet::config]
|
||||
/// pub trait Config: frame_system::Config {
|
||||
/// #[pallet::constant]
|
||||
/// type Foo: Get<u32>;
|
||||
/// #[pallet::constant]
|
||||
/// type Foo: Get<u32>;
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
@@ -2378,5 +2398,4 @@ pub mod pallet_prelude {
|
||||
/// }
|
||||
/// ```
|
||||
/// * use the newest nightly possible.
|
||||
///
|
||||
pub use frame_support_procedural::pallet;
|
||||
|
||||
@@ -17,15 +17,12 @@
|
||||
|
||||
//! Traits, types and structs to support a bounded BTreeMap.
|
||||
|
||||
use crate::{storage::StorageDecodeLength, traits::Get};
|
||||
use codec::{Decode, Encode, MaxEncodedLen};
|
||||
use sp_std::{
|
||||
borrow::Borrow, collections::btree_map::BTreeMap, convert::TryFrom, fmt, marker::PhantomData,
|
||||
ops::Deref,
|
||||
};
|
||||
use crate::{
|
||||
storage::StorageDecodeLength,
|
||||
traits::Get,
|
||||
};
|
||||
use codec::{Encode, Decode, MaxEncodedLen};
|
||||
|
||||
/// A bounded map based on a B-Tree.
|
||||
///
|
||||
@@ -46,7 +43,7 @@ where
|
||||
fn decode<I: codec::Input>(input: &mut I) -> Result<Self, codec::Error> {
|
||||
let inner = BTreeMap::<K, V>::decode(input)?;
|
||||
if inner.len() > S::get() as usize {
|
||||
return Err("BoundedBTreeMap exceeds its limit".into());
|
||||
return Err("BoundedBTreeMap exceeds its limit".into())
|
||||
}
|
||||
Ok(Self(inner, PhantomData))
|
||||
}
|
||||
@@ -280,7 +277,9 @@ where
|
||||
type Error = ();
|
||||
|
||||
fn try_from(value: BTreeMap<K, V>) -> Result<Self, Self::Error> {
|
||||
(value.len() <= Self::bound()).then(move || BoundedBTreeMap(value, PhantomData)).ok_or(())
|
||||
(value.len() <= Self::bound())
|
||||
.then(move || BoundedBTreeMap(value, PhantomData))
|
||||
.ok_or(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -303,9 +302,9 @@ impl<K, V, S> codec::EncodeLike<BTreeMap<K, V>> for BoundedBTreeMap<K, V, S> whe
|
||||
#[cfg(test)]
|
||||
pub mod test {
|
||||
use super::*;
|
||||
use crate::Twox128;
|
||||
use sp_io::TestExternalities;
|
||||
use sp_std::convert::TryInto;
|
||||
use crate::Twox128;
|
||||
|
||||
crate::parameter_types! {
|
||||
pub const Seven: u32 = 7;
|
||||
|
||||
@@ -17,15 +17,12 @@
|
||||
|
||||
//! Traits, types and structs to support a bounded `BTreeSet`.
|
||||
|
||||
use crate::{storage::StorageDecodeLength, traits::Get};
|
||||
use codec::{Decode, Encode, MaxEncodedLen};
|
||||
use sp_std::{
|
||||
borrow::Borrow, collections::btree_set::BTreeSet, convert::TryFrom, fmt, marker::PhantomData,
|
||||
ops::Deref,
|
||||
};
|
||||
use crate::{
|
||||
storage::StorageDecodeLength,
|
||||
traits::Get,
|
||||
};
|
||||
use codec::{Encode, Decode, MaxEncodedLen};
|
||||
|
||||
/// A bounded set based on a B-Tree.
|
||||
///
|
||||
@@ -45,7 +42,7 @@ where
|
||||
fn decode<I: codec::Input>(input: &mut I) -> Result<Self, codec::Error> {
|
||||
let inner = BTreeSet::<T>::decode(input)?;
|
||||
if inner.len() > S::get() as usize {
|
||||
return Err("BoundedBTreeSet exceeds its limit".into());
|
||||
return Err("BoundedBTreeSet exceeds its limit".into())
|
||||
}
|
||||
Ok(Self(inner, PhantomData))
|
||||
}
|
||||
@@ -266,7 +263,9 @@ where
|
||||
type Error = ();
|
||||
|
||||
fn try_from(value: BTreeSet<T>) -> Result<Self, Self::Error> {
|
||||
(value.len() <= Self::bound()).then(move || BoundedBTreeSet(value, PhantomData)).ok_or(())
|
||||
(value.len() <= Self::bound())
|
||||
.then(move || BoundedBTreeSet(value, PhantomData))
|
||||
.ok_or(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -281,16 +280,14 @@ impl<T, S> codec::DecodeLength for BoundedBTreeSet<T, S> {
|
||||
|
||||
impl<T, S> StorageDecodeLength for BoundedBTreeSet<T, S> {}
|
||||
|
||||
impl<T, S> codec::EncodeLike<BTreeSet<T>> for BoundedBTreeSet<T, S> where
|
||||
BTreeSet<T>: Encode
|
||||
{}
|
||||
impl<T, S> codec::EncodeLike<BTreeSet<T>> for BoundedBTreeSet<T, S> where BTreeSet<T>: Encode {}
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod test {
|
||||
use super::*;
|
||||
use crate::Twox128;
|
||||
use sp_io::TestExternalities;
|
||||
use sp_std::convert::TryInto;
|
||||
use crate::Twox128;
|
||||
|
||||
crate::parameter_types! {
|
||||
pub const Seven: u32 = 7;
|
||||
|
||||
@@ -18,17 +18,16 @@
|
||||
//! Traits, types and structs to support putting a bounded vector into storage, as a raw value, map
|
||||
//! or a double map.
|
||||
|
||||
use sp_std::prelude::*;
|
||||
use sp_std::{convert::TryFrom, fmt, marker::PhantomData};
|
||||
use codec::{Encode, Decode, EncodeLike, MaxEncodedLen};
|
||||
use crate::{
|
||||
storage::{StorageDecodeLength, StorageTryAppend},
|
||||
traits::Get,
|
||||
};
|
||||
use codec::{Decode, Encode, EncodeLike, MaxEncodedLen};
|
||||
use core::{
|
||||
ops::{Deref, Index, IndexMut},
|
||||
slice::SliceIndex,
|
||||
};
|
||||
use crate::{
|
||||
traits::Get,
|
||||
storage::{StorageDecodeLength, StorageTryAppend},
|
||||
};
|
||||
use sp_std::{convert::TryFrom, fmt, marker::PhantomData, prelude::*};
|
||||
|
||||
/// A bounded vector.
|
||||
///
|
||||
@@ -71,7 +70,7 @@ impl<T: Decode, S: Get<u32>> Decode for BoundedVec<T, S> {
|
||||
fn decode<I: codec::Input>(input: &mut I) -> Result<Self, codec::Error> {
|
||||
let inner = Vec::<T>::decode(input)?;
|
||||
if inner.len() > S::get() as usize {
|
||||
return Err("BoundedVec exceeds its limit".into());
|
||||
return Err("BoundedVec exceeds its limit".into())
|
||||
}
|
||||
Ok(Self(inner, PhantomData))
|
||||
}
|
||||
@@ -341,9 +340,9 @@ where
|
||||
#[cfg(test)]
|
||||
pub mod test {
|
||||
use super::*;
|
||||
use crate::Twox128;
|
||||
use sp_io::TestExternalities;
|
||||
use sp_std::convert::TryInto;
|
||||
use crate::Twox128;
|
||||
|
||||
crate::parameter_types! {
|
||||
pub const Seven: u32 = 7;
|
||||
|
||||
@@ -21,23 +21,17 @@
|
||||
// NOTE: could replace unhashed by having only one kind of storage (top trie being the child info
|
||||
// of null length parent storage key).
|
||||
|
||||
use crate::sp_std::prelude::*;
|
||||
use codec::{Codec, Encode, Decode};
|
||||
pub use sp_core::storage::{ChildInfo, ChildType};
|
||||
pub use crate::sp_io::KillStorageResult;
|
||||
use crate::sp_std::prelude::*;
|
||||
use codec::{Codec, Decode, Encode};
|
||||
pub use sp_core::storage::{ChildInfo, ChildType};
|
||||
|
||||
/// Return the value of the item in storage under `key`, or `None` if there is no explicit entry.
|
||||
pub fn get<T: Decode + Sized>(
|
||||
child_info: &ChildInfo,
|
||||
key: &[u8],
|
||||
) -> Option<T> {
|
||||
pub fn get<T: Decode + Sized>(child_info: &ChildInfo, key: &[u8]) -> Option<T> {
|
||||
match child_info.child_type() {
|
||||
ChildType::ParentKeyId => {
|
||||
let storage_key = child_info.storage_key();
|
||||
sp_io::default_child_storage::get(
|
||||
storage_key,
|
||||
key,
|
||||
).and_then(|v| {
|
||||
sp_io::default_child_storage::get(storage_key, key).and_then(|v| {
|
||||
Decode::decode(&mut &v[..]).map(Some).unwrap_or_else(|_| {
|
||||
// TODO #3700: error should be handleable.
|
||||
crate::runtime_print!(
|
||||
@@ -54,20 +48,13 @@ pub fn get<T: Decode + Sized>(
|
||||
|
||||
/// Return the value of the item in storage under `key`, or the type's default if there is no
|
||||
/// explicit entry.
|
||||
pub fn get_or_default<T: Decode + Sized + Default>(
|
||||
child_info: &ChildInfo,
|
||||
key: &[u8],
|
||||
) -> T {
|
||||
pub fn get_or_default<T: Decode + Sized + Default>(child_info: &ChildInfo, key: &[u8]) -> T {
|
||||
get(child_info, key).unwrap_or_else(Default::default)
|
||||
}
|
||||
|
||||
/// Return the value of the item in storage under `key`, or `default_value` if there is no
|
||||
/// explicit entry.
|
||||
pub fn get_or<T: Decode + Sized>(
|
||||
child_info: &ChildInfo,
|
||||
key: &[u8],
|
||||
default_value: T,
|
||||
) -> T {
|
||||
pub fn get_or<T: Decode + Sized>(child_info: &ChildInfo, key: &[u8], default_value: T) -> T {
|
||||
get(child_info, key).unwrap_or(default_value)
|
||||
}
|
||||
|
||||
@@ -82,27 +69,16 @@ pub fn get_or_else<T: Decode + Sized, F: FnOnce() -> T>(
|
||||
}
|
||||
|
||||
/// Put `value` in storage under `key`.
|
||||
pub fn put<T: Encode>(
|
||||
child_info: &ChildInfo,
|
||||
key: &[u8],
|
||||
value: &T,
|
||||
) {
|
||||
pub fn put<T: Encode>(child_info: &ChildInfo, key: &[u8], value: &T) {
|
||||
match child_info.child_type() {
|
||||
ChildType::ParentKeyId => value.using_encoded(|slice|
|
||||
sp_io::default_child_storage::set(
|
||||
child_info.storage_key(),
|
||||
key,
|
||||
slice,
|
||||
)
|
||||
),
|
||||
ChildType::ParentKeyId => value.using_encoded(|slice| {
|
||||
sp_io::default_child_storage::set(child_info.storage_key(), key, slice)
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
/// Remove `key` from storage, returning its value if it had an explicit entry or `None` otherwise.
|
||||
pub fn take<T: Decode + Sized>(
|
||||
child_info: &ChildInfo,
|
||||
key: &[u8],
|
||||
) -> Option<T> {
|
||||
pub fn take<T: Decode + Sized>(child_info: &ChildInfo, key: &[u8]) -> Option<T> {
|
||||
let r = get(child_info, key);
|
||||
if r.is_some() {
|
||||
kill(child_info, key);
|
||||
@@ -112,20 +88,13 @@ pub fn take<T: Decode + Sized>(
|
||||
|
||||
/// Remove `key` from storage, returning its value, or, if there was no explicit entry in storage,
|
||||
/// the default for its type.
|
||||
pub fn take_or_default<T: Codec + Sized + Default>(
|
||||
child_info: &ChildInfo,
|
||||
key: &[u8],
|
||||
) -> T {
|
||||
pub fn take_or_default<T: Codec + Sized + Default>(child_info: &ChildInfo, key: &[u8]) -> T {
|
||||
take(child_info, key).unwrap_or_else(Default::default)
|
||||
}
|
||||
|
||||
/// Return the value of the item in storage under `key`, or `default_value` if there is no
|
||||
/// explicit entry. Ensure there is no explicit entry on return.
|
||||
pub fn take_or<T: Codec + Sized>(
|
||||
child_info: &ChildInfo,
|
||||
key: &[u8],
|
||||
default_value: T,
|
||||
) -> T {
|
||||
pub fn take_or<T: Codec + Sized>(child_info: &ChildInfo, key: &[u8], default_value: T) -> T {
|
||||
take(child_info, key).unwrap_or(default_value)
|
||||
}
|
||||
|
||||
@@ -140,15 +109,11 @@ pub fn take_or_else<T: Codec + Sized, F: FnOnce() -> T>(
|
||||
}
|
||||
|
||||
/// Check to see if `key` has an explicit entry in storage.
|
||||
pub fn exists(
|
||||
child_info: &ChildInfo,
|
||||
key: &[u8],
|
||||
) -> bool {
|
||||
pub fn exists(child_info: &ChildInfo, key: &[u8]) -> bool {
|
||||
match child_info.child_type() {
|
||||
ChildType::ParentKeyId => sp_io::default_child_storage::read(
|
||||
child_info.storage_key(),
|
||||
key, &mut [0;0][..], 0,
|
||||
).is_some(),
|
||||
ChildType::ParentKeyId =>
|
||||
sp_io::default_child_storage::read(child_info.storage_key(), key, &mut [0; 0][..], 0)
|
||||
.is_some(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -171,86 +136,50 @@ pub fn exists(
|
||||
/// not make much sense because it is not cumulative when called inside the same block.
|
||||
/// Use this function to distribute the deletion of a single child trie across multiple
|
||||
/// blocks.
|
||||
pub fn kill_storage(
|
||||
child_info: &ChildInfo,
|
||||
limit: Option<u32>,
|
||||
) -> KillStorageResult {
|
||||
pub fn kill_storage(child_info: &ChildInfo, limit: Option<u32>) -> KillStorageResult {
|
||||
match child_info.child_type() {
|
||||
ChildType::ParentKeyId => sp_io::default_child_storage::storage_kill(
|
||||
child_info.storage_key(),
|
||||
limit
|
||||
),
|
||||
ChildType::ParentKeyId =>
|
||||
sp_io::default_child_storage::storage_kill(child_info.storage_key(), limit),
|
||||
}
|
||||
}
|
||||
|
||||
/// Ensure `key` has no explicit entry in storage.
|
||||
pub fn kill(
|
||||
child_info: &ChildInfo,
|
||||
key: &[u8],
|
||||
) {
|
||||
pub fn kill(child_info: &ChildInfo, key: &[u8]) {
|
||||
match child_info.child_type() {
|
||||
ChildType::ParentKeyId => {
|
||||
sp_io::default_child_storage::clear(
|
||||
child_info.storage_key(),
|
||||
key,
|
||||
);
|
||||
sp_io::default_child_storage::clear(child_info.storage_key(), key);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// Get a Vec of bytes from storage.
|
||||
pub fn get_raw(
|
||||
child_info: &ChildInfo,
|
||||
key: &[u8],
|
||||
) -> Option<Vec<u8>> {
|
||||
pub fn get_raw(child_info: &ChildInfo, key: &[u8]) -> Option<Vec<u8>> {
|
||||
match child_info.child_type() {
|
||||
ChildType::ParentKeyId => sp_io::default_child_storage::get(
|
||||
child_info.storage_key(),
|
||||
key,
|
||||
),
|
||||
ChildType::ParentKeyId => sp_io::default_child_storage::get(child_info.storage_key(), key),
|
||||
}
|
||||
}
|
||||
|
||||
/// Put a raw byte slice into storage.
|
||||
pub fn put_raw(
|
||||
child_info: &ChildInfo,
|
||||
key: &[u8],
|
||||
value: &[u8],
|
||||
) {
|
||||
pub fn put_raw(child_info: &ChildInfo, key: &[u8], value: &[u8]) {
|
||||
match child_info.child_type() {
|
||||
ChildType::ParentKeyId => sp_io::default_child_storage::set(
|
||||
child_info.storage_key(),
|
||||
key,
|
||||
value,
|
||||
),
|
||||
ChildType::ParentKeyId =>
|
||||
sp_io::default_child_storage::set(child_info.storage_key(), key, value),
|
||||
}
|
||||
}
|
||||
|
||||
/// Calculate current child root value.
|
||||
pub fn root(
|
||||
child_info: &ChildInfo,
|
||||
) -> Vec<u8> {
|
||||
pub fn root(child_info: &ChildInfo) -> Vec<u8> {
|
||||
match child_info.child_type() {
|
||||
ChildType::ParentKeyId => sp_io::default_child_storage::root(
|
||||
child_info.storage_key(),
|
||||
),
|
||||
ChildType::ParentKeyId => sp_io::default_child_storage::root(child_info.storage_key()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the length in bytes of the value without reading it. `None` if it does not exist.
|
||||
pub fn len(
|
||||
child_info: &ChildInfo,
|
||||
key: &[u8],
|
||||
) -> Option<u32> {
|
||||
pub fn len(child_info: &ChildInfo, key: &[u8]) -> Option<u32> {
|
||||
match child_info.child_type() {
|
||||
ChildType::ParentKeyId => {
|
||||
let mut buffer = [0; 0];
|
||||
sp_io::default_child_storage::read(
|
||||
child_info.storage_key(),
|
||||
key,
|
||||
&mut buffer,
|
||||
0,
|
||||
)
|
||||
}
|
||||
sp_io::default_child_storage::read(child_info.storage_key(), key, &mut buffer, 0)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,11 +15,13 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use sp_std::prelude::*;
|
||||
use sp_std::borrow::Borrow;
|
||||
use codec::{FullCodec, FullEncode, Decode, Encode, EncodeLike};
|
||||
use crate::{storage::{self, unhashed, KeyPrefixIterator, StorageAppend, PrefixIterator}, Never};
|
||||
use crate::hash::{StorageHasher, Twox128, ReversibleStorageHasher};
|
||||
use crate::{
|
||||
hash::{ReversibleStorageHasher, StorageHasher, Twox128},
|
||||
storage::{self, unhashed, KeyPrefixIterator, PrefixIterator, StorageAppend},
|
||||
Never,
|
||||
};
|
||||
use codec::{Decode, Encode, EncodeLike, FullCodec, FullEncode};
|
||||
use sp_std::{borrow::Borrow, prelude::*};
|
||||
|
||||
/// Generator for `StorageDoubleMap` used by `decl_storage`.
|
||||
///
|
||||
@@ -63,9 +65,8 @@ pub trait StorageDoubleMap<K1: FullEncode, K2: FullEncode, V: FullCodec> {
|
||||
let module_prefix_hashed = Twox128::hash(Self::module_prefix());
|
||||
let storage_prefix_hashed = Twox128::hash(Self::storage_prefix());
|
||||
|
||||
let mut result = Vec::with_capacity(
|
||||
module_prefix_hashed.len() + storage_prefix_hashed.len()
|
||||
);
|
||||
let mut result =
|
||||
Vec::with_capacity(module_prefix_hashed.len() + storage_prefix_hashed.len());
|
||||
|
||||
result.extend_from_slice(&module_prefix_hashed[..]);
|
||||
result.extend_from_slice(&storage_prefix_hashed[..]);
|
||||
@@ -80,7 +81,8 @@ pub trait StorageDoubleMap<K1: FullEncode, K2: FullEncode, V: FullCodec> {
|
||||
fn from_query_to_optional_value(v: Self::Query) -> Option<V>;
|
||||
|
||||
/// Generate the first part of the key used in top storage.
|
||||
fn storage_double_map_final_key1<KArg1>(k1: KArg1) -> Vec<u8> where
|
||||
fn storage_double_map_final_key1<KArg1>(k1: KArg1) -> Vec<u8>
|
||||
where
|
||||
KArg1: EncodeLike<K1>,
|
||||
{
|
||||
let module_prefix_hashed = Twox128::hash(Self::module_prefix());
|
||||
@@ -88,7 +90,7 @@ pub trait StorageDoubleMap<K1: FullEncode, K2: FullEncode, V: FullCodec> {
|
||||
let key_hashed = k1.borrow().using_encoded(Self::Hasher1::hash);
|
||||
|
||||
let mut final_key = Vec::with_capacity(
|
||||
module_prefix_hashed.len() + storage_prefix_hashed.len() + key_hashed.as_ref().len()
|
||||
module_prefix_hashed.len() + storage_prefix_hashed.len() + key_hashed.as_ref().len(),
|
||||
);
|
||||
|
||||
final_key.extend_from_slice(&module_prefix_hashed[..]);
|
||||
@@ -99,7 +101,8 @@ pub trait StorageDoubleMap<K1: FullEncode, K2: FullEncode, V: FullCodec> {
|
||||
}
|
||||
|
||||
/// Generate the full key used in top storage.
|
||||
fn storage_double_map_final_key<KArg1, KArg2>(k1: KArg1, k2: KArg2) -> Vec<u8> where
|
||||
fn storage_double_map_final_key<KArg1, KArg2>(k1: KArg1, k2: KArg2) -> Vec<u8>
|
||||
where
|
||||
KArg1: EncodeLike<K1>,
|
||||
KArg2: EncodeLike<K2>,
|
||||
{
|
||||
@@ -109,10 +112,10 @@ pub trait StorageDoubleMap<K1: FullEncode, K2: FullEncode, V: FullCodec> {
|
||||
let key2_hashed = k2.borrow().using_encoded(Self::Hasher2::hash);
|
||||
|
||||
let mut final_key = Vec::with_capacity(
|
||||
module_prefix_hashed.len()
|
||||
+ storage_prefix_hashed.len()
|
||||
+ key1_hashed.as_ref().len()
|
||||
+ key2_hashed.as_ref().len()
|
||||
module_prefix_hashed.len() +
|
||||
storage_prefix_hashed.len() +
|
||||
key1_hashed.as_ref().len() +
|
||||
key2_hashed.as_ref().len(),
|
||||
);
|
||||
|
||||
final_key.extend_from_slice(&module_prefix_hashed[..]);
|
||||
@@ -124,7 +127,8 @@ pub trait StorageDoubleMap<K1: FullEncode, K2: FullEncode, V: FullCodec> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<K1, K2, V, G> storage::StorageDoubleMap<K1, K2, V> for G where
|
||||
impl<K1, K2, V, G> storage::StorageDoubleMap<K1, K2, V> for G
|
||||
where
|
||||
K1: FullEncode,
|
||||
K2: FullEncode,
|
||||
V: FullCodec,
|
||||
@@ -132,21 +136,24 @@ impl<K1, K2, V, G> storage::StorageDoubleMap<K1, K2, V> for G where
|
||||
{
|
||||
type Query = G::Query;
|
||||
|
||||
fn hashed_key_for<KArg1, KArg2>(k1: KArg1, k2: KArg2) -> Vec<u8> where
|
||||
fn hashed_key_for<KArg1, KArg2>(k1: KArg1, k2: KArg2) -> Vec<u8>
|
||||
where
|
||||
KArg1: EncodeLike<K1>,
|
||||
KArg2: EncodeLike<K2>,
|
||||
{
|
||||
Self::storage_double_map_final_key(k1, k2)
|
||||
}
|
||||
|
||||
fn contains_key<KArg1, KArg2>(k1: KArg1, k2: KArg2) -> bool where
|
||||
fn contains_key<KArg1, KArg2>(k1: KArg1, k2: KArg2) -> bool
|
||||
where
|
||||
KArg1: EncodeLike<K1>,
|
||||
KArg2: EncodeLike<K2>,
|
||||
{
|
||||
unhashed::exists(&Self::storage_double_map_final_key(k1, k2))
|
||||
}
|
||||
|
||||
fn get<KArg1, KArg2>(k1: KArg1, k2: KArg2) -> Self::Query where
|
||||
fn get<KArg1, KArg2>(k1: KArg1, k2: KArg2) -> Self::Query
|
||||
where
|
||||
KArg1: EncodeLike<K1>,
|
||||
KArg2: EncodeLike<K2>,
|
||||
{
|
||||
@@ -156,11 +163,13 @@ impl<K1, K2, V, G> storage::StorageDoubleMap<K1, K2, V> for G where
|
||||
fn try_get<KArg1, KArg2>(k1: KArg1, k2: KArg2) -> Result<V, ()>
|
||||
where
|
||||
KArg1: EncodeLike<K1>,
|
||||
KArg2: EncodeLike<K2> {
|
||||
KArg2: EncodeLike<K2>,
|
||||
{
|
||||
unhashed::get(&Self::storage_double_map_final_key(k1, k2)).ok_or(())
|
||||
}
|
||||
|
||||
fn take<KArg1, KArg2>(k1: KArg1, k2: KArg2) -> Self::Query where
|
||||
fn take<KArg1, KArg2>(k1: KArg1, k2: KArg2) -> Self::Query
|
||||
where
|
||||
KArg1: EncodeLike<K1>,
|
||||
KArg2: EncodeLike<K2>,
|
||||
{
|
||||
@@ -170,16 +179,12 @@ impl<K1, K2, V, G> storage::StorageDoubleMap<K1, K2, V> for G where
|
||||
G::from_optional_value_to_query(value)
|
||||
}
|
||||
|
||||
fn swap<XKArg1, XKArg2, YKArg1, YKArg2>(
|
||||
x_k1: XKArg1,
|
||||
x_k2: XKArg2,
|
||||
y_k1: YKArg1,
|
||||
y_k2: YKArg2
|
||||
) where
|
||||
fn swap<XKArg1, XKArg2, YKArg1, YKArg2>(x_k1: XKArg1, x_k2: XKArg2, y_k1: YKArg1, y_k2: YKArg2)
|
||||
where
|
||||
XKArg1: EncodeLike<K1>,
|
||||
XKArg2: EncodeLike<K2>,
|
||||
YKArg1: EncodeLike<K1>,
|
||||
YKArg2: EncodeLike<K2>
|
||||
YKArg2: EncodeLike<K2>,
|
||||
{
|
||||
let final_x_key = Self::storage_double_map_final_key(x_k1, x_k2);
|
||||
let final_y_key = Self::storage_double_map_final_key(y_k1, y_k2);
|
||||
@@ -197,7 +202,8 @@ impl<K1, K2, V, G> storage::StorageDoubleMap<K1, K2, V> for G where
|
||||
}
|
||||
}
|
||||
|
||||
fn insert<KArg1, KArg2, VArg>(k1: KArg1, k2: KArg2, val: VArg) where
|
||||
fn insert<KArg1, KArg2, VArg>(k1: KArg1, k2: KArg2, val: VArg)
|
||||
where
|
||||
KArg1: EncodeLike<K1>,
|
||||
KArg2: EncodeLike<K2>,
|
||||
VArg: EncodeLike<V>,
|
||||
@@ -205,7 +211,8 @@ impl<K1, K2, V, G> storage::StorageDoubleMap<K1, K2, V> for G where
|
||||
unhashed::put(&Self::storage_double_map_final_key(k1, k2), &val.borrow())
|
||||
}
|
||||
|
||||
fn remove<KArg1, KArg2>(k1: KArg1, k2: KArg2) where
|
||||
fn remove<KArg1, KArg2>(k1: KArg1, k2: KArg2)
|
||||
where
|
||||
KArg1: EncodeLike<K1>,
|
||||
KArg2: EncodeLike<K2>,
|
||||
{
|
||||
@@ -213,12 +220,15 @@ impl<K1, K2, V, G> storage::StorageDoubleMap<K1, K2, V> for G where
|
||||
}
|
||||
|
||||
fn remove_prefix<KArg1>(k1: KArg1, limit: Option<u32>) -> sp_io::KillStorageResult
|
||||
where KArg1: EncodeLike<K1> {
|
||||
where
|
||||
KArg1: EncodeLike<K1>,
|
||||
{
|
||||
unhashed::kill_prefix(Self::storage_double_map_final_key1(k1).as_ref(), limit)
|
||||
}
|
||||
|
||||
fn iter_prefix_values<KArg1>(k1: KArg1) -> storage::PrefixIterator<V> where
|
||||
KArg1: ?Sized + EncodeLike<K1>
|
||||
fn iter_prefix_values<KArg1>(k1: KArg1) -> storage::PrefixIterator<V>
|
||||
where
|
||||
KArg1: ?Sized + EncodeLike<K1>,
|
||||
{
|
||||
let prefix = Self::storage_double_map_final_key1(k1);
|
||||
storage::PrefixIterator {
|
||||
@@ -229,12 +239,14 @@ impl<K1, K2, V, G> storage::StorageDoubleMap<K1, K2, V> for G where
|
||||
}
|
||||
}
|
||||
|
||||
fn mutate<KArg1, KArg2, R, F>(k1: KArg1, k2: KArg2, f: F) -> R where
|
||||
fn mutate<KArg1, KArg2, R, F>(k1: KArg1, k2: KArg2, f: F) -> R
|
||||
where
|
||||
KArg1: EncodeLike<K1>,
|
||||
KArg2: EncodeLike<K2>,
|
||||
F: FnOnce(&mut Self::Query) -> R,
|
||||
{
|
||||
Self::try_mutate(k1, k2, |v| Ok::<R, Never>(f(v))).expect("`Never` can not be constructed; qed")
|
||||
Self::try_mutate(k1, k2, |v| Ok::<R, Never>(f(v)))
|
||||
.expect("`Never` can not be constructed; qed")
|
||||
}
|
||||
|
||||
fn mutate_exists<KArg1, KArg2, R, F>(k1: KArg1, k2: KArg2, f: F) -> R
|
||||
@@ -243,10 +255,12 @@ impl<K1, K2, V, G> storage::StorageDoubleMap<K1, K2, V> for G where
|
||||
KArg2: EncodeLike<K2>,
|
||||
F: FnOnce(&mut Option<V>) -> R,
|
||||
{
|
||||
Self::try_mutate_exists(k1, k2, |v| Ok::<R, Never>(f(v))).expect("`Never` can not be constructed; qed")
|
||||
Self::try_mutate_exists(k1, k2, |v| Ok::<R, Never>(f(v)))
|
||||
.expect("`Never` can not be constructed; qed")
|
||||
}
|
||||
|
||||
fn try_mutate<KArg1, KArg2, R, E, F>(k1: KArg1, k2: KArg2, f: F) -> Result<R, E> where
|
||||
fn try_mutate<KArg1, KArg2, R, E, F>(k1: KArg1, k2: KArg2, f: F) -> Result<R, E>
|
||||
where
|
||||
KArg1: EncodeLike<K1>,
|
||||
KArg2: EncodeLike<K2>,
|
||||
F: FnOnce(&mut Self::Query) -> Result<R, E>,
|
||||
@@ -283,11 +297,8 @@ impl<K1, K2, V, G> storage::StorageDoubleMap<K1, K2, V> for G where
|
||||
ret
|
||||
}
|
||||
|
||||
fn append<Item, EncodeLikeItem, KArg1, KArg2>(
|
||||
k1: KArg1,
|
||||
k2: KArg2,
|
||||
item: EncodeLikeItem,
|
||||
) where
|
||||
fn append<Item, EncodeLikeItem, KArg1, KArg2>(k1: KArg1, k2: KArg2, item: EncodeLikeItem)
|
||||
where
|
||||
KArg1: EncodeLike<K1>,
|
||||
KArg2: EncodeLike<K2>,
|
||||
Item: Encode,
|
||||
@@ -303,7 +314,10 @@ impl<K1, K2, V, G> storage::StorageDoubleMap<K1, K2, V> for G where
|
||||
OldHasher2: StorageHasher,
|
||||
KeyArg1: EncodeLike<K1>,
|
||||
KeyArg2: EncodeLike<K2>,
|
||||
>(key1: KeyArg1, key2: KeyArg2) -> Option<V> {
|
||||
>(
|
||||
key1: KeyArg1,
|
||||
key2: KeyArg2,
|
||||
) -> Option<V> {
|
||||
let old_key = {
|
||||
let module_prefix_hashed = Twox128::hash(Self::module_prefix());
|
||||
let storage_prefix_hashed = Twox128::hash(Self::storage_prefix());
|
||||
@@ -311,10 +325,10 @@ impl<K1, K2, V, G> storage::StorageDoubleMap<K1, K2, V> for G where
|
||||
let key2_hashed = key2.borrow().using_encoded(OldHasher2::hash);
|
||||
|
||||
let mut final_key = Vec::with_capacity(
|
||||
module_prefix_hashed.len()
|
||||
+ storage_prefix_hashed.len()
|
||||
+ key1_hashed.as_ref().len()
|
||||
+ key2_hashed.as_ref().len()
|
||||
module_prefix_hashed.len() +
|
||||
storage_prefix_hashed.len() +
|
||||
key1_hashed.as_ref().len() +
|
||||
key2_hashed.as_ref().len(),
|
||||
);
|
||||
|
||||
final_key.extend_from_slice(&module_prefix_hashed[..]);
|
||||
@@ -331,14 +345,11 @@ impl<K1, K2, V, G> storage::StorageDoubleMap<K1, K2, V> for G where
|
||||
}
|
||||
}
|
||||
|
||||
impl<
|
||||
K1: FullCodec,
|
||||
K2: FullCodec,
|
||||
V: FullCodec,
|
||||
G: StorageDoubleMap<K1, K2, V>,
|
||||
> storage::IterableStorageDoubleMap<K1, K2, V> for G where
|
||||
impl<K1: FullCodec, K2: FullCodec, V: FullCodec, G: StorageDoubleMap<K1, K2, V>>
|
||||
storage::IterableStorageDoubleMap<K1, K2, V> for G
|
||||
where
|
||||
G::Hasher1: ReversibleStorageHasher,
|
||||
G::Hasher2: ReversibleStorageHasher
|
||||
G::Hasher2: ReversibleStorageHasher,
|
||||
{
|
||||
type PartialKeyIterator = KeyPrefixIterator<K2>;
|
||||
type PrefixIterator = PrefixIterator<(K2, V)>;
|
||||
@@ -367,7 +378,7 @@ impl<
|
||||
closure: |raw_key_without_prefix| {
|
||||
let mut key_material = G::Hasher2::reverse(raw_key_without_prefix);
|
||||
K2::decode(&mut key_material)
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -405,7 +416,7 @@ impl<
|
||||
let mut k2_material = G::Hasher2::reverse(k1_k2_material);
|
||||
let k2 = K2::decode(&mut k2_material)?;
|
||||
Ok((k1, k2))
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -418,8 +429,8 @@ impl<
|
||||
fn translate<O: Decode, F: FnMut(K1, K2, O) -> Option<V>>(mut f: F) {
|
||||
let prefix = G::prefix_hash();
|
||||
let mut previous_key = prefix.clone();
|
||||
while let Some(next) = sp_io::storage::next_key(&previous_key)
|
||||
.filter(|n| n.starts_with(&prefix))
|
||||
while let Some(next) =
|
||||
sp_io::storage::next_key(&previous_key).filter(|n| n.starts_with(&prefix))
|
||||
{
|
||||
previous_key = next;
|
||||
let value = match unhashed::get::<O>(&previous_key) {
|
||||
@@ -458,11 +469,11 @@ impl<
|
||||
/// Test iterators for StorageDoubleMap
|
||||
#[cfg(test)]
|
||||
mod test_iterators {
|
||||
use codec::{Encode, Decode};
|
||||
use crate::{
|
||||
hash::StorageHasher,
|
||||
storage::{generator::StorageDoubleMap, IterableStorageDoubleMap, unhashed},
|
||||
storage::{generator::StorageDoubleMap, unhashed, IterableStorageDoubleMap},
|
||||
};
|
||||
use codec::{Decode, Encode};
|
||||
|
||||
pub trait Config: 'static {
|
||||
type Origin;
|
||||
@@ -521,10 +532,7 @@ mod test_iterators {
|
||||
vec![(3, 3), (0, 0), (2, 2), (1, 1)],
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
DoubleMap::iter_values().collect::<Vec<_>>(),
|
||||
vec![3, 0, 2, 1],
|
||||
);
|
||||
assert_eq!(DoubleMap::iter_values().collect::<Vec<_>>(), vec![3, 0, 2, 1],);
|
||||
|
||||
assert_eq!(
|
||||
DoubleMap::drain().collect::<Vec<_>>(),
|
||||
@@ -551,15 +559,9 @@ mod test_iterators {
|
||||
vec![(1, 1), (2, 2), (0, 0), (3, 3)],
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
DoubleMap::iter_key_prefix(k1).collect::<Vec<_>>(),
|
||||
vec![1, 2, 0, 3],
|
||||
);
|
||||
assert_eq!(DoubleMap::iter_key_prefix(k1).collect::<Vec<_>>(), vec![1, 2, 0, 3],);
|
||||
|
||||
assert_eq!(
|
||||
DoubleMap::iter_prefix_values(k1).collect::<Vec<_>>(),
|
||||
vec![1, 2, 0, 3],
|
||||
);
|
||||
assert_eq!(DoubleMap::iter_prefix_values(k1).collect::<Vec<_>>(), vec![1, 2, 0, 3],);
|
||||
|
||||
assert_eq!(
|
||||
DoubleMap::drain_prefix(k1).collect::<Vec<_>>(),
|
||||
@@ -580,15 +582,12 @@ mod test_iterators {
|
||||
}
|
||||
|
||||
// Wrong key1
|
||||
unhashed::put(
|
||||
&[prefix.clone(), vec![1, 2, 3]].concat(),
|
||||
&3u64.encode()
|
||||
);
|
||||
unhashed::put(&[prefix.clone(), vec![1, 2, 3]].concat(), &3u64.encode());
|
||||
|
||||
// Wrong key2
|
||||
unhashed::put(
|
||||
&[prefix.clone(), crate::Blake2_128Concat::hash(&1u16.encode())].concat(),
|
||||
&3u64.encode()
|
||||
&3u64.encode(),
|
||||
);
|
||||
|
||||
// Wrong value
|
||||
@@ -597,11 +596,12 @@ mod test_iterators {
|
||||
prefix.clone(),
|
||||
crate::Blake2_128Concat::hash(&1u16.encode()),
|
||||
crate::Twox64Concat::hash(&2u32.encode()),
|
||||
].concat(),
|
||||
]
|
||||
.concat(),
|
||||
&vec![1],
|
||||
);
|
||||
|
||||
DoubleMap::translate(|_k1, _k2, v: u64| Some(v*2));
|
||||
DoubleMap::translate(|_k1, _k2, v: u64| Some(v * 2));
|
||||
assert_eq!(
|
||||
DoubleMap::iter().collect::<Vec<_>>(),
|
||||
vec![(3, 3, 6), (0, 0, 0), (2, 2, 4), (1, 1, 2)],
|
||||
|
||||
@@ -15,14 +15,15 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use crate::{
|
||||
hash::{ReversibleStorageHasher, StorageHasher, Twox128},
|
||||
storage::{self, unhashed, KeyPrefixIterator, PrefixIterator, StorageAppend},
|
||||
Never,
|
||||
};
|
||||
use codec::{Decode, Encode, EncodeLike, FullCodec, FullEncode};
|
||||
use sp_std::borrow::Borrow;
|
||||
#[cfg(not(feature = "std"))]
|
||||
use sp_std::prelude::*;
|
||||
use sp_std::borrow::Borrow;
|
||||
use codec::{FullCodec, FullEncode, Decode, Encode, EncodeLike};
|
||||
use crate::{
|
||||
storage::{self, unhashed, KeyPrefixIterator, StorageAppend, PrefixIterator},
|
||||
Never, hash::{StorageHasher, Twox128, ReversibleStorageHasher},
|
||||
};
|
||||
|
||||
/// Generator for `StorageMap` used by `decl_storage`.
|
||||
///
|
||||
@@ -54,9 +55,8 @@ pub trait StorageMap<K: FullEncode, V: FullCodec> {
|
||||
let module_prefix_hashed = Twox128::hash(Self::module_prefix());
|
||||
let storage_prefix_hashed = Twox128::hash(Self::storage_prefix());
|
||||
|
||||
let mut result = Vec::with_capacity(
|
||||
module_prefix_hashed.len() + storage_prefix_hashed.len()
|
||||
);
|
||||
let mut result =
|
||||
Vec::with_capacity(module_prefix_hashed.len() + storage_prefix_hashed.len());
|
||||
|
||||
result.extend_from_slice(&module_prefix_hashed[..]);
|
||||
result.extend_from_slice(&storage_prefix_hashed[..]);
|
||||
@@ -71,7 +71,8 @@ pub trait StorageMap<K: FullEncode, V: FullCodec> {
|
||||
fn from_query_to_optional_value(v: Self::Query) -> Option<V>;
|
||||
|
||||
/// Generate the full key used in top storage.
|
||||
fn storage_map_final_key<KeyArg>(key: KeyArg) -> Vec<u8> where
|
||||
fn storage_map_final_key<KeyArg>(key: KeyArg) -> Vec<u8>
|
||||
where
|
||||
KeyArg: EncodeLike<K>,
|
||||
{
|
||||
let module_prefix_hashed = Twox128::hash(Self::module_prefix());
|
||||
@@ -79,7 +80,7 @@ pub trait StorageMap<K: FullEncode, V: FullCodec> {
|
||||
let key_hashed = key.borrow().using_encoded(Self::Hasher::hash);
|
||||
|
||||
let mut final_key = Vec::with_capacity(
|
||||
module_prefix_hashed.len() + storage_prefix_hashed.len() + key_hashed.as_ref().len()
|
||||
module_prefix_hashed.len() + storage_prefix_hashed.len() + key_hashed.as_ref().len(),
|
||||
);
|
||||
|
||||
final_key.extend_from_slice(&module_prefix_hashed[..]);
|
||||
@@ -98,11 +99,9 @@ pub struct StorageMapIterator<K, V, Hasher> {
|
||||
_phantom: ::sp_std::marker::PhantomData<(K, V, Hasher)>,
|
||||
}
|
||||
|
||||
impl<
|
||||
K: Decode + Sized,
|
||||
V: Decode + Sized,
|
||||
Hasher: ReversibleStorageHasher
|
||||
> Iterator for StorageMapIterator<K, V, Hasher> {
|
||||
impl<K: Decode + Sized, V: Decode + Sized, Hasher: ReversibleStorageHasher> Iterator
|
||||
for StorageMapIterator<K, V, Hasher>
|
||||
{
|
||||
type Item = (K, V);
|
||||
|
||||
fn next(&mut self) -> Option<(K, V)> {
|
||||
@@ -117,27 +116,25 @@ impl<
|
||||
if self.drain {
|
||||
unhashed::kill(&self.previous_key)
|
||||
}
|
||||
let mut key_material = Hasher::reverse(&self.previous_key[self.prefix.len()..]);
|
||||
let mut key_material =
|
||||
Hasher::reverse(&self.previous_key[self.prefix.len()..]);
|
||||
match K::decode(&mut key_material) {
|
||||
Ok(key) => Some((key, value)),
|
||||
Err(_) => continue,
|
||||
}
|
||||
}
|
||||
},
|
||||
None => continue,
|
||||
}
|
||||
}
|
||||
},
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<
|
||||
K: FullCodec,
|
||||
V: FullCodec,
|
||||
G: StorageMap<K, V>,
|
||||
> storage::IterableStorageMap<K, V> for G where
|
||||
G::Hasher: ReversibleStorageHasher
|
||||
impl<K: FullCodec, V: FullCodec, G: StorageMap<K, V>> storage::IterableStorageMap<K, V> for G
|
||||
where
|
||||
G::Hasher: ReversibleStorageHasher,
|
||||
{
|
||||
type Iterator = PrefixIterator<(K, V)>;
|
||||
type KeyIterator = KeyPrefixIterator<K>;
|
||||
@@ -166,7 +163,7 @@ impl<
|
||||
closure: |raw_key_without_prefix| {
|
||||
let mut key_material = G::Hasher::reverse(raw_key_without_prefix);
|
||||
K::decode(&mut key_material)
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -180,8 +177,8 @@ impl<
|
||||
fn translate<O: Decode, F: FnMut(K, O) -> Option<V>>(mut f: F) {
|
||||
let prefix = G::prefix_hash();
|
||||
let mut previous_key = prefix.clone();
|
||||
while let Some(next) = sp_io::storage::next_key(&previous_key)
|
||||
.filter(|n| n.starts_with(&prefix))
|
||||
while let Some(next) =
|
||||
sp_io::storage::next_key(&previous_key).filter(|n| n.starts_with(&prefix))
|
||||
{
|
||||
previous_key = next;
|
||||
let value = match unhashed::get::<O>(&previous_key) {
|
||||
@@ -254,16 +251,21 @@ impl<K: FullEncode, V: FullCodec, G: StorageMap<K, V>> storage::StorageMap<K, V>
|
||||
}
|
||||
|
||||
fn mutate<KeyArg: EncodeLike<K>, R, F: FnOnce(&mut Self::Query) -> R>(key: KeyArg, f: F) -> R {
|
||||
Self::try_mutate(key, |v| Ok::<R, Never>(f(v))).expect("`Never` can not be constructed; qed")
|
||||
Self::try_mutate(key, |v| Ok::<R, Never>(f(v)))
|
||||
.expect("`Never` can not be constructed; qed")
|
||||
}
|
||||
|
||||
fn mutate_exists<KeyArg: EncodeLike<K>, R, F: FnOnce(&mut Option<V>) -> R>(key: KeyArg, f: F) -> R {
|
||||
Self::try_mutate_exists(key, |v| Ok::<R, Never>(f(v))).expect("`Never` can not be constructed; qed")
|
||||
fn mutate_exists<KeyArg: EncodeLike<K>, R, F: FnOnce(&mut Option<V>) -> R>(
|
||||
key: KeyArg,
|
||||
f: F,
|
||||
) -> R {
|
||||
Self::try_mutate_exists(key, |v| Ok::<R, Never>(f(v)))
|
||||
.expect("`Never` can not be constructed; qed")
|
||||
}
|
||||
|
||||
fn try_mutate<KeyArg: EncodeLike<K>, R, E, F: FnOnce(&mut Self::Query) -> Result<R, E>>(
|
||||
key: KeyArg,
|
||||
f: F
|
||||
f: F,
|
||||
) -> Result<R, E> {
|
||||
let final_key = Self::storage_map_final_key(key);
|
||||
let mut val = G::from_optional_value_to_query(unhashed::get(final_key.as_ref()));
|
||||
@@ -280,7 +282,7 @@ impl<K: FullEncode, V: FullCodec, G: StorageMap<K, V>> storage::StorageMap<K, V>
|
||||
|
||||
fn try_mutate_exists<KeyArg: EncodeLike<K>, R, E, F: FnOnce(&mut Option<V>) -> Result<R, E>>(
|
||||
key: KeyArg,
|
||||
f: F
|
||||
f: F,
|
||||
) -> Result<R, E> {
|
||||
let final_key = Self::storage_map_final_key(key);
|
||||
let mut val = unhashed::get(final_key.as_ref());
|
||||
@@ -319,7 +321,9 @@ impl<K: FullEncode, V: FullCodec, G: StorageMap<K, V>> storage::StorageMap<K, V>
|
||||
let key_hashed = key.borrow().using_encoded(OldHasher::hash);
|
||||
|
||||
let mut final_key = Vec::with_capacity(
|
||||
module_prefix_hashed.len() + storage_prefix_hashed.len() + key_hashed.as_ref().len()
|
||||
module_prefix_hashed.len() +
|
||||
storage_prefix_hashed.len() +
|
||||
key_hashed.as_ref().len(),
|
||||
);
|
||||
|
||||
final_key.extend_from_slice(&module_prefix_hashed[..]);
|
||||
@@ -338,11 +342,11 @@ impl<K: FullEncode, V: FullCodec, G: StorageMap<K, V>> storage::StorageMap<K, V>
|
||||
/// Test iterators for StorageMap
|
||||
#[cfg(test)]
|
||||
mod test_iterators {
|
||||
use codec::{Encode, Decode};
|
||||
use crate::{
|
||||
hash::StorageHasher,
|
||||
storage::{generator::StorageMap, IterableStorageMap, unhashed},
|
||||
storage::{generator::StorageMap, unhashed, IterableStorageMap},
|
||||
};
|
||||
use codec::{Decode, Encode};
|
||||
|
||||
pub trait Config: 'static {
|
||||
type Origin;
|
||||
@@ -421,7 +425,7 @@ mod test_iterators {
|
||||
&vec![1],
|
||||
);
|
||||
|
||||
Map::translate(|_k1, v: u64| Some(v*2));
|
||||
Map::translate(|_k1, v: u64| Some(v * 2));
|
||||
assert_eq!(Map::iter().collect::<Vec<_>>(), vec![(3, 6), (0, 0), (2, 4), (1, 2)]);
|
||||
})
|
||||
}
|
||||
|
||||
@@ -24,23 +24,25 @@
|
||||
//!
|
||||
//! This is internal api and is subject to change.
|
||||
|
||||
mod double_map;
|
||||
mod map;
|
||||
mod nmap;
|
||||
mod double_map;
|
||||
mod value;
|
||||
|
||||
pub use double_map::StorageDoubleMap;
|
||||
pub use map::StorageMap;
|
||||
pub use nmap::StorageNMap;
|
||||
pub use double_map::StorageDoubleMap;
|
||||
pub use value::StorageValue;
|
||||
|
||||
#[cfg(test)]
|
||||
#[allow(dead_code)]
|
||||
mod tests {
|
||||
use sp_io::TestExternalities;
|
||||
use crate::{
|
||||
assert_noop, assert_ok,
|
||||
storage::{generator::StorageValue, unhashed, IterableStorageMap},
|
||||
};
|
||||
use codec::Encode;
|
||||
use crate::storage::{unhashed, generator::StorageValue, IterableStorageMap};
|
||||
use crate::{assert_noop, assert_ok};
|
||||
use sp_io::TestExternalities;
|
||||
|
||||
struct Runtime;
|
||||
|
||||
@@ -80,7 +82,7 @@ mod tests {
|
||||
|
||||
// translate
|
||||
let translate_fn = |old: Option<u32>| -> Option<(u64, u64)> {
|
||||
old.map(|o| (o.into(), (o*2).into()))
|
||||
old.map(|o| (o.into(), (o * 2).into()))
|
||||
};
|
||||
let res = Value::translate(translate_fn);
|
||||
debug_assert!(res.is_ok());
|
||||
@@ -105,11 +107,16 @@ mod tests {
|
||||
);
|
||||
|
||||
// do translation.
|
||||
NumberMap::translate(|k: u32, v: u64| if k % 2 == 0 { Some((k as u64) << 32 | v) } else { None });
|
||||
NumberMap::translate(
|
||||
|k: u32, v: u64| if k % 2 == 0 { Some((k as u64) << 32 | v) } else { None },
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
NumberMap::iter().collect::<Vec<_>>(),
|
||||
(0..50u32).map(|x| x * 2).map(|x| (x, (x as u64) << 32 | x as u64)).collect::<Vec<_>>(),
|
||||
(0..50u32)
|
||||
.map(|x| x * 2)
|
||||
.map(|x| (x, (x as u64) << 32 | x as u64))
|
||||
.collect::<Vec<_>>(),
|
||||
);
|
||||
})
|
||||
}
|
||||
@@ -123,20 +130,29 @@ mod tests {
|
||||
assert_eq!(DoubleMap::get(0, 0), 0);
|
||||
|
||||
// `assert_noop` ensures that the state does not change
|
||||
assert_noop!(Value::try_mutate(|value| -> Result<(), &'static str> {
|
||||
*value = (2, 2);
|
||||
Err("don't change value")
|
||||
}), "don't change value");
|
||||
assert_noop!(
|
||||
Value::try_mutate(|value| -> Result<(), &'static str> {
|
||||
*value = (2, 2);
|
||||
Err("don't change value")
|
||||
}),
|
||||
"don't change value"
|
||||
);
|
||||
|
||||
assert_noop!(NumberMap::try_mutate(0, |value| -> Result<(), &'static str> {
|
||||
*value = 4;
|
||||
Err("don't change value")
|
||||
}), "don't change value");
|
||||
assert_noop!(
|
||||
NumberMap::try_mutate(0, |value| -> Result<(), &'static str> {
|
||||
*value = 4;
|
||||
Err("don't change value")
|
||||
}),
|
||||
"don't change value"
|
||||
);
|
||||
|
||||
assert_noop!(DoubleMap::try_mutate(0, 0, |value| -> Result<(), &'static str> {
|
||||
*value = 6;
|
||||
Err("don't change value")
|
||||
}), "don't change value");
|
||||
assert_noop!(
|
||||
DoubleMap::try_mutate(0, 0, |value| -> Result<(), &'static str> {
|
||||
*value = 6;
|
||||
Err("don't change value")
|
||||
}),
|
||||
"don't change value"
|
||||
);
|
||||
|
||||
// Showing this explicitly for clarity
|
||||
assert_eq!(Value::get(), (0, 0));
|
||||
|
||||
@@ -228,7 +228,7 @@ where
|
||||
fn try_mutate<KArg, R, E, F>(key: KArg, f: F) -> Result<R, E>
|
||||
where
|
||||
KArg: EncodeLikeTuple<K::KArg> + TupleToEncodedIter,
|
||||
F: FnOnce(&mut Self::Query) -> Result<R, E>
|
||||
F: FnOnce(&mut Self::Query) -> Result<R, E>,
|
||||
{
|
||||
let final_key = Self::storage_n_map_final_key::<K, _>(key);
|
||||
let mut val = G::from_optional_value_to_query(unhashed::get(final_key.as_ref()));
|
||||
@@ -373,7 +373,7 @@ impl<K: ReversibleKeyGenerator, V: FullCodec, G: StorageNMap<K, V>>
|
||||
closure: |raw_key_without_prefix| {
|
||||
let (final_key, _) = K::decode_final_key(raw_key_without_prefix)?;
|
||||
Ok(final_key)
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -394,16 +394,16 @@ impl<K: ReversibleKeyGenerator, V: FullCodec, G: StorageNMap<K, V>>
|
||||
Some(value) => value,
|
||||
None => {
|
||||
log::error!("Invalid translate: fail to decode old value");
|
||||
continue;
|
||||
}
|
||||
continue
|
||||
},
|
||||
};
|
||||
|
||||
let final_key = match K::decode_final_key(&previous_key[prefix.len()..]) {
|
||||
Ok((final_key, _)) => final_key,
|
||||
Err(_) => {
|
||||
log::error!("Invalid translate: fail to decode key");
|
||||
continue;
|
||||
}
|
||||
continue
|
||||
},
|
||||
};
|
||||
|
||||
match f(final_key, value) {
|
||||
@@ -452,10 +452,7 @@ mod test_iterators {
|
||||
|
||||
fn key_after_prefix(mut prefix: Vec<u8>) -> Vec<u8> {
|
||||
let last = prefix.iter_mut().last().unwrap();
|
||||
assert!(
|
||||
*last != 255,
|
||||
"mock function not implemented for this prefix"
|
||||
);
|
||||
assert!(*last != 255, "mock function not implemented for this prefix");
|
||||
*last += 1;
|
||||
prefix
|
||||
}
|
||||
@@ -498,10 +495,7 @@ mod test_iterators {
|
||||
vec![((3, 3), 3), ((0, 0), 0), ((2, 2), 2), ((1, 1), 1)],
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
NMap::iter_keys().collect::<Vec<_>>(),
|
||||
vec![(3, 3), (0, 0), (2, 2), (1, 1)],
|
||||
);
|
||||
assert_eq!(NMap::iter_keys().collect::<Vec<_>>(), vec![(3, 3), (0, 0), (2, 2), (1, 1)],);
|
||||
|
||||
assert_eq!(NMap::iter_values().collect::<Vec<_>>(), vec![3, 0, 2, 1],);
|
||||
|
||||
@@ -511,10 +505,7 @@ mod test_iterators {
|
||||
);
|
||||
|
||||
assert_eq!(NMap::iter().collect::<Vec<_>>(), vec![]);
|
||||
assert_eq!(
|
||||
unhashed::get(&key_before_prefix(prefix.clone())),
|
||||
Some(1u64)
|
||||
);
|
||||
assert_eq!(unhashed::get(&key_before_prefix(prefix.clone())), Some(1u64));
|
||||
assert_eq!(unhashed::get(&key_after_prefix(prefix.clone())), Some(1u64));
|
||||
|
||||
// Prefix iterator
|
||||
@@ -533,15 +524,9 @@ mod test_iterators {
|
||||
vec![(1, 1), (2, 2), (0, 0), (3, 3)],
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
NMap::iter_key_prefix((k1,)).collect::<Vec<_>>(),
|
||||
vec![1, 2, 0, 3],
|
||||
);
|
||||
assert_eq!(NMap::iter_key_prefix((k1,)).collect::<Vec<_>>(), vec![1, 2, 0, 3],);
|
||||
|
||||
assert_eq!(
|
||||
NMap::iter_prefix_values((k1,)).collect::<Vec<_>>(),
|
||||
vec![1, 2, 0, 3],
|
||||
);
|
||||
assert_eq!(NMap::iter_prefix_values((k1,)).collect::<Vec<_>>(), vec![1, 2, 0, 3],);
|
||||
|
||||
assert_eq!(
|
||||
NMap::drain_prefix((k1,)).collect::<Vec<_>>(),
|
||||
@@ -549,10 +534,7 @@ mod test_iterators {
|
||||
);
|
||||
|
||||
assert_eq!(NMap::iter_prefix((k1,)).collect::<Vec<_>>(), vec![]);
|
||||
assert_eq!(
|
||||
unhashed::get(&key_before_prefix(prefix.clone())),
|
||||
Some(1u64)
|
||||
);
|
||||
assert_eq!(unhashed::get(&key_before_prefix(prefix.clone())), Some(1u64));
|
||||
assert_eq!(unhashed::get(&key_after_prefix(prefix.clone())), Some(1u64));
|
||||
|
||||
// Translate
|
||||
@@ -569,11 +551,7 @@ mod test_iterators {
|
||||
|
||||
// Wrong key2
|
||||
unhashed::put(
|
||||
&[
|
||||
prefix.clone(),
|
||||
crate::Blake2_128Concat::hash(&1u16.encode()),
|
||||
]
|
||||
.concat(),
|
||||
&[prefix.clone(), crate::Blake2_128Concat::hash(&1u16.encode())].concat(),
|
||||
&3u64.encode(),
|
||||
);
|
||||
|
||||
|
||||
@@ -15,12 +15,12 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use codec::{FullCodec, Encode, EncodeLike, Decode};
|
||||
use crate::{
|
||||
Never,
|
||||
hash::{StorageHasher, Twox128},
|
||||
storage::{self, unhashed, StorageAppend},
|
||||
hash::{Twox128, StorageHasher},
|
||||
Never,
|
||||
};
|
||||
use codec::{Decode, Encode, EncodeLike, FullCodec};
|
||||
|
||||
/// Generator for `StorageValue` used by `decl_storage`.
|
||||
///
|
||||
@@ -78,7 +78,8 @@ impl<T: FullCodec, G: StorageValue<T>> storage::StorageValue<T> for G {
|
||||
|
||||
// attempt to get the length directly.
|
||||
let maybe_old = unhashed::get_raw(&key)
|
||||
.map(|old_data| O::decode(&mut &old_data[..]).map_err(|_| ())).transpose()?;
|
||||
.map(|old_data| O::decode(&mut &old_data[..]).map_err(|_| ()))
|
||||
.transpose()?;
|
||||
let maybe_new = f(maybe_old);
|
||||
if let Some(new) = maybe_new.as_ref() {
|
||||
new.using_encoded(|d| unhashed::put_raw(&key, d));
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
//! Operation on runtime storage using hashed keys.
|
||||
|
||||
use super::unhashed;
|
||||
use codec::{Decode, Encode};
|
||||
use sp_std::prelude::*;
|
||||
use codec::{Encode, Decode};
|
||||
|
||||
/// Return the value of the item in storage under `key`, or `None` if there is no explicit entry.
|
||||
pub fn get<T, HashFn, R>(hash: &HashFn, key: &[u8]) -> Option<T>
|
||||
|
||||
@@ -17,10 +17,9 @@
|
||||
|
||||
//! Some utilities for helping access storage with arbitrary key types.
|
||||
|
||||
use crate::{hash::ReversibleStorageHasher, storage::unhashed, StorageHasher, Twox128};
|
||||
use codec::{Decode, Encode};
|
||||
use sp_std::prelude::*;
|
||||
use codec::{Encode, Decode};
|
||||
use crate::{StorageHasher, Twox128, storage::unhashed};
|
||||
use crate::hash::ReversibleStorageHasher;
|
||||
|
||||
use super::PrefixIterator;
|
||||
|
||||
@@ -34,14 +33,18 @@ pub struct StorageIterator<T> {
|
||||
|
||||
impl<T> StorageIterator<T> {
|
||||
/// Construct iterator to iterate over map items in `module` for the map called `item`.
|
||||
#[deprecated(note="Please use the storage_iter or storage_iter_with_suffix functions instead")]
|
||||
#[deprecated(
|
||||
note = "Please use the storage_iter or storage_iter_with_suffix functions instead"
|
||||
)]
|
||||
pub fn new(module: &[u8], item: &[u8]) -> Self {
|
||||
#[allow(deprecated)]
|
||||
Self::with_suffix(module, item, &[][..])
|
||||
}
|
||||
|
||||
/// Construct iterator to iterate over map items in `module` for the map called `item`.
|
||||
#[deprecated(note="Please use the storage_iter or storage_iter_with_suffix functions instead")]
|
||||
#[deprecated(
|
||||
note = "Please use the storage_iter or storage_iter_with_suffix functions instead"
|
||||
)]
|
||||
pub fn with_suffix(module: &[u8], item: &[u8], suffix: &[u8]) -> Self {
|
||||
let mut prefix = Vec::new();
|
||||
prefix.extend_from_slice(&Twox128::hash(module));
|
||||
@@ -75,10 +78,10 @@ impl<T: Decode + Sized> Iterator for StorageIterator<T> {
|
||||
frame_support::storage::unhashed::kill(&next);
|
||||
}
|
||||
Some((self.previous_key[self.prefix.len()..].to_vec(), value))
|
||||
}
|
||||
},
|
||||
None => continue,
|
||||
}
|
||||
}
|
||||
},
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
@@ -95,14 +98,18 @@ pub struct StorageKeyIterator<K, T, H: ReversibleStorageHasher> {
|
||||
|
||||
impl<K, T, H: ReversibleStorageHasher> StorageKeyIterator<K, T, H> {
|
||||
/// Construct iterator to iterate over map items in `module` for the map called `item`.
|
||||
#[deprecated(note="Please use the storage_key_iter or storage_key_iter_with_suffix functions instead")]
|
||||
#[deprecated(
|
||||
note = "Please use the storage_key_iter or storage_key_iter_with_suffix functions instead"
|
||||
)]
|
||||
pub fn new(module: &[u8], item: &[u8]) -> Self {
|
||||
#[allow(deprecated)]
|
||||
Self::with_suffix(module, item, &[][..])
|
||||
}
|
||||
|
||||
/// Construct iterator to iterate over map items in `module` for the map called `item`.
|
||||
#[deprecated(note="Please use the storage_key_iter or storage_key_iter_with_suffix functions instead")]
|
||||
#[deprecated(
|
||||
note = "Please use the storage_key_iter or storage_key_iter_with_suffix functions instead"
|
||||
)]
|
||||
pub fn with_suffix(module: &[u8], item: &[u8], suffix: &[u8]) -> Self {
|
||||
let mut prefix = Vec::new();
|
||||
prefix.extend_from_slice(&Twox128::hash(module));
|
||||
@@ -141,13 +148,13 @@ impl<K: Decode + Sized, T: Decode + Sized, H: ReversibleStorageHasher> Iterator
|
||||
frame_support::storage::unhashed::kill(&next);
|
||||
}
|
||||
Some((key, value))
|
||||
}
|
||||
},
|
||||
None => continue,
|
||||
}
|
||||
}
|
||||
},
|
||||
Err(_) => continue,
|
||||
}
|
||||
}
|
||||
},
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
@@ -187,7 +194,11 @@ pub fn storage_key_iter<K: Decode + Sized, T: Decode + Sized, H: ReversibleStora
|
||||
}
|
||||
|
||||
/// Construct iterator to iterate over map items in `module` for the map called `item`.
|
||||
pub fn storage_key_iter_with_suffix<K: Decode + Sized, T: Decode + Sized, H: ReversibleStorageHasher>(
|
||||
pub fn storage_key_iter_with_suffix<
|
||||
K: Decode + Sized,
|
||||
T: Decode + Sized,
|
||||
H: ReversibleStorageHasher,
|
||||
>(
|
||||
module: &[u8],
|
||||
item: &[u8],
|
||||
suffix: &[u8],
|
||||
@@ -279,7 +290,7 @@ pub fn take_storage_item<K: Encode + Sized, T: Decode + Sized, H: StorageHasher>
|
||||
pub fn move_storage_from_pallet(
|
||||
storage_name: &[u8],
|
||||
old_pallet_name: &[u8],
|
||||
new_pallet_name: &[u8]
|
||||
new_pallet_name: &[u8],
|
||||
) {
|
||||
let mut new_prefix = Vec::new();
|
||||
new_prefix.extend_from_slice(&Twox128::hash(new_pallet_name));
|
||||
@@ -347,18 +358,14 @@ pub fn move_prefix(from_prefix: &[u8], to_prefix: &[u8]) {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{
|
||||
move_pallet, move_prefix, move_storage_from_pallet, storage_iter, storage_key_iter,
|
||||
};
|
||||
use crate::{
|
||||
pallet_prelude::{StorageValue, StorageMap, Twox64Concat, Twox128},
|
||||
hash::StorageHasher,
|
||||
pallet_prelude::{StorageMap, StorageValue, Twox128, Twox64Concat},
|
||||
};
|
||||
use sp_io::TestExternalities;
|
||||
use super::{
|
||||
move_prefix,
|
||||
move_pallet,
|
||||
move_storage_from_pallet,
|
||||
storage_iter,
|
||||
storage_key_iter,
|
||||
};
|
||||
|
||||
struct OldPalletStorageValuePrefix;
|
||||
impl frame_support::traits::StorageInstance for OldPalletStorageValuePrefix {
|
||||
@@ -459,21 +466,22 @@ mod tests {
|
||||
OldStorageMap::insert(3, 4);
|
||||
|
||||
assert_eq!(
|
||||
storage_key_iter::<i32, i32, Twox64Concat>(b"my_old_pallet", b"foo_map").collect::<Vec<_>>(),
|
||||
storage_key_iter::<i32, i32, Twox64Concat>(b"my_old_pallet", b"foo_map")
|
||||
.collect::<Vec<_>>(),
|
||||
vec![(1, 2), (3, 4)],
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
storage_iter(b"my_old_pallet", b"foo_map").drain().map(|t| t.1).collect::<Vec<i32>>(),
|
||||
storage_iter(b"my_old_pallet", b"foo_map")
|
||||
.drain()
|
||||
.map(|t| t.1)
|
||||
.collect::<Vec<i32>>(),
|
||||
vec![2, 4],
|
||||
);
|
||||
assert_eq!(OldStorageMap::iter().collect::<Vec<_>>(), vec![]);
|
||||
|
||||
// Empty because storage iterator skips over the entry under the first key
|
||||
assert_eq!(
|
||||
storage_iter::<i32>(b"my_old_pallet", b"foo_value").drain().next(),
|
||||
None
|
||||
);
|
||||
assert_eq!(storage_iter::<i32>(b"my_old_pallet", b"foo_value").drain().next(), None);
|
||||
assert_eq!(OldStorageValue::get(), Some(3));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -17,31 +17,31 @@
|
||||
|
||||
//! Stuff to do with the runtime's storage.
|
||||
|
||||
use sp_core::storage::ChildInfo;
|
||||
use sp_std::prelude::*;
|
||||
use codec::{FullCodec, FullEncode, Encode, EncodeLike, Decode};
|
||||
use crate::{
|
||||
hash::{Twox128, StorageHasher, ReversibleStorageHasher},
|
||||
hash::{ReversibleStorageHasher, StorageHasher, Twox128},
|
||||
storage::types::{
|
||||
EncodeLikeTuple, HasKeyPrefix, HasReversibleKeyPrefix, KeyGenerator,
|
||||
ReversibleKeyGenerator, TupleToEncodedIter,
|
||||
},
|
||||
};
|
||||
use codec::{Decode, Encode, EncodeLike, FullCodec, FullEncode};
|
||||
use sp_core::storage::ChildInfo;
|
||||
use sp_runtime::generic::{Digest, DigestItem};
|
||||
pub use sp_runtime::TransactionOutcome;
|
||||
use sp_std::prelude::*;
|
||||
pub use types::Key;
|
||||
|
||||
pub mod unhashed;
|
||||
pub mod hashed;
|
||||
pub mod bounded_btree_map;
|
||||
pub mod bounded_btree_set;
|
||||
pub mod bounded_vec;
|
||||
pub mod weak_bounded_vec;
|
||||
pub mod child;
|
||||
#[doc(hidden)]
|
||||
pub mod generator;
|
||||
pub mod hashed;
|
||||
pub mod migration;
|
||||
pub mod types;
|
||||
pub mod unhashed;
|
||||
pub mod weak_bounded_vec;
|
||||
|
||||
#[cfg(all(feature = "std", any(test, debug_assertions)))]
|
||||
mod debug_helper {
|
||||
@@ -101,9 +101,7 @@ pub fn require_transaction() {
|
||||
///
|
||||
/// Transactions can be nested to any depth. Commits happen to the parent transaction.
|
||||
pub fn with_transaction<R>(f: impl FnOnce() -> TransactionOutcome<R>) -> R {
|
||||
use sp_io::storage::{
|
||||
start_transaction, commit_transaction, rollback_transaction,
|
||||
};
|
||||
use sp_io::storage::{commit_transaction, rollback_transaction, start_transaction};
|
||||
use TransactionOutcome::*;
|
||||
|
||||
start_transaction();
|
||||
@@ -112,8 +110,14 @@ pub fn with_transaction<R>(f: impl FnOnce() -> TransactionOutcome<R>) -> R {
|
||||
let _guard = debug_helper::inc_transaction_level();
|
||||
|
||||
match f() {
|
||||
Commit(res) => { commit_transaction(); res },
|
||||
Rollback(res) => { rollback_transaction(); res },
|
||||
Commit(res) => {
|
||||
commit_transaction();
|
||||
res
|
||||
},
|
||||
Rollback(res) => {
|
||||
rollback_transaction();
|
||||
res
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -205,7 +209,10 @@ pub trait StorageValue<T: FullCodec> {
|
||||
///
|
||||
/// `None` does not mean that `get()` does not return a value. The default value is completly
|
||||
/// ignored by this function.
|
||||
fn decode_len() -> Option<usize> where T: StorageDecodeLength {
|
||||
fn decode_len() -> Option<usize>
|
||||
where
|
||||
T: StorageDecodeLength,
|
||||
{
|
||||
T::decode_len(&Self::hashed_key())
|
||||
}
|
||||
}
|
||||
@@ -252,7 +259,10 @@ pub trait StorageMap<K: FullEncode, V: FullCodec> {
|
||||
/// Mutate the value under a key.
|
||||
///
|
||||
/// Deletes the item if mutated to a `None`.
|
||||
fn mutate_exists<KeyArg: EncodeLike<K>, R, F: FnOnce(&mut Option<V>) -> R>(key: KeyArg, f: F) -> R;
|
||||
fn mutate_exists<KeyArg: EncodeLike<K>, R, F: FnOnce(&mut Option<V>) -> R>(
|
||||
key: KeyArg,
|
||||
f: F,
|
||||
) -> R;
|
||||
|
||||
/// Mutate the item, only if an `Ok` value is returned. Deletes the item if mutated to a `None`.
|
||||
fn try_mutate_exists<KeyArg: EncodeLike<K>, R, E, F: FnOnce(&mut Option<V>) -> Result<R, E>>(
|
||||
@@ -292,7 +302,8 @@ pub trait StorageMap<K: FullEncode, V: FullCodec> {
|
||||
/// `None` does not mean that `get()` does not return a value. The default value is completly
|
||||
/// ignored by this function.
|
||||
fn decode_len<KeyArg: EncodeLike<K>>(key: KeyArg) -> Option<usize>
|
||||
where V: StorageDecodeLength,
|
||||
where
|
||||
V: StorageDecodeLength,
|
||||
{
|
||||
V::decode_len(&Self::hashed_key_for(key))
|
||||
}
|
||||
@@ -337,11 +348,9 @@ pub trait IterableStorageMap<K: FullEncode, V: FullCodec>: StorageMap<K, V> {
|
||||
}
|
||||
|
||||
/// A strongly-typed double map in storage whose secondary keys and values can be iterated over.
|
||||
pub trait IterableStorageDoubleMap<
|
||||
K1: FullCodec,
|
||||
K2: FullCodec,
|
||||
V: FullCodec
|
||||
>: StorageDoubleMap<K1, K2, V> {
|
||||
pub trait IterableStorageDoubleMap<K1: FullCodec, K2: FullCodec, V: FullCodec>:
|
||||
StorageDoubleMap<K1, K2, V>
|
||||
{
|
||||
/// The type that iterates over all `key2`.
|
||||
type PartialKeyIterator: Iterator<Item = K2>;
|
||||
|
||||
@@ -401,19 +410,22 @@ pub trait IterableStorageNMap<K: ReversibleKeyGenerator, V: FullCodec>: StorageN
|
||||
/// remove values whose prefix is `kp` to the map while doing this, you'll get undefined
|
||||
/// results.
|
||||
fn iter_prefix<KP>(kp: KP) -> PrefixIterator<(<K as HasKeyPrefix<KP>>::Suffix, V)>
|
||||
where K: HasReversibleKeyPrefix<KP>;
|
||||
where
|
||||
K: HasReversibleKeyPrefix<KP>;
|
||||
|
||||
/// Enumerate all suffix keys in the map with prefix key `kp` in no particular order. If you
|
||||
/// add or remove values whose prefix is `kp` to the map while doing this, you'll get undefined
|
||||
/// results.
|
||||
fn iter_key_prefix<KP>(kp: KP) -> KeyPrefixIterator<<K as HasKeyPrefix<KP>>::Suffix>
|
||||
where K: HasReversibleKeyPrefix<KP>;
|
||||
where
|
||||
K: HasReversibleKeyPrefix<KP>;
|
||||
|
||||
/// Remove all elements from the map with prefix key `kp` and iterate through them in no
|
||||
/// particular order. If you add elements with prefix key `kp` to the map while doing this,
|
||||
/// you'll get undefined results.
|
||||
fn drain_prefix<KP>(kp: KP) -> PrefixIterator<(<K as HasKeyPrefix<KP>>::Suffix, V)>
|
||||
where K: HasReversibleKeyPrefix<KP>;
|
||||
where
|
||||
K: HasReversibleKeyPrefix<KP>;
|
||||
|
||||
/// Enumerate all elements in the map in no particular order. If you add or remove values to
|
||||
/// the map while doing this, you'll get undefined results.
|
||||
@@ -499,11 +511,13 @@ pub trait StorageDoubleMap<K1: FullEncode, K2: FullEncode, V: FullCodec> {
|
||||
|
||||
/// Remove all values under the first key.
|
||||
fn remove_prefix<KArg1>(k1: KArg1, limit: Option<u32>) -> sp_io::KillStorageResult
|
||||
where KArg1: ?Sized + EncodeLike<K1>;
|
||||
where
|
||||
KArg1: ?Sized + EncodeLike<K1>;
|
||||
|
||||
/// Iterate over values that share the first key.
|
||||
fn iter_prefix_values<KArg1>(k1: KArg1) -> PrefixIterator<V>
|
||||
where KArg1: ?Sized + EncodeLike<K1>;
|
||||
where
|
||||
KArg1: ?Sized + EncodeLike<K1>;
|
||||
|
||||
/// Mutate the value under the given keys.
|
||||
fn mutate<KArg1, KArg2, R, F>(k1: KArg1, k2: KArg2, f: F) -> R
|
||||
@@ -542,11 +556,8 @@ pub trait StorageDoubleMap<K1: FullEncode, K2: FullEncode, V: FullCodec> {
|
||||
/// If the storage item is not encoded properly, the storage will be overwritten
|
||||
/// and set to `[item]`. Any default value set for the storage item will be ignored
|
||||
/// on overwrite.
|
||||
fn append<Item, EncodeLikeItem, KArg1, KArg2>(
|
||||
k1: KArg1,
|
||||
k2: KArg2,
|
||||
item: EncodeLikeItem,
|
||||
) where
|
||||
fn append<Item, EncodeLikeItem, KArg1, KArg2>(k1: KArg1, k2: KArg2, item: EncodeLikeItem)
|
||||
where
|
||||
KArg1: EncodeLike<K1>,
|
||||
KArg2: EncodeLike<K2>,
|
||||
Item: Encode,
|
||||
@@ -566,10 +577,10 @@ pub trait StorageDoubleMap<K1: FullEncode, K2: FullEncode, V: FullCodec> {
|
||||
/// `None` does not mean that `get()` does not return a value. The default value is completly
|
||||
/// ignored by this function.
|
||||
fn decode_len<KArg1, KArg2>(key1: KArg1, key2: KArg2) -> Option<usize>
|
||||
where
|
||||
KArg1: EncodeLike<K1>,
|
||||
KArg2: EncodeLike<K2>,
|
||||
V: StorageDecodeLength,
|
||||
where
|
||||
KArg1: EncodeLike<K1>,
|
||||
KArg2: EncodeLike<K2>,
|
||||
V: StorageDecodeLength,
|
||||
{
|
||||
V::decode_len(&Self::hashed_key_for(key1, key2))
|
||||
}
|
||||
@@ -583,7 +594,10 @@ pub trait StorageDoubleMap<K1: FullEncode, K2: FullEncode, V: FullCodec> {
|
||||
OldHasher2: StorageHasher,
|
||||
KeyArg1: EncodeLike<K1>,
|
||||
KeyArg2: EncodeLike<K2>,
|
||||
>(key1: KeyArg1, key2: KeyArg2) -> Option<V>;
|
||||
>(
|
||||
key1: KeyArg1,
|
||||
key2: KeyArg2,
|
||||
) -> Option<V>;
|
||||
}
|
||||
|
||||
/// An implementation of a map with an arbitrary number of keys.
|
||||
@@ -625,10 +639,13 @@ pub trait StorageNMap<K: KeyGenerator, V: FullCodec> {
|
||||
|
||||
/// Remove all values under the partial prefix key.
|
||||
fn remove_prefix<KP>(partial_key: KP, limit: Option<u32>) -> sp_io::KillStorageResult
|
||||
where K: HasKeyPrefix<KP>;
|
||||
where
|
||||
K: HasKeyPrefix<KP>;
|
||||
|
||||
/// Iterate over values that share the partial prefix key.
|
||||
fn iter_prefix_values<KP>(partial_key: KP) -> PrefixIterator<V> where K: HasKeyPrefix<KP>;
|
||||
fn iter_prefix_values<KP>(partial_key: KP) -> PrefixIterator<V>
|
||||
where
|
||||
K: HasKeyPrefix<KP>;
|
||||
|
||||
/// Mutate the value under a key.
|
||||
fn mutate<KArg, R, F>(key: KArg, f: F) -> R
|
||||
@@ -741,7 +758,7 @@ impl<T> Iterator for PrefixIterator<T> {
|
||||
self.previous_key,
|
||||
);
|
||||
continue
|
||||
}
|
||||
},
|
||||
};
|
||||
if self.drain {
|
||||
unhashed::kill(&self.previous_key)
|
||||
@@ -756,11 +773,11 @@ impl<T> Iterator for PrefixIterator<T> {
|
||||
e,
|
||||
);
|
||||
continue
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
Some(item)
|
||||
}
|
||||
},
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
@@ -807,12 +824,12 @@ impl<T> Iterator for KeyPrefixIterator<T> {
|
||||
Ok(item) => return Some(item),
|
||||
Err(e) => {
|
||||
log::error!("key failed to decode at {:?}: {:?}", self.previous_key, e);
|
||||
continue;
|
||||
}
|
||||
continue
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
return None;
|
||||
return None
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -871,7 +888,10 @@ impl<K: Decode + Sized, T: Decode + Sized> ChildTriePrefixIterator<(K, T)> {
|
||||
/// Construct iterator to iterate over child trie items in `child_info` with the prefix `prefix`.
|
||||
///
|
||||
/// NOTE: Iterator with [`Self::drain`] will remove any key or value who failed to decode
|
||||
pub fn with_prefix_over_key<H: ReversibleStorageHasher>(child_info: &ChildInfo, prefix: &[u8]) -> Self {
|
||||
pub fn with_prefix_over_key<H: ReversibleStorageHasher>(
|
||||
child_info: &ChildInfo,
|
||||
prefix: &[u8],
|
||||
) -> Self {
|
||||
let prefix = prefix.to_vec();
|
||||
let previous_key = prefix.clone();
|
||||
let closure = |raw_key_without_prefix: &[u8], raw_value: &[u8]| {
|
||||
@@ -888,7 +908,7 @@ impl<K: Decode + Sized, T: Decode + Sized> ChildTriePrefixIterator<(K, T)> {
|
||||
drain: false,
|
||||
fetch_previous_key: true,
|
||||
closure,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -905,7 +925,7 @@ impl<T> Iterator for ChildTriePrefixIterator<T> {
|
||||
&self.child_info.storage_key(),
|
||||
&self.previous_key,
|
||||
)
|
||||
.filter(|n| n.starts_with(&self.prefix))
|
||||
.filter(|n| n.starts_with(&self.prefix))
|
||||
};
|
||||
break match maybe_next {
|
||||
Some(next) => {
|
||||
@@ -918,7 +938,7 @@ impl<T> Iterator for ChildTriePrefixIterator<T> {
|
||||
self.previous_key,
|
||||
);
|
||||
continue
|
||||
}
|
||||
},
|
||||
};
|
||||
if self.drain {
|
||||
child::kill(&self.child_info, &self.previous_key)
|
||||
@@ -933,11 +953,11 @@ impl<T> Iterator for ChildTriePrefixIterator<T> {
|
||||
e,
|
||||
);
|
||||
continue
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
Some(item)
|
||||
}
|
||||
},
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
@@ -999,8 +1019,8 @@ pub trait StoragePrefixedMap<Value: FullCodec> {
|
||||
fn translate_values<OldValue: Decode, F: FnMut(OldValue) -> Option<Value>>(mut f: F) {
|
||||
let prefix = Self::final_prefix();
|
||||
let mut previous_key = prefix.clone().to_vec();
|
||||
while let Some(next) = sp_io::storage::next_key(&previous_key)
|
||||
.filter(|n| n.starts_with(&prefix))
|
||||
while let Some(next) =
|
||||
sp_io::storage::next_key(&previous_key).filter(|n| n.starts_with(&prefix))
|
||||
{
|
||||
previous_key = next;
|
||||
let maybe_value = unhashed::get::<OldValue>(&previous_key);
|
||||
@@ -1010,10 +1030,7 @@ pub trait StoragePrefixedMap<Value: FullCodec> {
|
||||
None => unhashed::kill(&previous_key),
|
||||
},
|
||||
None => {
|
||||
log::error!(
|
||||
"old key failed to decode at {:?}",
|
||||
previous_key,
|
||||
);
|
||||
log::error!("old key failed to decode at {:?}", previous_key,);
|
||||
continue
|
||||
},
|
||||
}
|
||||
@@ -1218,13 +1235,13 @@ where
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use sp_core::hashing::twox_128;
|
||||
use crate::{hash::Identity, assert_ok};
|
||||
use sp_io::TestExternalities;
|
||||
use generator::StorageValue as _;
|
||||
use crate::{assert_ok, hash::Identity};
|
||||
use bounded_vec::BoundedVec;
|
||||
use weak_bounded_vec::WeakBoundedVec;
|
||||
use core::convert::{TryFrom, TryInto};
|
||||
use generator::StorageValue as _;
|
||||
use sp_core::hashing::twox_128;
|
||||
use sp_io::TestExternalities;
|
||||
use weak_bounded_vec::WeakBoundedVec;
|
||||
|
||||
#[test]
|
||||
fn prefixed_map_works() {
|
||||
@@ -1363,8 +1380,7 @@ mod test {
|
||||
#[test]
|
||||
fn key_prefix_iterator_works() {
|
||||
TestExternalities::default().execute_with(|| {
|
||||
use crate::storage::generator::StorageMap;
|
||||
use crate::hash::Twox64Concat;
|
||||
use crate::{hash::Twox64Concat, storage::generator::StorageMap};
|
||||
struct MyStorageMap;
|
||||
impl StorageMap<u64, u64> for MyStorageMap {
|
||||
type Query = u64;
|
||||
@@ -1426,30 +1442,21 @@ mod test {
|
||||
assert_eq!(
|
||||
ChildTriePrefixIterator::with_prefix(&child_info_a, &[2])
|
||||
.collect::<Vec<(Vec<u8>, u16)>>(),
|
||||
vec![
|
||||
(vec![], 8),
|
||||
(vec![2, 3], 8),
|
||||
],
|
||||
vec![(vec![], 8), (vec![2, 3], 8),],
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
ChildTriePrefixIterator::with_prefix(&child_info_a, &[2])
|
||||
.drain()
|
||||
.collect::<Vec<(Vec<u8>, u16)>>(),
|
||||
vec![
|
||||
(vec![], 8),
|
||||
(vec![2, 3], 8),
|
||||
],
|
||||
vec![(vec![], 8), (vec![2, 3], 8),],
|
||||
);
|
||||
|
||||
// The only remaining is the ones outside prefix
|
||||
assert_eq!(
|
||||
ChildTriePrefixIterator::with_prefix(&child_info_a, &[])
|
||||
.collect::<Vec<(Vec<u8>, u8)>>(),
|
||||
vec![
|
||||
(vec![1, 2, 3], 8),
|
||||
(vec![3], 8),
|
||||
],
|
||||
vec![(vec![1, 2, 3], 8), (vec![3], 8),],
|
||||
);
|
||||
|
||||
child::put(&child_info_a, &[1, 2, 3], &8u16);
|
||||
@@ -1461,28 +1468,21 @@ mod test {
|
||||
assert_eq!(
|
||||
ChildTriePrefixIterator::with_prefix_over_key::<Identity>(&child_info_a, &[2])
|
||||
.collect::<Vec<(u16, u16)>>(),
|
||||
vec![
|
||||
(u16::decode(&mut &[2, 3][..]).unwrap(), 8),
|
||||
],
|
||||
vec![(u16::decode(&mut &[2, 3][..]).unwrap(), 8),],
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
ChildTriePrefixIterator::with_prefix_over_key::<Identity>(&child_info_a, &[2])
|
||||
.drain()
|
||||
.collect::<Vec<(u16, u16)>>(),
|
||||
vec![
|
||||
(u16::decode(&mut &[2, 3][..]).unwrap(), 8),
|
||||
],
|
||||
vec![(u16::decode(&mut &[2, 3][..]).unwrap(), 8),],
|
||||
);
|
||||
|
||||
// The only remaining is the ones outside prefix
|
||||
assert_eq!(
|
||||
ChildTriePrefixIterator::with_prefix(&child_info_a, &[])
|
||||
.collect::<Vec<(Vec<u8>, u8)>>(),
|
||||
vec![
|
||||
(vec![1, 2, 3], 8),
|
||||
(vec![3], 8),
|
||||
],
|
||||
vec![(vec![1, 2, 3], 8), (vec![3], 8),],
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -18,14 +18,14 @@
|
||||
//! Storage map type. Implements StorageDoubleMap, StorageIterableDoubleMap,
|
||||
//! StoragePrefixedDoubleMap traits and their methods directly.
|
||||
|
||||
use codec::{Decode, Encode, EncodeLike, FullCodec, MaxEncodedLen};
|
||||
use crate::{
|
||||
storage::{
|
||||
StorageAppend, StorageTryAppend, StorageDecodeLength, StoragePrefixedMap,
|
||||
types::{OptionQuery, QueryKindTrait, OnEmptyGetter},
|
||||
types::{OnEmptyGetter, OptionQuery, QueryKindTrait},
|
||||
StorageAppend, StorageDecodeLength, StoragePrefixedMap, StorageTryAppend,
|
||||
},
|
||||
traits::{GetDefault, StorageInstance, Get, StorageInfo},
|
||||
traits::{Get, GetDefault, StorageInfo, StorageInstance},
|
||||
};
|
||||
use codec::{Decode, Encode, EncodeLike, FullCodec, MaxEncodedLen};
|
||||
use frame_metadata::{DefaultByteGetter, StorageEntryModifier};
|
||||
use sp_arithmetic::traits::SaturatedConversion;
|
||||
use sp_std::prelude::*;
|
||||
@@ -36,9 +36,9 @@ use sp_std::prelude::*;
|
||||
/// Each value is stored at:
|
||||
/// ```nocompile
|
||||
/// Twox128(Prefix::pallet_prefix())
|
||||
/// ++ Twox128(Prefix::STORAGE_PREFIX)
|
||||
/// ++ Hasher1(encode(key1))
|
||||
/// ++ Hasher2(encode(key2))
|
||||
/// ++ Twox128(Prefix::STORAGE_PREFIX)
|
||||
/// ++ Hasher1(encode(key1))
|
||||
/// ++ Hasher2(encode(key2))
|
||||
/// ```
|
||||
///
|
||||
/// # Warning
|
||||
@@ -53,18 +53,26 @@ pub struct StorageDoubleMap<
|
||||
Hasher2,
|
||||
Key2,
|
||||
Value,
|
||||
QueryKind=OptionQuery,
|
||||
OnEmpty=GetDefault,
|
||||
MaxValues=GetDefault,
|
||||
QueryKind = OptionQuery,
|
||||
OnEmpty = GetDefault,
|
||||
MaxValues = GetDefault,
|
||||
>(
|
||||
core::marker::PhantomData<
|
||||
(Prefix, Hasher1, Key1, Hasher2, Key2, Value, QueryKind, OnEmpty, MaxValues)
|
||||
>
|
||||
core::marker::PhantomData<(
|
||||
Prefix,
|
||||
Hasher1,
|
||||
Key1,
|
||||
Hasher2,
|
||||
Key2,
|
||||
Value,
|
||||
QueryKind,
|
||||
OnEmpty,
|
||||
MaxValues,
|
||||
)>,
|
||||
);
|
||||
|
||||
impl<Prefix, Hasher1, Key1, Hasher2, Key2, Value, QueryKind, OnEmpty, MaxValues>
|
||||
crate::storage::generator::StorageDoubleMap<Key1, Key2, Value> for
|
||||
StorageDoubleMap<Prefix, Hasher1, Key1, Hasher2, Key2, Value, QueryKind, OnEmpty, MaxValues>
|
||||
crate::storage::generator::StorageDoubleMap<Key1, Key2, Value>
|
||||
for StorageDoubleMap<Prefix, Hasher1, Key1, Hasher2, Key2, Value, QueryKind, OnEmpty, MaxValues>
|
||||
where
|
||||
Prefix: StorageInstance,
|
||||
Hasher1: crate::hash::StorageHasher,
|
||||
@@ -94,8 +102,8 @@ where
|
||||
}
|
||||
|
||||
impl<Prefix, Hasher1, Key1, Hasher2, Key2, Value, QueryKind, OnEmpty, MaxValues>
|
||||
StoragePrefixedMap<Value> for
|
||||
StorageDoubleMap<Prefix, Hasher1, Key1, Hasher2, Key2, Value, QueryKind, OnEmpty, MaxValues>
|
||||
StoragePrefixedMap<Value>
|
||||
for StorageDoubleMap<Prefix, Hasher1, Key1, Hasher2, Key2, Value, QueryKind, OnEmpty, MaxValues>
|
||||
where
|
||||
Prefix: StorageInstance,
|
||||
Hasher1: crate::hash::StorageHasher,
|
||||
@@ -161,7 +169,8 @@ where
|
||||
pub fn try_get<KArg1, KArg2>(k1: KArg1, k2: KArg2) -> Result<Value, ()>
|
||||
where
|
||||
KArg1: EncodeLike<Key1>,
|
||||
KArg2: EncodeLike<Key2> {
|
||||
KArg2: EncodeLike<Key2>,
|
||||
{
|
||||
<Self as crate::storage::StorageDoubleMap<Key1, Key2, Value>>::try_get(k1, k2)
|
||||
}
|
||||
|
||||
@@ -175,8 +184,12 @@ where
|
||||
}
|
||||
|
||||
/// Swap the values of two key-pairs.
|
||||
pub fn swap<XKArg1, XKArg2, YKArg1, YKArg2>(x_k1: XKArg1, x_k2: XKArg2, y_k1: YKArg1, y_k2: YKArg2)
|
||||
where
|
||||
pub fn swap<XKArg1, XKArg2, YKArg1, YKArg2>(
|
||||
x_k1: XKArg1,
|
||||
x_k2: XKArg2,
|
||||
y_k1: YKArg1,
|
||||
y_k2: YKArg2,
|
||||
) where
|
||||
XKArg1: EncodeLike<Key1>,
|
||||
XKArg2: EncodeLike<Key2>,
|
||||
YKArg1: EncodeLike<Key1>,
|
||||
@@ -206,13 +219,16 @@ where
|
||||
|
||||
/// Remove all values under the first key.
|
||||
pub fn remove_prefix<KArg1>(k1: KArg1, limit: Option<u32>) -> sp_io::KillStorageResult
|
||||
where KArg1: ?Sized + EncodeLike<Key1> {
|
||||
where
|
||||
KArg1: ?Sized + EncodeLike<Key1>,
|
||||
{
|
||||
<Self as crate::storage::StorageDoubleMap<Key1, Key2, Value>>::remove_prefix(k1, limit)
|
||||
}
|
||||
|
||||
/// Iterate over values that share the first key.
|
||||
pub fn iter_prefix_values<KArg1>(k1: KArg1) -> crate::storage::PrefixIterator<Value>
|
||||
where KArg1: ?Sized + EncodeLike<Key1>
|
||||
where
|
||||
KArg1: ?Sized + EncodeLike<Key1>,
|
||||
{
|
||||
<Self as crate::storage::StorageDoubleMap<Key1, Key2, Value>>::iter_prefix_values(k1)
|
||||
}
|
||||
@@ -266,11 +282,8 @@ where
|
||||
/// If the storage item is not encoded properly, the storage will be overwritten
|
||||
/// and set to `[item]`. Any default value set for the storage item will be ignored
|
||||
/// on overwrite.
|
||||
pub fn append<Item, EncodeLikeItem, KArg1, KArg2>(
|
||||
k1: KArg1,
|
||||
k2: KArg2,
|
||||
item: EncodeLikeItem,
|
||||
) where
|
||||
pub fn append<Item, EncodeLikeItem, KArg1, KArg2>(k1: KArg1, k2: KArg2, item: EncodeLikeItem)
|
||||
where
|
||||
KArg1: EncodeLike<Key1>,
|
||||
KArg2: EncodeLike<Key2>,
|
||||
Item: Encode,
|
||||
@@ -310,10 +323,16 @@ where
|
||||
OldHasher2: crate::StorageHasher,
|
||||
KeyArg1: EncodeLike<Key1>,
|
||||
KeyArg2: EncodeLike<Key2>,
|
||||
>(key1: KeyArg1, key2: KeyArg2) -> Option<Value> {
|
||||
<
|
||||
Self as crate::storage::StorageDoubleMap<Key1, Key2, Value>
|
||||
>::migrate_keys::<OldHasher1, OldHasher2, _, _>(key1, key2)
|
||||
>(
|
||||
key1: KeyArg1,
|
||||
key2: KeyArg2,
|
||||
) -> Option<Value> {
|
||||
<Self as crate::storage::StorageDoubleMap<Key1, Key2, Value>>::migrate_keys::<
|
||||
OldHasher1,
|
||||
OldHasher2,
|
||||
_,
|
||||
_,
|
||||
>(key1, key2)
|
||||
}
|
||||
|
||||
/// Remove all value of the storage.
|
||||
@@ -360,9 +379,9 @@ where
|
||||
EncodeLikeItem: EncodeLike<Item>,
|
||||
Value: StorageTryAppend<Item>,
|
||||
{
|
||||
<
|
||||
Self as crate::storage::TryAppendDoubleMap<Key1, Key2, Value, Item>
|
||||
>::try_append(key1, key2, item)
|
||||
<Self as crate::storage::TryAppendDoubleMap<Key1, Key2, Value, Item>>::try_append(
|
||||
key1, key2, item,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -401,7 +420,9 @@ where
|
||||
///
|
||||
/// If you add elements with first key `k1` to the map while doing this, you'll get undefined
|
||||
/// results.
|
||||
pub fn drain_prefix(k1: impl EncodeLike<Key1>) -> crate::storage::PrefixIterator<(Key2, Value)> {
|
||||
pub fn drain_prefix(
|
||||
k1: impl EncodeLike<Key1>,
|
||||
) -> crate::storage::PrefixIterator<(Key2, Value)> {
|
||||
<Self as crate::storage::IterableStorageDoubleMap<Key1, Key2, Value>>::drain_prefix(k1)
|
||||
}
|
||||
|
||||
@@ -448,8 +469,8 @@ pub trait StorageDoubleMapMetadata {
|
||||
}
|
||||
|
||||
impl<Prefix, Hasher1, Hasher2, Key1, Key2, Value, QueryKind, OnEmpty, MaxValues>
|
||||
StorageDoubleMapMetadata for
|
||||
StorageDoubleMap<Prefix, Hasher1, Key1, Hasher2, Key2, Value, QueryKind, OnEmpty, MaxValues>
|
||||
StorageDoubleMapMetadata
|
||||
for StorageDoubleMap<Prefix, Hasher1, Key1, Hasher2, Key2, Value, QueryKind, OnEmpty, MaxValues>
|
||||
where
|
||||
Prefix: StorageInstance,
|
||||
Hasher1: crate::hash::StorageHasher,
|
||||
@@ -470,8 +491,8 @@ where
|
||||
}
|
||||
|
||||
impl<Prefix, Hasher1, Hasher2, Key1, Key2, Value, QueryKind, OnEmpty, MaxValues>
|
||||
crate::traits::StorageInfoTrait for
|
||||
StorageDoubleMap<Prefix, Hasher1, Key1, Hasher2, Key2, Value, QueryKind, OnEmpty, MaxValues>
|
||||
crate::traits::StorageInfoTrait
|
||||
for StorageDoubleMap<Prefix, Hasher1, Key1, Hasher2, Key2, Value, QueryKind, OnEmpty, MaxValues>
|
||||
where
|
||||
Prefix: StorageInstance,
|
||||
Hasher1: crate::hash::StorageHasher,
|
||||
@@ -484,27 +505,25 @@ where
|
||||
MaxValues: Get<Option<u32>>,
|
||||
{
|
||||
fn storage_info() -> Vec<StorageInfo> {
|
||||
vec![
|
||||
StorageInfo {
|
||||
pallet_name: Self::module_prefix().to_vec(),
|
||||
storage_name: Self::storage_prefix().to_vec(),
|
||||
prefix: Self::final_prefix().to_vec(),
|
||||
max_values: MaxValues::get(),
|
||||
max_size: Some(
|
||||
Hasher1::max_len::<Key1>()
|
||||
.saturating_add(Hasher2::max_len::<Key2>())
|
||||
.saturating_add(Value::max_encoded_len())
|
||||
.saturated_into(),
|
||||
),
|
||||
}
|
||||
]
|
||||
vec![StorageInfo {
|
||||
pallet_name: Self::module_prefix().to_vec(),
|
||||
storage_name: Self::storage_prefix().to_vec(),
|
||||
prefix: Self::final_prefix().to_vec(),
|
||||
max_values: MaxValues::get(),
|
||||
max_size: Some(
|
||||
Hasher1::max_len::<Key1>()
|
||||
.saturating_add(Hasher2::max_len::<Key2>())
|
||||
.saturating_add(Value::max_encoded_len())
|
||||
.saturated_into(),
|
||||
),
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
||||
/// It doesn't require to implement `MaxEncodedLen` and give no information for `max_size`.
|
||||
impl<Prefix, Hasher1, Hasher2, Key1, Key2, Value, QueryKind, OnEmpty, MaxValues>
|
||||
crate::traits::PartialStorageInfoTrait for
|
||||
StorageDoubleMap<Prefix, Hasher1, Key1, Hasher2, Key2, Value, QueryKind, OnEmpty, MaxValues>
|
||||
crate::traits::PartialStorageInfoTrait
|
||||
for StorageDoubleMap<Prefix, Hasher1, Key1, Hasher2, Key2, Value, QueryKind, OnEmpty, MaxValues>
|
||||
where
|
||||
Prefix: StorageInstance,
|
||||
Hasher1: crate::hash::StorageHasher,
|
||||
@@ -517,29 +536,28 @@ where
|
||||
MaxValues: Get<Option<u32>>,
|
||||
{
|
||||
fn partial_storage_info() -> Vec<StorageInfo> {
|
||||
vec![
|
||||
StorageInfo {
|
||||
pallet_name: Self::module_prefix().to_vec(),
|
||||
storage_name: Self::storage_prefix().to_vec(),
|
||||
prefix: Self::final_prefix().to_vec(),
|
||||
max_values: MaxValues::get(),
|
||||
max_size: None
|
||||
}
|
||||
]
|
||||
vec![StorageInfo {
|
||||
pallet_name: Self::module_prefix().to_vec(),
|
||||
storage_name: Self::storage_prefix().to_vec(),
|
||||
prefix: Self::final_prefix().to_vec(),
|
||||
max_values: MaxValues::get(),
|
||||
max_size: None,
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use sp_io::{TestExternalities, hashing::twox_128};
|
||||
use crate::hash::*;
|
||||
use crate::storage::types::ValueQuery;
|
||||
use crate::{hash::*, storage::types::ValueQuery};
|
||||
use frame_metadata::StorageEntryModifier;
|
||||
use sp_io::{hashing::twox_128, TestExternalities};
|
||||
|
||||
struct Prefix;
|
||||
impl StorageInstance for Prefix {
|
||||
fn pallet_prefix() -> &'static str { "test" }
|
||||
fn pallet_prefix() -> &'static str {
|
||||
"test"
|
||||
}
|
||||
const STORAGE_PREFIX: &'static str = "foo";
|
||||
}
|
||||
|
||||
@@ -552,11 +570,17 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn test() {
|
||||
type A = StorageDoubleMap<
|
||||
Prefix, Blake2_128Concat, u16, Twox64Concat, u8, u32, OptionQuery
|
||||
>;
|
||||
type A =
|
||||
StorageDoubleMap<Prefix, Blake2_128Concat, u16, Twox64Concat, u8, u32, OptionQuery>;
|
||||
type AValueQueryWithAnOnEmpty = StorageDoubleMap<
|
||||
Prefix, Blake2_128Concat, u16, Twox64Concat, u8, u32, ValueQuery, ADefault
|
||||
Prefix,
|
||||
Blake2_128Concat,
|
||||
u16,
|
||||
Twox64Concat,
|
||||
u8,
|
||||
u32,
|
||||
ValueQuery,
|
||||
ADefault,
|
||||
>;
|
||||
type B = StorageDoubleMap<Prefix, Blake2_256, u16, Twox128, u8, u32, ValueQuery>;
|
||||
type C = StorageDoubleMap<Prefix, Blake2_128Concat, u16, Twox64Concat, u8, u8, ValueQuery>;
|
||||
@@ -598,17 +622,20 @@ mod test {
|
||||
|
||||
A::remove(2, 20);
|
||||
let _: Result<(), ()> = AValueQueryWithAnOnEmpty::try_mutate(2, 20, |v| {
|
||||
*v = *v * 2; Ok(())
|
||||
*v = *v * 2;
|
||||
Ok(())
|
||||
});
|
||||
let _: Result<(), ()> = AValueQueryWithAnOnEmpty::try_mutate(2, 20, |v| {
|
||||
*v = *v * 2; Ok(())
|
||||
*v = *v * 2;
|
||||
Ok(())
|
||||
});
|
||||
assert_eq!(A::contains_key(2, 20), true);
|
||||
assert_eq!(A::get(2, 20), Some(97 * 4));
|
||||
|
||||
A::remove(2, 20);
|
||||
let _: Result<(), ()> = AValueQueryWithAnOnEmpty::try_mutate(2, 20, |v| {
|
||||
*v = *v * 2; Err(())
|
||||
*v = *v * 2;
|
||||
Err(())
|
||||
});
|
||||
assert_eq!(A::contains_key(2, 20), false);
|
||||
|
||||
@@ -647,7 +674,6 @@ mod test {
|
||||
assert_eq!(A::contains_key(2, 20), true);
|
||||
assert_eq!(A::get(2, 20), Some(100));
|
||||
|
||||
|
||||
A::insert(2, 20, 10);
|
||||
assert_eq!(A::take(2, 20), Some(10));
|
||||
assert_eq!(A::contains_key(2, 20), false);
|
||||
@@ -672,7 +698,7 @@ mod test {
|
||||
|
||||
C::insert(3, 30, 10);
|
||||
C::insert(4, 40, 10);
|
||||
A::translate_values::<u8,_>(|v| Some((v * 2).into()));
|
||||
A::translate_values::<u8, _>(|v| Some((v * 2).into()));
|
||||
assert_eq!(A::iter().collect::<Vec<_>>(), vec![(4, 40, 20), (3, 30, 20)]);
|
||||
|
||||
A::insert(3, 30, 10);
|
||||
@@ -683,7 +709,7 @@ mod test {
|
||||
|
||||
C::insert(3, 30, 10);
|
||||
C::insert(4, 40, 10);
|
||||
A::translate::<u8,_>(|k1, k2, v| Some((k1 * k2 as u16 * v as u16).into()));
|
||||
A::translate::<u8, _>(|k1, k2, v| Some((k1 * k2 as u16 * v as u16).into()));
|
||||
assert_eq!(A::iter().collect::<Vec<_>>(), vec![(4, 40, 1600), (3, 30, 900)]);
|
||||
|
||||
assert_eq!(A::MODIFIER, StorageEntryModifier::Optional);
|
||||
|
||||
@@ -75,24 +75,16 @@ impl<H: StorageHasher, K: FullCodec> KeyGenerator for Key<H, K> {
|
||||
const HASHER_METADATA: &'static [frame_metadata::StorageHasher] = &[H::METADATA];
|
||||
|
||||
fn final_key<KArg: EncodeLikeTuple<Self::KArg> + TupleToEncodedIter>(key: KArg) -> Vec<u8> {
|
||||
H::hash(
|
||||
&key.to_encoded_iter()
|
||||
.next()
|
||||
.expect("should have at least one element!"),
|
||||
)
|
||||
.as_ref()
|
||||
.to_vec()
|
||||
H::hash(&key.to_encoded_iter().next().expect("should have at least one element!"))
|
||||
.as_ref()
|
||||
.to_vec()
|
||||
}
|
||||
|
||||
fn migrate_key<KArg: EncodeLikeTuple<Self::KArg> + TupleToEncodedIter>(
|
||||
key: &KArg,
|
||||
hash_fns: Self::HArg,
|
||||
) -> Vec<u8> {
|
||||
(hash_fns.0)(
|
||||
&key.to_encoded_iter()
|
||||
.next()
|
||||
.expect("should have at least one element!"),
|
||||
)
|
||||
(hash_fns.0)(&key.to_encoded_iter().next().expect("should have at least one element!"))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,9 +110,8 @@ impl KeyGenerator for Tuple {
|
||||
for_tuples!( type HArg = ( #(Tuple::HashFn),* ); );
|
||||
type HashFn = Box<dyn FnOnce(&[u8]) -> Vec<u8>>;
|
||||
|
||||
const HASHER_METADATA: &'static [frame_metadata::StorageHasher] = &[
|
||||
for_tuples!( #(Tuple::Hasher::METADATA),* )
|
||||
];
|
||||
const HASHER_METADATA: &'static [frame_metadata::StorageHasher] =
|
||||
&[for_tuples!( #(Tuple::Hasher::METADATA),* )];
|
||||
|
||||
fn final_key<KArg: EncodeLikeTuple<Self::KArg> + TupleToEncodedIter>(key: KArg) -> Vec<u8> {
|
||||
let mut final_key = Vec::new();
|
||||
@@ -210,9 +201,7 @@ pub trait TupleToEncodedIter {
|
||||
#[tuple_types_custom_trait_bound(Encode)]
|
||||
impl TupleToEncodedIter for Tuple {
|
||||
fn to_encoded_iter(&self) -> sp_std::vec::IntoIter<Vec<u8>> {
|
||||
[for_tuples!( #(self.Tuple.encode()),* )]
|
||||
.to_vec()
|
||||
.into_iter()
|
||||
[for_tuples!( #(self.Tuple.encode()),* )].to_vec().into_iter()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -246,7 +235,7 @@ impl ReversibleKeyGenerator for Tuple {
|
||||
fn decode_final_key(key_material: &[u8]) -> Result<(Self::Key, &[u8]), codec::Error> {
|
||||
let mut current_key_material = key_material;
|
||||
Ok((
|
||||
(for_tuples!{
|
||||
(for_tuples! {
|
||||
#({
|
||||
let (key, material) = Tuple::decode_final_key(current_key_material)?;
|
||||
current_key_material = material;
|
||||
|
||||
@@ -18,14 +18,14 @@
|
||||
//! Storage map type. Implements StorageMap, StorageIterableMap, StoragePrefixedMap traits and their
|
||||
//! methods directly.
|
||||
|
||||
use codec::{FullCodec, Decode, EncodeLike, Encode, MaxEncodedLen};
|
||||
use crate::{
|
||||
storage::{
|
||||
StorageAppend, StorageTryAppend, StorageDecodeLength, StoragePrefixedMap,
|
||||
types::{OptionQuery, QueryKindTrait, OnEmptyGetter},
|
||||
types::{OnEmptyGetter, OptionQuery, QueryKindTrait},
|
||||
StorageAppend, StorageDecodeLength, StoragePrefixedMap, StorageTryAppend,
|
||||
},
|
||||
traits::{GetDefault, StorageInstance, Get, StorageInfo},
|
||||
traits::{Get, GetDefault, StorageInfo, StorageInstance},
|
||||
};
|
||||
use codec::{Decode, Encode, EncodeLike, FullCodec, MaxEncodedLen};
|
||||
use frame_metadata::{DefaultByteGetter, StorageEntryModifier};
|
||||
use sp_arithmetic::traits::SaturatedConversion;
|
||||
use sp_std::prelude::*;
|
||||
@@ -35,8 +35,8 @@ use sp_std::prelude::*;
|
||||
/// Each value is stored at:
|
||||
/// ```nocompile
|
||||
/// Twox128(Prefix::pallet_prefix())
|
||||
/// ++ Twox128(Prefix::STORAGE_PREFIX)
|
||||
/// ++ Hasher1(encode(key))
|
||||
/// ++ Twox128(Prefix::STORAGE_PREFIX)
|
||||
/// ++ Hasher1(encode(key))
|
||||
/// ```
|
||||
///
|
||||
/// # Warning
|
||||
@@ -44,10 +44,14 @@ use sp_std::prelude::*;
|
||||
/// If the keys are not trusted (e.g. can be set by a user), a cryptographic `hasher` such as
|
||||
/// `blake2_128_concat` must be used. Otherwise, other values in storage can be compromised.
|
||||
pub struct StorageMap<
|
||||
Prefix, Hasher, Key, Value, QueryKind=OptionQuery, OnEmpty=GetDefault, MaxValues=GetDefault,
|
||||
>(
|
||||
core::marker::PhantomData<(Prefix, Hasher, Key, Value, QueryKind, OnEmpty, MaxValues)>
|
||||
);
|
||||
Prefix,
|
||||
Hasher,
|
||||
Key,
|
||||
Value,
|
||||
QueryKind = OptionQuery,
|
||||
OnEmpty = GetDefault,
|
||||
MaxValues = GetDefault,
|
||||
>(core::marker::PhantomData<(Prefix, Hasher, Key, Value, QueryKind, OnEmpty, MaxValues)>);
|
||||
|
||||
impl<Prefix, Hasher, Key, Value, QueryKind, OnEmpty, MaxValues>
|
||||
crate::storage::generator::StorageMap<Key, Value>
|
||||
@@ -77,9 +81,8 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<Prefix, Hasher, Key, Value, QueryKind, OnEmpty, MaxValues>
|
||||
StoragePrefixedMap<Value> for
|
||||
StorageMap<Prefix, Hasher, Key, Value, QueryKind, OnEmpty, MaxValues>
|
||||
impl<Prefix, Hasher, Key, Value, QueryKind, OnEmpty, MaxValues> StoragePrefixedMap<Value>
|
||||
for StorageMap<Prefix, Hasher, Key, Value, QueryKind, OnEmpty, MaxValues>
|
||||
where
|
||||
Prefix: StorageInstance,
|
||||
Hasher: crate::hash::StorageHasher,
|
||||
@@ -148,7 +151,7 @@ where
|
||||
/// Mutate the value under a key.
|
||||
pub fn mutate<KeyArg: EncodeLike<Key>, R, F: FnOnce(&mut QueryKind::Query) -> R>(
|
||||
key: KeyArg,
|
||||
f: F
|
||||
f: F,
|
||||
) -> R {
|
||||
<Self as crate::storage::StorageMap<Key, Value>>::mutate(key, f)
|
||||
}
|
||||
@@ -165,7 +168,7 @@ where
|
||||
/// Mutate the value under a key. Deletes the item if mutated to a `None`.
|
||||
pub fn mutate_exists<KeyArg: EncodeLike<Key>, R, F: FnOnce(&mut Option<Value>) -> R>(
|
||||
key: KeyArg,
|
||||
f: F
|
||||
f: F,
|
||||
) -> R {
|
||||
<Self as crate::storage::StorageMap<Key, Value>>::mutate_exists(key, f)
|
||||
}
|
||||
@@ -198,7 +201,7 @@ where
|
||||
EncodeLikeKey: EncodeLike<Key>,
|
||||
Item: Encode,
|
||||
EncodeLikeItem: EncodeLike<Item>,
|
||||
Value: StorageAppend<Item>
|
||||
Value: StorageAppend<Item>,
|
||||
{
|
||||
<Self as crate::storage::StorageMap<Key, Value>>::append(key, item)
|
||||
}
|
||||
@@ -216,7 +219,8 @@ where
|
||||
/// `None` does not mean that `get()` does not return a value. The default value is completly
|
||||
/// ignored by this function.
|
||||
pub fn decode_len<KeyArg: EncodeLike<Key>>(key: KeyArg) -> Option<usize>
|
||||
where Value: StorageDecodeLength,
|
||||
where
|
||||
Value: StorageDecodeLength,
|
||||
{
|
||||
<Self as crate::storage::StorageMap<Key, Value>>::decode_len(key)
|
||||
}
|
||||
@@ -225,7 +229,7 @@ where
|
||||
///
|
||||
/// If the key doesn't exist, then it's a no-op. If it does, then it returns its value.
|
||||
pub fn migrate_key<OldHasher: crate::hash::StorageHasher, KeyArg: EncodeLike<Key>>(
|
||||
key: KeyArg
|
||||
key: KeyArg,
|
||||
) -> Option<Value> {
|
||||
<Self as crate::storage::StorageMap<Key, Value>>::migrate_key::<OldHasher, _>(key)
|
||||
}
|
||||
@@ -263,19 +267,14 @@ where
|
||||
/// Try and append the given item to the value in the storage.
|
||||
///
|
||||
/// Is only available if `Value` of the storage implements [`StorageTryAppend`].
|
||||
pub fn try_append<KArg, Item, EncodeLikeItem>(
|
||||
key: KArg,
|
||||
item: EncodeLikeItem,
|
||||
) -> Result<(), ()>
|
||||
pub fn try_append<KArg, Item, EncodeLikeItem>(key: KArg, item: EncodeLikeItem) -> Result<(), ()>
|
||||
where
|
||||
KArg: EncodeLike<Key> + Clone,
|
||||
Item: Encode,
|
||||
EncodeLikeItem: EncodeLike<Item>,
|
||||
Value: StorageTryAppend<Item>,
|
||||
{
|
||||
<
|
||||
Self as crate::storage::TryAppendMap<Key, Value, Item>
|
||||
>::try_append(key, item)
|
||||
<Self as crate::storage::TryAppendMap<Key, Value, Item>>::try_append(key, item)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -332,7 +331,8 @@ pub trait StorageMapMetadata {
|
||||
}
|
||||
|
||||
impl<Prefix, Hasher, Key, Value, QueryKind, OnEmpty, MaxValues> StorageMapMetadata
|
||||
for StorageMap<Prefix, Hasher, Key, Value, QueryKind, OnEmpty, MaxValues> where
|
||||
for StorageMap<Prefix, Hasher, Key, Value, QueryKind, OnEmpty, MaxValues>
|
||||
where
|
||||
Prefix: StorageInstance,
|
||||
Hasher: crate::hash::StorageHasher,
|
||||
Key: FullCodec,
|
||||
@@ -348,9 +348,8 @@ impl<Prefix, Hasher, Key, Value, QueryKind, OnEmpty, MaxValues> StorageMapMetada
|
||||
DefaultByteGetter(&OnEmptyGetter::<QueryKind::Query, OnEmpty>(core::marker::PhantomData));
|
||||
}
|
||||
|
||||
impl<Prefix, Hasher, Key, Value, QueryKind, OnEmpty, MaxValues>
|
||||
crate::traits::StorageInfoTrait for
|
||||
StorageMap<Prefix, Hasher, Key, Value, QueryKind, OnEmpty, MaxValues>
|
||||
impl<Prefix, Hasher, Key, Value, QueryKind, OnEmpty, MaxValues> crate::traits::StorageInfoTrait
|
||||
for StorageMap<Prefix, Hasher, Key, Value, QueryKind, OnEmpty, MaxValues>
|
||||
where
|
||||
Prefix: StorageInstance,
|
||||
Hasher: crate::hash::StorageHasher,
|
||||
@@ -361,26 +360,24 @@ where
|
||||
MaxValues: Get<Option<u32>>,
|
||||
{
|
||||
fn storage_info() -> Vec<StorageInfo> {
|
||||
vec![
|
||||
StorageInfo {
|
||||
pallet_name: Self::module_prefix().to_vec(),
|
||||
storage_name: Self::storage_prefix().to_vec(),
|
||||
prefix: Self::final_prefix().to_vec(),
|
||||
max_values: MaxValues::get(),
|
||||
max_size: Some(
|
||||
Hasher::max_len::<Key>()
|
||||
.saturating_add(Value::max_encoded_len())
|
||||
.saturated_into(),
|
||||
),
|
||||
}
|
||||
]
|
||||
vec![StorageInfo {
|
||||
pallet_name: Self::module_prefix().to_vec(),
|
||||
storage_name: Self::storage_prefix().to_vec(),
|
||||
prefix: Self::final_prefix().to_vec(),
|
||||
max_values: MaxValues::get(),
|
||||
max_size: Some(
|
||||
Hasher::max_len::<Key>()
|
||||
.saturating_add(Value::max_encoded_len())
|
||||
.saturated_into(),
|
||||
),
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
||||
/// It doesn't require to implement `MaxEncodedLen` and give no information for `max_size`.
|
||||
impl<Prefix, Hasher, Key, Value, QueryKind, OnEmpty, MaxValues>
|
||||
crate::traits::PartialStorageInfoTrait for
|
||||
StorageMap<Prefix, Hasher, Key, Value, QueryKind, OnEmpty, MaxValues>
|
||||
crate::traits::PartialStorageInfoTrait
|
||||
for StorageMap<Prefix, Hasher, Key, Value, QueryKind, OnEmpty, MaxValues>
|
||||
where
|
||||
Prefix: StorageInstance,
|
||||
Hasher: crate::hash::StorageHasher,
|
||||
@@ -391,29 +388,28 @@ where
|
||||
MaxValues: Get<Option<u32>>,
|
||||
{
|
||||
fn partial_storage_info() -> Vec<StorageInfo> {
|
||||
vec![
|
||||
StorageInfo {
|
||||
pallet_name: Self::module_prefix().to_vec(),
|
||||
storage_name: Self::storage_prefix().to_vec(),
|
||||
prefix: Self::final_prefix().to_vec(),
|
||||
max_values: MaxValues::get(),
|
||||
max_size: None,
|
||||
}
|
||||
]
|
||||
vec![StorageInfo {
|
||||
pallet_name: Self::module_prefix().to_vec(),
|
||||
storage_name: Self::storage_prefix().to_vec(),
|
||||
prefix: Self::final_prefix().to_vec(),
|
||||
max_values: MaxValues::get(),
|
||||
max_size: None,
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use sp_io::{TestExternalities, hashing::twox_128};
|
||||
use crate::hash::*;
|
||||
use crate::storage::types::ValueQuery;
|
||||
use crate::{hash::*, storage::types::ValueQuery};
|
||||
use frame_metadata::StorageEntryModifier;
|
||||
use sp_io::{hashing::twox_128, TestExternalities};
|
||||
|
||||
struct Prefix;
|
||||
impl StorageInstance for Prefix {
|
||||
fn pallet_prefix() -> &'static str { "test" }
|
||||
fn pallet_prefix() -> &'static str {
|
||||
"test"
|
||||
}
|
||||
const STORAGE_PREFIX: &'static str = "foo";
|
||||
}
|
||||
|
||||
@@ -427,9 +423,8 @@ mod test {
|
||||
#[test]
|
||||
fn test() {
|
||||
type A = StorageMap<Prefix, Blake2_128Concat, u16, u32, OptionQuery>;
|
||||
type AValueQueryWithAnOnEmpty = StorageMap<
|
||||
Prefix, Blake2_128Concat, u16, u32, ValueQuery, ADefault
|
||||
>;
|
||||
type AValueQueryWithAnOnEmpty =
|
||||
StorageMap<Prefix, Blake2_128Concat, u16, u32, ValueQuery, ADefault>;
|
||||
type B = StorageMap<Prefix, Blake2_256, u16, u32, ValueQuery>;
|
||||
type C = StorageMap<Prefix, Blake2_128Concat, u16, u8, ValueQuery>;
|
||||
type WithLen = StorageMap<Prefix, Blake2_128Concat, u16, Vec<u32>>;
|
||||
@@ -471,17 +466,20 @@ mod test {
|
||||
|
||||
A::remove(2);
|
||||
let _: Result<(), ()> = AValueQueryWithAnOnEmpty::try_mutate(2, |v| {
|
||||
*v = *v * 2; Ok(())
|
||||
*v = *v * 2;
|
||||
Ok(())
|
||||
});
|
||||
let _: Result<(), ()> = AValueQueryWithAnOnEmpty::try_mutate(2, |v| {
|
||||
*v = *v * 2; Ok(())
|
||||
*v = *v * 2;
|
||||
Ok(())
|
||||
});
|
||||
assert_eq!(A::contains_key(2), true);
|
||||
assert_eq!(A::get(2), Some(97 * 4));
|
||||
|
||||
A::remove(2);
|
||||
let _: Result<(), ()> = AValueQueryWithAnOnEmpty::try_mutate(2, |v| {
|
||||
*v = *v * 2; Err(())
|
||||
*v = *v * 2;
|
||||
Err(())
|
||||
});
|
||||
assert_eq!(A::contains_key(2), false);
|
||||
|
||||
@@ -519,7 +517,6 @@ mod test {
|
||||
assert_eq!(A::contains_key(2), true);
|
||||
assert_eq!(A::get(2), Some(100));
|
||||
|
||||
|
||||
A::insert(2, 10);
|
||||
assert_eq!(A::take(2), Some(10));
|
||||
assert_eq!(A::contains_key(2), false);
|
||||
@@ -543,7 +540,7 @@ mod test {
|
||||
|
||||
C::insert(3, 10);
|
||||
C::insert(4, 10);
|
||||
A::translate_values::<u8,_>(|v| Some((v * 2).into()));
|
||||
A::translate_values::<u8, _>(|v| Some((v * 2).into()));
|
||||
assert_eq!(A::iter().collect::<Vec<_>>(), vec![(4, 20), (3, 20)]);
|
||||
|
||||
A::insert(3, 10);
|
||||
@@ -554,7 +551,7 @@ mod test {
|
||||
|
||||
C::insert(3, 10);
|
||||
C::insert(4, 10);
|
||||
A::translate::<u8,_>(|k, v| Some((k * v as u16).into()));
|
||||
A::translate::<u8, _>(|k, v| Some((k * v as u16).into()));
|
||||
assert_eq!(A::iter().collect::<Vec<_>>(), vec![(4, 40), (3, 30)]);
|
||||
|
||||
assert_eq!(A::MODIFIER, StorageEntryModifier::Optional);
|
||||
|
||||
@@ -30,7 +30,7 @@ mod value;
|
||||
pub use double_map::{StorageDoubleMap, StorageDoubleMapMetadata};
|
||||
pub use key::{
|
||||
EncodeLikeTuple, HasKeyPrefix, HasReversibleKeyPrefix, Key, KeyGenerator,
|
||||
ReversibleKeyGenerator, TupleToEncodedIter, KeyGeneratorMaxEncodedLen,
|
||||
KeyGeneratorMaxEncodedLen, ReversibleKeyGenerator, TupleToEncodedIter,
|
||||
};
|
||||
pub use map::{StorageMap, StorageMapMetadata};
|
||||
pub use nmap::{StorageNMap, StorageNMapMetadata};
|
||||
|
||||
@@ -21,12 +21,12 @@
|
||||
use crate::{
|
||||
storage::{
|
||||
types::{
|
||||
EncodeLikeTuple, HasKeyPrefix, HasReversibleKeyPrefix, OnEmptyGetter,
|
||||
OptionQuery, QueryKindTrait, TupleToEncodedIter,
|
||||
EncodeLikeTuple, HasKeyPrefix, HasReversibleKeyPrefix, OnEmptyGetter, OptionQuery,
|
||||
QueryKindTrait, TupleToEncodedIter,
|
||||
},
|
||||
KeyGenerator, PrefixIterator, StorageAppend, StorageDecodeLength, StoragePrefixedMap,
|
||||
},
|
||||
traits::{Get, GetDefault, StorageInstance, StorageInfo},
|
||||
traits::{Get, GetDefault, StorageInfo, StorageInstance},
|
||||
};
|
||||
use codec::{Decode, Encode, EncodeLike, FullCodec, MaxEncodedLen};
|
||||
use frame_metadata::{DefaultByteGetter, StorageEntryModifier};
|
||||
@@ -39,9 +39,9 @@ use sp_std::prelude::*;
|
||||
/// Each value is stored at:
|
||||
/// ```nocompile
|
||||
/// Twox128(Prefix::pallet_prefix())
|
||||
/// ++ Twox128(Prefix::STORAGE_PREFIX)
|
||||
/// ++ Hasher1(encode(key1))
|
||||
/// ++ Hasher2(encode(key2))
|
||||
/// ++ Twox128(Prefix::STORAGE_PREFIX)
|
||||
/// ++ Hasher1(encode(key1))
|
||||
/// ++ Hasher2(encode(key2))
|
||||
/// ++ ...
|
||||
/// ++ HasherN(encode(keyN))
|
||||
/// ```
|
||||
@@ -52,10 +52,13 @@ use sp_std::prelude::*;
|
||||
/// such as `blake2_128_concat` must be used for the key hashers. Otherwise, other values
|
||||
/// in storage can be compromised.
|
||||
pub struct StorageNMap<
|
||||
Prefix, Key, Value, QueryKind = OptionQuery, OnEmpty = GetDefault, MaxValues=GetDefault,
|
||||
>(
|
||||
core::marker::PhantomData<(Prefix, Key, Value, QueryKind, OnEmpty, MaxValues)>,
|
||||
);
|
||||
Prefix,
|
||||
Key,
|
||||
Value,
|
||||
QueryKind = OptionQuery,
|
||||
OnEmpty = GetDefault,
|
||||
MaxValues = GetDefault,
|
||||
>(core::marker::PhantomData<(Prefix, Key, Value, QueryKind, OnEmpty, MaxValues)>);
|
||||
|
||||
impl<Prefix, Key, Value, QueryKind, OnEmpty, MaxValues>
|
||||
crate::storage::generator::StorageNMap<Key, Value>
|
||||
@@ -83,8 +86,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<Prefix, Key, Value, QueryKind, OnEmpty, MaxValues>
|
||||
crate::storage::StoragePrefixedMap<Value>
|
||||
impl<Prefix, Key, Value, QueryKind, OnEmpty, MaxValues> crate::storage::StoragePrefixedMap<Value>
|
||||
for StorageNMap<Prefix, Key, Value, QueryKind, OnEmpty, MaxValues>
|
||||
where
|
||||
Prefix: StorageInstance,
|
||||
@@ -113,7 +115,9 @@ where
|
||||
MaxValues: Get<Option<u32>>,
|
||||
{
|
||||
/// Get the storage key used to fetch a value corresponding to a specific key.
|
||||
pub fn hashed_key_for<KArg: EncodeLikeTuple<Key::KArg> + TupleToEncodedIter>(key: KArg) -> Vec<u8> {
|
||||
pub fn hashed_key_for<KArg: EncodeLikeTuple<Key::KArg> + TupleToEncodedIter>(
|
||||
key: KArg,
|
||||
) -> Vec<u8> {
|
||||
<Self as crate::storage::StorageNMap<Key, Value>>::hashed_key_for(key)
|
||||
}
|
||||
|
||||
@@ -123,7 +127,9 @@ where
|
||||
}
|
||||
|
||||
/// Load the value associated with the given key from the map.
|
||||
pub fn get<KArg: EncodeLikeTuple<Key::KArg> + TupleToEncodedIter>(key: KArg) -> QueryKind::Query {
|
||||
pub fn get<KArg: EncodeLikeTuple<Key::KArg> + TupleToEncodedIter>(
|
||||
key: KArg,
|
||||
) -> QueryKind::Query {
|
||||
<Self as crate::storage::StorageNMap<Key, Value>>::get(key)
|
||||
}
|
||||
|
||||
@@ -137,7 +143,9 @@ where
|
||||
}
|
||||
|
||||
/// Take a value from storage, removing it afterwards.
|
||||
pub fn take<KArg: EncodeLikeTuple<Key::KArg> + TupleToEncodedIter>(key: KArg) -> QueryKind::Query {
|
||||
pub fn take<KArg: EncodeLikeTuple<Key::KArg> + TupleToEncodedIter>(
|
||||
key: KArg,
|
||||
) -> QueryKind::Query {
|
||||
<Self as crate::storage::StorageNMap<Key, Value>>::take(key)
|
||||
}
|
||||
|
||||
@@ -248,7 +256,9 @@ where
|
||||
///
|
||||
/// `None` does not mean that `get()` does not return a value. The default value is completly
|
||||
/// ignored by this function.
|
||||
pub fn decode_len<KArg: EncodeLikeTuple<Key::KArg> + TupleToEncodedIter>(key: KArg) -> Option<usize>
|
||||
pub fn decode_len<KArg: EncodeLikeTuple<Key::KArg> + TupleToEncodedIter>(
|
||||
key: KArg,
|
||||
) -> Option<usize>
|
||||
where
|
||||
Value: StorageDecodeLength,
|
||||
{
|
||||
@@ -260,7 +270,7 @@ where
|
||||
/// If the key doesn't exist, then it's a no-op. If it does, then it returns its value.
|
||||
pub fn migrate_keys<KArg>(key: KArg, hash_fns: Key::HArg) -> Option<Value>
|
||||
where
|
||||
KArg: EncodeLikeTuple<Key::KArg> + TupleToEncodedIter
|
||||
KArg: EncodeLikeTuple<Key::KArg> + TupleToEncodedIter,
|
||||
{
|
||||
<Self as crate::storage::StorageNMap<Key, Value>>::migrate_keys::<_>(key, hash_fns)
|
||||
}
|
||||
@@ -398,15 +408,13 @@ where
|
||||
{
|
||||
const MODIFIER: StorageEntryModifier = QueryKind::METADATA;
|
||||
const NAME: &'static str = Prefix::STORAGE_PREFIX;
|
||||
const DEFAULT: DefaultByteGetter = DefaultByteGetter(
|
||||
&OnEmptyGetter::<QueryKind::Query, OnEmpty>(core::marker::PhantomData),
|
||||
);
|
||||
const DEFAULT: DefaultByteGetter =
|
||||
DefaultByteGetter(&OnEmptyGetter::<QueryKind::Query, OnEmpty>(core::marker::PhantomData));
|
||||
const HASHERS: &'static [frame_metadata::StorageHasher] = Key::HASHER_METADATA;
|
||||
}
|
||||
|
||||
impl<Prefix, Key, Value, QueryKind, OnEmpty, MaxValues>
|
||||
crate::traits::StorageInfoTrait for
|
||||
StorageNMap<Prefix, Key, Value, QueryKind, OnEmpty, MaxValues>
|
||||
impl<Prefix, Key, Value, QueryKind, OnEmpty, MaxValues> crate::traits::StorageInfoTrait
|
||||
for StorageNMap<Prefix, Key, Value, QueryKind, OnEmpty, MaxValues>
|
||||
where
|
||||
Prefix: StorageInstance,
|
||||
Key: super::key::KeyGenerator + super::key::KeyGeneratorMaxEncodedLen,
|
||||
@@ -416,26 +424,23 @@ where
|
||||
MaxValues: Get<Option<u32>>,
|
||||
{
|
||||
fn storage_info() -> Vec<StorageInfo> {
|
||||
vec![
|
||||
StorageInfo {
|
||||
pallet_name: Self::module_prefix().to_vec(),
|
||||
storage_name: Self::storage_prefix().to_vec(),
|
||||
prefix: Self::final_prefix().to_vec(),
|
||||
max_values: MaxValues::get(),
|
||||
max_size: Some(
|
||||
Key::key_max_encoded_len()
|
||||
.saturating_add(Value::max_encoded_len())
|
||||
.saturated_into(),
|
||||
),
|
||||
}
|
||||
]
|
||||
vec![StorageInfo {
|
||||
pallet_name: Self::module_prefix().to_vec(),
|
||||
storage_name: Self::storage_prefix().to_vec(),
|
||||
prefix: Self::final_prefix().to_vec(),
|
||||
max_values: MaxValues::get(),
|
||||
max_size: Some(
|
||||
Key::key_max_encoded_len()
|
||||
.saturating_add(Value::max_encoded_len())
|
||||
.saturated_into(),
|
||||
),
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
||||
/// It doesn't require to implement `MaxEncodedLen` and give no information for `max_size`.
|
||||
impl<Prefix, Key, Value, QueryKind, OnEmpty, MaxValues>
|
||||
crate::traits::PartialStorageInfoTrait for
|
||||
StorageNMap<Prefix, Key, Value, QueryKind, OnEmpty, MaxValues>
|
||||
impl<Prefix, Key, Value, QueryKind, OnEmpty, MaxValues> crate::traits::PartialStorageInfoTrait
|
||||
for StorageNMap<Prefix, Key, Value, QueryKind, OnEmpty, MaxValues>
|
||||
where
|
||||
Prefix: StorageInstance,
|
||||
Key: super::key::KeyGenerator,
|
||||
@@ -445,22 +450,22 @@ where
|
||||
MaxValues: Get<Option<u32>>,
|
||||
{
|
||||
fn partial_storage_info() -> Vec<StorageInfo> {
|
||||
vec![
|
||||
StorageInfo {
|
||||
pallet_name: Self::module_prefix().to_vec(),
|
||||
storage_name: Self::storage_prefix().to_vec(),
|
||||
prefix: Self::final_prefix().to_vec(),
|
||||
max_values: MaxValues::get(),
|
||||
max_size: None,
|
||||
}
|
||||
]
|
||||
vec![StorageInfo {
|
||||
pallet_name: Self::module_prefix().to_vec(),
|
||||
storage_name: Self::storage_prefix().to_vec(),
|
||||
prefix: Self::final_prefix().to_vec(),
|
||||
max_values: MaxValues::get(),
|
||||
max_size: None,
|
||||
}]
|
||||
}
|
||||
}
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::hash::*;
|
||||
use crate::storage::types::{Key, ValueQuery};
|
||||
use crate::{
|
||||
hash::*,
|
||||
storage::types::{Key, ValueQuery},
|
||||
};
|
||||
use frame_metadata::StorageEntryModifier;
|
||||
use sp_io::{hashing::twox_128, TestExternalities};
|
||||
|
||||
@@ -627,15 +632,9 @@ mod test {
|
||||
assert_eq!(A::iter().collect::<Vec<_>>(), vec![(4, 40), (3, 30)]);
|
||||
|
||||
assert_eq!(A::MODIFIER, StorageEntryModifier::Optional);
|
||||
assert_eq!(
|
||||
AValueQueryWithAnOnEmpty::MODIFIER,
|
||||
StorageEntryModifier::Default
|
||||
);
|
||||
assert_eq!(AValueQueryWithAnOnEmpty::MODIFIER, StorageEntryModifier::Default);
|
||||
assert_eq!(A::NAME, "Foo");
|
||||
assert_eq!(
|
||||
AValueQueryWithAnOnEmpty::DEFAULT.0.default_byte(),
|
||||
98u32.encode()
|
||||
);
|
||||
assert_eq!(AValueQueryWithAnOnEmpty::DEFAULT.0.default_byte(), 98u32.encode());
|
||||
assert_eq!(A::DEFAULT.0.default_byte(), Option::<u32>::None.encode());
|
||||
|
||||
WithLen::remove_all(None);
|
||||
@@ -787,41 +786,23 @@ mod test {
|
||||
C::insert((3, 30), 10);
|
||||
C::insert((4, 40), 10);
|
||||
A::translate_values::<u8, _>(|v| Some((v * 2).into()));
|
||||
assert_eq!(
|
||||
A::iter().collect::<Vec<_>>(),
|
||||
vec![((4, 40), 20), ((3, 30), 20)]
|
||||
);
|
||||
assert_eq!(A::iter().collect::<Vec<_>>(), vec![((4, 40), 20), ((3, 30), 20)]);
|
||||
|
||||
A::insert((3, 30), 10);
|
||||
A::insert((4, 40), 10);
|
||||
assert_eq!(
|
||||
A::iter().collect::<Vec<_>>(),
|
||||
vec![((4, 40), 10), ((3, 30), 10)]
|
||||
);
|
||||
assert_eq!(
|
||||
A::drain().collect::<Vec<_>>(),
|
||||
vec![((4, 40), 10), ((3, 30), 10)]
|
||||
);
|
||||
assert_eq!(A::iter().collect::<Vec<_>>(), vec![((4, 40), 10), ((3, 30), 10)]);
|
||||
assert_eq!(A::drain().collect::<Vec<_>>(), vec![((4, 40), 10), ((3, 30), 10)]);
|
||||
assert_eq!(A::iter().collect::<Vec<_>>(), vec![]);
|
||||
|
||||
C::insert((3, 30), 10);
|
||||
C::insert((4, 40), 10);
|
||||
A::translate::<u8, _>(|(k1, k2), v| Some((k1 * k2 as u16 * v as u16).into()));
|
||||
assert_eq!(
|
||||
A::iter().collect::<Vec<_>>(),
|
||||
vec![((4, 40), 1600), ((3, 30), 900)]
|
||||
);
|
||||
assert_eq!(A::iter().collect::<Vec<_>>(), vec![((4, 40), 1600), ((3, 30), 900)]);
|
||||
|
||||
assert_eq!(A::MODIFIER, StorageEntryModifier::Optional);
|
||||
assert_eq!(
|
||||
AValueQueryWithAnOnEmpty::MODIFIER,
|
||||
StorageEntryModifier::Default
|
||||
);
|
||||
assert_eq!(AValueQueryWithAnOnEmpty::MODIFIER, StorageEntryModifier::Default);
|
||||
assert_eq!(A::NAME, "Foo");
|
||||
assert_eq!(
|
||||
AValueQueryWithAnOnEmpty::DEFAULT.0.default_byte(),
|
||||
98u32.encode()
|
||||
);
|
||||
assert_eq!(AValueQueryWithAnOnEmpty::DEFAULT.0.default_byte(), 98u32.encode());
|
||||
assert_eq!(A::DEFAULT.0.default_byte(), Option::<u32>::None.encode());
|
||||
|
||||
WithLen::remove_all(None);
|
||||
@@ -833,14 +814,8 @@ mod test {
|
||||
A::insert((3, 31), 12);
|
||||
A::insert((4, 40), 13);
|
||||
A::insert((4, 41), 14);
|
||||
assert_eq!(
|
||||
A::iter_prefix_values((3,)).collect::<Vec<_>>(),
|
||||
vec![12, 11]
|
||||
);
|
||||
assert_eq!(
|
||||
A::iter_prefix_values((4,)).collect::<Vec<_>>(),
|
||||
vec![13, 14]
|
||||
);
|
||||
assert_eq!(A::iter_prefix_values((3,)).collect::<Vec<_>>(), vec![12, 11]);
|
||||
assert_eq!(A::iter_prefix_values((4,)).collect::<Vec<_>>(), vec![13, 14]);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -848,52 +823,32 @@ mod test {
|
||||
fn test_3_keys() {
|
||||
type A = StorageNMap<
|
||||
Prefix,
|
||||
(
|
||||
Key<Blake2_128Concat, u16>,
|
||||
Key<Blake2_128Concat, u16>,
|
||||
Key<Twox64Concat, u16>,
|
||||
),
|
||||
(Key<Blake2_128Concat, u16>, Key<Blake2_128Concat, u16>, Key<Twox64Concat, u16>),
|
||||
u32,
|
||||
OptionQuery,
|
||||
>;
|
||||
type AValueQueryWithAnOnEmpty = StorageNMap<
|
||||
Prefix,
|
||||
(
|
||||
Key<Blake2_128Concat, u16>,
|
||||
Key<Blake2_128Concat, u16>,
|
||||
Key<Twox64Concat, u16>,
|
||||
),
|
||||
(Key<Blake2_128Concat, u16>, Key<Blake2_128Concat, u16>, Key<Twox64Concat, u16>),
|
||||
u32,
|
||||
ValueQuery,
|
||||
ADefault,
|
||||
>;
|
||||
type B = StorageNMap<
|
||||
Prefix,
|
||||
(
|
||||
Key<Blake2_256, u16>,
|
||||
Key<Blake2_256, u16>,
|
||||
Key<Twox128, u16>,
|
||||
),
|
||||
(Key<Blake2_256, u16>, Key<Blake2_256, u16>, Key<Twox128, u16>),
|
||||
u32,
|
||||
ValueQuery,
|
||||
>;
|
||||
type C = StorageNMap<
|
||||
Prefix,
|
||||
(
|
||||
Key<Blake2_128Concat, u16>,
|
||||
Key<Blake2_128Concat, u16>,
|
||||
Key<Twox64Concat, u16>,
|
||||
),
|
||||
(Key<Blake2_128Concat, u16>, Key<Blake2_128Concat, u16>, Key<Twox64Concat, u16>),
|
||||
u8,
|
||||
ValueQuery,
|
||||
>;
|
||||
type WithLen = StorageNMap<
|
||||
Prefix,
|
||||
(
|
||||
Key<Blake2_128Concat, u16>,
|
||||
Key<Blake2_128Concat, u16>,
|
||||
Key<Twox64Concat, u16>,
|
||||
),
|
||||
(Key<Blake2_128Concat, u16>, Key<Blake2_128Concat, u16>, Key<Twox64Concat, u16>),
|
||||
Vec<u32>,
|
||||
>;
|
||||
|
||||
@@ -916,11 +871,7 @@ mod test {
|
||||
assert_eq!(AValueQueryWithAnOnEmpty::get((1, 10, 100)), 30);
|
||||
|
||||
A::swap::<
|
||||
(
|
||||
Key<Blake2_128Concat, u16>,
|
||||
Key<Blake2_128Concat, u16>,
|
||||
Key<Twox64Concat, u16>,
|
||||
),
|
||||
(Key<Blake2_128Concat, u16>, Key<Blake2_128Concat, u16>, Key<Twox64Concat, u16>),
|
||||
_,
|
||||
_,
|
||||
>((1, 10, 100), (2, 20, 200));
|
||||
@@ -1020,17 +971,11 @@ mod test {
|
||||
C::insert((3, 30, 300), 10);
|
||||
C::insert((4, 40, 400), 10);
|
||||
A::translate_values::<u8, _>(|v| Some((v * 2).into()));
|
||||
assert_eq!(
|
||||
A::iter().collect::<Vec<_>>(),
|
||||
vec![((4, 40, 400), 20), ((3, 30, 300), 20)]
|
||||
);
|
||||
assert_eq!(A::iter().collect::<Vec<_>>(), vec![((4, 40, 400), 20), ((3, 30, 300), 20)]);
|
||||
|
||||
A::insert((3, 30, 300), 10);
|
||||
A::insert((4, 40, 400), 10);
|
||||
assert_eq!(
|
||||
A::iter().collect::<Vec<_>>(),
|
||||
vec![((4, 40, 400), 10), ((3, 30, 300), 10)]
|
||||
);
|
||||
assert_eq!(A::iter().collect::<Vec<_>>(), vec![((4, 40, 400), 10), ((3, 30, 300), 10)]);
|
||||
assert_eq!(
|
||||
A::drain().collect::<Vec<_>>(),
|
||||
vec![((4, 40, 400), 10), ((3, 30, 300), 10)]
|
||||
@@ -1042,21 +987,12 @@ mod test {
|
||||
A::translate::<u8, _>(|(k1, k2, k3), v| {
|
||||
Some((k1 * k2 as u16 * v as u16 / k3 as u16).into())
|
||||
});
|
||||
assert_eq!(
|
||||
A::iter().collect::<Vec<_>>(),
|
||||
vec![((4, 40, 400), 4), ((3, 30, 300), 3)]
|
||||
);
|
||||
assert_eq!(A::iter().collect::<Vec<_>>(), vec![((4, 40, 400), 4), ((3, 30, 300), 3)]);
|
||||
|
||||
assert_eq!(A::MODIFIER, StorageEntryModifier::Optional);
|
||||
assert_eq!(
|
||||
AValueQueryWithAnOnEmpty::MODIFIER,
|
||||
StorageEntryModifier::Default
|
||||
);
|
||||
assert_eq!(AValueQueryWithAnOnEmpty::MODIFIER, StorageEntryModifier::Default);
|
||||
assert_eq!(A::NAME, "Foo");
|
||||
assert_eq!(
|
||||
AValueQueryWithAnOnEmpty::DEFAULT.0.default_byte(),
|
||||
98u32.encode()
|
||||
);
|
||||
assert_eq!(AValueQueryWithAnOnEmpty::DEFAULT.0.default_byte(), 98u32.encode());
|
||||
assert_eq!(A::DEFAULT.0.default_byte(), Option::<u32>::None.encode());
|
||||
|
||||
WithLen::remove_all(None);
|
||||
@@ -1068,22 +1004,10 @@ mod test {
|
||||
A::insert((3, 30, 301), 12);
|
||||
A::insert((4, 40, 400), 13);
|
||||
A::insert((4, 40, 401), 14);
|
||||
assert_eq!(
|
||||
A::iter_prefix_values((3,)).collect::<Vec<_>>(),
|
||||
vec![11, 12]
|
||||
);
|
||||
assert_eq!(
|
||||
A::iter_prefix_values((4,)).collect::<Vec<_>>(),
|
||||
vec![14, 13]
|
||||
);
|
||||
assert_eq!(
|
||||
A::iter_prefix_values((3, 30)).collect::<Vec<_>>(),
|
||||
vec![11, 12]
|
||||
);
|
||||
assert_eq!(
|
||||
A::iter_prefix_values((4, 40)).collect::<Vec<_>>(),
|
||||
vec![14, 13]
|
||||
);
|
||||
assert_eq!(A::iter_prefix_values((3,)).collect::<Vec<_>>(), vec![11, 12]);
|
||||
assert_eq!(A::iter_prefix_values((4,)).collect::<Vec<_>>(), vec![14, 13]);
|
||||
assert_eq!(A::iter_prefix_values((3, 30)).collect::<Vec<_>>(), vec![11, 12]);
|
||||
assert_eq!(A::iter_prefix_values((4, 40)).collect::<Vec<_>>(), vec![14, 13]);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,15 +17,15 @@
|
||||
|
||||
//! Storage value type. Implements StorageValue trait and its method directly.
|
||||
|
||||
use codec::{FullCodec, Decode, EncodeLike, Encode, MaxEncodedLen};
|
||||
use crate::{
|
||||
storage::{
|
||||
StorageAppend, StorageTryAppend, StorageDecodeLength,
|
||||
types::{OptionQuery, QueryKindTrait, OnEmptyGetter},
|
||||
generator::{StorageValue as StorageValueT},
|
||||
generator::StorageValue as StorageValueT,
|
||||
types::{OnEmptyGetter, OptionQuery, QueryKindTrait},
|
||||
StorageAppend, StorageDecodeLength, StorageTryAppend,
|
||||
},
|
||||
traits::{GetDefault, StorageInstance, StorageInfo},
|
||||
traits::{GetDefault, StorageInfo, StorageInstance},
|
||||
};
|
||||
use codec::{Decode, Encode, EncodeLike, FullCodec, MaxEncodedLen};
|
||||
use frame_metadata::{DefaultByteGetter, StorageEntryModifier};
|
||||
use sp_arithmetic::traits::SaturatedConversion;
|
||||
use sp_std::prelude::*;
|
||||
@@ -36,12 +36,12 @@ use sp_std::prelude::*;
|
||||
/// ```nocompile
|
||||
/// Twox128(Prefix::pallet_prefix()) ++ Twox128(Prefix::STORAGE_PREFIX)
|
||||
/// ```
|
||||
pub struct StorageValue<Prefix, Value, QueryKind=OptionQuery, OnEmpty=GetDefault>(
|
||||
core::marker::PhantomData<(Prefix, Value, QueryKind, OnEmpty)>
|
||||
pub struct StorageValue<Prefix, Value, QueryKind = OptionQuery, OnEmpty = GetDefault>(
|
||||
core::marker::PhantomData<(Prefix, Value, QueryKind, OnEmpty)>,
|
||||
);
|
||||
|
||||
impl<Prefix, Value, QueryKind, OnEmpty> crate::storage::generator::StorageValue<Value> for
|
||||
StorageValue<Prefix, Value, QueryKind, OnEmpty>
|
||||
impl<Prefix, Value, QueryKind, OnEmpty> crate::storage::generator::StorageValue<Value>
|
||||
for StorageValue<Prefix, Value, QueryKind, OnEmpty>
|
||||
where
|
||||
Prefix: StorageInstance,
|
||||
Value: FullCodec,
|
||||
@@ -71,13 +71,19 @@ where
|
||||
OnEmpty: crate::traits::Get<QueryKind::Query> + 'static,
|
||||
{
|
||||
/// Get the storage key.
|
||||
pub fn hashed_key() -> [u8; 32] { <Self as crate::storage::StorageValue<Value>>::hashed_key() }
|
||||
pub fn hashed_key() -> [u8; 32] {
|
||||
<Self as crate::storage::StorageValue<Value>>::hashed_key()
|
||||
}
|
||||
|
||||
/// Does the value (explicitly) exist in storage?
|
||||
pub fn exists() -> bool { <Self as crate::storage::StorageValue<Value>>::exists() }
|
||||
pub fn exists() -> bool {
|
||||
<Self as crate::storage::StorageValue<Value>>::exists()
|
||||
}
|
||||
|
||||
/// Load the value from the provided storage instance.
|
||||
pub fn get() -> QueryKind::Query { <Self as crate::storage::StorageValue<Value>>::get() }
|
||||
pub fn get() -> QueryKind::Query {
|
||||
<Self as crate::storage::StorageValue<Value>>::get()
|
||||
}
|
||||
|
||||
/// Try to get the underlying value from the provided storage instance; `Ok` if it exists,
|
||||
/// `Err` if not.
|
||||
@@ -120,7 +126,9 @@ where
|
||||
/// Store a value under this key into the provided storage instance.
|
||||
///
|
||||
/// this uses the query type rather than the underlying value.
|
||||
pub fn set(val: QueryKind::Query) { <Self as crate::storage::StorageValue<Value>>::set(val) }
|
||||
pub fn set(val: QueryKind::Query) {
|
||||
<Self as crate::storage::StorageValue<Value>>::set(val)
|
||||
}
|
||||
|
||||
/// Mutate the value
|
||||
pub fn mutate<R, F: FnOnce(&mut QueryKind::Query) -> R>(f: F) -> R {
|
||||
@@ -135,10 +143,14 @@ where
|
||||
}
|
||||
|
||||
/// Clear the storage value.
|
||||
pub fn kill() { <Self as crate::storage::StorageValue<Value>>::kill() }
|
||||
pub fn kill() {
|
||||
<Self as crate::storage::StorageValue<Value>>::kill()
|
||||
}
|
||||
|
||||
/// Take a value from storage, removing it afterwards.
|
||||
pub fn take() -> QueryKind::Query { <Self as crate::storage::StorageValue<Value>>::take() }
|
||||
pub fn take() -> QueryKind::Query {
|
||||
<Self as crate::storage::StorageValue<Value>>::take()
|
||||
}
|
||||
|
||||
/// Append the given item to the value in the storage.
|
||||
///
|
||||
@@ -153,7 +165,7 @@ where
|
||||
where
|
||||
Item: Encode,
|
||||
EncodeLikeItem: EncodeLike<Item>,
|
||||
Value: StorageAppend<Item>
|
||||
Value: StorageAppend<Item>,
|
||||
{
|
||||
<Self as crate::storage::StorageValue<Value>>::append(item)
|
||||
}
|
||||
@@ -169,7 +181,10 @@ where
|
||||
///
|
||||
/// `None` does not mean that `get()` does not return a value. The default value is completly
|
||||
/// ignored by this function.
|
||||
pub fn decode_len() -> Option<usize> where Value: StorageDecodeLength {
|
||||
pub fn decode_len() -> Option<usize>
|
||||
where
|
||||
Value: StorageDecodeLength,
|
||||
{
|
||||
<Self as crate::storage::StorageValue<Value>>::decode_len()
|
||||
}
|
||||
|
||||
@@ -194,7 +209,8 @@ pub trait StorageValueMetadata {
|
||||
}
|
||||
|
||||
impl<Prefix, Value, QueryKind, OnEmpty> StorageValueMetadata
|
||||
for StorageValue<Prefix, Value, QueryKind, OnEmpty> where
|
||||
for StorageValue<Prefix, Value, QueryKind, OnEmpty>
|
||||
where
|
||||
Prefix: StorageInstance,
|
||||
Value: FullCodec,
|
||||
QueryKind: QueryKindTrait<Value, OnEmpty>,
|
||||
@@ -206,64 +222,57 @@ impl<Prefix, Value, QueryKind, OnEmpty> StorageValueMetadata
|
||||
DefaultByteGetter(&OnEmptyGetter::<QueryKind::Query, OnEmpty>(core::marker::PhantomData));
|
||||
}
|
||||
|
||||
impl<Prefix, Value, QueryKind, OnEmpty>
|
||||
crate::traits::StorageInfoTrait for
|
||||
StorageValue<Prefix, Value, QueryKind, OnEmpty>
|
||||
impl<Prefix, Value, QueryKind, OnEmpty> crate::traits::StorageInfoTrait
|
||||
for StorageValue<Prefix, Value, QueryKind, OnEmpty>
|
||||
where
|
||||
Prefix: StorageInstance,
|
||||
Value: FullCodec + MaxEncodedLen,
|
||||
QueryKind: QueryKindTrait<Value, OnEmpty>,
|
||||
OnEmpty: crate::traits::Get<QueryKind::Query> + 'static
|
||||
OnEmpty: crate::traits::Get<QueryKind::Query> + 'static,
|
||||
{
|
||||
fn storage_info() -> Vec<StorageInfo> {
|
||||
vec![
|
||||
StorageInfo {
|
||||
pallet_name: Self::module_prefix().to_vec(),
|
||||
storage_name: Self::storage_prefix().to_vec(),
|
||||
prefix: Self::hashed_key().to_vec(),
|
||||
max_values: Some(1),
|
||||
max_size: Some(
|
||||
Value::max_encoded_len()
|
||||
.saturated_into(),
|
||||
),
|
||||
}
|
||||
]
|
||||
vec![StorageInfo {
|
||||
pallet_name: Self::module_prefix().to_vec(),
|
||||
storage_name: Self::storage_prefix().to_vec(),
|
||||
prefix: Self::hashed_key().to_vec(),
|
||||
max_values: Some(1),
|
||||
max_size: Some(Value::max_encoded_len().saturated_into()),
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
||||
/// It doesn't require to implement `MaxEncodedLen` and give no information for `max_size`.
|
||||
impl<Prefix, Value, QueryKind, OnEmpty>
|
||||
crate::traits::PartialStorageInfoTrait for
|
||||
StorageValue<Prefix, Value, QueryKind, OnEmpty>
|
||||
impl<Prefix, Value, QueryKind, OnEmpty> crate::traits::PartialStorageInfoTrait
|
||||
for StorageValue<Prefix, Value, QueryKind, OnEmpty>
|
||||
where
|
||||
Prefix: StorageInstance,
|
||||
Value: FullCodec,
|
||||
QueryKind: QueryKindTrait<Value, OnEmpty>,
|
||||
OnEmpty: crate::traits::Get<QueryKind::Query> + 'static
|
||||
OnEmpty: crate::traits::Get<QueryKind::Query> + 'static,
|
||||
{
|
||||
fn partial_storage_info() -> Vec<StorageInfo> {
|
||||
vec![
|
||||
StorageInfo {
|
||||
pallet_name: Self::module_prefix().to_vec(),
|
||||
storage_name: Self::storage_prefix().to_vec(),
|
||||
prefix: Self::hashed_key().to_vec(),
|
||||
max_values: Some(1),
|
||||
max_size: None,
|
||||
}
|
||||
]
|
||||
vec![StorageInfo {
|
||||
pallet_name: Self::module_prefix().to_vec(),
|
||||
storage_name: Self::storage_prefix().to_vec(),
|
||||
prefix: Self::hashed_key().to_vec(),
|
||||
max_values: Some(1),
|
||||
max_size: None,
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use sp_io::{TestExternalities, hashing::twox_128};
|
||||
use crate::storage::types::ValueQuery;
|
||||
use frame_metadata::StorageEntryModifier;
|
||||
use sp_io::{hashing::twox_128, TestExternalities};
|
||||
|
||||
struct Prefix;
|
||||
impl StorageInstance for Prefix {
|
||||
fn pallet_prefix() -> &'static str { "test" }
|
||||
fn pallet_prefix() -> &'static str {
|
||||
"test"
|
||||
}
|
||||
const STORAGE_PREFIX: &'static str = "foo";
|
||||
}
|
||||
|
||||
@@ -309,10 +318,16 @@ mod test {
|
||||
assert_eq!(A::try_get(), Ok(4));
|
||||
|
||||
A::set(Some(4));
|
||||
let _: Result<(), ()> = A::try_mutate(|v| { *v = Some(v.unwrap() * 2); Ok(()) });
|
||||
let _: Result<(), ()> = A::try_mutate(|v| {
|
||||
*v = Some(v.unwrap() * 2);
|
||||
Ok(())
|
||||
});
|
||||
assert_eq!(A::try_get(), Ok(8));
|
||||
|
||||
let _: Result<(), ()> = A::try_mutate(|v| { *v = Some(v.unwrap() * 2); Err(()) });
|
||||
let _: Result<(), ()> = A::try_mutate(|v| {
|
||||
*v = Some(v.unwrap() * 2);
|
||||
Err(())
|
||||
});
|
||||
assert_eq!(A::try_get(), Ok(8));
|
||||
|
||||
A::kill();
|
||||
@@ -321,7 +336,8 @@ mod test {
|
||||
|
||||
AValueQueryWithAnOnEmpty::kill();
|
||||
let _: Result<(), ()> = AValueQueryWithAnOnEmpty::try_mutate(|v| {
|
||||
*v = *v * 2; Ok(())
|
||||
*v = *v * 2;
|
||||
Ok(())
|
||||
});
|
||||
assert_eq!(AValueQueryWithAnOnEmpty::try_get(), Ok(97 * 2));
|
||||
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
|
||||
//! Operation on unhashed runtime storage.
|
||||
|
||||
use codec::{Decode, Encode};
|
||||
use sp_std::prelude::*;
|
||||
use codec::{Encode, Decode};
|
||||
|
||||
/// Return the value of the item in storage under `key`, or `None` if there is no explicit entry.
|
||||
pub fn get<T: Decode + Sized>(key: &[u8]) -> Option<T> {
|
||||
|
||||
@@ -18,17 +18,16 @@
|
||||
//! Traits, types and structs to support putting a bounded vector into storage, as a raw value, map
|
||||
//! or a double map.
|
||||
|
||||
use sp_std::prelude::*;
|
||||
use sp_std::{convert::TryFrom, fmt, marker::PhantomData};
|
||||
use codec::{Encode, Decode, MaxEncodedLen};
|
||||
use crate::{
|
||||
storage::{StorageDecodeLength, StorageTryAppend},
|
||||
traits::Get,
|
||||
};
|
||||
use codec::{Decode, Encode, MaxEncodedLen};
|
||||
use core::{
|
||||
ops::{Deref, Index, IndexMut},
|
||||
slice::SliceIndex,
|
||||
};
|
||||
use crate::{
|
||||
traits::Get,
|
||||
storage::{StorageDecodeLength, StorageTryAppend},
|
||||
};
|
||||
use sp_std::{convert::TryFrom, fmt, marker::PhantomData, prelude::*};
|
||||
|
||||
/// A weakly bounded vector.
|
||||
///
|
||||
@@ -317,9 +316,9 @@ where
|
||||
#[cfg(test)]
|
||||
pub mod test {
|
||||
use super::*;
|
||||
use crate::Twox128;
|
||||
use sp_io::TestExternalities;
|
||||
use sp_std::convert::TryInto;
|
||||
use crate::Twox128;
|
||||
|
||||
crate::parameter_types! {
|
||||
pub const Seven: u32 = 7;
|
||||
|
||||
@@ -20,62 +20,67 @@
|
||||
//! NOTE: If you're looking for `parameter_types`, it has moved in to the top-level module.
|
||||
|
||||
pub mod tokens;
|
||||
pub use tokens::fungible;
|
||||
pub use tokens::fungibles;
|
||||
pub use tokens::currency::{
|
||||
Currency, LockIdentifier, LockableCurrency, ReservableCurrency, NamedReservableCurrency,
|
||||
VestingSchedule,
|
||||
pub use tokens::{
|
||||
currency::{
|
||||
Currency, LockIdentifier, LockableCurrency, NamedReservableCurrency, ReservableCurrency,
|
||||
VestingSchedule,
|
||||
},
|
||||
fungible, fungibles,
|
||||
imbalance::{Imbalance, OnUnbalanced, SignedImbalance},
|
||||
BalanceStatus, ExistenceRequirement, WithdrawReasons,
|
||||
};
|
||||
pub use tokens::imbalance::{Imbalance, OnUnbalanced, SignedImbalance};
|
||||
pub use tokens::{ExistenceRequirement, WithdrawReasons, BalanceStatus};
|
||||
|
||||
mod members;
|
||||
pub use members::{
|
||||
Contains, ContainsLengthBound, SortedMembers, InitializeMembers, ChangeMembers, All, IsInVec,
|
||||
AsContains,
|
||||
All, AsContains, ChangeMembers, Contains, ContainsLengthBound, InitializeMembers, IsInVec,
|
||||
SortedMembers,
|
||||
};
|
||||
|
||||
mod validation;
|
||||
pub use validation::{
|
||||
ValidatorSet, ValidatorSetWithIdentification, OneSessionHandler, FindAuthor, VerifySeal,
|
||||
EstimateNextNewSession, EstimateNextSessionRotation, KeyOwnerProofSystem, ValidatorRegistration,
|
||||
Lateness,
|
||||
EstimateNextNewSession, EstimateNextSessionRotation, FindAuthor, KeyOwnerProofSystem, Lateness,
|
||||
OneSessionHandler, ValidatorRegistration, ValidatorSet, ValidatorSetWithIdentification,
|
||||
VerifySeal,
|
||||
};
|
||||
|
||||
mod filter;
|
||||
pub use filter::{
|
||||
Filter, FilterStack, FilterStackGuard, ClearFilterGuard, InstanceFilter, IntegrityTest,
|
||||
AllowAll, DenyAll,
|
||||
AllowAll, ClearFilterGuard, DenyAll, Filter, FilterStack, FilterStackGuard, InstanceFilter,
|
||||
IntegrityTest,
|
||||
};
|
||||
|
||||
mod misc;
|
||||
pub use misc::{
|
||||
Len, Get, GetDefault, HandleLifetime, TryDrop, Time, UnixTime, IsType, IsSubType, ExecuteBlock,
|
||||
SameOrOther, OnNewAccount, OnKilledAccount, OffchainWorker, GetBacking, Backing, ExtrinsicCall,
|
||||
EnsureInherentsAreFirst, ConstU32,
|
||||
Backing, ConstU32, EnsureInherentsAreFirst, ExecuteBlock, ExtrinsicCall, Get, GetBacking,
|
||||
GetDefault, HandleLifetime, IsSubType, IsType, Len, OffchainWorker, OnKilledAccount,
|
||||
OnNewAccount, SameOrOther, Time, TryDrop, UnixTime,
|
||||
};
|
||||
|
||||
mod stored_map;
|
||||
pub use stored_map::{StoredMap, StorageMapShim};
|
||||
pub use stored_map::{StorageMapShim, StoredMap};
|
||||
mod randomness;
|
||||
pub use randomness::Randomness;
|
||||
|
||||
mod metadata;
|
||||
pub use metadata::{
|
||||
CallMetadata, GetCallMetadata, GetCallName, PalletInfo, PalletVersion, GetPalletVersion,
|
||||
PALLET_VERSION_STORAGE_KEY_POSTFIX, PalletInfoAccess,
|
||||
CallMetadata, GetCallMetadata, GetCallName, GetPalletVersion, PalletInfo, PalletInfoAccess,
|
||||
PalletVersion, PALLET_VERSION_STORAGE_KEY_POSTFIX,
|
||||
};
|
||||
|
||||
mod hooks;
|
||||
pub use hooks::{Hooks, OnGenesis, OnInitialize, OnFinalize, OnIdle, OnRuntimeUpgrade, OnTimestampSet};
|
||||
#[cfg(feature = "try-runtime")]
|
||||
pub use hooks::{OnRuntimeUpgradeHelpersExt, ON_RUNTIME_UPGRADE_PREFIX};
|
||||
#[cfg(feature = "std")]
|
||||
pub use hooks::GenesisBuild;
|
||||
pub use hooks::{
|
||||
Hooks, OnFinalize, OnGenesis, OnIdle, OnInitialize, OnRuntimeUpgrade, OnTimestampSet,
|
||||
};
|
||||
#[cfg(feature = "try-runtime")]
|
||||
pub use hooks::{OnRuntimeUpgradeHelpersExt, ON_RUNTIME_UPGRADE_PREFIX};
|
||||
|
||||
pub mod schedule;
|
||||
mod storage;
|
||||
pub use storage::{Instance, PartialStorageInfoTrait, StorageInstance, StorageInfo, StorageInfoTrait};
|
||||
pub use storage::{
|
||||
Instance, PartialStorageInfoTrait, StorageInfo, StorageInfoTrait, StorageInstance,
|
||||
};
|
||||
|
||||
mod dispatch;
|
||||
pub use dispatch::{EnsureOrigin, OriginTrait, UnfilteredDispatchable};
|
||||
|
||||
@@ -32,11 +32,15 @@ pub enum AllowAll {}
|
||||
pub enum DenyAll {}
|
||||
|
||||
impl<T> Filter<T> for AllowAll {
|
||||
fn filter(_: &T) -> bool { true }
|
||||
fn filter(_: &T) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Filter<T> for DenyAll {
|
||||
fn filter(_: &T) -> bool { false }
|
||||
fn filter(_: &T) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/// Trait to add a constraint onto the filter.
|
||||
@@ -101,17 +105,28 @@ pub trait InstanceFilter<T>: Sized + Send + Sync {
|
||||
fn filter(&self, _: &T) -> bool;
|
||||
|
||||
/// Determines whether `self` matches at least everything that `_o` does.
|
||||
fn is_superset(&self, _o: &Self) -> bool { false }
|
||||
fn is_superset(&self, _o: &Self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> InstanceFilter<T> for () {
|
||||
fn filter(&self, _: &T) -> bool { true }
|
||||
fn is_superset(&self, _o: &Self) -> bool { true }
|
||||
fn filter(&self, _: &T) -> bool {
|
||||
true
|
||||
}
|
||||
fn is_superset(&self, _o: &Self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
/// Re-expected for the macro.
|
||||
#[doc(hidden)]
|
||||
pub use sp_std::{mem::{swap, take}, cell::RefCell, vec::Vec, boxed::Box};
|
||||
pub use sp_std::{
|
||||
boxed::Box,
|
||||
cell::RefCell,
|
||||
mem::{swap, take},
|
||||
vec::Vec,
|
||||
};
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! impl_filter_stack {
|
||||
@@ -206,7 +221,9 @@ pub mod test_impl_filter_stack {
|
||||
pub struct IsCallable;
|
||||
pub struct BaseFilter;
|
||||
impl Filter<u32> for BaseFilter {
|
||||
fn filter(x: &u32) -> bool { x % 2 == 0 }
|
||||
fn filter(x: &u32) -> bool {
|
||||
x % 2 == 0
|
||||
}
|
||||
}
|
||||
impl_filter_stack!(
|
||||
crate::traits::filter::test_impl_filter_stack::IsCallable,
|
||||
|
||||
@@ -17,9 +17,9 @@
|
||||
|
||||
//! Traits for hooking tasks to events in a blockchain's lifecycle.
|
||||
|
||||
use impl_trait_for_tuples::impl_for_tuples;
|
||||
use sp_arithmetic::traits::Saturating;
|
||||
use sp_runtime::traits::MaybeSerializeDeserialize;
|
||||
use impl_trait_for_tuples::impl_for_tuples;
|
||||
|
||||
/// The block initialization trait.
|
||||
///
|
||||
@@ -33,7 +33,9 @@ pub trait OnInitialize<BlockNumber> {
|
||||
/// NOTE: This function is called BEFORE ANY extrinsic in a block is applied,
|
||||
/// including inherent extrinsics. Hence for instance, if you runtime includes
|
||||
/// `pallet_timestamp`, the `timestamp` is not yet up to date at this point.
|
||||
fn on_initialize(_n: BlockNumber) -> crate::weights::Weight { 0 }
|
||||
fn on_initialize(_n: BlockNumber) -> crate::weights::Weight {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
#[impl_for_tuples(30)]
|
||||
@@ -71,7 +73,7 @@ pub trait OnIdle<BlockNumber> {
|
||||
/// in a block are applied but before `on_finalize` is executed.
|
||||
fn on_idle(
|
||||
_n: BlockNumber,
|
||||
_remaining_weight: crate::weights::Weight
|
||||
_remaining_weight: crate::weights::Weight,
|
||||
) -> crate::weights::Weight {
|
||||
0
|
||||
}
|
||||
@@ -79,7 +81,7 @@ pub trait OnIdle<BlockNumber> {
|
||||
|
||||
#[impl_for_tuples(30)]
|
||||
impl<BlockNumber: Clone> OnIdle<BlockNumber> for Tuple {
|
||||
fn on_idle(n: BlockNumber, remaining_weight: crate::weights::Weight) -> crate::weights::Weight {
|
||||
fn on_idle(n: BlockNumber, remaining_weight: crate::weights::Weight) -> crate::weights::Weight {
|
||||
let mut weight = 0;
|
||||
for_tuples!( #(
|
||||
let adjusted_remaining_weight = remaining_weight.saturating_sub(weight);
|
||||
@@ -170,13 +172,17 @@ pub trait OnRuntimeUpgrade {
|
||||
///
|
||||
/// This hook is never meant to be executed on-chain but is meant to be used by testing tools.
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn pre_upgrade() -> Result<(), &'static str> { Ok(()) }
|
||||
fn pre_upgrade() -> Result<(), &'static str> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Execute some post-checks after a runtime upgrade.
|
||||
///
|
||||
/// This hook is never meant to be executed on-chain but is meant to be used by testing tools.
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn post_upgrade() -> Result<(), &'static str> { Ok(()) }
|
||||
fn post_upgrade() -> Result<(), &'static str> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[impl_for_tuples(30)]
|
||||
@@ -214,7 +220,7 @@ pub trait Hooks<BlockNumber> {
|
||||
/// and pass the result to the next `on_idle` hook if it exists.
|
||||
fn on_idle(
|
||||
_n: BlockNumber,
|
||||
_remaining_weight: crate::weights::Weight
|
||||
_remaining_weight: crate::weights::Weight,
|
||||
) -> crate::weights::Weight {
|
||||
0
|
||||
}
|
||||
@@ -222,7 +228,9 @@ pub trait Hooks<BlockNumber> {
|
||||
/// The block is being initialized. Implement to have something happen.
|
||||
///
|
||||
/// Return the non-negotiable weight consumed in the block.
|
||||
fn on_initialize(_n: BlockNumber) -> crate::weights::Weight { 0 }
|
||||
fn on_initialize(_n: BlockNumber) -> crate::weights::Weight {
|
||||
0
|
||||
}
|
||||
|
||||
/// Perform a module upgrade.
|
||||
///
|
||||
@@ -238,7 +246,9 @@ pub trait Hooks<BlockNumber> {
|
||||
/// block local data are not accessible.
|
||||
///
|
||||
/// Return the non-negotiable weight consumed for runtime upgrade.
|
||||
fn on_runtime_upgrade() -> crate::weights::Weight { 0 }
|
||||
fn on_runtime_upgrade() -> crate::weights::Weight {
|
||||
0
|
||||
}
|
||||
|
||||
/// Execute some pre-checks prior to a runtime upgrade.
|
||||
///
|
||||
@@ -282,7 +292,7 @@ pub trait Hooks<BlockNumber> {
|
||||
/// A trait to define the build function of a genesis config, T and I are placeholder for pallet
|
||||
/// trait and pallet instance.
|
||||
#[cfg(feature = "std")]
|
||||
pub trait GenesisBuild<T, I=()>: Default + MaybeSerializeDeserialize {
|
||||
pub trait GenesisBuild<T, I = ()>: Default + MaybeSerializeDeserialize {
|
||||
/// The build function is called within an externalities allowing storage APIs.
|
||||
/// Thus one can write to storage using regular pallet storages.
|
||||
fn build(&self);
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
//! Traits for dealing with the idea of membership.
|
||||
|
||||
use sp_std::{prelude::*, marker::PhantomData};
|
||||
use sp_std::{marker::PhantomData, prelude::*};
|
||||
|
||||
/// A trait for querying whether a type can be said to "contain" a value.
|
||||
pub trait Contains<T> {
|
||||
@@ -28,7 +28,9 @@ pub trait Contains<T> {
|
||||
/// A `Contains` implementation which always returns `true`.
|
||||
pub struct All<T>(PhantomData<T>);
|
||||
impl<T> Contains<T> for All<T> {
|
||||
fn contains(_: &T) -> bool { true }
|
||||
fn contains(_: &T) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
#[impl_trait_for_tuples::impl_for_tuples(30)]
|
||||
@@ -77,32 +79,46 @@ pub trait SortedMembers<T: Ord> {
|
||||
fn sorted_members() -> Vec<T>;
|
||||
|
||||
/// Return `true` if this "contains" the given value `t`.
|
||||
fn contains(t: &T) -> bool { Self::sorted_members().binary_search(t).is_ok() }
|
||||
fn contains(t: &T) -> bool {
|
||||
Self::sorted_members().binary_search(t).is_ok()
|
||||
}
|
||||
|
||||
/// Get the number of items in the set.
|
||||
fn count() -> usize { Self::sorted_members().len() }
|
||||
fn count() -> usize {
|
||||
Self::sorted_members().len()
|
||||
}
|
||||
|
||||
/// Add an item that would satisfy `contains`. It does not make sure any other
|
||||
/// state is correctly maintained or generated.
|
||||
///
|
||||
/// **Should be used for benchmarking only!!!**
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
fn add(_t: &T) { unimplemented!() }
|
||||
fn add(_t: &T) {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
/// Adapter struct for turning an `OrderedMembership` impl into a `Contains` impl.
|
||||
pub struct AsContains<OM>(PhantomData<(OM,)>);
|
||||
impl<T: Ord + Eq, OM: SortedMembers<T>> Contains<T> for AsContains<OM> {
|
||||
fn contains(t: &T) -> bool { OM::contains(t) }
|
||||
fn contains(t: &T) -> bool {
|
||||
OM::contains(t)
|
||||
}
|
||||
}
|
||||
|
||||
/// Trivial utility for implementing `Contains`/`OrderedMembership` with a `Vec`.
|
||||
pub struct IsInVec<T>(PhantomData<T>);
|
||||
impl<X: Eq, T: super::Get<Vec<X>>> Contains<X> for IsInVec<T> {
|
||||
fn contains(t: &X) -> bool { T::get().contains(t) }
|
||||
fn contains(t: &X) -> bool {
|
||||
T::get().contains(t)
|
||||
}
|
||||
}
|
||||
impl<X: Ord + PartialOrd, T: super::Get<Vec<X>>> SortedMembers<X> for IsInVec<T> {
|
||||
fn sorted_members() -> Vec<X> { let mut r = T::get(); r.sort(); r }
|
||||
fn sorted_members() -> Vec<X> {
|
||||
let mut r = T::get();
|
||||
r.sort();
|
||||
r
|
||||
}
|
||||
}
|
||||
|
||||
/// A trait for querying bound for the length of an implementation of `Contains`
|
||||
@@ -174,19 +190,19 @@ pub trait ChangeMembers<AccountId: Clone + Ord> {
|
||||
(Some(old), Some(new)) if old == new => {
|
||||
old_i = old_iter.next();
|
||||
new_i = new_iter.next();
|
||||
}
|
||||
},
|
||||
(Some(old), Some(new)) if old < new => {
|
||||
outgoing.push(old.clone());
|
||||
old_i = old_iter.next();
|
||||
}
|
||||
},
|
||||
(Some(old), None) => {
|
||||
outgoing.push(old.clone());
|
||||
old_i = old_iter.next();
|
||||
}
|
||||
},
|
||||
(_, Some(new)) => {
|
||||
incoming.push(new.clone());
|
||||
new_i = new_iter.next();
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
(incoming, outgoing)
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
//! Traits for managing information attached to pallets and their constituents.
|
||||
|
||||
use codec::{Encode, Decode};
|
||||
use codec::{Decode, Encode};
|
||||
use sp_runtime::RuntimeDebug;
|
||||
|
||||
/// Provides information about the pallet setup in the runtime.
|
||||
@@ -91,11 +91,7 @@ pub struct PalletVersion {
|
||||
impl PalletVersion {
|
||||
/// Creates a new instance of `Self`.
|
||||
pub fn new(major: u16, minor: u8, patch: u8) -> Self {
|
||||
Self {
|
||||
major,
|
||||
minor,
|
||||
patch,
|
||||
}
|
||||
Self { major, minor, patch }
|
||||
}
|
||||
|
||||
/// Returns the storage key for a pallet version.
|
||||
@@ -139,13 +135,10 @@ impl PalletVersion {
|
||||
|
||||
impl sp_std::cmp::PartialOrd for PalletVersion {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<sp_std::cmp::Ordering> {
|
||||
let res = self.major
|
||||
let res = self
|
||||
.major
|
||||
.cmp(&other.major)
|
||||
.then_with(||
|
||||
self.minor
|
||||
.cmp(&other.minor)
|
||||
.then_with(|| self.patch.cmp(&other.patch)
|
||||
));
|
||||
.then_with(|| self.minor.cmp(&other.minor).then_with(|| self.patch.cmp(&other.patch)));
|
||||
|
||||
Some(res)
|
||||
}
|
||||
|
||||
@@ -17,9 +17,9 @@
|
||||
|
||||
//! Smaller traits used in FRAME which don't need their own file.
|
||||
|
||||
use sp_runtime::{traits::Block as BlockT, DispatchError};
|
||||
use sp_arithmetic::traits::AtLeast32Bit;
|
||||
use crate::dispatch::Parameter;
|
||||
use sp_arithmetic::traits::AtLeast32Bit;
|
||||
use sp_runtime::{traits::Block as BlockT, DispatchError};
|
||||
|
||||
/// Anything that can have a `::len()` method.
|
||||
pub trait Len {
|
||||
@@ -27,7 +27,10 @@ pub trait Len {
|
||||
fn len(&self) -> usize;
|
||||
}
|
||||
|
||||
impl<T: IntoIterator + Clone,> Len for T where <T as IntoIterator>::IntoIter: ExactSizeIterator {
|
||||
impl<T: IntoIterator + Clone> Len for T
|
||||
where
|
||||
<T as IntoIterator>::IntoIter: ExactSizeIterator,
|
||||
{
|
||||
fn len(&self) -> usize {
|
||||
self.clone().into_iter().len()
|
||||
}
|
||||
@@ -42,7 +45,9 @@ pub trait Get<T> {
|
||||
}
|
||||
|
||||
impl<T: Default> Get<T> for () {
|
||||
fn get() -> T { T::default() }
|
||||
fn get() -> T {
|
||||
T::default()
|
||||
}
|
||||
}
|
||||
|
||||
/// Implement Get by returning Default for any type that implements Default.
|
||||
@@ -123,7 +128,10 @@ impl<A, B> SameOrOther<A, B> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn same(self) -> Result<A, B> where A: Default {
|
||||
pub fn same(self) -> Result<A, B>
|
||||
where
|
||||
A: Default,
|
||||
{
|
||||
match self {
|
||||
SameOrOther::Same(a) => Ok(a),
|
||||
SameOrOther::None => Ok(A::default()),
|
||||
@@ -131,7 +139,10 @@ impl<A, B> SameOrOther<A, B> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn other(self) -> Result<B, A> where B: Default {
|
||||
pub fn other(self) -> Result<B, A>
|
||||
where
|
||||
B: Default,
|
||||
{
|
||||
match self {
|
||||
SameOrOther::Same(a) => Err(a),
|
||||
SameOrOther::None => Ok(B::default()),
|
||||
@@ -157,10 +168,14 @@ pub trait OnKilledAccount<AccountId> {
|
||||
/// A simple, generic one-parameter event notifier/handler.
|
||||
pub trait HandleLifetime<T> {
|
||||
/// An account was created.
|
||||
fn created(_t: &T) -> Result<(), DispatchError> { Ok(()) }
|
||||
fn created(_t: &T) -> Result<(), DispatchError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// An account was killed.
|
||||
fn killed(_t: &T) -> Result<(), DispatchError> { Ok(()) }
|
||||
fn killed(_t: &T) -> Result<(), DispatchError> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> HandleLifetime<T> for () {}
|
||||
@@ -195,10 +210,18 @@ pub trait IsType<T>: Into<T> + From<T> {
|
||||
}
|
||||
|
||||
impl<T> IsType<T> for T {
|
||||
fn from_ref(t: &T) -> &Self { t }
|
||||
fn into_ref(&self) -> &T { self }
|
||||
fn from_mut(t: &mut T) -> &mut Self { t }
|
||||
fn into_mut(&mut self) -> &mut T { self }
|
||||
fn from_ref(t: &T) -> &Self {
|
||||
t
|
||||
}
|
||||
fn into_ref(&self) -> &T {
|
||||
self
|
||||
}
|
||||
fn from_mut(t: &mut T) -> &mut Self {
|
||||
t
|
||||
}
|
||||
fn into_mut(&mut self) -> &mut T {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// Something that can be checked to be a of sub type `T`.
|
||||
@@ -300,8 +323,6 @@ pub trait GetBacking {
|
||||
fn get_backing(&self) -> Option<Backing>;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// A trait to ensure the inherent are before non-inherent in a block.
|
||||
///
|
||||
/// This is typically implemented on runtime, through `construct_runtime!`.
|
||||
@@ -319,7 +340,8 @@ pub trait ExtrinsicCall: sp_runtime::traits::Extrinsic {
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl<Call, Extra> ExtrinsicCall for sp_runtime::testing::TestXt<Call, Extra> where
|
||||
impl<Call, Extra> ExtrinsicCall for sp_runtime::testing::TestXt<Call, Extra>
|
||||
where
|
||||
Call: codec::Codec + Sync + Send,
|
||||
{
|
||||
fn call(&self) -> &Self::Call {
|
||||
@@ -328,7 +350,7 @@ impl<Call, Extra> ExtrinsicCall for sp_runtime::testing::TestXt<Call, Extra> whe
|
||||
}
|
||||
|
||||
impl<Address, Call, Signature, Extra> ExtrinsicCall
|
||||
for sp_runtime::generic::UncheckedExtrinsic<Address, Call, Signature, Extra>
|
||||
for sp_runtime::generic::UncheckedExtrinsic<Address, Call, Signature, Extra>
|
||||
where
|
||||
Extra: sp_runtime::traits::SignedExtension,
|
||||
{
|
||||
|
||||
@@ -17,9 +17,9 @@
|
||||
|
||||
//! Traits and associated utilities for scheduling dispatchables in FRAME.
|
||||
|
||||
use sp_std::{prelude::*, fmt::Debug};
|
||||
use codec::{Encode, Decode, Codec, EncodeLike};
|
||||
use sp_runtime::{RuntimeDebug, DispatchError};
|
||||
use codec::{Codec, Decode, Encode, EncodeLike};
|
||||
use sp_runtime::{DispatchError, RuntimeDebug};
|
||||
use sp_std::{fmt::Debug, prelude::*};
|
||||
|
||||
/// Information relating to the period of a scheduled task. First item is the length of the
|
||||
/// period and the second is the number of times it should be executed in total before the task
|
||||
@@ -61,7 +61,7 @@ pub trait Anon<BlockNumber, Call, Origin> {
|
||||
maybe_periodic: Option<Period<BlockNumber>>,
|
||||
priority: Priority,
|
||||
origin: Origin,
|
||||
call: Call
|
||||
call: Call,
|
||||
) -> Result<Self::Address, DispatchError>;
|
||||
|
||||
/// Cancel a scheduled task. If periodic, then it will cancel all further instances of that,
|
||||
@@ -107,7 +107,7 @@ pub trait Named<BlockNumber, Call, Origin> {
|
||||
maybe_periodic: Option<Period<BlockNumber>>,
|
||||
priority: Priority,
|
||||
origin: Origin,
|
||||
call: Call
|
||||
call: Call,
|
||||
) -> Result<Self::Address, ()>;
|
||||
|
||||
/// Cancel a scheduled, named task. If periodic, then it will cancel all further instances
|
||||
|
||||
@@ -17,10 +17,9 @@
|
||||
|
||||
//! Traits and associated datatypes for managing abstract stored values.
|
||||
|
||||
use crate::{storage::StorageMap, traits::misc::HandleLifetime};
|
||||
use codec::FullCodec;
|
||||
use sp_runtime::DispatchError;
|
||||
use crate::storage::StorageMap;
|
||||
use crate::traits::misc::HandleLifetime;
|
||||
|
||||
/// An abstraction of a value stored within storage, but possibly as part of a larger composite
|
||||
/// item.
|
||||
@@ -47,25 +46,26 @@ pub trait StoredMap<K, T: Default> {
|
||||
let r = f(&mut account);
|
||||
*x = Some(account);
|
||||
r
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
/// Mutate the item, removing or resetting to default value if it has been mutated to `None`.
|
||||
///
|
||||
/// This is infallible as long as the value does not get destroyed.
|
||||
fn mutate_exists<R>(
|
||||
k: &K,
|
||||
f: impl FnOnce(&mut Option<T>) -> R,
|
||||
) -> Result<R, DispatchError> {
|
||||
fn mutate_exists<R>(k: &K, f: impl FnOnce(&mut Option<T>) -> R) -> Result<R, DispatchError> {
|
||||
Self::try_mutate_exists(k, |x| -> Result<R, DispatchError> { Ok(f(x)) })
|
||||
}
|
||||
|
||||
/// Set the item to something new.
|
||||
fn insert(k: &K, t: T) -> Result<(), DispatchError> { Self::mutate(k, |i| *i = t) }
|
||||
fn insert(k: &K, t: T) -> Result<(), DispatchError> {
|
||||
Self::mutate(k, |i| *i = t)
|
||||
}
|
||||
|
||||
/// Remove the item or otherwise replace it with its default value; we don't care which.
|
||||
fn remove(k: &K) -> Result<(), DispatchError> { Self::mutate_exists(k, |x| *x = None) }
|
||||
fn remove(k: &K) -> Result<(), DispatchError> {
|
||||
Self::mutate_exists(k, |x| *x = None)
|
||||
}
|
||||
}
|
||||
|
||||
/// A shim for placing around a storage item in order to use it as a `StoredValue`. Ideally this
|
||||
@@ -81,12 +81,15 @@ pub trait StoredMap<K, T: Default> {
|
||||
/// system module's `CallOnCreatedAccount` and `CallKillAccount`.
|
||||
pub struct StorageMapShim<S, L, K, T>(sp_std::marker::PhantomData<(S, L, K, T)>);
|
||||
impl<
|
||||
S: StorageMap<K, T, Query=T>,
|
||||
L: HandleLifetime<K>,
|
||||
K: FullCodec,
|
||||
T: FullCodec + Default,
|
||||
> StoredMap<K, T> for StorageMapShim<S, L, K, T> {
|
||||
fn get(k: &K) -> T { S::get(k) }
|
||||
S: StorageMap<K, T, Query = T>,
|
||||
L: HandleLifetime<K>,
|
||||
K: FullCodec,
|
||||
T: FullCodec + Default,
|
||||
> StoredMap<K, T> for StorageMapShim<S, L, K, T>
|
||||
{
|
||||
fn get(k: &K) -> T {
|
||||
S::get(k)
|
||||
}
|
||||
fn insert(k: &K, t: T) -> Result<(), DispatchError> {
|
||||
if !S::contains_key(&k) {
|
||||
L::created(k)?;
|
||||
|
||||
@@ -17,15 +17,15 @@
|
||||
|
||||
//! Traits for working with tokens and their associated datastructures.
|
||||
|
||||
pub mod currency;
|
||||
pub mod fungible;
|
||||
pub mod fungibles;
|
||||
pub mod currency;
|
||||
pub mod imbalance;
|
||||
mod misc;
|
||||
pub mod nonfungible;
|
||||
pub mod nonfungibles;
|
||||
mod misc;
|
||||
pub use misc::{
|
||||
BalanceConversion, BalanceStatus, DepositConsequence,
|
||||
ExistenceRequirement, WithdrawConsequence, WithdrawReasons,
|
||||
};
|
||||
pub use imbalance::Imbalance;
|
||||
pub use misc::{
|
||||
BalanceConversion, BalanceStatus, DepositConsequence, ExistenceRequirement,
|
||||
WithdrawConsequence, WithdrawReasons,
|
||||
};
|
||||
|
||||
@@ -17,17 +17,19 @@
|
||||
|
||||
//! The Currency trait and associated types.
|
||||
|
||||
use sp_std::fmt::Debug;
|
||||
use sp_runtime::traits::MaybeSerializeDeserialize;
|
||||
use crate::dispatch::{DispatchResult, DispatchError};
|
||||
use super::misc::{Balance, WithdrawReasons, ExistenceRequirement};
|
||||
use super::imbalance::{Imbalance, SignedImbalance};
|
||||
use super::{
|
||||
imbalance::{Imbalance, SignedImbalance},
|
||||
misc::{Balance, ExistenceRequirement, WithdrawReasons},
|
||||
};
|
||||
use crate::dispatch::{DispatchError, DispatchResult};
|
||||
use codec::MaxEncodedLen;
|
||||
use sp_runtime::traits::MaybeSerializeDeserialize;
|
||||
use sp_std::fmt::Debug;
|
||||
|
||||
mod reservable;
|
||||
pub use reservable::{ReservableCurrency, NamedReservableCurrency};
|
||||
pub use reservable::{NamedReservableCurrency, ReservableCurrency};
|
||||
mod lockable;
|
||||
pub use lockable::{LockableCurrency, VestingSchedule, LockIdentifier};
|
||||
pub use lockable::{LockIdentifier, LockableCurrency, VestingSchedule};
|
||||
|
||||
/// Abstraction over a fungible assets system.
|
||||
pub trait Currency<AccountId> {
|
||||
@@ -36,11 +38,11 @@ pub trait Currency<AccountId> {
|
||||
|
||||
/// The opaque token type for an imbalance. This is returned by unbalanced operations
|
||||
/// and must be dealt with. It may be dropped but cannot be cloned.
|
||||
type PositiveImbalance: Imbalance<Self::Balance, Opposite=Self::NegativeImbalance>;
|
||||
type PositiveImbalance: Imbalance<Self::Balance, Opposite = Self::NegativeImbalance>;
|
||||
|
||||
/// The opaque token type for an imbalance. This is returned by unbalanced operations
|
||||
/// and must be dealt with. It may be dropped but cannot be cloned.
|
||||
type NegativeImbalance: Imbalance<Self::Balance, Opposite=Self::PositiveImbalance>;
|
||||
type NegativeImbalance: Imbalance<Self::Balance, Opposite = Self::PositiveImbalance>;
|
||||
|
||||
// PUBLIC IMMUTABLES
|
||||
|
||||
@@ -123,17 +125,14 @@ pub trait Currency<AccountId> {
|
||||
///
|
||||
/// As much funds up to `value` will be deducted as possible. If this is less than `value`,
|
||||
/// then a non-zero second item will be returned.
|
||||
fn slash(
|
||||
who: &AccountId,
|
||||
value: Self::Balance
|
||||
) -> (Self::NegativeImbalance, Self::Balance);
|
||||
fn slash(who: &AccountId, value: Self::Balance) -> (Self::NegativeImbalance, Self::Balance);
|
||||
|
||||
/// Mints `value` to the free balance of `who`.
|
||||
///
|
||||
/// If `who` doesn't exist, nothing is done and an Err returned.
|
||||
fn deposit_into_existing(
|
||||
who: &AccountId,
|
||||
value: Self::Balance
|
||||
value: Self::Balance,
|
||||
) -> Result<Self::PositiveImbalance, DispatchError>;
|
||||
|
||||
/// Similar to deposit_creating, only accepts a `NegativeImbalance` and returns nothing on
|
||||
@@ -152,17 +151,11 @@ pub trait Currency<AccountId> {
|
||||
/// Adds up to `value` to the free balance of `who`. If `who` doesn't exist, it is created.
|
||||
///
|
||||
/// Infallible.
|
||||
fn deposit_creating(
|
||||
who: &AccountId,
|
||||
value: Self::Balance,
|
||||
) -> Self::PositiveImbalance;
|
||||
fn deposit_creating(who: &AccountId, value: Self::Balance) -> Self::PositiveImbalance;
|
||||
|
||||
/// Similar to deposit_creating, only accepts a `NegativeImbalance` and returns nothing on
|
||||
/// success.
|
||||
fn resolve_creating(
|
||||
who: &AccountId,
|
||||
value: Self::NegativeImbalance,
|
||||
) {
|
||||
fn resolve_creating(who: &AccountId, value: Self::NegativeImbalance) {
|
||||
let v = value.peek();
|
||||
drop(value.offset(Self::deposit_creating(who, v)));
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user