forked from spacebar/rust-nex
rework Any
This commit is contained in:
parent
ec8b75603f
commit
b79e47d127
13 changed files with 283 additions and 89 deletions
29
Cargo.lock
generated
29
Cargo.lock
generated
|
|
@ -861,6 +861,16 @@ dependencies = [
|
||||||
"hybrid-array",
|
"hybrid-array",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ctor"
|
||||||
|
version = "1.0.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "01334b89b69ff726750c5ce5073fc8bd860e99aa9a8fc5ca11b04730e3aee97a"
|
||||||
|
dependencies = [
|
||||||
|
"link-section",
|
||||||
|
"linktime-proc-macro",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ctutils"
|
name = "ctutils"
|
||||||
version = "0.4.2"
|
version = "0.4.2"
|
||||||
|
|
@ -1022,7 +1032,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
|
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"windows-sys 0.52.0",
|
"windows-sys 0.61.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -1572,7 +1582,7 @@ dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"socket2 0.5.10",
|
"socket2 0.6.3",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tower-service",
|
"tower-service",
|
||||||
"tracing",
|
"tracing",
|
||||||
|
|
@ -1821,6 +1831,18 @@ dependencies = [
|
||||||
"vcpkg",
|
"vcpkg",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "link-section"
|
||||||
|
version = "0.18.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c2b1dd6fe32e55c0fc0ea9493aa57459ca3cf4ff3c857c7d0302290150da6e4f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "linktime-proc-macro"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8c7b0a3383c2a1002d11349c92c85a666a5fb679e96c79d782cf0dbe557fd6ee"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "litemap"
|
name = "litemap"
|
||||||
version = "0.8.2"
|
version = "0.8.2"
|
||||||
|
|
@ -2403,6 +2425,7 @@ dependencies = [
|
||||||
"bytemuck",
|
"bytemuck",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"chrono",
|
"chrono",
|
||||||
|
"ctor",
|
||||||
"dotenv",
|
"dotenv",
|
||||||
"futures",
|
"futures",
|
||||||
"hex",
|
"hex",
|
||||||
|
|
@ -3625,7 +3648,7 @@ version = "0.1.11"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
|
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-sys 0.48.0",
|
"windows-sys 0.61.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
|
||||||
|
|
@ -17,20 +17,16 @@ use syn::{parse_macro_input, Data, DeriveInput, Lit, LitStr};
|
||||||
pub fn rmc_serialize(input: TokenStream) -> TokenStream {
|
pub fn rmc_serialize(input: TokenStream) -> TokenStream {
|
||||||
let derive_input = parse_macro_input!(input as DeriveInput);
|
let derive_input = parse_macro_input!(input as DeriveInput);
|
||||||
|
|
||||||
let (serialize, deserialize, write_size, version) = match &derive_input.data {
|
let (serialize, deserialize, write_size, version, rmc_struct_impl) = match &derive_input.data {
|
||||||
Data::Struct(s) => rmc_serialize_struct(s, &derive_input),
|
Data::Struct(s) => rmc_serialize_struct(s, &derive_input.ident, &derive_input),
|
||||||
Data::Enum(e) => rmc_serialize_enum(e, &derive_input),
|
Data::Enum(e) => rmc_serialize_enum(e, &derive_input),
|
||||||
Data::Union(_) => {
|
Data::Union(_) => {
|
||||||
unimplemented!("serialize a union is not allowed");
|
unimplemented!("serializing a union is not allowed");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// generate base data
|
// generate base data
|
||||||
|
|
||||||
let str_name = Lit::Str(LitStr::new(
|
|
||||||
&derive_input.ident.to_string(),
|
|
||||||
derive_input.ident.span(),
|
|
||||||
));
|
|
||||||
let ident = derive_input.ident;
|
let ident = derive_input.ident;
|
||||||
|
|
||||||
let write_size = if let Some(v) = write_size {
|
let write_size = if let Some(v) = write_size {
|
||||||
|
|
@ -52,6 +48,7 @@ pub fn rmc_serialize(input: TokenStream) -> TokenStream {
|
||||||
} else {
|
} else {
|
||||||
quote! {}
|
quote! {}
|
||||||
};
|
};
|
||||||
|
let rmc_struct_impl = rmc_struct_impl.unwrap_or_default();
|
||||||
|
|
||||||
let tokens = quote! {
|
let tokens = quote! {
|
||||||
impl rnex_core::rmc::structures::RmcSerialize for #ident{
|
impl rnex_core::rmc::structures::RmcSerialize for #ident{
|
||||||
|
|
@ -67,11 +64,8 @@ pub fn rmc_serialize(input: TokenStream) -> TokenStream {
|
||||||
#write_size
|
#write_size
|
||||||
|
|
||||||
#version
|
#version
|
||||||
|
|
||||||
fn name() -> &'static str{
|
|
||||||
#str_name
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
#rmc_struct_impl
|
||||||
};
|
};
|
||||||
|
|
||||||
tokens.into()
|
tokens.into()
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
use proc_macro2::{Literal, Span, TokenStream};
|
use proc_macro2::{Literal, Span, TokenStream};
|
||||||
use quote::quote;
|
use quote::{quote, ToTokens};
|
||||||
use syn::{
|
use syn::{
|
||||||
bracketed, parse::Parse, punctuated::Punctuated, token::Bracket, DataEnum, DataStruct,
|
bracketed, ext, parse::Parse, punctuated::Punctuated, token::Bracket, DataEnum, DataStruct,
|
||||||
DeriveInput, Field, Fields, Ident, Meta, Token, Variant,
|
DeriveInput, Field, Fields, Ident, LitStr, Meta, Token, Variant,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::util::fold_tokenable;
|
use crate::util::fold_tokenable;
|
||||||
|
|
@ -235,14 +235,60 @@ fn generate_struct_version(attr: Option<&RmcStructAttr>) -> proc_macro2::TokenSt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn gen_rmc_struct_impl(
|
||||||
|
struct_ident: &Ident,
|
||||||
|
extended_struct: Option<&Field>,
|
||||||
|
) -> proc_macro2::TokenStream {
|
||||||
|
let self_name_str_lit = LitStr::new(&struct_ident.to_string(), struct_ident.span());
|
||||||
|
let register = if let Some(extended_struct) = extended_struct {
|
||||||
|
let extended_struct_ty = &extended_struct.ty;
|
||||||
|
let ext_ty_name = LitStr::new(
|
||||||
|
&extended_struct_ty.to_token_stream().to_string(),
|
||||||
|
Span::call_site(),
|
||||||
|
);
|
||||||
|
quote! {
|
||||||
|
#[::rnex_core::ctor(unsafe)]
|
||||||
|
#[allow(nonstandard_style)]
|
||||||
|
fn register_fun() {
|
||||||
|
println!("registering {} as parent of {}", #self_name_str_lit, #ext_ty_name);
|
||||||
|
let mut wr = <#extended_struct_ty as ::rnex_core::rmc::structures::RmcStruct>::get_struct_info()
|
||||||
|
.inheritors
|
||||||
|
.write()
|
||||||
|
.expect("poisoned");
|
||||||
|
wr.push(<#struct_ident as ::rnex_core::rmc::structures::RmcStruct>::get_struct_info());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
quote! {}
|
||||||
|
};
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
impl ::rnex_core::rmc::structures::RmcStruct for #struct_ident {
|
||||||
|
fn get_struct_info() -> &'static ::rnex_core::rmc::structures::RmcStructInfo {
|
||||||
|
#register
|
||||||
|
static STRUCT_DATA: ::rnex_core::rmc::structures::RmcStructInfo =
|
||||||
|
::rnex_core::rmc::structures::RmcStructInfo {
|
||||||
|
inheritors: ::std::sync::RwLock::new(::std::vec::Vec::new()),
|
||||||
|
name: #self_name_str_lit,
|
||||||
|
};
|
||||||
|
|
||||||
|
&STRUCT_DATA
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn rmc_serialize_struct(
|
pub fn rmc_serialize_struct(
|
||||||
s: &DataStruct,
|
s: &DataStruct,
|
||||||
|
name: &Ident,
|
||||||
derive_input: &DeriveInput,
|
derive_input: &DeriveInput,
|
||||||
) -> (
|
) -> (
|
||||||
proc_macro2::TokenStream,
|
proc_macro2::TokenStream,
|
||||||
proc_macro2::TokenStream,
|
proc_macro2::TokenStream,
|
||||||
Option<proc_macro2::TokenStream>,
|
Option<proc_macro2::TokenStream>,
|
||||||
Option<proc_macro2::TokenStream>,
|
Option<proc_macro2::TokenStream>,
|
||||||
|
Option<proc_macro2::TokenStream>,
|
||||||
) {
|
) {
|
||||||
let struct_attr = derive_input.attrs.iter().find(|a| {
|
let struct_attr = derive_input.attrs.iter().find(|a| {
|
||||||
a.path().segments.len() == 1
|
a.path().segments.len() == 1
|
||||||
|
|
@ -285,8 +331,19 @@ pub fn rmc_serialize_struct(
|
||||||
generate_deserialize_struct(s, extended_struct, elements, struct_attr.is_some());
|
generate_deserialize_struct(s, extended_struct, elements, struct_attr.is_some());
|
||||||
let write_size = generate_write_size_struct(s, struct_attr.is_some());
|
let write_size = generate_write_size_struct(s, struct_attr.is_some());
|
||||||
let version = generate_struct_version(struct_attr);
|
let version = generate_struct_version(struct_attr);
|
||||||
|
let rmc_struct_impl = if struct_attr.is_some() {
|
||||||
|
Some(gen_rmc_struct_impl(name, extended_struct))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
(serialize, deserialize, Some(write_size), Some(version))
|
(
|
||||||
|
serialize,
|
||||||
|
deserialize,
|
||||||
|
Some(write_size),
|
||||||
|
Some(version),
|
||||||
|
rmc_struct_impl,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn field_to_ident(field: &Field, idx: usize) -> Ident {
|
fn field_to_ident(field: &Field, idx: usize) -> Ident {
|
||||||
|
|
@ -405,6 +462,7 @@ pub fn rmc_serialize_enum(
|
||||||
proc_macro2::TokenStream,
|
proc_macro2::TokenStream,
|
||||||
Option<proc_macro2::TokenStream>,
|
Option<proc_macro2::TokenStream>,
|
||||||
Option<proc_macro2::TokenStream>,
|
Option<proc_macro2::TokenStream>,
|
||||||
|
Option<proc_macro2::TokenStream>,
|
||||||
) {
|
) {
|
||||||
let repr_attr = derive_input.attrs.iter().find(|a| {
|
let repr_attr = derive_input.attrs.iter().find(|a| {
|
||||||
a.path().segments.len() == 1
|
a.path().segments.len() == 1
|
||||||
|
|
@ -422,5 +480,5 @@ pub fn rmc_serialize_enum(
|
||||||
let serialize = rmc_generate_serialize_enum(&enum_data, &ty);
|
let serialize = rmc_generate_serialize_enum(&enum_data, &ty);
|
||||||
let deserialize = rmc_generate_deserialize_enum(&enum_data, &ty);
|
let deserialize = rmc_generate_deserialize_enum(&enum_data, &ty);
|
||||||
|
|
||||||
(serialize, deserialize, None, None)
|
(serialize, deserialize, None, None, None)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@ sha2 = "0.10.9"
|
||||||
urlencoding = "2.1.3"
|
urlencoding = "2.1.3"
|
||||||
futures = "0.3.32"
|
futures = "0.3.32"
|
||||||
async-trait = "0.1.89"
|
async-trait = "0.1.89"
|
||||||
|
ctor = "1.0.7"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
# criterion = "0.7.0"
|
# criterion = "0.7.0"
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,8 @@ pub type PID = i64;
|
||||||
#[cfg(not(feature = "big_pid"))]
|
#[cfg(not(feature = "big_pid"))]
|
||||||
pub type PID = i32;
|
pub type PID = i32;
|
||||||
|
|
||||||
|
pub use ctor::ctor;
|
||||||
|
|
||||||
extern crate self as rnex_core;
|
extern crate self as rnex_core;
|
||||||
|
|
||||||
pub mod prudp;
|
pub mod prudp;
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,7 @@ use rnex_core::rmc::structures::ranking::UploadCompetitionData;
|
||||||
use std::sync::{Arc, Weak};
|
use std::sync::{Arc, Weak};
|
||||||
use tokio::sync::{Mutex, RwLock};
|
use tokio::sync::{Mutex, RwLock};
|
||||||
|
|
||||||
|
use crate::rmc::structures::matchmake::Gathering;
|
||||||
use crate::rmc::structures::matchmake::MatchmakeSessionSearchCriteria;
|
use crate::rmc::structures::matchmake::MatchmakeSessionSearchCriteria;
|
||||||
|
|
||||||
cfg_if! {
|
cfg_if! {
|
||||||
|
|
@ -419,13 +420,11 @@ impl MatchmakeExtension for User {
|
||||||
|
|
||||||
async fn create_matchmake_session(
|
async fn create_matchmake_session(
|
||||||
&self,
|
&self,
|
||||||
gathering: Any,
|
gathering: Any<Gathering>,
|
||||||
message: String,
|
message: String,
|
||||||
) -> Result<(u32, Vec<u8>), ErrorCode> {
|
) -> Result<(u32, Vec<u8>), ErrorCode> {
|
||||||
info!("gathering: {:?}", gathering);
|
info!("gathering: {:?}", gathering);
|
||||||
let Some(Ok(session)): Option<Result<MatchmakeSession, _>> = gathering.try_get() else {
|
let session: MatchmakeSession = gathering.try_get_as()?;
|
||||||
return Err(ErrorCode::Core_InvalidArgument);
|
|
||||||
};
|
|
||||||
|
|
||||||
let session = self
|
let session = self
|
||||||
.create_matchmake_session_with_param(CreateMatchmakeSessionParam {
|
.create_matchmake_session_with_param(CreateMatchmakeSessionParam {
|
||||||
|
|
@ -517,14 +516,10 @@ impl MatchmakeExtension for User {
|
||||||
async fn auto_matchmake_with_search_criteria_postpone(
|
async fn auto_matchmake_with_search_criteria_postpone(
|
||||||
&self,
|
&self,
|
||||||
criteria: Vec<MatchmakeSessionSearchCriteria>,
|
criteria: Vec<MatchmakeSessionSearchCriteria>,
|
||||||
gathering: Any,
|
gathering: Any<Gathering>,
|
||||||
join_message: String,
|
join_message: String,
|
||||||
) -> Result<Any, ErrorCode> {
|
) -> Result<Any<Gathering>, ErrorCode> {
|
||||||
let session: MatchmakeSession = gathering
|
let session: MatchmakeSession = gathering.try_get_as()?;
|
||||||
.try_get()
|
|
||||||
.map(|v| v.ok())
|
|
||||||
.flatten()
|
|
||||||
.ok_or(ErrorCode::Core_InvalidArgument)?;
|
|
||||||
|
|
||||||
println!("{:?}", criteria);
|
println!("{:?}", criteria);
|
||||||
|
|
||||||
|
|
@ -548,7 +543,7 @@ impl MatchmakeExtension for User {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Matchmake for User {
|
impl Matchmake for User {
|
||||||
async fn find_by_single_id(&self, gid: u32) -> Result<(bool, Any), ErrorCode> {
|
async fn find_by_single_id(&self, gid: u32) -> Result<(bool, Any<Gathering>), ErrorCode> {
|
||||||
let s = self.matchmake_manager.get_session(gid).await?;
|
let s = self.matchmake_manager.get_session(gid).await?;
|
||||||
let s = s.lock().await;
|
let s = s.lock().await;
|
||||||
Ok((
|
Ok((
|
||||||
|
|
|
||||||
|
|
@ -5,17 +5,32 @@ use rnex_core::{
|
||||||
rmc::{response::ErrorCode, structures::any::Any},
|
rmc::{response::ErrorCode, structures::any::Any},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{kerberos::KerberosDateTime, rmc::protocols::friends_wiiu::NNAInfo};
|
use crate::{
|
||||||
|
kerberos::KerberosDateTime,
|
||||||
|
rmc::{protocols::friends_wiiu::NNAInfo, structures::data::Data},
|
||||||
|
};
|
||||||
|
|
||||||
#[derive(RmcSerialize, Debug, Clone)]
|
#[derive(RmcSerialize, Debug, Clone)]
|
||||||
#[rmc_struct(0)]
|
#[rmc_struct(0)]
|
||||||
pub struct NintendoCreateAccountData {
|
pub struct NintendoCreateAccountData {
|
||||||
|
#[extends]
|
||||||
|
pub data: Data,
|
||||||
pub nna_info: NNAInfo,
|
pub nna_info: NNAInfo,
|
||||||
pub nex_token: String,
|
pub nex_token: String,
|
||||||
pub birthday: KerberosDateTime,
|
pub birthday: KerberosDateTime,
|
||||||
pub unk: u64,
|
pub unk: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(RmcSerialize, Debug, Clone)]
|
||||||
|
#[rmc_struct(0)]
|
||||||
|
pub struct AccountExtraInfo {
|
||||||
|
#[extends]
|
||||||
|
pub data: Data,
|
||||||
|
pub unk1: u64,
|
||||||
|
pub unk2: u32,
|
||||||
|
pub nex_token: String,
|
||||||
|
}
|
||||||
|
|
||||||
#[rmc_proto(25)]
|
#[rmc_proto(25)]
|
||||||
pub trait AccountManagement {
|
pub trait AccountManagement {
|
||||||
#[method_id(27)]
|
#[method_id(27)]
|
||||||
|
|
|
||||||
|
|
@ -5,13 +5,14 @@ use rnex_core::rmc::response::ErrorCode;
|
||||||
use rnex_core::PID;
|
use rnex_core::PID;
|
||||||
|
|
||||||
use crate::rmc::structures::any::Any;
|
use crate::rmc::structures::any::Any;
|
||||||
|
use crate::rmc::structures::matchmake::Gathering;
|
||||||
|
|
||||||
#[rmc_proto(21)]
|
#[rmc_proto(21)]
|
||||||
pub trait Matchmake {
|
pub trait Matchmake {
|
||||||
#[method_id(2)]
|
#[method_id(2)]
|
||||||
async fn unregister_gathering(&self, gid: u32) -> Result<bool, ErrorCode>;
|
async fn unregister_gathering(&self, gid: u32) -> Result<bool, ErrorCode>;
|
||||||
#[method_id(21)]
|
#[method_id(21)]
|
||||||
async fn find_by_single_id(&self, gid: u32) -> Result<(bool, Any), ErrorCode>;
|
async fn find_by_single_id(&self, gid: u32) -> Result<(bool, Any<Gathering>), ErrorCode>;
|
||||||
#[method_id(41)]
|
#[method_id(41)]
|
||||||
async fn get_session_urls(&self, gid: u32) -> Result<Vec<StationUrl>, ErrorCode>;
|
async fn get_session_urls(&self, gid: u32) -> Result<Vec<StationUrl>, ErrorCode>;
|
||||||
#[method_id(42)]
|
#[method_id(42)]
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ use rnex_core::rmc::structures::matchmake::{
|
||||||
|
|
||||||
use crate::rmc::protocols::notifications::NotificationEvent;
|
use crate::rmc::protocols::notifications::NotificationEvent;
|
||||||
use crate::rmc::structures::any::Any;
|
use crate::rmc::structures::any::Any;
|
||||||
use crate::rmc::structures::matchmake::MatchmakeSessionSearchCriteria;
|
use crate::rmc::structures::matchmake::{Gathering, MatchmakeSessionSearchCriteria};
|
||||||
|
|
||||||
#[rmc_proto(109)]
|
#[rmc_proto(109)]
|
||||||
pub trait MatchmakeExtension {
|
pub trait MatchmakeExtension {
|
||||||
|
|
@ -18,7 +18,7 @@ pub trait MatchmakeExtension {
|
||||||
#[method_id(6)]
|
#[method_id(6)]
|
||||||
async fn create_matchmake_session(
|
async fn create_matchmake_session(
|
||||||
&self,
|
&self,
|
||||||
gathering: Any,
|
gathering: Any<Gathering>,
|
||||||
message: String,
|
message: String,
|
||||||
) -> Result<(u32, Vec<u8>), ErrorCode>;
|
) -> Result<(u32, Vec<u8>), ErrorCode>;
|
||||||
|
|
||||||
|
|
@ -40,9 +40,9 @@ pub trait MatchmakeExtension {
|
||||||
async fn auto_matchmake_with_search_criteria_postpone(
|
async fn auto_matchmake_with_search_criteria_postpone(
|
||||||
&self,
|
&self,
|
||||||
criteria: Vec<MatchmakeSessionSearchCriteria>,
|
criteria: Vec<MatchmakeSessionSearchCriteria>,
|
||||||
gathering: Any,
|
gathering: Any<Gathering>,
|
||||||
join_msg: String,
|
join_msg: String,
|
||||||
) -> Result<Any, ErrorCode>;
|
) -> Result<Any<Gathering>, ErrorCode>;
|
||||||
|
|
||||||
#[method_id(30)]
|
#[method_id(30)]
|
||||||
async fn join_matchmake_session_ex(
|
async fn join_matchmake_session_ex(
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ use rnex_core::rmc::response::ErrorCode;
|
||||||
use rnex_core::rmc::structures::qresult::QResult;
|
use rnex_core::rmc::structures::qresult::QResult;
|
||||||
|
|
||||||
use crate::rmc::structures::any::Any;
|
use crate::rmc::structures::any::Any;
|
||||||
|
use crate::rmc::structures::data::Data;
|
||||||
|
|
||||||
#[rmc_proto(11)]
|
#[rmc_proto(11)]
|
||||||
pub trait Secure {
|
pub trait Secure {
|
||||||
|
|
@ -17,7 +18,7 @@ pub trait Secure {
|
||||||
async fn register_ex(
|
async fn register_ex(
|
||||||
&self,
|
&self,
|
||||||
station_urls: Vec<StationUrl>,
|
station_urls: Vec<StationUrl>,
|
||||||
data: Any,
|
data: Any<Data>,
|
||||||
) -> Result<(QResult, u32, StationUrl), ErrorCode>;
|
) -> Result<(QResult, u32, StationUrl), ErrorCode>;
|
||||||
#[method_id(7)]
|
#[method_id(7)]
|
||||||
async fn replace_url(&self, target: StationUrl, dest: StationUrl) -> Result<(), ErrorCode>;
|
async fn replace_url(&self, target: StationUrl, dest: StationUrl) -> Result<(), ErrorCode>;
|
||||||
|
|
|
||||||
|
|
@ -456,6 +456,13 @@ pub enum ErrorCode {
|
||||||
Ess_GameSessionMaintenance = 0x00750003,
|
Ess_GameSessionMaintenance = 0x00750003,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<super::structures::Error> for ErrorCode {
|
||||||
|
fn from(value: super::structures::Error) -> Self {
|
||||||
|
error!("rmc error occurred during method runtime: {}", value);
|
||||||
|
Self::Core_InvalidArgument
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Into<u32> for ErrorCode {
|
impl Into<u32> for ErrorCode {
|
||||||
fn into(self) -> u32 {
|
fn into(self) -> u32 {
|
||||||
unsafe { transmute(self) }
|
unsafe { transmute(self) }
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,20 @@
|
||||||
use rnex_core::rmc::structures::{Result, RmcSerialize};
|
use rnex_core::rmc::structures::{Result, RmcSerialize};
|
||||||
use std::io::{Cursor, Read, Write};
|
use std::{
|
||||||
|
io::{Cursor, Read, Write},
|
||||||
|
marker::PhantomData,
|
||||||
|
};
|
||||||
use v_byte_helpers::{IS_BIG_ENDIAN, ReadExtensions};
|
use v_byte_helpers::{IS_BIG_ENDIAN, ReadExtensions};
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone)]
|
use crate::rmc::structures::{RmcStruct, data::Data};
|
||||||
pub struct Any {
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct Any<T: RmcStruct = Data> {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub data: Vec<u8>,
|
pub data: Vec<u8>,
|
||||||
|
pub phantom_data: PhantomData<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RmcSerialize for Any {
|
impl<T: RmcStruct> RmcSerialize for Any<T> {
|
||||||
fn serialize(&self, writer: &mut (impl Write + ?Sized)) -> Result<()> {
|
fn serialize(&self, writer: &mut (impl Write + ?Sized)) -> Result<()> {
|
||||||
self.name.serialize(writer)?;
|
self.name.serialize(writer)?;
|
||||||
|
|
||||||
|
|
@ -21,25 +27,131 @@ impl RmcSerialize for Any {
|
||||||
fn deserialize(mut reader: &mut (impl Read + ?Sized)) -> Result<Self> {
|
fn deserialize(mut reader: &mut (impl Read + ?Sized)) -> Result<Self> {
|
||||||
let name = String::deserialize(reader)?;
|
let name = String::deserialize(reader)?;
|
||||||
|
|
||||||
|
if !T::get_struct_info().is_inheritor(&name) {
|
||||||
|
return Err(super::Error::InheritanceError);
|
||||||
|
}
|
||||||
|
|
||||||
// also length ?
|
// also length ?
|
||||||
let _len2: u32 = reader.read_struct(IS_BIG_ENDIAN)?;
|
let _len2: u32 = reader.read_struct(IS_BIG_ENDIAN)?;
|
||||||
let data = Vec::deserialize(reader)?;
|
let data = Vec::deserialize(reader)?;
|
||||||
|
|
||||||
Ok(Any { name, data })
|
Ok(Any {
|
||||||
|
name,
|
||||||
|
data,
|
||||||
|
phantom_data: PhantomData,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Any {
|
impl<T: RmcStruct> Any<T> {
|
||||||
pub fn try_get<T: RmcSerialize>(&self) -> Option<Result<T>> {
|
pub fn try_into<U: RmcStruct>(self) -> Result<Any<U>> {
|
||||||
if self.name != T::name() {
|
if !U::get_struct_info().is_inheritor(&self.name) {
|
||||||
return None;
|
return Err(super::Error::InheritanceError);
|
||||||
}
|
}
|
||||||
return Some(T::deserialize(&mut Cursor::new(&self.data[..])));
|
Ok(Any {
|
||||||
|
data: self.data,
|
||||||
|
name: self.name,
|
||||||
|
phantom_data: PhantomData,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
pub fn new<T: RmcSerialize>(val: &T) -> Result<Self> {
|
pub fn try_get_as<U: RmcStruct>(&self) -> Result<U> {
|
||||||
|
if !U::get_struct_info().is_inheritor(&self.name) {
|
||||||
|
return Err(super::Error::InheritanceError);
|
||||||
|
}
|
||||||
|
return U::deserialize(&mut Cursor::new(&self.data[..]));
|
||||||
|
}
|
||||||
|
pub fn new<U: RmcStruct>(val: &U) -> Result<Self> {
|
||||||
|
if !T::get_struct_info().is_inheritor(U::get_struct_info().name) {
|
||||||
|
return Err(super::Error::InheritanceError);
|
||||||
|
}
|
||||||
return Ok(Self {
|
return Ok(Self {
|
||||||
name: T::name().to_owned(),
|
name: U::get_struct_info().name.to_owned(),
|
||||||
data: val.to_data()?,
|
data: val.to_data()?,
|
||||||
|
phantom_data: PhantomData,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get(&self) -> Result<T> {
|
||||||
|
return T::deserialize(&mut Cursor::new(&self.data[..]));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn emplace_parent<E: RmcStruct>(&mut self, parent: &E) -> Result<()> {
|
||||||
|
// validate if E is actually a parent of the contained struct
|
||||||
|
if !E::get_struct_info().is_inheritor(&self.name) {
|
||||||
|
return Err(super::Error::InheritanceError);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut cur = Cursor::new(&self.data[..]);
|
||||||
|
// skip the parent part of the struct
|
||||||
|
let _ = T::deserialize(&mut cur)?;
|
||||||
|
let end_of_parent_pos = cur.position();
|
||||||
|
let rest_of_struct = &self
|
||||||
|
.data
|
||||||
|
.get(end_of_parent_pos as usize..)
|
||||||
|
.ok_or(super::Error::OOB)?;
|
||||||
|
|
||||||
|
let mut new_data = parent.to_data()?;
|
||||||
|
new_data.extend_from_slice(&rest_of_struct);
|
||||||
|
|
||||||
|
self.data = new_data;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use std::io::Cursor;
|
||||||
|
|
||||||
|
use macros::{RmcSerialize, rmc_struct};
|
||||||
|
|
||||||
|
use crate::rmc::structures::RmcSerialize;
|
||||||
|
use crate::rmc::structures::any::Any;
|
||||||
|
#[derive(RmcSerialize)]
|
||||||
|
#[rmc_struct(0)]
|
||||||
|
struct StructB {
|
||||||
|
valb: u32,
|
||||||
|
}
|
||||||
|
#[derive(RmcSerialize)]
|
||||||
|
#[rmc_struct(0)]
|
||||||
|
struct StructA {
|
||||||
|
#[extends]
|
||||||
|
base: StructB,
|
||||||
|
vala: u32,
|
||||||
|
}
|
||||||
|
#[derive(RmcSerialize)]
|
||||||
|
#[rmc_struct(0)]
|
||||||
|
struct Unrelated {
|
||||||
|
vala: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test() {
|
||||||
|
let initial: Any<StructA> = Any::new(&StructA {
|
||||||
|
base: StructB { valb: 10 },
|
||||||
|
vala: 11,
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let encoded = initial.to_data().unwrap();
|
||||||
|
|
||||||
|
let mut reser_b: Any<StructB> = Any::deserialize(&mut Cursor::new(&encoded[..])).unwrap();
|
||||||
|
|
||||||
|
let mut data_b: StructB = reser_b.get().unwrap();
|
||||||
|
assert_eq!(data_b.valb, 10);
|
||||||
|
data_b.valb = 20;
|
||||||
|
|
||||||
|
reser_b.emplace_parent(&data_b).unwrap();
|
||||||
|
|
||||||
|
let data_a: StructA = reser_b.try_get_as().unwrap();
|
||||||
|
assert_eq!(data_a.vala, 11);
|
||||||
|
assert_eq!(data_a.base.valb, 20);
|
||||||
|
|
||||||
|
let data: Any<StructA> = reser_b.try_into().unwrap();
|
||||||
|
let data: Any<StructB> = data.try_into().unwrap();
|
||||||
|
let fail: Result<Any<Unrelated>, _> = data.try_into();
|
||||||
|
assert!(fail.is_err());
|
||||||
|
let fail: Result<Any<Unrelated>, _> = Any::deserialize(&mut Cursor::new(&encoded[..]));
|
||||||
|
assert!(fail.is_err());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,9 @@
|
||||||
use crate::rmc::structures::helpers::DummyWriter;
|
use crate::rmc::structures::helpers::DummyWriter;
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
|
use ctor::ctor;
|
||||||
use std::io::{Read, Write};
|
use std::io::{Read, Write};
|
||||||
use std::string::FromUtf8Error;
|
use std::string::FromUtf8Error;
|
||||||
|
use std::sync::RwLock;
|
||||||
use std::{fmt, io};
|
use std::{fmt, io};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
//ideas for the future: make a proc macro library which allows generation of struct reads
|
//ideas for the future: make a proc macro library which allows generation of struct reads
|
||||||
|
|
@ -21,11 +23,15 @@ pub enum Error {
|
||||||
StationUrlInvalid,
|
StationUrlInvalid,
|
||||||
#[error("error formatting text: {0}")]
|
#[error("error formatting text: {0}")]
|
||||||
FormatError(#[from] fmt::Error),
|
FormatError(#[from] fmt::Error),
|
||||||
|
#[error("tried to validate inheritance chain")]
|
||||||
|
InheritanceError,
|
||||||
#[error("uncategorized rmc error occurred: {0}")]
|
#[error("uncategorized rmc error occurred: {0}")]
|
||||||
Other(Box<dyn std::error::Error + Send + Sync>),
|
Other(Box<dyn std::error::Error + Send + Sync>),
|
||||||
|
#[error("unexpected out of bounds read/write")]
|
||||||
|
OOB,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type Result<T> = std::result::Result<T, Error>;
|
pub type Result<T, E = Error> = std::result::Result<T, E>;
|
||||||
|
|
||||||
pub mod any;
|
pub mod any;
|
||||||
pub mod buffer;
|
pub mod buffer;
|
||||||
|
|
@ -68,9 +74,6 @@ pub trait RmcSerialize {
|
||||||
|
|
||||||
Ok(data)
|
Ok(data)
|
||||||
}
|
}
|
||||||
fn name() -> &'static str {
|
|
||||||
"NoNameSpecified"
|
|
||||||
}
|
|
||||||
fn version() -> Option<u8> {
|
fn version() -> Option<u8> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
@ -79,21 +82,6 @@ pub trait RmcSerialize {
|
||||||
trait SendWrite: Send + Write {}
|
trait SendWrite: Send + Write {}
|
||||||
impl<T: Send + Write> SendWrite for T {}
|
impl<T: Send + Write> SendWrite for T {}
|
||||||
|
|
||||||
// beware that this trait throws away most of the optimizations which come with using
|
|
||||||
// the regular `Serialize` trait, ONLY use this when it is 100% required to have dyn
|
|
||||||
// compatibility
|
|
||||||
#[async_trait]
|
|
||||||
trait DynRmcSerialize: Send + Sync {
|
|
||||||
async fn serialize(&self, writer: &mut dyn SendWrite) -> Result<()>;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[async_trait]
|
|
||||||
impl<T: RmcSerialize + Send + Sync> DynRmcSerialize for T {
|
|
||||||
async fn serialize(&self, writer: &mut dyn SendWrite) -> Result<()> {
|
|
||||||
<Self as RmcSerialize>::serialize(&self, writer)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl RmcSerialize for () {
|
impl RmcSerialize for () {
|
||||||
fn serialize(&self, _writer: &mut (impl Write + ?Sized)) -> Result<()> {
|
fn serialize(&self, _writer: &mut (impl Write + ?Sized)) -> Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -106,31 +94,28 @@ impl RmcSerialize for () {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trait RmcInternalAnyUnknownAs<T: RmcStruct>: AsRef<T> + DynRmcSerialize + RmcStructInstance {}
|
pub struct RmcStructInfo {
|
||||||
|
// this may never be locked after initialization
|
||||||
trait RmcCastable {
|
pub inheritors: RwLock<Vec<&'static RmcStructInfo>>,
|
||||||
// consumes box and returns a Box containing a Box with the requested Struct details
|
pub name: &'static str,
|
||||||
fn cast_to(self: Box<Self>, destination: &RmcStructInfo) -> Box<dyn std::any::Any>;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct RmcStructInfo {
|
|
||||||
inheritors: Vec<&'static RmcStructInfo>,
|
|
||||||
name: &'static str,
|
|
||||||
deserialize_abstract: fn(&mut dyn Read) -> Box<dyn std::any::Any>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RmcStructInfo {
|
impl RmcStructInfo {
|
||||||
fn deserialze_abstract_as<T: RmcStruct>(
|
fn is_inheritor(&self, name: &str) -> bool {
|
||||||
reader: &impl Read,
|
if name == self.name {
|
||||||
) -> Box<dyn RmcInternalAnyUnknownAs<T>> {
|
return true;
|
||||||
todo!()
|
}
|
||||||
|
let inheritors = self.inheritors.read().expect("poisoned");
|
||||||
|
for inheritor in inheritors.iter() {
|
||||||
|
if inheritor.is_inheritor(name) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trait RmcStruct {
|
pub trait RmcStruct: RmcSerialize {
|
||||||
fn get_struct_info() -> &'static RmcStructInfo;
|
fn get_struct_info() -> &'static RmcStructInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
trait RmcStructInstance {
|
|
||||||
fn get_self_struct_info(&self) -> &'static RmcStructInfo;
|
|
||||||
}
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue