feat: stuff
This commit is contained in:
parent
6f02339464
commit
b8d2cd7b09
3 changed files with 308 additions and 13 deletions
|
|
@ -3,13 +3,93 @@ extern crate proc_macro;
|
||||||
use proc_macro2::{Ident, Literal, Span, TokenTree};
|
use proc_macro2::{Ident, Literal, Span, TokenTree};
|
||||||
use proc_macro::TokenStream;
|
use proc_macro::TokenStream;
|
||||||
use std::iter::FromIterator;
|
use std::iter::FromIterator;
|
||||||
use syn::{parse_macro_input, DeriveInput, Data, PathSegment, TraitItem, FieldsNamed, Fields, Visibility, Type, TypePath, Path, ImplItem, ImplItemConst, Expr, ExprLit, Lit};
|
use std::mem;
|
||||||
|
use syn::{parse_macro_input, DeriveInput, Data, PathSegment, TraitItem, FieldsNamed, Fields, Visibility, Type, TypePath, Path, ImplItem, ImplItemConst, Expr, ExprLit, Lit, TypeParamBound, TraitBound, TraitBoundModifier, LitInt, Token, FnArg, Receiver, PatType, Pat, TypeInfer, TypeReference, TraitItemFn, Signature, Block, Stmt, Local, LocalInit, LitStr, PathArguments};
|
||||||
use quote::{quote, ToTokens, TokenStreamExt};
|
use quote::{quote, ToTokens, TokenStreamExt};
|
||||||
use syn::parse::ParseStream;
|
use syn::buffer::TokenBuffer;
|
||||||
|
use syn::parse::{Parse, ParseBuffer, ParseStream};
|
||||||
use syn::punctuated::Punctuated;
|
use syn::punctuated::Punctuated;
|
||||||
use syn::spanned::Spanned;
|
use syn::spanned::Spanned;
|
||||||
|
use syn::token::Comma;
|
||||||
use syn::Visibility::Public;
|
use syn::Visibility::Public;
|
||||||
|
|
||||||
|
fn self_referece_type() -> Type {
|
||||||
|
Type::Reference(
|
||||||
|
TypeReference {
|
||||||
|
and_token: Default::default(),
|
||||||
|
lifetime: None,
|
||||||
|
mutability: None,
|
||||||
|
elem: Box::new(Type::Path(
|
||||||
|
TypePath {
|
||||||
|
qself: None,
|
||||||
|
path: Path {
|
||||||
|
leading_colon: None,
|
||||||
|
segments: {
|
||||||
|
let mut punct = Punctuated::new();
|
||||||
|
|
||||||
|
punct.push_value(PathSegment{
|
||||||
|
ident: Ident::new("Self", Span::call_site()),
|
||||||
|
arguments: PathArguments::None
|
||||||
|
});
|
||||||
|
|
||||||
|
punct
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
))
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ProtoInputParams{
|
||||||
|
proto_num: LitInt,
|
||||||
|
properties: Option<(Token![,], Punctuated<Ident, Token![,]>)>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Parse for ProtoInputParams{
|
||||||
|
fn parse(input: ParseStream) -> syn::Result<Self> {
|
||||||
|
let proto_num = input.parse()?;
|
||||||
|
|
||||||
|
if let Some(seperator) = input.parse()?{
|
||||||
|
let mut punctuated = Punctuated::new();
|
||||||
|
loop {
|
||||||
|
punctuated.push_value(
|
||||||
|
input.parse()?
|
||||||
|
);
|
||||||
|
if let Some(punct) = input.parse()? {
|
||||||
|
punctuated.push_punct(punct);
|
||||||
|
} else {
|
||||||
|
return Ok(
|
||||||
|
Self{
|
||||||
|
proto_num,
|
||||||
|
properties: Some((seperator, punctuated))
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Ok(
|
||||||
|
Self{
|
||||||
|
proto_num,
|
||||||
|
properties: None
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn single_ident_path(ident: Ident) -> Path{
|
||||||
|
Path{
|
||||||
|
segments: {
|
||||||
|
let mut punc = Punctuated::new();
|
||||||
|
punc.push(PathSegment::from(ident));
|
||||||
|
punc
|
||||||
|
},
|
||||||
|
leading_colon: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Example of user-defined [derive mode macro][1]
|
/// Example of user-defined [derive mode macro][1]
|
||||||
///
|
///
|
||||||
/// [1]: https://doc.rust-lang.org/reference/procedural-macros.html#derive-mode-macros
|
/// [1]: https://doc.rust-lang.org/reference/procedural-macros.html#derive-mode-macros
|
||||||
|
|
@ -167,7 +247,26 @@ pub fn rmc_serialize(input: TokenStream) -> TokenStream {
|
||||||
|
|
||||||
#[proc_macro_attribute]
|
#[proc_macro_attribute]
|
||||||
pub fn rmc_proto(attr: TokenStream, input: TokenStream) -> TokenStream{
|
pub fn rmc_proto(attr: TokenStream, input: TokenStream) -> TokenStream{
|
||||||
let mut proto_num = parse_macro_input!(attr as syn::LitInt);
|
|
||||||
|
let mut params = parse_macro_input!(attr as ProtoInputParams);
|
||||||
|
|
||||||
|
let ProtoInputParams{
|
||||||
|
proto_num,
|
||||||
|
properties
|
||||||
|
} = params;
|
||||||
|
|
||||||
|
let no_return_data = properties.is_some_and(|p| p.1.iter().any(|i|{
|
||||||
|
i.to_string() == "NoReturn"
|
||||||
|
}));
|
||||||
|
|
||||||
|
let param_err_return = match no_return_data{
|
||||||
|
true => quote!{
|
||||||
|
return;
|
||||||
|
},
|
||||||
|
false => quote!{
|
||||||
|
return Err(ErrorCode::Core_InvalidArgument);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let mut input = parse_macro_input!(input as syn::ItemTrait);
|
let mut input = parse_macro_input!(input as syn::ItemTrait);
|
||||||
|
|
||||||
|
|
@ -175,7 +274,7 @@ pub fn rmc_proto(attr: TokenStream, input: TokenStream) -> TokenStream{
|
||||||
let info_struct_ident = Ident::new(&info_struct_ident, input.ident.span());
|
let info_struct_ident = Ident::new(&info_struct_ident, input.ident.span());
|
||||||
|
|
||||||
let raw_details_struct = syn::ItemStruct{
|
let raw_details_struct = syn::ItemStruct{
|
||||||
vis: Visibility::Public(Default::default()),
|
vis: Public(Default::default()),
|
||||||
struct_token: Default::default(),
|
struct_token: Default::default(),
|
||||||
fields: Fields::Unit,
|
fields: Fields::Unit,
|
||||||
semi_token: Some(Default::default()),
|
semi_token: Some(Default::default()),
|
||||||
|
|
@ -235,9 +334,27 @@ pub fn rmc_proto(attr: TokenStream, input: TokenStream) -> TokenStream{
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|
||||||
let funcs = input.items.iter().filter_map(|v| if let TraitItem::Fn(v) = v {Some(v)} else { None });
|
let mut raw_trait = input.clone();
|
||||||
|
|
||||||
|
raw_trait.ident = Ident::new(&format!("Raw{}",raw_trait.ident.to_string()), raw_trait.ident.span());
|
||||||
|
raw_trait.colon_token = Some(Default::default());
|
||||||
|
raw_trait.supertraits = {
|
||||||
|
let mut punct = Punctuated::new();
|
||||||
|
punct.push(TypeParamBound::Trait(TraitBound{
|
||||||
|
path: single_ident_path(input.ident.clone()),
|
||||||
|
lifetimes: None,
|
||||||
|
modifier: TraitBoundModifier::None,
|
||||||
|
paren_token: None
|
||||||
|
}));
|
||||||
|
punct
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut functions: Vec<(LitInt, Ident)> = Vec::new();
|
||||||
|
|
||||||
|
let funcs = raw_trait.items.iter_mut().filter_map(|v| if let TraitItem::Fn(v) = v {Some(v)} else { None });
|
||||||
|
|
||||||
for func in funcs{
|
for func in funcs{
|
||||||
|
|
||||||
if matches!(func.default, Some(_)){
|
if matches!(func.default, Some(_)){
|
||||||
return syn::Error::new(func.default.span(), "rmc methods may not have bodies").to_compile_error().into();
|
return syn::Error::new(func.default.span(), "rmc methods may not have bodies").to_compile_error().into();
|
||||||
}
|
}
|
||||||
|
|
@ -248,13 +365,152 @@ pub fn rmc_proto(attr: TokenStream, input: TokenStream) -> TokenStream{
|
||||||
return syn::Error::new(span, "every function inside of an rmc protocol must have a method id").to_compile_error().into();
|
return syn::Error::new(span, "every function inside of an rmc protocol must have a method id").to_compile_error().into();
|
||||||
};
|
};
|
||||||
|
|
||||||
todo!("generate raw impl")
|
let Ok(func_id): Result<LitInt, _> = attr.parse_args() else {
|
||||||
|
return syn::Error::new(Span::call_site(), "todo: put a propper error message here").to_compile_error().into();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
if !func.sig.inputs.first().is_some_and(|v| matches!(v, FnArg::Receiver(Receiver{
|
||||||
|
colon_token: None,
|
||||||
|
mutability: None,
|
||||||
|
reference: Some(_),
|
||||||
|
..
|
||||||
|
}))){
|
||||||
|
return syn::Error::new(func.sig.inputs.span(), "every protocol function must have a ` & self ` as its first parameter.").to_compile_error().into();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let old_ident = func.sig.ident.clone();
|
||||||
|
|
||||||
|
func.sig.ident = Ident::new(&format!("raw_{}", func.sig.ident), func.sig.ident.span());
|
||||||
|
|
||||||
|
let mut new_params: Punctuated<_,_> = Punctuated::new();
|
||||||
|
|
||||||
|
new_params.push_value(FnArg::Receiver(Receiver{
|
||||||
|
attrs: vec![],
|
||||||
|
mutability: None,
|
||||||
|
ty: Box::new(self_referece_type()),
|
||||||
|
colon_token: None,
|
||||||
|
self_token: Default::default(),
|
||||||
|
reference: Some((Default::default(), None))
|
||||||
|
}));
|
||||||
|
|
||||||
|
new_params.push_punct(Comma::default());
|
||||||
|
/*
|
||||||
|
new_params.push_value(FnArg::Typed(PatType{
|
||||||
|
attrs: vec![],
|
||||||
|
pat: Box::new(Pat::Verbatim(quote! { method_id })),
|
||||||
|
colon_token: Default::default(),
|
||||||
|
ty: Box::new(Type::Verbatim(quote!{u32}))
|
||||||
|
}));
|
||||||
|
|
||||||
|
new_params.push_punct(Comma::default());*/
|
||||||
|
|
||||||
|
new_params.push_value(FnArg::Typed(PatType{
|
||||||
|
attrs: vec![],
|
||||||
|
pat: Box::new(Pat::Verbatim(quote! {data})),
|
||||||
|
colon_token: Default::default(),
|
||||||
|
ty: Box::new(Type::Verbatim(quote!{::std::vec::Vec<u8>}))
|
||||||
|
}));
|
||||||
|
|
||||||
|
mem::swap(&mut new_params, &mut func.sig.inputs);
|
||||||
|
let old_params = new_params;
|
||||||
|
|
||||||
|
|
||||||
|
let mut inner_raw_tokens = quote!{
|
||||||
|
let mut cursor = ::std::io::Cursor::new(data);
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut call_params = quote!{};
|
||||||
|
|
||||||
|
|
||||||
|
for param in old_params.iter().skip(1).filter_map(|v| if let FnArg::Typed(t) = v {
|
||||||
|
Some(t)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}){
|
||||||
|
let param_name = &*param.pat;
|
||||||
|
let ty = &*param.ty;
|
||||||
|
|
||||||
|
inner_raw_tokens.append_all(quote!{
|
||||||
|
let Ok(#param_name) = <#ty as crate::rmc::structures::RmcSerialize>::deserialize(&mut cursor) else {
|
||||||
|
#param_err_return
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
call_params.append_all(quote!{#param_name ,})
|
||||||
|
}
|
||||||
|
|
||||||
|
inner_raw_tokens.append_all(quote!{
|
||||||
|
let retval = self.#old_ident(#call_params).await;
|
||||||
|
});
|
||||||
|
|
||||||
|
if !no_return_data{
|
||||||
|
//let
|
||||||
|
|
||||||
|
//inner_raw_tokens.append_all()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
let braced = quote! {
|
||||||
|
{
|
||||||
|
#inner_raw_tokens
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let braced = braced.into();
|
||||||
|
|
||||||
|
func.default = Some(
|
||||||
|
parse_macro_input!(braced as Block)
|
||||||
|
);
|
||||||
|
|
||||||
|
functions.push((func_id, func.sig.ident.clone()));
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut inner_match = quote!{};
|
||||||
|
|
||||||
|
for toks in functions.iter().map(|(lit, ident)|{
|
||||||
|
quote! {
|
||||||
|
#lit => self.#ident(data).await,
|
||||||
|
}
|
||||||
|
}){
|
||||||
|
inner_match.append_all(toks);
|
||||||
|
}
|
||||||
|
|
||||||
|
if no_return_data{
|
||||||
|
inner_match.append_all(quote!{
|
||||||
|
_ => return
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
//
|
||||||
|
inner_match.append_all(quote!{
|
||||||
|
_ => return
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
raw_trait.items.push(
|
||||||
|
TraitItem::Verbatim(
|
||||||
|
quote!{
|
||||||
|
async fn rmc_call_proto(&self, method_id: u32, data: Vec<u8>){
|
||||||
|
match method_id{
|
||||||
|
#inner_match
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
let regular_trait_name = &input.ident;
|
||||||
|
let raw_trait_name = &raw_trait.ident;
|
||||||
|
|
||||||
quote!{
|
quote!{
|
||||||
#input
|
#input
|
||||||
#raw_details_struct
|
#raw_details_struct
|
||||||
#raw_details_impl_block
|
#raw_details_impl_block
|
||||||
|
#raw_trait
|
||||||
|
|
||||||
|
impl<T: #regular_trait_name + crate::rmc::protocols::ImplementRemoteCalls> #raw_trait_name for T{}
|
||||||
}.into()
|
}.into()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -294,3 +550,9 @@ pub fn rmc_struct(attr: TokenStream, input: TokenStream) -> TokenStream{
|
||||||
|
|
||||||
out.into()
|
out.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[proc_macro_attribute]
|
||||||
|
pub fn connection(_attr: TokenStream, input: TokenStream) -> TokenStream{
|
||||||
|
// this attribute doesnt do anything by itself, see `rmc_struct`
|
||||||
|
input
|
||||||
|
}
|
||||||
|
|
@ -514,9 +514,9 @@ pub struct NewEncryptionPair<E: StreamCipher> {
|
||||||
|
|
||||||
pub struct CommonConnection {
|
pub struct CommonConnection {
|
||||||
pub user_id: u32,
|
pub user_id: u32,
|
||||||
session_id: u8,
|
|
||||||
pub socket_addr: PRUDPSockAddr,
|
pub socket_addr: PRUDPSockAddr,
|
||||||
pub server_port: VirtualPort
|
pub server_port: VirtualPort,
|
||||||
|
session_id: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct InternalConnection<E: CryptoHandlerConnectionInstance> {
|
struct InternalConnection<E: CryptoHandlerConnectionInstance> {
|
||||||
|
|
@ -670,6 +670,8 @@ impl<T: CryptoHandler> InternalSocket<T> {
|
||||||
.write_to(&mut vec)
|
.write_to(&mut vec)
|
||||||
.expect("somehow failed to convert backet to bytes");
|
.expect("somehow failed to convert backet to bytes");
|
||||||
|
|
||||||
|
println!("{}", hex::encode(&vec));
|
||||||
|
|
||||||
self.socket
|
self.socket
|
||||||
.send_to(&vec, dest.regular_socket_addr)
|
.send_to(&vec, dest.regular_socket_addr)
|
||||||
.await
|
.await
|
||||||
|
|
|
||||||
|
|
@ -11,10 +11,11 @@ use tokio::sync::{Mutex, Notify};
|
||||||
use tokio::time::{sleep_until, Instant};
|
use tokio::time::{sleep_until, Instant};
|
||||||
use crate::prudp::socket::{ExternalConnection, SendingConnection};
|
use crate::prudp::socket::{ExternalConnection, SendingConnection};
|
||||||
use crate::rmc::structures::connection_data::ConnectionData;
|
use crate::rmc::structures::connection_data::ConnectionData;
|
||||||
|
use crate::rmc::structures::matchmake::AutoMatchmakeParam;
|
||||||
|
|
||||||
struct RmcConnection(SendingConnection, RmcResponseReceiver);
|
pub struct RmcConnection(pub SendingConnection, pub RmcResponseReceiver);
|
||||||
|
|
||||||
struct RmcResponseReceiver(Notify, Mutex<HashMap<(u16, u32), Vec<u8>>>);
|
pub struct RmcResponseReceiver(Notify, Mutex<HashMap<(u16, u32), Vec<u8>>>);
|
||||||
|
|
||||||
impl RmcResponseReceiver{
|
impl RmcResponseReceiver{
|
||||||
// returns none if timed out
|
// returns none if timed out
|
||||||
|
|
@ -48,17 +49,29 @@ impl RmcResponseReceiver{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait RemoteObject{
|
||||||
|
fn new(conn: RmcConnection) -> Self;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RemoteObject for (){
|
||||||
|
fn new(_: RmcConnection) -> Self {}
|
||||||
|
}
|
||||||
|
|
||||||
pub trait RmcCallable{
|
pub trait RmcCallable{
|
||||||
|
//type Remote: RemoteObject;
|
||||||
|
//fn new_callable(remote: Self::Remote);
|
||||||
async fn rmc_call(&self, protocol_id: u16, method_id: u32, rest: Vec<u8>);
|
async fn rmc_call(&self, protocol_id: u16, method_id: u32, rest: Vec<u8>);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
macro_rules! define_rmc_proto {
|
macro_rules! define_rmc_proto {
|
||||||
(proto $name:ident{
|
(proto $name:ident{
|
||||||
$($protocol:path),*
|
$($protocol:path),*
|
||||||
}) => {
|
}) => {
|
||||||
paste!{
|
paste!{
|
||||||
trait [<Local $name>]: std::any::Any $( + [<Raw $protocol>])* {
|
trait [<Local $name>]: std::any::Any $( + [<Raw $protocol>] + $protocol)* {
|
||||||
async fn rmc_call(&self, protocol_id: u16, method_id: u32, rest: Vec<u8>){
|
async fn rmc_call(&self, protocol_id: u16, method_id: u32, rest: Vec<u8>){
|
||||||
match protocol_id{
|
match protocol_id{
|
||||||
$(
|
$(
|
||||||
|
|
@ -77,16 +90,21 @@ trait RawNotif{
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
trait Notif{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
struct RawNotifInfo;
|
struct RawNotifInfo;
|
||||||
impl RawNotifInfo{
|
impl RawNotifInfo{
|
||||||
const PROTOCOL_ID: u16 = 10;
|
const PROTOCOL_ID: u16 = 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rmc_proto(1)]
|
pub trait ImplementRemoteCalls{}
|
||||||
|
|
||||||
|
#[rmc_proto(1, NoReturn)]
|
||||||
pub trait Another{
|
pub trait Another{
|
||||||
#[method_id(1)]
|
#[method_id(1)]
|
||||||
async fn test();
|
async fn test(&self, thing: AutoMatchmakeParam);
|
||||||
}
|
}
|
||||||
|
|
||||||
define_rmc_proto!{
|
define_rmc_proto!{
|
||||||
|
|
@ -103,7 +121,20 @@ struct TestProtoImplementor{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
impl Notif for TestProtoImplementor{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
impl RawNotif for TestProtoImplementor{
|
impl RawNotif for TestProtoImplementor{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Another for TestProtoImplementor{
|
||||||
|
async fn test(&self, thing: AutoMatchmakeParam) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ImplementRemoteCalls for TestProtoImplementor{}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue