mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-30 23:37:56 +00:00
Implement StorageNMap (#8635)
* Implement StorageNMap * Change copyright date to 2021 * Rewrite keys to use impl_for_tuples instead of recursion * Implement prefix iteration on StorageNMap * Implement EncodeLike for key arguments * Rename KeyGenerator::Arg to KeyGenerator::KArg * Support StorageNMap in decl_storage and #[pallet::storage] macros * Use StorageNMap in assets pallet * Support migrate_keys in StorageNMap * Reduce line characters on select files * Refactor crate imports in decl_storage macros * Some more line char reductions and doc comment update * Update UI test expectations * Revert whitespace changes to untouched files * Generate Key struct instead of a 1-tuple when only 1 pair of key and hasher is provided * Revert formatting changes to unrelated files * Introduce KeyGeneratorInner * Add tests for StorageNMap in FRAMEv2 pallet macro * Small fixes to unit tests for StorageNMap * Bump runtime metadata version * Remove unused import * Update tests to use runtime metadata v13 * Introduce and use EncodeLikeTuple as a trait bound for KArg * Add some rustdocs * Revert usage of StorageNMap in assets pallet * Make use of ext::PunctuatedTrailing * Add rustdoc for final_hash * Fix StorageNMap proc macro expansions for single key cases * Create associated const in KeyGenerator for hasher metadata * Refactor code according to comments from Basti * Add module docs for generator/nmap.rs * Re-export storage::Key as NMapKey in pallet prelude * Seal the EncodeLikeTuple trait * Extract sealing code out of key.rs Co-authored-by: Shawn Tabrizi <shawntabrizi@gmail.com>
This commit is contained in:
@@ -50,7 +50,7 @@ impl syn::parse::Parse for PalletStorageAttr {
|
||||
}
|
||||
|
||||
/// The value and key types used by storages. Needed to expand metadata.
|
||||
pub enum Metadata{
|
||||
pub enum Metadata {
|
||||
Value { value: syn::GenericArgument },
|
||||
Map { value: syn::GenericArgument, key: syn::GenericArgument },
|
||||
DoubleMap {
|
||||
@@ -58,6 +58,11 @@ pub enum Metadata{
|
||||
key1: syn::GenericArgument,
|
||||
key2: syn::GenericArgument
|
||||
},
|
||||
NMap {
|
||||
keys: Vec<syn::Type>,
|
||||
keygen: syn::GenericArgument,
|
||||
value: syn::GenericArgument,
|
||||
},
|
||||
}
|
||||
|
||||
pub enum QueryKind {
|
||||
@@ -115,6 +120,64 @@ fn retrieve_arg(
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse the 2nd type argument to `StorageNMap` and return its keys.
|
||||
fn collect_keys(keygen: &syn::GenericArgument) -> syn::Result<Vec<syn::Type>> {
|
||||
if let syn::GenericArgument::Type(syn::Type::Tuple(tup)) = keygen {
|
||||
tup
|
||||
.elems
|
||||
.iter()
|
||||
.map(extract_key)
|
||||
.collect::<syn::Result<Vec<_>>>()
|
||||
} else if let syn::GenericArgument::Type(ty) = keygen {
|
||||
Ok(vec![extract_key(ty)?])
|
||||
} else {
|
||||
let msg = format!("Invalid pallet::storage, expected tuple of Key structs or Key struct");
|
||||
Err(syn::Error::new(keygen.span(), msg))
|
||||
}
|
||||
}
|
||||
|
||||
/// In `Key<H, K>`, extract K and return it.
|
||||
fn extract_key(ty: &syn::Type) -> syn::Result<syn::Type> {
|
||||
let typ = if let syn::Type::Path(typ) = ty {
|
||||
typ
|
||||
} else {
|
||||
let msg = "Invalid pallet::storage, expected type path";
|
||||
return Err(syn::Error::new(ty.span(), msg));
|
||||
};
|
||||
|
||||
let key_struct = typ.path.segments.last().ok_or_else(|| {
|
||||
let msg = "Invalid pallet::storage, expected type path with at least one segment";
|
||||
syn::Error::new(typ.path.span(), msg)
|
||||
})?;
|
||||
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));
|
||||
}
|
||||
|
||||
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));
|
||||
};
|
||||
|
||||
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 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));
|
||||
}
|
||||
};
|
||||
|
||||
Ok(key)
|
||||
}
|
||||
|
||||
impl StorageDef {
|
||||
pub fn try_from(
|
||||
attr_span: proc_macro2::Span,
|
||||
@@ -177,11 +240,21 @@ impl StorageDef {
|
||||
value: retrieve_arg(&typ.path.segments[0], 5)?,
|
||||
}
|
||||
}
|
||||
"StorageNMap" => {
|
||||
query_kind = retrieve_arg(&typ.path.segments[0], 3);
|
||||
let keygen = retrieve_arg(&typ.path.segments[0], 1)?;
|
||||
let keys = collect_keys(&keygen)?;
|
||||
Metadata::NMap {
|
||||
keys,
|
||||
keygen,
|
||||
value: retrieve_arg(&typ.path.segments[0], 2)?,
|
||||
}
|
||||
}
|
||||
found => {
|
||||
let msg = format!(
|
||||
"Invalid pallet::storage, expected ident: `StorageValue` or \
|
||||
`StorageMap` or `StorageDoubleMap` in order to expand metadata, found \
|
||||
`{}`",
|
||||
`StorageMap` or `StorageDoubleMap` or `StorageNMap` in order \
|
||||
to expand metadata, found `{}`",
|
||||
found,
|
||||
);
|
||||
return Err(syn::Error::new(item.ty.span(), msg));
|
||||
|
||||
Reference in New Issue
Block a user