Implement additional codegen for calling server handler methods
All checks were successful
Build library & run tests / build (tcp) (push) Successful in 33s
Build library & run tests / build (unix) (push) Successful in 34s

This commit is contained in:
Kodi Craft 2024-06-23 01:46:42 +02:00
parent 033482c076
commit c892053cbd
Signed by: kodi
GPG Key ID: 69D9EED60B242822

View File

@ -83,6 +83,7 @@ fn derive_protocol(input: proc_macro2::TokenStream) -> proc_macro2::TokenStream
let mut variant_fields = variant.fields.iter(); let mut variant_fields = variant.fields.iter();
let question_field = variant_fields.next().unwrap(); let question_field = variant_fields.next().unwrap();
let question_args = field_to_args(question_field); let question_args = field_to_args(question_field);
let question_handler_args = field_to_handler_args(question_field);
let question_tuple_args = field_to_tuple_args(question_field); let question_tuple_args = field_to_tuple_args(question_field);
let answer_type = variant_fields.next().unwrap().ty.clone(); let answer_type = variant_fields.next().unwrap().ty.clone();
@ -114,14 +115,14 @@ fn derive_protocol(input: proc_macro2::TokenStream) -> proc_macro2::TokenStream
}); });
// There is a function that the server uses to call the appropriate function when receiving a query // There is a function that the server uses to call the appropriate function when receiving a query
server_handler.push(quote! { server_handler.push(quote! {
#question_enum_name::#var_name(#question_args) => { #question_enum_name::#var_name(#question_tuple_args) => {
let answer = self.handler.#var_name(#question_tuple_args); let answer = self.handler.lock().await.#var_name(#question_handler_args).await;
return #answer_enum_name::#var_name(answer); return #answer_enum_name::#var_name(answer);
} },
}); });
// The function that the server needs to implement // The function that the server needs to implement
server_trait.push(quote! { server_trait.push(quote! {
fn #var_name(&mut self, #question_args) -> #answer_type; async fn #var_name(&mut self, #question_args) -> #answer_type;
}); });
// The function that the client uses to communicate // The function that the client uses to communicate
client_impl.push(quote! { client_impl.push(quote! {
@ -212,6 +213,13 @@ fn derive_protocol(input: proc_macro2::TokenStream) -> proc_macro2::TokenStream
to_send: tokio::sync::mpsc::Sender<(u64, #answer_enum_name)>, to_send: tokio::sync::mpsc::Sender<(u64, #answer_enum_name)>,
received: tokio::sync::mpsc::Receiver<(u64, #question_enum_name)>, received: tokio::sync::mpsc::Receiver<(u64, #question_enum_name)>,
} }
impl<H: #server_trait_name> #server_connection_struct_name<H> {
async fn handle(&self, question: #question_enum_name) -> #answer_enum_name {
match question {
#(#server_handler)*
}
}
}
}; };
// Create a struct to hold queries behind an Arc<Mutex<>> to enable async access // Create a struct to hold queries behind an Arc<Mutex<>> to enable async access
@ -437,3 +445,17 @@ fn field_to_tuple_args(field: &Field) -> proc_macro2::TokenStream {
quote! { (arg) } quote! { (arg) }
} }
} }
fn field_to_handler_args(field: &Field) -> proc_macro2::TokenStream {
let type_ = &field.ty;
if let syn::Type::Tuple(tuple) = type_ {
let mut args = Vec::new();
for (i, elem) in tuple.elems.iter().enumerate() {
let arg = Ident::new(&format!("arg{}", i), elem.span());
args.push(quote! { #arg });
}
quote! { #( #args ), * }
} else {
quote! { arg }
}
}