use crate::parse::deps::*;
use proc_macro2::TokenStream;
use quote::{ToTokens, format_ident, quote};
use syn::Ident;
mod graphql_impl;
type Result = syn::Result<TokenStream>;
pub use crate::parse::{CidomapStruct, CidomapStructDef};
impl crate::codegen::CodegenWrapper<CidomapStruct> {
pub fn codegen(&self) -> syn::Result<TokenStream> {
let CidomapStruct { name, vis, .. } = &self.0;
let mut token_stream = quote! {
#[derive(::core::clone::Clone, ::core::fmt::Debug)]
#vis struct #name;
};
let graphql_name = format_ident!("{name}Graphql");
impl_cidomap(&self.0, &graphql_name)?.to_tokens(&mut token_stream);
graphql_impl::graphql_impl(&self.0, &graphql_name)?.to_tokens(&mut token_stream);
crate::parse::embed_generated_code(
self.opts.embed_generated_code,
name,
token_stream,
"cidomap",
)
}
}
fn impl_cidomap(cidomap: &CidomapStruct, graphql_name: &Ident) -> Result {
let cidomap_name = &cidomap.name;
let opts = &cidomap.opts;
let fields = &cidomap.fields;
let mut type_iter = Vec::new();
let mut async_type_iter = Vec::new();
for f in fields {
let ty = &f.field.ty;
type_iter.push(quote! {
t.next_type::<#ty>()?;
});
async_type_iter.push(quote! {
t.next_type::<#ty>().await?;
})
}
let CidomapStructDef {
start_block,
max_block,
max_processing_order,
initial_filters,
init,
create,
error,
network,
events,
} = &opts.config;
let output_init_fn = init
.as_ref()
.map(|init_fn| quote! {
fn init<'a>(
cx: ::cido::__internal::Context<'a, Self>,
) -> ::std::pin::Pin<::std::boxed::Box<dyn ::std::future::Future<Output = ::std::result::Result<(), Self::Error>> + 'a>>
{
::std::boxed::Box::pin(async move {#init_fn(cx).await })
}
}).unwrap_or_else(|| quote! {});
let output_create_fn = create
.as_ref()
.map(|create_fn| quote! {
fn create<'a>(
cx: ::cido::__internal::Context<'a, Self>,
) -> ::std::pin::Pin<::std::boxed::Box<dyn ::std::future::Future<Output = ::std::result::Result<(), Self::Error>> + 'a>>
{
::std::boxed::Box::pin(async move {#create_fn(cx).await })
}
}).unwrap_or_else(|| quote! {});
let max_processing_order = match *max_processing_order {
1 => quote! {One},
2 => quote! {Two},
3 => quote! {Three},
_ => {
return Err(syn::Error::new(
proc_macro2::Span::call_site(),
format!("Invalid processing order {max_processing_order}"),
));
}
};
let max_block = max_block
.clone()
.unwrap_or_else(|| syn::parse_quote!(::core::option::Option::None));
Ok(quote! {
impl ::cido::__internal::Cidomap for #cidomap_name {
type Error = #error;
type Network = #network;
type Events = #events;
type Graphql = #graphql_name;
const MAX_PROCESSING_ORDER: ::cido::__internal::ProcessingOrder = ::cido::__internal::ProcessingOrder::#max_processing_order;
const START_BLOCK: <Self::Network as ::cido::__internal::Network>::BlockNumber = #start_block;
const MAX_BLOCK: ::core::option::Option<<Self::Network as ::cido::__internal::Network>::BlockNumber> = #max_block;
fn type_iter<T: ::cido::__internal::TypeIter<Self>>(t: &mut T) -> ::std::result::Result<(), ::cido::__internal::CidomapError> {
#(#type_iter)*
::std::result::Result::Ok(())
}
fn async_type_iter<T: ::cido::__internal::AsyncTypeIter<Self>>(t: &mut T) -> ::cido::__internal::futures::future::BoxFuture<'_, ::std::result::Result<(), ::cido::__internal::CidomapError>> {
::std::boxed::Box::pin(async move {
#(#async_type_iter)*
::std::result::Result::Ok(())
})
}
fn initial_filters(
) -> ::std::result::Result<::std::vec::Vec<<Self::Network as ::cido::__internal::Network>::TriggerFilter>, <Self::Network as ::cido::__internal::Network>::Error> {
#initial_filters()
}
#output_init_fn
#output_create_fn
}
pub fn main() -> ::core::result::Result<(), ::cido::__internal::CidomapError> {
::cido::__internal::run::<#cidomap_name>()
}
})
}