config: Handle hasher and header

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
This commit is contained in:
Alexandru Vasile
2024-05-08 08:34:52 +00:00
parent a1434a9764
commit 609b701d4d
4 changed files with 125 additions and 8 deletions
+104 -4
View File
@@ -3,9 +3,10 @@
// see LICENSE for license details.
use heck::ToSnakeCase as _;
use scale_info::{TypeDef, TypeDefComposite};
use scale_typegen::typegen::ir::ToTokensWithSettings;
use scale_typegen::TypeGenerator;
use std::collections::HashSet;
use std::{any::Any, collections::HashSet};
use subxt_metadata::{CustomValueMetadata, Metadata};
use proc_macro2::TokenStream as TokenStream2;
@@ -20,14 +21,113 @@ pub fn generate_custom_values(
let mut fn_names_taken = HashSet::new();
let custom = metadata.custom();
let custom_types = custom.iter().map(|custom| {
let name = format_ident!("{}", custom.name());
let name_str = custom.name();
let Ok(ty) = type_gen.resolve_type_path(custom.type_id()) else {
let name = format_ident!("{}", name_str);
let Ok(ty_path) = type_gen.resolve_type_path(custom.type_id()) else {
return quote! {};
};
let ty = ty.to_token_stream(type_gen.settings());
let ty = ty_path.to_token_stream(type_gen.settings());
let mut maybe_impl = None;
let mut extra = None;
if name_str == "Hashing" {
// Extract hasher name
let ty_path_str = ty.to_string();
if ty_path_str.contains("BlakeTwo256") {
maybe_impl = Some(quote! {
impl #crate_path::config::Hasher for #ty {
type Output = #crate_path::utils::H256;
fn hash(s: &[u8]) -> Self::Output {
let mut bytes = Vec::new();
#crate_path::storage::utils::hash_bytes(s, #crate_path::storage::utils::StorageHasher::Blake2_256, &mut bytes);
let arr: [u8; 32] = bytes.try_into().expect("Invalid hashing output provided");
arr.into()
}
}
});
}
}
if name_str == "Header" {
// Extract header number from the provided type.
let Ok(ty_res) = type_gen.resolve_type(custom.type_id()) else {
return quote! {};
};
let TypeDef::Composite(composite) = &ty_res.type_def else {
return quote! {};
};
// Sanity check for the number type.
let number_ty = composite.fields.iter().find_map(
|field| if let Some(n) = &field.name {
if n == "number" {
Some(field.ty.id)
} else {
None
}
} else {
None
}
);
if let Some(num) = number_ty {
let Ok(ty_path) = type_gen.resolve_type_path(num) else {
return quote! {};
};
if !ty_path.is_compact() {
let ty = ty_path.to_token_stream(type_gen.settings());
extra = Some(quote! {
pub type HeaderNumber = #ty;
});
} else {
// Ty is compact.
let Ok(ty_res) = type_gen.resolve_type(num) else {
return quote! {};
};
let TypeDef::Compact(compact) = &ty_res.type_def else {
return quote! {};
};
let compact_ty_id = compact.type_param.id;
let Ok(ty_path) = type_gen.resolve_type_path(compact_ty_id) else {
return quote! {};
};
let ty = ty_path.to_token_stream(type_gen.settings());
extra = Some(quote! {
pub type HeaderNumber = #ty;
});
}
maybe_impl = Some(quote! {
impl #crate_path::config::Header for #ty {
type Number = HeaderNumber;
type Hasher = Hashing;
// If we got to this point, the `number` field exists on the header
// structure.
fn number(&self) -> Self::Number {
self.number
}
}
});
}
}
quote! {
pub type #name = #ty;
#maybe_impl
#extra
}
});