srpc_macro/
lib.rs

1use heck::ToSnakeCase;
2use proc_macro::TokenStream;
3use proc_macro_error::abort;
4use quote::{format_ident, quote, ToTokens};
5use syn::{Block, FnArg, Ident, ImplItem, ItemImpl, ItemStruct, PatType, ReturnType, Type};
6
7#[proc_macro]
8pub fn top_route(_: TokenStream) -> TokenStream {
9    quote!(__srpc_inner_ctx).into()
10}
11
12#[proc_macro_attribute]
13#[proc_macro_error::proc_macro_error]
14pub fn rpc(attrs: TokenStream, item: TokenStream) -> TokenStream {
15    match syn::parse::<ItemStruct>(item.clone()) {
16        Ok(item) => struct_rpc(attrs, item),
17        Err(_) => {
18            let item = syn::parse::<ItemImpl>(item).unwrap();
19            match syn::parse::<Ident>(attrs.clone()) {
20                Ok(ident) => {
21                    let rpc: Result<RpcProvider, String> =
22                        Some(ident.to_string().as_str()).try_into();
23                    match rpc {
24                        Ok(rpc) => impl_rpc_provider(rpc, item),
25                        Err(span) => {
26                            return syn::Error::new(ident.span(), span)
27                                .to_compile_error()
28                                .into()
29                        }
30                    }
31                }
32                Err(_) => impl_rpc_provider(RpcProvider::RwLock, item),
33            }
34        }
35    }
36}
37
38fn struct_rpc(_: TokenStream, item: ItemStruct) -> TokenStream {
39    let ident = &item.ident;
40    let vis = &item.vis;
41    let peer_name = format_ident!("{}Peer", &ident);
42    let (implgen, tygen, whre) = item.generics.split_for_impl();
43
44    let ty_params = item.generics.type_params().map(|s| &s.ident);
45
46    quote!(
47        #item
48        #vis struct #peer_name #tygen #whre (pub ::srpc::__private::canary::Channel, ::core::marker::PhantomData<( #(#ty_params),* )>);
49        impl #implgen From<::srpc::__private::canary::Channel> for #peer_name #tygen #whre {
50            fn from(c: ::srpc::__private::canary::Channel) -> Self {
51                #peer_name(c, ::core::marker::PhantomData::default())
52            }
53        }
54        impl #implgen From<#peer_name #tygen> for ::srpc::__private::canary::Channel #whre {
55            fn from(c: #peer_name #tygen) -> Self {
56                c.0
57            }
58        }
59        impl #implgen ::srpc::Peer for #ident #tygen #whre {
60            type Struct = #peer_name #tygen;
61        }
62    )
63    .into()
64}
65
66#[derive(Clone)]
67struct Method<'a> {
68    ident: &'a Ident,
69    output: Option<&'a Box<Type>>,
70    inputs: Option<Vec<&'a PatType>>,
71    mutable: bool,
72    consume: MethodKind,
73    block: &'a Block,
74}
75
76#[derive(Clone)]
77enum MethodKind {
78    Normal,        // normal rpc
79    Consume,       // consume channel
80    Manual,        // reintroduce
81    Server,        // similar to manual, but does not create a client method
82    Client,        // create a client method
83    ServerManual,  // similar to manual, but does not create a client method
84    ClientManual,  // create a manual client method
85    ServerConsume, // similar to consume, but does not create a client method
86    ClientConsume, // create a client method that consumes
87}
88
89enum RpcProvider {
90    RwLock,
91    Mutex,
92    Ref,
93}
94
95impl TryFrom<Option<&str>> for RpcProvider {
96    type Error = String;
97
98    fn try_from(value: Option<&str>) -> Result<Self, Self::Error> {
99        match value {
100            Some(s) => match s {
101                "rw" => Ok(RpcProvider::RwLock),
102                "rwlock" => Ok(RpcProvider::RwLock),
103                "mutex" => Ok(RpcProvider::Mutex),
104                "mtx" => Ok(RpcProvider::Mutex),
105                "none" => Ok(RpcProvider::Ref),
106                _ => Err(format!("{:?} not expected in this context, possible values are: `rw`, `rwlock`, `mutex`, `mtx` or `none`", s))
107            },
108            None => Ok(RpcProvider::RwLock)
109        }
110    }
111}
112
113impl RpcProvider {
114    fn get_meta(&self, mutable: bool, meta: &syn::Ident) -> quote::__private::TokenStream {
115        match self {
116            RpcProvider::RwLock => {
117                if mutable {
118                    quote!(#meta.write().await)
119                } else {
120                    quote!(#meta.read().await)
121                }
122            }
123            RpcProvider::Mutex => quote! {
124                #meta.lock().await
125            },
126            RpcProvider::Ref => quote! {
127                #meta
128            },
129        }
130    }
131    fn get_type<T: ToTokens>(&self, top: T) -> quote::__private::TokenStream {
132        match self {
133            RpcProvider::RwLock => quote! {
134                ::srpc::__private::RwLock<#top>
135            },
136            RpcProvider::Mutex => quote! {
137                ::srpc::__private::Mutex<#top>
138            },
139            RpcProvider::Ref => quote! {
140                #top
141            },
142        }
143    }
144}
145
146fn impl_rpc_provider(provider: RpcProvider, mut item: ItemImpl) -> TokenStream {
147    item.attrs.clear();
148    let methods = {
149        let mut items = item
150            .items
151            .clone()
152            .into_iter()
153            .filter(|s| {
154                if let ImplItem::Method(_) = s {
155                    true
156                } else {
157                    false
158                }
159            })
160            .map(|s| {
161                if let ImplItem::Method(s) = s {
162                    s
163                } else {
164                    unreachable!("please report this bug")
165                }
166            })
167            .collect::<Vec<_>>();
168        // this is done to prevent a bug. a rewrite of the macro should be done,
169        // but it works for now.
170        items.sort_by_cached_key(|elem| elem.attrs.len());
171        items
172    };
173
174    let top_type_name = {
175        if let Type::Path(s) = *item.self_ty.clone() {
176            s.path.segments.first().unwrap().clone().ident
177        } else {
178            panic!("unexpected type")
179        }
180    };
181    let top_type = &item.self_ty;
182
183    let top_type_meta = provider.get_type(&top_type);
184    let mut method_names = methods.iter().map(|s| &s.sig.ident).collect::<Vec<_>>();
185    method_names.sort();
186    method_names.dedup();
187    let repr = {
188        match method_names.len() {
189            0 => quote! { #[derive(::srpc::__private::Serialize, ::srpc::__private::Deserialize)] },
190            num if num < (u8::MAX as usize) => quote! {
191                #[derive(::srpc::__private::Serialize_repr, ::srpc::__private::Deserialize_repr)]
192                #[repr(u8)]
193            },
194            num if num < (u16::MAX as usize) => quote! {
195                #[derive(::srpc::__private::Serialize_repr, ::srpc::__private::Deserialize_repr)]
196                #[repr(u16)]
197            },
198            num if num < (u32::MAX as usize) => quote! {
199                #[derive(::srpc::__private::Serialize_repr, ::srpc::__private::Deserialize_repr)]
200                #[repr(u32)]
201            },
202            _ => quote! {
203                #[derive(::srpc::__private::Serialize_repr, ::srpc::__private::Deserialize_repr)]
204                #[repr(u64)]
205            },
206        }
207    };
208
209    let enum_repr = quote! (
210        #[allow(non_camel_case_types)]
211        #repr
212        enum __srpc_action {
213            #(#method_names),*
214        }
215    );
216
217    let methods = methods.iter().map(|s| {
218        let output = match &s.sig.output {
219            ReturnType::Default => None,
220            ReturnType::Type(_, ty) => Some(ty),
221        };
222        let block = &s.block;
223
224        let mut mutable = false;
225        let consume = s
226            .attrs
227            .iter()
228            .any(|attr| quote!(#[consume]).to_string() == quote!(#attr).to_string());
229        let manual = s
230            .attrs
231            .iter()
232            .any(|attr| quote!(#[manual]).to_string() == quote!(#attr).to_string());
233        let server = s
234            .attrs
235            .iter()
236            .any(|attr| quote!(#[server]).to_string() == quote!(#attr).to_string());
237        let server_consume = s
238            .attrs
239            .iter()
240            .any(|attr| quote!(#[server_consume]).to_string() == quote!(#attr).to_string());
241        let client = s
242            .attrs
243            .iter()
244            .any(|attr| quote!(#[client]).to_string() == quote!(#attr).to_string());
245        let client_consume = s
246            .attrs
247            .iter()
248            .any(|attr| quote!(#[client_consume]).to_string() == quote!(#attr).to_string());
249        let client_manual = s
250            .attrs
251            .iter()
252            .any(|attr| quote!(#[client_manual]).to_string() == quote!(#attr).to_string());
253        let server_manual = s
254            .attrs
255            .iter()
256            .any(|attr| quote!(#[server_manual]).to_string() == quote!(#attr).to_string());
257        let consume = match (
258            consume,
259            manual,
260            client,
261            server,
262            server_consume,
263            client_consume,
264            client_manual,
265            server_manual,
266        ) {
267            (true, false, false, false, false, false, false, false) => MethodKind::Consume,
268            (false, true, false, false, false, false, false, false) => MethodKind::Manual,
269            (false, false, true, false, false, false, false, false) => MethodKind::Client,
270            (false, false, false, true, false, false, false, false) => MethodKind::Server,
271            (false, false, false, false, true, false, false, false) => MethodKind::ServerConsume,
272            (false, false, false, false, false, true, false, false) => MethodKind::ClientConsume,
273            (false, false, false, false, false, false, false, false) => MethodKind::Normal,
274            (false, false, false, false, false, false, true, false) => MethodKind::ClientManual,
275            (false, false, false, false, false, false, false, true) => MethodKind::ServerManual,
276            (consume, manual, client, server, server_consume, client_consume, client_manual, server_manual)
277                if consume as u8
278                    + manual as u8
279                    + client as u8
280                    + server as u8
281                    + server_consume as u8
282                    + client_consume as u8
283                    + client_manual as u8
284                    + server_manual as u8
285                    > 1 =>
286            {
287                abort!(
288                    &s.sig.ident.span(),
289                    "cannot have a method with more than one modifier"
290                )
291            }
292            (_, _, _, _, _, _, _, _) => panic!("zasdfasdfasdf"),
293        };
294
295        let iter = s
296            .sig
297            .inputs
298            .iter()
299            .filter_map(|i| match i {
300                FnArg::Receiver(s) => {
301                    mutable = s.mutability.is_some();
302                    None
303                }
304                FnArg::Typed(ty) => Some(ty),
305            })
306            .collect::<Vec<_>>();
307        let inputs = if !iter.is_empty() { Some(iter) } else { None };
308        Method {
309            ident: &s.sig.ident,
310            output,
311            inputs,
312            mutable,
313            consume,
314            block,
315        }
316    });
317
318    let meta_ident = format_ident!("__srpc_inner_meta");
319    let channel_ident = format_ident!("__srpc_inner_channel");
320    let context_ident = format_ident!("__srpc_inner_ctx");
321
322    let matches = methods.clone().map(|method| {
323        let ident = method.ident;
324        let inputs = method.inputs;
325
326        let meta = provider.get_meta(method.mutable, &meta_ident);
327
328        match (inputs, method.output, method.consume) {
329            (None, None, MethodKind::Normal) => quote!(
330                __srpc_action::#ident => {
331                    #meta.#ident(&#context_ident).await;
332                },
333            ),
334            (None, Some(_), MethodKind::Normal) => quote!(
335                __srpc_action::#ident => {
336                    let res = #meta.#ident(&#context_ident).await;
337                    #channel_ident.send(res).await?;
338                },
339            ),
340            (Some(inputs), None, MethodKind::Normal) => {
341                let mut args = vec![];
342                inputs.iter().map(|s| {
343                    let s = &s.pat;
344                    let arg = format_ident!("{}", quote!(#s).to_string());
345                    args.push(arg);
346                }).for_each(drop);
347                let inputs = inputs.into_iter().map(|s| &s.ty);
348
349                let inputs = quote!( ( #(#args),*  ): ( #(#inputs),* ) );
350                quote!(
351                    __srpc_action::#ident => {
352                        #[allow(unused_parens)]
353                        let #inputs = #channel_ident.receive().await?;
354                        #meta.#ident(#(#args),* , &#context_ident).await;
355                    },
356                )
357            },
358            (Some(inputs), Some(_), MethodKind::Normal) => {
359                let mut args = vec![];
360                inputs.iter().map(|s| {
361                    args.push(&s.pat);
362                }).for_each(drop);
363                let inputs = inputs.into_iter().map(|s| &s.ty);
364
365                let inputs = quote!( ( #(#args),*  ): ( #(#inputs),* ) );
366                quote!(
367                    __srpc_action::#ident => {
368                        #[allow(unused_parens)]
369                        let #inputs = #channel_ident.receive().await?;
370                        let res = #meta.#ident(#(#args),* , &#context_ident).await;
371                        #channel_ident.send(res).await?;
372                    },
373                )
374            },
375            (Some(inputs), Some(_), MethodKind::Consume) => {
376                if inputs.len() != 1 {
377                    abort!(method.ident.span(), "methods that consume can only have one argument with type Channel and return a canary::Result<()>")
378                }
379                quote! {
380                    __srpc_action::#ident => {
381                        return #meta.#ident(#channel_ident, &#context_ident).await;
382                    },
383                }
384            }
385            (Some(inputs), Some(_), MethodKind::Manual) => {
386                if inputs.len() != 1 {
387                    abort!(method.ident.span(), "manual methods can only have one argument with type Channel and return a canary::Result<Channel>")
388                }
389                quote! {
390                    __srpc_action::#ident => {
391                        match #meta.#ident(#channel_ident, &#context_ident).await {
392                            Ok(chan) => #channel_ident = chan,
393                            Err(e) => return Err(e),
394                        }
395                    },
396                }
397            },
398            (Some(inputs), Some(_), MethodKind::Server) => {
399                if inputs.len() != 1 {
400                    abort!(method.ident.span(), "manual methods can only have one argument with type Channel and return a canary::Result<Channel>")
401                }
402                quote! {
403                    __srpc_action::#ident => {
404                        match #meta.#ident(&mut #channel_ident, &#context_ident).await {
405                            Ok(_) => (),
406                            Err(e) => return Err(e),
407                        }
408                    },
409                }
410            },
411            (Some(inputs), Some(_), MethodKind::ServerConsume) => {
412                if inputs.len() != 1 {
413                    abort!(method.ident.span(), "methods that consume can only have one argument with type Channel and return a canary::Result<()>")
414                }
415                quote! {
416                    __srpc_action::#ident => {
417                        return #meta.#ident(#channel_ident, &#context_ident).await;
418                    },
419                }
420            }
421
422            (Some(inputs), Some(_), MethodKind::ServerManual) => {
423                if inputs.len() != 1 {
424                    abort!(method.ident.span(), "manual methods can only have one argument with type Channel and return a canary::Result<Channel>")
425                }
426                quote! {
427                    __srpc_action::#ident => {
428                        match #meta.#ident(#channel_ident, &#context_ident).await {
429                            Ok(chan) => #channel_ident = chan,
430                            Err(e) => return Err(e),
431                        }
432                    },
433                }
434            },
435
436            (_, _, MethodKind::Client) => quote!(),
437            (_, _, MethodKind::ClientConsume) => quote!(),
438            (_, _, MethodKind::ClientManual) => quote!(),
439            (_, _, MethodKind::Server) => abort!(method.ident.span(), "server methods need an argument with type Channel and return a canary::Result<Channel>"),
440            (_, _, MethodKind::ServerConsume) => abort!(method.ident.span(), "server methods need an argument with type Channel and a context, and return a canary::Result<()>"),
441            (_, _, MethodKind::ServerManual) => abort!(method.ident.span(), "server methods need an argument with type Channel and a context, and return a canary::Result<Channel>"),
442            (_, _, MethodKind::Consume) => abort!(method.ident.span(), "methods that consume need an argument with type Channel and return a canary::Result<()>"),
443            (None, None, MethodKind::Manual) => abort!(method.ident.span(), "manual methods need an argument with type Channel and return a canary::Result<Channel>"),
444            (_, _, MethodKind::Manual) => abort!(method.ident.span(), "manual methods can only return a canary::Result<Channel>"),
445        }
446    }).collect::<Vec<_>>();
447
448    let (_, ty_generics, whr) = item.generics.split_for_impl();
449    let impl_generics = {
450        let s = item.generics.type_params().map(|s| {
451            let mut s = s.clone();
452            s.bounds.push(syn::parse2(quote!(Send)).unwrap());
453            s.bounds.push(syn::parse2(quote!(Sync)).unwrap());
454            s.bounds.push(syn::parse2(quote!('static)).unwrap());
455            s.bounds
456                .push(syn::parse2(quote!(::srpc::__private::Serialize)).unwrap());
457            s.bounds
458                .push(syn::parse2(quote!(::srpc::__private::DeserializeOwned)).unwrap());
459            s
460        });
461        quote!(<#(#s),*>)
462    };
463    let endpoint = &top_type_name.to_string().to_snake_case();
464    let function = {
465        let impl_generics = impl_generics.clone();
466        quote! {
467            impl #impl_generics ::srpc::__private::canary::service::Service for #top_type #whr {
468                const ENDPOINT: &'static str = #endpoint;
469                type Pipeline = ();
470                type Meta = ::std::sync::Arc<#top_type_meta>;
471                fn service(
472                    #meta_ident: ::std::sync::Arc<#top_type_meta>,
473                ) -> ::srpc::__private::canary::service::Svc {
474                    ::srpc::__private::canary::service::run_metadata(
475                        #meta_ident,
476                        |#meta_ident: ::std::sync::Arc<#top_type_meta>, mut #channel_ident: ::srpc::__private::canary::Channel, #context_ident: ::srpc::__private::canary::Ctx| async move {
477                        loop {
478                            match #channel_ident.receive::<__srpc_action>().await? {
479                                #(#matches)*
480                            }
481                        }
482                    })
483                }
484            }
485        }
486    };
487
488    let peer_name = format_ident!("{}Peer", top_type_name);
489
490    let peer_methods = methods.map(|method| {
491        let has_output = method.output.is_some();
492        let has_input = method.inputs.is_some();
493
494        let res = method.output
495            .map(|s| *s.clone())
496            .unwrap_or(syn::parse2(quote!(())).unwrap());
497        let result = quote!( ::srpc::__private::canary::Result<#res> );
498
499        let inputs = method.inputs.unwrap_or_default();
500        let mut params = vec![];
501        let name = method.ident;
502
503        let args = inputs.clone().into_iter().map(|inp| {
504            let mut inp = inp.clone();
505            let ty = inp.ty;
506            let ty: Type = syn::parse2(quote!(impl std::borrow::Borrow<#ty>)).unwrap();
507            inp.ty = Box::new(ty);
508
509            let ret = quote!( #inp );
510
511            let arg = inp.pat;
512            params.push(arg);
513            ret
514        }).collect::<Vec<_>>();
515
516        match (has_output, has_input, &method.consume) {
517            (true, true, MethodKind::Normal) => quote! {
518                pub async fn #name(&mut self #(,#args)*) -> #result {
519                    self.0.send(__srpc_action::#name).await?;
520                    #[allow(unused_parens)]
521                    self.0.send((#(#params.borrow()),*)).await?;
522                    self.0.receive().await
523                }
524            },
525            (true, false, MethodKind::Normal) => quote! {
526                pub async fn #name(&mut self) -> #result {
527                    self.0.send(__srpc_action::#name).await?;
528                    self.0.receive().await
529                }
530            },
531            (false, true, MethodKind::Normal) => quote! {
532                pub async fn #name(&mut self #(,#args)*) -> #result {
533                    self.0.send(__srpc_action::#name).await?;
534                    #[allow(unused_parens)]
535                    self.0.send((#(#params.borrow()),*)).await?;
536                    Ok(())
537                }
538            },
539            (false, false, MethodKind::Normal) => quote! {
540                pub async fn #name(&mut self) -> #result {
541                    self.0.send(__srpc_action::#name).await?;
542                    Ok(())
543                }
544            },
545            (true, true, MethodKind::Consume) => quote! {
546                pub async fn #name(mut self) -> ::srpc::__private::canary::Result<::srpc::__private::canary::Channel> {
547                    self.0.send(__srpc_action::#name).await?;
548                    Ok(self.0)
549                }
550            },
551            (true, true, MethodKind::ClientConsume) => {
552                let block = method.block;
553                let mut inputs = inputs.clone();
554                let chan_ident = &inputs.first().take().unwrap().pat;
555                inputs.remove(0);
556                quote! { // todo!
557                    pub async fn #name(mut self #(,#inputs)*) -> #res {
558                        self.0.send(__srpc_action::#name).await?;
559
560                        let #chan_ident = self.0;
561
562                        let __private_srpc_inner_result = {
563                            #block
564                        };
565                        __private_srpc_inner_result
566                    }
567                }
568            },
569            (true, true, MethodKind::ClientManual) => {
570                let block = method.block;
571                let mut inputs = inputs.clone();
572                let chan_ident = &inputs.first().take().unwrap().pat;
573                let chan = inputs.remove(0);
574                let chan_ty = &chan.ty;
575                quote! { // todo!
576                    pub async fn #name(&mut self #(,#inputs)*) -> #res {
577                        self.0.send(__srpc_action::#name).await?;
578
579                        let #chan_ident: #chan_ty = &mut self.0;
580
581                        let __private_srpc_inner_result = {
582                            #block
583                        };
584                        __private_srpc_inner_result
585                    }
586                }
587            },
588
589            (true, true, MethodKind::Manual) => quote! {
590                pub async fn #name(mut self) -> ::srpc::__private::canary::Result<::srpc::__private::canary::Channel> {
591                    self.0.send(__srpc_action::#name).await?;
592                    Ok(self.0)
593                }
594            },
595            (_, true, MethodKind::Client) => {
596                let block = method.block;
597                let mut inputs = inputs.clone();
598                let chan_ident = &inputs.first().take().unwrap().pat;
599                inputs.remove(0);
600                quote! {
601                    pub async fn #name(self #(,#inputs)*) -> #res {
602                        self.0.send(__srpc_action::#name).await?;
603
604                        let #chan_ident = self.0;
605
606                        let __private_srpc_inner_result = {
607                            #block
608                        };
609                        __private_srpc_inner_result
610                    }
611                }
612            },
613            (_, _, MethodKind::Server) => quote!(),
614            (_, _, MethodKind::ServerConsume) => quote!(),
615            (_, _, MethodKind::ServerManual) => quote!(),
616            (_, _, MethodKind::Client) => abort!(method.ident.span(), "client methods can only have an argument with type &mut Channel"),
617            (_, _, MethodKind::ClientManual) => abort!(method.ident.span(), "manual methods need to have an argument with type &mut Channel and return a canary::Result<T>"),
618            (_, _, MethodKind::ClientConsume) => abort!(method.ident.span(), "methods that consume need to have an argument with type Channel and return a canary::Result<T>"),
619            (_, _, MethodKind::Consume) => abort!(method.ident.span(), "methods that consume can only have an argument with type Channel and return a canary::Result<()>"),
620            (_, _, MethodKind::Manual) => abort!(method.ident.span(), "manual methods can only have an argument with type Channel and return a canary::Result<Channel>"),
621        }
622
623    }).collect::<Vec<_>>();
624    let peer_impl = quote! {
625        impl #impl_generics #peer_name #ty_generics #whr {
626            #(#peer_methods)*
627        }
628    };
629
630    let items = item
631        .items
632        .into_iter()
633        .filter(|s| {
634            let mut stay = true;
635            if let ImplItem::Method(method) = &s {
636                let attrs = &method.attrs;
637                for attr in attrs {
638                    if quote!(#[client]).to_string() == quote!(#attr).to_string()
639                        || quote!(#[client_consume]).to_string() == quote!(#attr).to_string()
640                        || quote!(#[client_manual]).to_string() == quote!(#attr).to_string()
641                    {
642                        stay = false;
643                    }
644                }
645            }
646            stay
647        })
648        .map(|mut s| {
649            if let ImplItem::Method(method) = &mut s {
650                let attrs = method.attrs.clone();
651                let mut new_attrs = vec![];
652                for attr in attrs {
653                    if quote!(#[consume]).to_string() != quote!(#attr).to_string()
654                        && quote!(#[manual]).to_string() != quote!(#attr).to_string()
655                        && quote!(#[server]).to_string() != quote!(#attr).to_string()
656                        && quote!(#[server_consume]).to_string() != quote!(#attr).to_string()
657                        && quote!(#[server_manual]).to_string() != quote!(#attr).to_string()
658                    {
659                        new_attrs.push(attr)
660                    }
661                }
662                method.attrs = new_attrs;
663            }
664            s
665        })
666        .collect::<Vec<_>>();
667    item.items = items;
668    item.generics
669        .type_params_mut()
670        .map(|s| {
671            s.bounds
672                .push(syn::parse2(quote!(::srpc::__private::Serialize)).unwrap());
673            s.bounds
674                .push(syn::parse2(quote!(::srpc::__private::DeserializeOwned)).unwrap());
675        })
676        .for_each(drop);
677
678    item.items
679        .iter_mut()
680        .map(|f| {
681            if let ImplItem::Method(f) = f {
682                let typed =
683                    syn::parse2(quote!(#context_ident: &::srpc::__private::canary::Ctx)).unwrap();
684                f.sig.inputs.push(typed);
685            }
686        })
687        .for_each(drop);
688
689    let ts = quote!(
690        const _: () = {
691            #[cfg(not(target_arch = "wasm32"))]
692            #item
693            #enum_repr
694            #[cfg(not(target_arch = "wasm32"))]
695            #function
696            #peer_impl
697        };
698    );
699    ts.into()
700}