use super::DeclStorageDefExt;
use crate::NUMBER_OF_INSTANCE;
use proc_macro2::{Span, TokenStream};
use quote::quote;
pub(crate) const INHERENT_INSTANCE_NAME: &str = "__InherentHiddenInstance";
struct InstanceDef {
prefix: String,
instance_struct: syn::Ident,
doc: TokenStream,
index: u8,
}
pub fn decl_and_impl(def: &DeclStorageDefExt) -> TokenStream {
let scrate = &def.hidden_crate;
let mut impls = TokenStream::new();
impls.extend(reexport_instance_trait(scrate, def));
if let Some(module_instance) = &def.module_instance {
let instance_defs = (1..=NUMBER_OF_INSTANCE)
.map(|i| {
let name = format!("Instance{}", i);
InstanceDef {
instance_struct: syn::Ident::new(&name, proc_macro2::Span::call_site()),
prefix: name,
doc: quote!(#[doc=r"Module instance"]),
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,
}));
for instance_def in instance_defs {
impls.extend(create_and_impl_instance_struct(scrate, &instance_def, def));
}
}
let inherent_instance = syn::Ident::new(INHERENT_INSTANCE_NAME, Span::call_site());
if let Some(default_instance) =
def.module_instance.as_ref().and_then(|i| i.instance_default.as_ref())
{
impls.extend(quote! {
#[doc(hidden)]
pub type #inherent_instance = #default_instance;
});
} else {
let instance_def = InstanceDef {
prefix: String::new(),
instance_struct: inherent_instance,
doc: quote!(
#[doc(hidden)]
),
index: 0,
};
impls.extend(create_and_impl_instance_struct(scrate, &instance_def, def));
}
impls
}
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!(
use #scrate::traits::Instance as #instance_trait;
)
} else {
quote!()
}
}
fn create_and_impl_instance_struct(
scrate: &TokenStream,
instance_def: &InstanceDef,
def: &DeclStorageDefExt,
) -> TokenStream {
let instance_trait = quote!( #scrate::traits::Instance );
let instance_struct = &instance_def.instance_struct;
let prefix = format!("{}{}", instance_def.prefix, def.crate_name);
let doc = &instance_def.doc;
let index = instance_def.index;
quote! {
#[derive(
Clone, Eq, PartialEq,
#scrate::codec::Encode,
#scrate::codec::Decode,
#scrate::scale_info::TypeInfo,
#scrate::RuntimeDebug,
)]
#doc
pub struct #instance_struct;
impl #instance_trait for #instance_struct {
const PREFIX: &'static str = #prefix;
const INDEX: u8 = #index;
}
}
}