multi_rpc_macros/
lib.rs

1use proc_macro::TokenStream;
2use quote::{format_ident, quote};
3use syn::{parse_macro_input, ItemImpl, ItemTrait};
4
5mod protocols;
6use protocols::{JsonRpSee, Protocol, RestAxum, Tarpc};
7
8const PROTOCOLS: &[&dyn Protocol] = &[&Tarpc, &RestAxum, &JsonRpSee];
9
10#[proc_macro_attribute]
11pub fn multi_rpc_trait(_attr: TokenStream, input: TokenStream) -> TokenStream {
12    let mut item_trait = parse_macro_input!(input as ItemTrait);
13    let trait_ident = item_trait.ident.clone();
14    let generated_mod_ident = format_ident!("{}_generated", trait_ident.to_string().to_lowercase());
15
16    let generated_trait_code: Vec<_> = PROTOCOLS.iter().map(|p| p.transform_trait(&mut item_trait)).collect();
17
18    quote! {
19        #item_trait
20        pub mod #generated_mod_ident {
21            use super::*;
22            use std::sync::Arc;
23            use multi_rpc::error::RpcError;
24            #(#generated_trait_code)*
25        }
26    }.into()
27}
28
29#[proc_macro_attribute]
30pub fn multi_rpc_impl(_attr: TokenStream, input: TokenStream) -> TokenStream {
31    let item_impl = parse_macro_input!(input as ItemImpl);
32
33    // ✅ Create the module name (e.g., `greeter_impls`) from the trait name.
34    let trait_ident = &item_impl.trait_.as_ref().unwrap().1.segments.last().unwrap().ident;
35    let impls_mod_ident = format_ident!("{}_impls", trait_ident.to_string().to_lowercase());
36
37    let generated_impl_code: Vec<_> = PROTOCOLS.iter().map(|p| p.transform_impl(&item_impl)).collect();
38
39    quote! {
40        #item_impl
41
42        // ✅ Wrap all generated code in the namespaced module.
43        pub mod #impls_mod_ident {
44            // `use super::*;` allows the generated code to find `MyGreeter`, `greeter_generated`, etc.
45            use super::*;
46            use std::sync::Arc;
47
48            #(#generated_impl_code)*
49        }
50    }.into()
51}
52
53#[proc_macro_attribute]
54pub fn rest(_attr: TokenStream, item: TokenStream) -> TokenStream {
55    item
56}