Building some more necessary structures out of the protocol definition
This commit is contained in:
63
src/lib.rs
63
src/lib.rs
@@ -16,7 +16,7 @@ You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
use proc_macro::TokenStream;
|
||||
use quote::quote;
|
||||
use quote::{format_ident, quote};
|
||||
use syn::{parse_macro_input, spanned::Spanned, DeriveInput, Field, Ident};
|
||||
|
||||
#[proc_macro_derive(Protocol)]
|
||||
@@ -35,7 +35,11 @@ pub fn derive_protocol(input: TokenStream) -> TokenStream {
|
||||
let vis = &input.vis;
|
||||
|
||||
let mut server_trait = Vec::new();
|
||||
let mut server_enum = Vec::new();
|
||||
let mut client_impl = Vec::new();
|
||||
let mut client_enum = Vec::new();
|
||||
|
||||
let mut query_enum = Vec::new();
|
||||
|
||||
for variant in &enum_.variants {
|
||||
// Every variant must have 2 fields
|
||||
@@ -55,32 +59,81 @@ pub fn derive_protocol(input: TokenStream) -> TokenStream {
|
||||
let question_args = field_to_args(question_field);
|
||||
let answer_type = variant_fields.next().unwrap().ty.clone();
|
||||
|
||||
// The variants that either the server or the client will use
|
||||
// The "server" enum contains messages the server can send, the "client" enum contains messages the client can send
|
||||
server_enum.push(quote! {
|
||||
#var_name(#answer_type)
|
||||
});
|
||||
client_enum.push(quote! {
|
||||
#var_name(#question_field)
|
||||
});
|
||||
// The function that the server needs to implement
|
||||
server_trait.push(quote! {
|
||||
fn #var_name(&mut self, #question_args) -> #answer_type;
|
||||
});
|
||||
// The function that the client uses to communicate
|
||||
client_impl.push(quote! {
|
||||
pub fn #var_name(&mut self, #question_args) -> #answer_type {
|
||||
::std::unimplemented!()
|
||||
}
|
||||
})
|
||||
});
|
||||
// The query enum is the same as the source enum, but the second field is always wrapped in a Option<>
|
||||
query_enum.push(quote! {
|
||||
#var_name(#question_field, Option<#answer_type>)
|
||||
});
|
||||
}
|
||||
|
||||
// Create enums for the types of messages the server and client will use
|
||||
let server_enum_name = format_ident!("{}Answer", name);
|
||||
let server_enum = quote! {
|
||||
#vis enum #server_enum_name {
|
||||
#(#server_enum), *
|
||||
}
|
||||
};
|
||||
let client_enum_name = format_ident!("{}Question", name);
|
||||
let client_enum = quote! {
|
||||
#vis enum #client_enum_name {
|
||||
#(#client_enum), *
|
||||
}
|
||||
};
|
||||
// Create an enum to represent the queries the client has sent
|
||||
let query_enum_name = format_ident!("{}Query", name);
|
||||
let query_enum = quote! {
|
||||
#vis enum #query_enum_name {
|
||||
#(#query_enum), *
|
||||
}
|
||||
};
|
||||
// Create a trait which the server will have to implement
|
||||
let server_trait_name = Ident::new(&format!("{}Server", name), name.span());
|
||||
let server_trait_name = format_ident!("{}Server", name);
|
||||
let server_trait = quote! {
|
||||
#vis trait #server_trait_name {
|
||||
#(#server_trait)*
|
||||
}
|
||||
};
|
||||
let client_struct_name = Ident::new(&format!("{}Client", name), name.span());
|
||||
// Create a struct which the client will use to communicate
|
||||
let client_struct_name = format_ident!("{}Client", name);
|
||||
let client_struct = quote! {
|
||||
#vis struct #client_struct_name; // TODO: This struct will have some fields to handle the actual connection
|
||||
#vis struct #client_struct_name {
|
||||
queries: ::std::collections::HashMap<u64, #query_enum_name>,
|
||||
send_queue: tokio::sync::mpsc::Sender<#client_enum_name>,
|
||||
recv_queue: tokio::sync::mpsc::Receiver<#server_enum_name>,
|
||||
} // TODO: This struct will have some fields to handle the actual connection
|
||||
impl #client_struct_name {
|
||||
pub fn new(send_queue: tokio::sync::mpsc::Sender<#client_enum_name>, recv_queue: tokio::sync::mpsc::Receiver<#server_enum_name>) -> Self {
|
||||
Self {
|
||||
queries: ::std::collections::HashMap::new(),
|
||||
send_queue,
|
||||
recv_queue,
|
||||
}
|
||||
}
|
||||
#(#client_impl)*
|
||||
}
|
||||
};
|
||||
|
||||
let expanded = quote! {
|
||||
#server_enum
|
||||
#client_enum
|
||||
#query_enum
|
||||
#server_trait
|
||||
#client_struct
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user