feat: stuff happend
This commit is contained in:
parent
b8d2cd7b09
commit
fa37331780
11 changed files with 511 additions and 343 deletions
173
macros/src/protos.rs
Normal file
173
macros/src/protos.rs
Normal file
|
|
@ -0,0 +1,173 @@
|
|||
use proc_macro2::{Ident, Span, TokenStream, TokenTree};
|
||||
use quote::{quote, ToTokens};
|
||||
use syn::{LitInt, Token, Type};
|
||||
use syn::token::{Brace, Paren, Semi};
|
||||
|
||||
pub struct ProtoMethodData{
|
||||
pub id: LitInt,
|
||||
pub name: Ident,
|
||||
pub parameters: Vec<(Ident, Type)>
|
||||
}
|
||||
|
||||
|
||||
/// This is a representation of the code generated by `rmc_proto` it serves to split the logic of
|
||||
/// acquiring data from the actual generation to tidy up the process into first getting then
|
||||
/// generating.
|
||||
///
|
||||
/// Use the [`ToTokens`] trait to generate the actual code.
|
||||
pub struct RmcProtocolData{
|
||||
pub has_returns: bool,
|
||||
pub id: LitInt,
|
||||
pub name: Ident,
|
||||
pub methods: Vec<ProtoMethodData>
|
||||
}
|
||||
|
||||
impl ToTokens for RmcProtocolData{
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
let Self{
|
||||
has_returns,
|
||||
name,
|
||||
id,
|
||||
methods
|
||||
} = self;
|
||||
|
||||
// this gives us the name which the identifier of the corresponding Raw trait
|
||||
let raw_name = Ident::new(&format!("Raw{}", name), name.span());
|
||||
|
||||
|
||||
// boilerplate tokens which all raw traits need
|
||||
quote!{
|
||||
#[doc(hidden)]
|
||||
pub trait #raw_name: #name
|
||||
}.to_tokens(tokens);
|
||||
|
||||
// generate the body of the raw protocol trait
|
||||
Brace::default().surround(tokens, |tokens|{
|
||||
//generate each raw method
|
||||
for method in methods{
|
||||
let ProtoMethodData {
|
||||
name,
|
||||
parameters,
|
||||
..
|
||||
} = method;
|
||||
|
||||
let raw_name = Ident::new(&format!("raw_{}", name), name.span());
|
||||
quote!{
|
||||
async fn #raw_name
|
||||
}.to_tokens(tokens);
|
||||
|
||||
Paren::default().surround(tokens, |tokens|{
|
||||
quote!{ &self, data: ::std::vec::Vec<u8> }.to_tokens(tokens);
|
||||
});
|
||||
|
||||
quote!{
|
||||
-> ::core::result::Result<Vec<u8>, ErrorCode>
|
||||
}.to_tokens(tokens);
|
||||
|
||||
Brace::default().surround(tokens, |tokens|{
|
||||
quote! { let mut cursor = ::std::io::Cursor::new(data); }.to_tokens(tokens);
|
||||
|
||||
for (param_name, param_type) in parameters{
|
||||
quote!{
|
||||
let Ok(#param_name) =
|
||||
<#param_type as crate::rmc::structures::RmcSerialize>::deserialize(
|
||||
&mut cursor
|
||||
) else {
|
||||
return Err(ErrorCode::Core_InvalidArgument);
|
||||
};
|
||||
}.to_tokens(tokens)
|
||||
}
|
||||
|
||||
quote!{
|
||||
let retval = self.#name
|
||||
}.to_tokens(tokens);
|
||||
|
||||
Paren::default().surround(tokens, |tokens|{
|
||||
for (paren_name, _) in parameters{
|
||||
quote!{#paren_name,}.to_tokens(tokens);
|
||||
}
|
||||
});
|
||||
|
||||
quote!{
|
||||
.await;
|
||||
}.to_tokens(tokens);
|
||||
|
||||
if *has_returns{
|
||||
quote!{
|
||||
let retval = retval?;
|
||||
let mut vec = Vec::new();
|
||||
crate::rmc::structures::RmcSerialize::serialize(&retval, &mut vec).ok();
|
||||
Ok(vec)
|
||||
}.to_tokens(tokens);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
quote!{
|
||||
async fn rmc_call_proto(
|
||||
&self,
|
||||
remote_response_connection: &crate::prudp::socket::SendingConnection,
|
||||
method_id: u32,
|
||||
call_id: u32,
|
||||
data: Vec<u8>,
|
||||
)
|
||||
}.to_tokens(tokens);
|
||||
|
||||
Brace::default().surround(tokens, |tokens|{
|
||||
quote! {
|
||||
let ret = match method_id
|
||||
}.to_tokens(tokens);
|
||||
|
||||
Brace::default().surround(tokens, |tokens|{
|
||||
for method in methods{
|
||||
let ProtoMethodData{
|
||||
id,
|
||||
name,
|
||||
..
|
||||
} = method;
|
||||
|
||||
let raw_name = Ident::new(&format!("raw_{}", name), name.span());
|
||||
|
||||
quote!{
|
||||
#id => self.#raw_name(data).await,
|
||||
}.to_tokens(tokens);
|
||||
}
|
||||
quote!{
|
||||
_ => Err(crate::rmc::response::ErrorCode::Core_NotImplemented)
|
||||
}.to_tokens(tokens);
|
||||
});
|
||||
|
||||
Semi::default().to_tokens(tokens);
|
||||
|
||||
if *has_returns{
|
||||
quote!{
|
||||
crate::rmc::response::send_result(
|
||||
remote_response_connection,
|
||||
ret,
|
||||
#id,
|
||||
method_id,
|
||||
call_id,
|
||||
).await
|
||||
}.to_tokens(tokens);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
quote!{
|
||||
impl<T: #name> RawAuth for T{}
|
||||
}.to_tokens(tokens);
|
||||
|
||||
let raw_info_name = Ident::new(&format!("Raw{}Info", name), Span::call_site());
|
||||
|
||||
|
||||
quote!{
|
||||
#[doc(hidden)]
|
||||
pub struct #raw_info_name;
|
||||
|
||||
impl #raw_info_name {
|
||||
pub const PROTOCOL_ID: u16 = #id;
|
||||
}
|
||||
}.to_tokens(tokens);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue