1#![feature(box_patterns)]
2
3use proc_macro::TokenStream;
4
5use proc_macro2::{Ident, Span};
6use quote::quote;
7use syn::{ItemFn, ReturnType, Type, TypePath, TypeTuple};
8
9#[proc_macro_attribute]
14#[cfg(not(test))] pub fn ffi_raw_method(_args: TokenStream, item: TokenStream) -> TokenStream {
16 let raw_item = proc_macro2::TokenStream::from(item.clone());
17 let raw_sig = syn::parse_macro_input!(item as ItemFn).sig;
18 let raw_ident = raw_sig.ident;
19 let new_ident = Ident::new(&format!("ffi_raw_{}", raw_ident), Span::call_site());
20 let new_item = quote! {
21 #[inline]
22 #[no_mangle]
23 pub extern "C" fn #new_ident(mut req: ::fcplug_callee::Buffer) -> ::fcplug_callee::FFIResult {
24 #raw_item
25 ::fcplug_callee::callback(::std::stringify!(#new_ident), #raw_ident, &mut req)
26 }
27 };
28 TokenStream::from(new_item)
29}
30
31#[proc_macro_attribute]
36#[cfg(not(test))] pub fn ffi_pb_method(_args: TokenStream, item: TokenStream) -> TokenStream {
38 let raw_item = proc_macro2::TokenStream::from(item.clone());
39 let raw_sig = syn::parse_macro_input!(item as ItemFn).sig;
40 let raw_ident = raw_sig.ident;
41 let new_ident = Ident::new(&format!("ffi_pb_{}", raw_ident), Span::call_site());
42 let new_item = quote! {
43 #[inline]
44 #[no_mangle]
45 pub extern "C" fn #new_ident(mut req: ::fcplug_callee::Buffer) -> ::fcplug_callee::FFIResult {
46 #raw_item
47 ::fcplug_callee::protobuf::callback(::std::stringify!(#new_ident), #raw_ident, &mut req)
48 }
49 };
50 TokenStream::from(new_item)
51}
52
53
54#[proc_macro_attribute]
59#[cfg(not(test))] pub fn ffi_fb_method(_args: TokenStream, item: TokenStream) -> TokenStream {
61 const FORMAT: &'static str = "fn ${FN_NAME}<'a>(req: FbRequest<'a, EchoRequest<'a>>) -> (${RESPONSE_TYPE}Args<'a>, FbResponseWriter<${RESPONSE_TYPE}<'a>>){}";
62 let format_msg = format!("The function signature format must satisfy: {}", FORMAT);
63 let raw_item = proc_macro2::TokenStream::from(item.clone());
64 let raw_sig = syn::parse_macro_input!(item as ItemFn).sig;
65 let raw_ident = raw_sig.ident;
66 let new_ident = Ident::new(&format!("ffi_fb_{}", raw_ident), Span::call_site());
67 let resp_type = match raw_sig.output {
69 ReturnType::Type(_, box Type::Tuple(TypeTuple { elems, .. })) => {
70 if let Type::Path(TypePath { path, .. }) = elems.first().expect(&format_msg) {
71 let ident = format!("{}", path.segments.first().expect(&format_msg).ident);
72 if ident.ends_with("Args") {
73 Ident::new(ident.strip_suffix("Args").expect(&format_msg), Span::call_site())
74 } else {
75 panic!("{}", format_msg)
76 }
77 } else {
78 panic!("{}", format_msg)
79 }
80 }
81 _ => panic!("{}", format_msg)
82 };
83
84 let new_item = quote! {
85 #[inline]
86 #[no_mangle]
87 pub extern "C" fn #new_ident(mut req: ::fcplug_callee::Buffer) -> ::fcplug_callee::FFIResult {
88 #raw_item
89 let (_resp_, mut _w_) = #raw_ident(::fcplug_callee::flatbuf::FbRequest::try_from_buffer(&mut req)?);
90 let _resp_ = #resp_type::create(&mut _w_, &_resp_);
91 _w_.finish_minimal(_resp_);
92 ::fcplug_callee::FFIResult::ok(::fcplug_callee::ABIResponse::try_into_buffer(_w_).unwrap())
93 }
94 };
95 TokenStream::from(new_item)
96}