Skip to content

Commit

Permalink
Dramatically simplify macro def
Browse files Browse the repository at this point in the history
  • Loading branch information
sug0 committed Dec 5, 2024
1 parent 5ea554f commit b9ebedd
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 77 deletions.
95 changes: 20 additions & 75 deletions crates/module-macros/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,52 +1,29 @@
extern crate proc_macro;

use quote::{quote, ToTokens};

#[proc_macro_derive(ModuleFromMiddleware)]
pub fn derive_module_from_middleware(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
derive_module_from_middleware_inner(input.into()).into()
use quote::quote;

/// Generate an IBC module from a type that implements
/// an IBC middleware module.
///
/// ## Example
///
/// ```ignore
/// from_middleware! {
/// impl<M> Module for Middleware<M>
/// where
/// M: Module,
/// }
/// ```
#[proc_macro]
pub fn from_middleware(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
from_middleware_inner(input.into()).into()
}

fn derive_module_from_middleware_inner(
input: proc_macro2::TokenStream,
fn from_middleware_inner(
impl_def_up_to_block: proc_macro2::TokenStream,
) -> proc_macro2::TokenStream {
let _struct = syn::parse2::<syn::ItemStruct>(input).expect("Expected struct definition");

let struct_generics = &_struct.generics;
let struct_generics_params = &struct_generics.params;

let (name, types) = fetch_name_with_generic_params(&_struct);
let where_clauses = {
let mut clauses =
struct_generics
.where_clause
.clone()
.unwrap_or_else(|| syn::WhereClause {
where_token: Default::default(),
predicates: syn::punctuated::Punctuated::new(),
});

for ty in types {
clauses
.predicates
.push(syn::WherePredicate::Type(syn::PredicateType {
lifetimes: None,
bounded_ty: syn::Type::Verbatim(ty),
colon_token: Default::default(),
bounds: {
let mut b = syn::punctuated::Punctuated::new();
b.push(syn::TypeParamBound::Verbatim(quote!(Module)));
b
},
}));
}

quote!(#clauses)
};

quote! {
impl<#struct_generics_params> Module for #name
#where_clauses
#impl_def_up_to_block
{
#[inline(always)]
fn on_chan_open_init_validate(
Expand Down Expand Up @@ -251,35 +228,3 @@ fn derive_module_from_middleware_inner(
}
}
}

fn fetch_name_with_generic_params(
_struct: &syn::ItemStruct,
) -> (proc_macro2::TokenStream, Vec<proc_macro2::TokenStream>) {
let mut types = vec![];
let mut consts = vec![];
let mut lifetimes = vec![];

for param in _struct.generics.params.iter() {
match param {
syn::GenericParam::Type(type_) => types.push(type_.ident.to_token_stream()),
syn::GenericParam::Lifetime(life_def) => {
lifetimes.push(life_def.lifetime.to_token_stream())
}
syn::GenericParam::Const(constant) => consts.push(constant.ident.to_token_stream()),
}
}

let ident = &_struct.ident;
let (all_params, types) = {
let (mut output, mut consts, types) = (lifetimes, consts, types);
output.append(&mut consts);
output.extend(types.iter().cloned());
(output, types)
};

let name = quote! {
#ident < #(#all_params),* >
};

(name, types)
}
8 changes: 6 additions & 2 deletions crates/module/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -239,14 +239,18 @@ pub trait MiddlewareModule {

#[cfg(test)]
mod tests {
use ibc_middleware_module_macros::ModuleFromMiddleware;
use ibc_middleware_module_macros::from_middleware;
use ibc_testkit::testapp::ibc::applications::transfer::types::DummyTransferModule;

use super::*;

#[derive(Debug, ModuleFromMiddleware)]
#[derive(Debug)]
struct DummyMiddleware<M>(M);

from_middleware! {
impl<M: Module> Module for DummyMiddleware<M>
}

impl<M> MiddlewareModule for DummyMiddleware<M>
where
M: Module,
Expand Down

0 comments on commit b9ebedd

Please sign in to comment.