use quote::{format_ident, ToTokens};
use crate::ir::{EnumeratedTypedField, ModuleStructIR};
pub struct SchemaEventsItem {
module_ident: syn::Ident,
events: Vec<syn::Type>,
fields: Vec<EnumeratedTypedField>
}
impl ToTokens for SchemaEventsItem {
fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
let module_ident = &self.module_ident;
let events = self.events.iter().map(|ty| {
quote::quote!(odra::schema::event(&<#ty as odra::casper_event_standard::EventInstance>::name()))
}).collect::<Vec<_>>();
let types = self.events.iter().map(|event| {
quote::quote!(.chain(<#event as odra::schema::SchemaCustomTypes>::schema_types()))
}).collect::<Vec<_>>();
let events_chain = self
.fields
.iter()
.map(|f| {
let ty = &f.ty;
quote::quote!(.chain(<#ty as odra::schema::SchemaEvents>::schema_events()))
})
.collect::<Vec<_>>();
let types_chain = self
.fields
.iter()
.map(|f| {
let ty = &f.ty;
quote::quote!(.chain(<#ty as odra::schema::SchemaEvents>::custom_types()))
})
.collect::<Vec<_>>();
let item = quote::quote! {
#[automatically_derived]
#[cfg(not(target_arch = "wasm32"))]
impl odra::schema::SchemaEvents for #module_ident {
fn schema_events() -> odra::prelude::Vec<odra::schema::casper_contract_schema::Event> {
odra::prelude::vec::Vec::<odra::schema::casper_contract_schema::Event>::new()
.into_iter()
.chain(odra::prelude::vec![#(#events),*])
#(#events_chain)*
.collect::<odra::prelude::BTreeSet<odra::schema::casper_contract_schema::Event>>()
.into_iter()
.collect()
}
fn custom_types() -> odra::prelude::Vec<Option<odra::schema::casper_contract_schema::CustomType>> {
odra::prelude::vec::Vec::<Option<odra::schema::casper_contract_schema::CustomType>>::new()
.into_iter()
#(#types)*
#(#types_chain)*
.collect::<odra::prelude::BTreeSet<Option<odra::schema::casper_contract_schema::CustomType>>>()
.into_iter()
.collect()
}
}
};
item.to_tokens(tokens);
}
}
impl TryFrom<&ModuleStructIR> for SchemaEventsItem {
type Error = syn::Error;
fn try_from(ir: &ModuleStructIR) -> Result<Self, Self::Error> {
Ok(Self {
module_ident: ir.module_ident(),
events: ir.events(),
fields: ir.typed_fields()?
})
}
}
pub struct FactorySchemaEventsItem {
module_ident: syn::Ident,
event_ident: syn::Ident,
}
impl TryFrom<&ModuleStructIR> for FactorySchemaEventsItem {
type Error = syn::Error;
fn try_from(ir: &ModuleStructIR) -> Result<Self, Self::Error> {
Ok(Self {
module_ident: ir.module_ident(),
event_ident: format_ident!("{}ContractDeployed", ir.module_ident()),
})
}
}
impl ToTokens for FactorySchemaEventsItem {
fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
let module_ident = &self.module_ident;
let event_ident = &self.event_ident;
let item = quote::quote! {
#[automatically_derived]
#[cfg(not(target_arch = "wasm32"))]
impl odra::schema::SchemaEvents for #module_ident {
fn schema_events() -> odra::prelude::Vec<odra::schema::casper_contract_schema::Event> {
odra::prelude::vec![
odra::schema::event(
&<#event_ident as odra::casper_event_standard::EventInstance>::name()
)
]
}
fn custom_types() -> odra::prelude::Vec<Option<odra::schema::casper_contract_schema::CustomType>> {
<#event_ident as odra::schema::SchemaCustomTypes>::schema_types()
}
}
};
item.to_tokens(tokens);
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::test_utils;
#[test]
fn custom_types_works() {
let ir = test_utils::mock::module_definition();
let item = SchemaEventsItem::try_from(&ir).unwrap();
let expected = quote::quote!(
#[automatically_derived]
#[cfg(not(target_arch = "wasm32"))]
impl odra::schema::SchemaEvents for CounterPack {
fn schema_events() -> odra::prelude::Vec<odra::schema::casper_contract_schema::Event>
{
odra::prelude::vec::Vec::<odra::schema::casper_contract_schema::Event>::new()
.into_iter()
.chain(odra::prelude::vec![
odra::schema::event(
&<OnTransfer as odra::casper_event_standard::EventInstance>::name()
),
odra::schema::event(
&<OnApprove as odra::casper_event_standard::EventInstance>::name()
)
])
.chain(<SubModule<Counter> as odra::schema::SchemaEvents>::schema_events())
.chain(<SubModule<Counter> as odra::schema::SchemaEvents>::schema_events())
.chain(<SubModule<Counter> as odra::schema::SchemaEvents>::schema_events())
.chain(<Var<u32> as odra::schema::SchemaEvents>::schema_events())
.chain(<Mapping<u8, Counter> as odra::schema::SchemaEvents>::schema_events())
.collect::<odra::prelude::BTreeSet<odra::schema::casper_contract_schema::Event>>()
.into_iter()
.collect()
}
fn custom_types(
) -> odra::prelude::Vec<Option<odra::schema::casper_contract_schema::CustomType>>
{
odra::prelude::vec::Vec::<
Option<odra::schema::casper_contract_schema::CustomType>
>::new()
.into_iter()
.chain(<OnTransfer as odra::schema::SchemaCustomTypes>::schema_types())
.chain(<OnApprove as odra::schema::SchemaCustomTypes>::schema_types())
.chain(<SubModule<Counter> as odra::schema::SchemaEvents>::custom_types())
.chain(<SubModule<Counter> as odra::schema::SchemaEvents>::custom_types())
.chain(<SubModule<Counter> as odra::schema::SchemaEvents>::custom_types())
.chain(<Var<u32> as odra::schema::SchemaEvents>::custom_types())
.chain(<Mapping<u8, Counter> as odra::schema::SchemaEvents>::custom_types())
.collect::<odra::prelude::BTreeSet<
Option<odra::schema::casper_contract_schema::CustomType>
>>()
.into_iter()
.collect()
}
}
);
test_utils::assert_eq(item, expected);
}
#[test]
fn test_factory_module() {
let module = test_utils::mock::factory_module_definition();
let item = FactorySchemaEventsItem::try_from(&module).unwrap();
let expected = quote::quote! {
#[automatically_derived]
#[cfg(not(target_arch = "wasm32"))]
impl odra::schema::SchemaEvents for CounterPack {
fn schema_events() -> odra::prelude::Vec<odra::schema::casper_contract_schema::Event>
{
odra::prelude::vec![
odra::schema::event(
&<CounterPackContractDeployed as odra::casper_event_standard::EventInstance>::name()
)
]
}
fn custom_types(
) -> odra::prelude::Vec<Option<odra::schema::casper_contract_schema::CustomType>>
{
<CounterPackContractDeployed as odra::schema::SchemaCustomTypes>::schema_types()
}
}
};
test_utils::assert_eq(item, expected);
}
}