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",
|
||||
]
|
||||
|
||||
[[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]]
|
||||
name = "ctutils"
|
||||
version = "0.4.2"
|
||||
|
|
@ -1022,7 +1032,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -1572,7 +1582,7 @@ dependencies = [
|
|||
"libc",
|
||||
"percent-encoding",
|
||||
"pin-project-lite",
|
||||
"socket2 0.5.10",
|
||||
"socket2 0.6.3",
|
||||
"tokio",
|
||||
"tower-service",
|
||||
"tracing",
|
||||
|
|
@ -1821,6 +1831,18 @@ dependencies = [
|
|||
"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]]
|
||||
name = "litemap"
|
||||
version = "0.8.2"
|
||||
|
|
@ -2403,6 +2425,7 @@ dependencies = [
|
|||
"bytemuck",
|
||||
"cfg-if",
|
||||
"chrono",
|
||||
"ctor",
|
||||
"dotenv",
|
||||
"futures",
|
||||
"hex",
|
||||
|
|
@ -3625,7 +3648,7 @@ version = "0.1.11"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
|
||||
dependencies = [
|
||||
"windows-sys 0.48.0",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
|
|||
|
|
@ -17,20 +17,16 @@ use syn::{parse_macro_input, Data, DeriveInput, Lit, LitStr};
|
|||
pub fn rmc_serialize(input: TokenStream) -> TokenStream {
|
||||
let derive_input = parse_macro_input!(input as DeriveInput);
|
||||
|
||||
let (serialize, deserialize, write_size, version) = match &derive_input.data {
|
||||
Data::Struct(s) => rmc_serialize_struct(s, &derive_input),
|
||||
let (serialize, deserialize, write_size, version, rmc_struct_impl) = match &derive_input.data {
|
||||
Data::Struct(s) => rmc_serialize_struct(s, &derive_input.ident, &derive_input),
|
||||
Data::Enum(e) => rmc_serialize_enum(e, &derive_input),
|
||||
Data::Union(_) => {
|
||||
unimplemented!("serialize a union is not allowed");
|
||||
unimplemented!("serializing a union is not allowed");
|
||||
}
|
||||
};
|
||||
|
||||
// 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 write_size = if let Some(v) = write_size {
|
||||
|
|
@ -52,6 +48,7 @@ pub fn rmc_serialize(input: TokenStream) -> TokenStream {
|
|||
} else {
|
||||
quote! {}
|
||||
};
|
||||
let rmc_struct_impl = rmc_struct_impl.unwrap_or_default();
|
||||
|
||||
let tokens = quote! {
|
||||
impl rnex_core::rmc::structures::RmcSerialize for #ident{
|
||||
|
|
@ -67,11 +64,8 @@ pub fn rmc_serialize(input: TokenStream) -> TokenStream {
|
|||
#write_size
|
||||
|
||||
#version
|
||||
|
||||
fn name() -> &'static str{
|
||||
#str_name
|
||||
}
|
||||
}
|
||||
#rmc_struct_impl
|
||||
};
|
||||
|
||||
tokens.into()
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
use proc_macro2::{Literal, Span, TokenStream};
|
||||
use quote::quote;
|
||||
use quote::{quote, ToTokens};
|
||||
use syn::{
|
||||
bracketed, parse::Parse, punctuated::Punctuated, token::Bracket, DataEnum, DataStruct,
|
||||
DeriveInput, Field, Fields, Ident, Meta, Token, Variant,
|
||||
bracketed, ext, parse::Parse, punctuated::Punctuated, token::Bracket, DataEnum, DataStruct,
|
||||
DeriveInput, Field, Fields, Ident, LitStr, Meta, Token, Variant,
|
||||
};
|
||||
|
||||
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(
|
||||
s: &DataStruct,
|
||||
name: &Ident,
|
||||
derive_input: &DeriveInput,
|
||||
) -> (
|
||||
proc_macro2::TokenStream,
|
||||
proc_macro2::TokenStream,
|
||||
Option<proc_macro2::TokenStream>,
|
||||
Option<proc_macro2::TokenStream>,
|
||||
Option<proc_macro2::TokenStream>,
|
||||
) {
|
||||
let struct_attr = derive_input.attrs.iter().find(|a| {
|
||||
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());
|
||||
let write_size = generate_write_size_struct(s, struct_attr.is_some());
|
||||
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 {
|
||||
|
|
@ -405,6 +462,7 @@ pub fn rmc_serialize_enum(
|
|||
proc_macro2::TokenStream,
|
||||
Option<proc_macro2::TokenStream>,
|
||||
Option<proc_macro2::TokenStream>,
|
||||
Option<proc_macro2::TokenStream>,
|
||||
) {
|
||||
let repr_attr = derive_input.attrs.iter().find(|a| {
|
||||
a.path().segments.len() == 1
|
||||
|
|
@ -422,5 +480,5 @@ pub fn rmc_serialize_enum(
|
|||
let serialize = rmc_generate_serialize_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"
|
||||
futures = "0.3.32"
|
||||
async-trait = "0.1.89"
|
||||
ctor = "1.0.7"
|
||||
|
||||
[dev-dependencies]
|
||||
# criterion = "0.7.0"
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@ pub type PID = i64;
|
|||
#[cfg(not(feature = "big_pid"))]
|
||||
pub type PID = i32;
|
||||
|
||||
pub use ctor::ctor;
|
||||
|
||||
extern crate self as rnex_core;
|
||||
|
||||
pub mod prudp;
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@ use rnex_core::rmc::structures::ranking::UploadCompetitionData;
|
|||
use std::sync::{Arc, Weak};
|
||||
use tokio::sync::{Mutex, RwLock};
|
||||
|
||||
use crate::rmc::structures::matchmake::Gathering;
|
||||
use crate::rmc::structures::matchmake::MatchmakeSessionSearchCriteria;
|
||||
|
||||
cfg_if! {
|
||||
|
|
@ -419,13 +420,11 @@ impl MatchmakeExtension for User {
|
|||
|
||||
async fn create_matchmake_session(
|
||||
&self,
|
||||
gathering: Any,
|
||||
gathering: Any<Gathering>,
|
||||
message: String,
|
||||
) -> Result<(u32, Vec<u8>), ErrorCode> {
|
||||
info!("gathering: {:?}", gathering);
|
||||
let Some(Ok(session)): Option<Result<MatchmakeSession, _>> = gathering.try_get() else {
|
||||
return Err(ErrorCode::Core_InvalidArgument);
|
||||
};
|
||||
let session: MatchmakeSession = gathering.try_get_as()?;
|
||||
|
||||
let session = self
|
||||
.create_matchmake_session_with_param(CreateMatchmakeSessionParam {
|
||||
|
|
@ -517,14 +516,10 @@ impl MatchmakeExtension for User {
|
|||
async fn auto_matchmake_with_search_criteria_postpone(
|
||||
&self,
|
||||
criteria: Vec<MatchmakeSessionSearchCriteria>,
|
||||
gathering: Any,
|
||||
gathering: Any<Gathering>,
|
||||
join_message: String,
|
||||
) -> Result<Any, ErrorCode> {
|
||||
let session: MatchmakeSession = gathering
|
||||
.try_get()
|
||||
.map(|v| v.ok())
|
||||
.flatten()
|
||||
.ok_or(ErrorCode::Core_InvalidArgument)?;
|
||||
) -> Result<Any<Gathering>, ErrorCode> {
|
||||
let session: MatchmakeSession = gathering.try_get_as()?;
|
||||
|
||||
println!("{:?}", criteria);
|
||||
|
||||
|
|
@ -548,7 +543,7 @@ impl MatchmakeExtension 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 = s.lock().await;
|
||||
Ok((
|
||||
|
|
|
|||
|
|
@ -5,17 +5,32 @@ use rnex_core::{
|
|||
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)]
|
||||
#[rmc_struct(0)]
|
||||
pub struct NintendoCreateAccountData {
|
||||
#[extends]
|
||||
pub data: Data,
|
||||
pub nna_info: NNAInfo,
|
||||
pub nex_token: String,
|
||||
pub birthday: KerberosDateTime,
|
||||
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)]
|
||||
pub trait AccountManagement {
|
||||
#[method_id(27)]
|
||||
|
|
|
|||
|
|
@ -5,13 +5,14 @@ use rnex_core::rmc::response::ErrorCode;
|
|||
use rnex_core::PID;
|
||||
|
||||
use crate::rmc::structures::any::Any;
|
||||
use crate::rmc::structures::matchmake::Gathering;
|
||||
|
||||
#[rmc_proto(21)]
|
||||
pub trait Matchmake {
|
||||
#[method_id(2)]
|
||||
async fn unregister_gathering(&self, gid: u32) -> Result<bool, ErrorCode>;
|
||||
#[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)]
|
||||
async fn get_session_urls(&self, gid: u32) -> Result<Vec<StationUrl>, ErrorCode>;
|
||||
#[method_id(42)]
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ use rnex_core::rmc::structures::matchmake::{
|
|||
|
||||
use crate::rmc::protocols::notifications::NotificationEvent;
|
||||
use crate::rmc::structures::any::Any;
|
||||
use crate::rmc::structures::matchmake::MatchmakeSessionSearchCriteria;
|
||||
use crate::rmc::structures::matchmake::{Gathering, MatchmakeSessionSearchCriteria};
|
||||
|
||||
#[rmc_proto(109)]
|
||||
pub trait MatchmakeExtension {
|
||||
|
|
@ -18,7 +18,7 @@ pub trait MatchmakeExtension {
|
|||
#[method_id(6)]
|
||||
async fn create_matchmake_session(
|
||||
&self,
|
||||
gathering: Any,
|
||||
gathering: Any<Gathering>,
|
||||
message: String,
|
||||
) -> Result<(u32, Vec<u8>), ErrorCode>;
|
||||
|
||||
|
|
@ -40,9 +40,9 @@ pub trait MatchmakeExtension {
|
|||
async fn auto_matchmake_with_search_criteria_postpone(
|
||||
&self,
|
||||
criteria: Vec<MatchmakeSessionSearchCriteria>,
|
||||
gathering: Any,
|
||||
gathering: Any<Gathering>,
|
||||
join_msg: String,
|
||||
) -> Result<Any, ErrorCode>;
|
||||
) -> Result<Any<Gathering>, ErrorCode>;
|
||||
|
||||
#[method_id(30)]
|
||||
async fn join_matchmake_session_ex(
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ use rnex_core::rmc::response::ErrorCode;
|
|||
use rnex_core::rmc::structures::qresult::QResult;
|
||||
|
||||
use crate::rmc::structures::any::Any;
|
||||
use crate::rmc::structures::data::Data;
|
||||
|
||||
#[rmc_proto(11)]
|
||||
pub trait Secure {
|
||||
|
|
@ -17,7 +18,7 @@ pub trait Secure {
|
|||
async fn register_ex(
|
||||
&self,
|
||||
station_urls: Vec<StationUrl>,
|
||||
data: Any,
|
||||
data: Any<Data>,
|
||||
) -> Result<(QResult, u32, StationUrl), ErrorCode>;
|
||||
#[method_id(7)]
|
||||
async fn replace_url(&self, target: StationUrl, dest: StationUrl) -> Result<(), ErrorCode>;
|
||||
|
|
|
|||
|
|
@ -456,6 +456,13 @@ pub enum ErrorCode {
|
|||
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 {
|
||||
fn into(self) -> u32 {
|
||||
unsafe { transmute(self) }
|
||||
|
|
|
|||
|
|
@ -1,14 +1,20 @@
|
|||
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};
|
||||
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub struct Any {
|
||||
use crate::rmc::structures::{RmcStruct, data::Data};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Any<T: RmcStruct = Data> {
|
||||
pub name: String,
|
||||
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<()> {
|
||||
self.name.serialize(writer)?;
|
||||
|
||||
|
|
@ -21,25 +27,131 @@ impl RmcSerialize for Any {
|
|||
fn deserialize(mut reader: &mut (impl Read + ?Sized)) -> Result<Self> {
|
||||
let name = String::deserialize(reader)?;
|
||||
|
||||
if !T::get_struct_info().is_inheritor(&name) {
|
||||
return Err(super::Error::InheritanceError);
|
||||
}
|
||||
|
||||
// also length ?
|
||||
let _len2: u32 = reader.read_struct(IS_BIG_ENDIAN)?;
|
||||
let data = Vec::deserialize(reader)?;
|
||||
|
||||
Ok(Any { name, data })
|
||||
Ok(Any {
|
||||
name,
|
||||
data,
|
||||
phantom_data: PhantomData,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Any {
|
||||
pub fn try_get<T: RmcSerialize>(&self) -> Option<Result<T>> {
|
||||
if self.name != T::name() {
|
||||
return None;
|
||||
impl<T: RmcStruct> Any<T> {
|
||||
pub fn try_into<U: RmcStruct>(self) -> Result<Any<U>> {
|
||||
if !U::get_struct_info().is_inheritor(&self.name) {
|
||||
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 {
|
||||
name: T::name().to_owned(),
|
||||
name: U::get_struct_info().name.to_owned(),
|
||||
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 async_trait::async_trait;
|
||||
use ctor::ctor;
|
||||
use std::io::{Read, Write};
|
||||
use std::string::FromUtf8Error;
|
||||
use std::sync::RwLock;
|
||||
use std::{fmt, io};
|
||||
use thiserror::Error;
|
||||
//ideas for the future: make a proc macro library which allows generation of struct reads
|
||||
|
|
@ -21,11 +23,15 @@ pub enum Error {
|
|||
StationUrlInvalid,
|
||||
#[error("error formatting text: {0}")]
|
||||
FormatError(#[from] fmt::Error),
|
||||
#[error("tried to validate inheritance chain")]
|
||||
InheritanceError,
|
||||
#[error("uncategorized rmc error occurred: {0}")]
|
||||
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 buffer;
|
||||
|
|
@ -68,9 +74,6 @@ pub trait RmcSerialize {
|
|||
|
||||
Ok(data)
|
||||
}
|
||||
fn name() -> &'static str {
|
||||
"NoNameSpecified"
|
||||
}
|
||||
fn version() -> Option<u8> {
|
||||
None
|
||||
}
|
||||
|
|
@ -79,21 +82,6 @@ pub trait RmcSerialize {
|
|||
trait SendWrite: Send + Write {}
|
||||
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 () {
|
||||
fn serialize(&self, _writer: &mut (impl Write + ?Sized)) -> Result<()> {
|
||||
Ok(())
|
||||
|
|
@ -106,31 +94,28 @@ impl RmcSerialize for () {
|
|||
}
|
||||
}
|
||||
|
||||
trait RmcInternalAnyUnknownAs<T: RmcStruct>: AsRef<T> + DynRmcSerialize + RmcStructInstance {}
|
||||
|
||||
trait RmcCastable {
|
||||
// consumes box and returns a Box containing a Box with the requested Struct details
|
||||
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>,
|
||||
pub struct RmcStructInfo {
|
||||
// this may never be locked after initialization
|
||||
pub inheritors: RwLock<Vec<&'static RmcStructInfo>>,
|
||||
pub name: &'static str,
|
||||
}
|
||||
|
||||
impl RmcStructInfo {
|
||||
fn deserialze_abstract_as<T: RmcStruct>(
|
||||
reader: &impl Read,
|
||||
) -> Box<dyn RmcInternalAnyUnknownAs<T>> {
|
||||
todo!()
|
||||
fn is_inheritor(&self, name: &str) -> bool {
|
||||
if name == self.name {
|
||||
return true;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
trait RmcStructInstance {
|
||||
fn get_self_struct_info(&self) -> &'static RmcStructInfo;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue