This commit is contained in:
Maple 2025-11-12 22:41:34 +01:00 committed by Maple
commit 5782951e68
25 changed files with 956 additions and 501 deletions

245
Cargo.lock generated
View file

@ -41,6 +41,24 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "anes"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299"
[[package]]
name = "anstyle"
version = "1.0.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78"
[[package]]
name = "anyhow"
version = "1.0.100"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61"
[[package]] [[package]]
name = "async-stream" name = "async-stream"
version = "0.3.6" version = "0.3.6"
@ -222,6 +240,12 @@ version = "1.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a"
[[package]]
name = "cast"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
[[package]] [[package]]
name = "cc" name = "cc"
version = "1.2.31" version = "1.2.31"
@ -257,6 +281,33 @@ dependencies = [
"windows-link", "windows-link",
] ]
[[package]]
name = "ciborium"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e"
dependencies = [
"ciborium-io",
"ciborium-ll",
"serde",
]
[[package]]
name = "ciborium-io"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757"
[[package]]
name = "ciborium-ll"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9"
dependencies = [
"ciborium-io",
"half",
]
[[package]] [[package]]
name = "cipher" name = "cipher"
version = "0.4.4" version = "0.4.4"
@ -267,6 +318,31 @@ dependencies = [
"inout", "inout",
] ]
[[package]]
name = "clap"
version = "4.5.51"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c26d721170e0295f191a69bd9a1f93efcdb0aff38684b61ab5750468972e5f5"
dependencies = [
"clap_builder",
]
[[package]]
name = "clap_builder"
version = "4.5.51"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75835f0c7bf681bfd05abe44e965760fea999a5286c6eb2d59883634fd02011a"
dependencies = [
"anstyle",
"clap_lex",
]
[[package]]
name = "clap_lex"
version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d"
[[package]] [[package]]
name = "cookie" name = "cookie"
version = "0.18.1" version = "0.18.1"
@ -294,6 +370,70 @@ version = "0.8.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
[[package]]
name = "criterion"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e1c047a62b0cc3e145fa84415a3191f628e980b194c2755aa12300a4e6cbd928"
dependencies = [
"anes",
"cast",
"ciborium",
"clap",
"criterion-plot",
"itertools",
"num-traits",
"oorandom",
"plotters",
"rayon",
"regex",
"serde",
"serde_json",
"tinytemplate",
"walkdir",
]
[[package]]
name = "criterion-plot"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b1bcc0dc7dfae599d84ad0b1a55f80cde8af3725da8313b528da95ef783e338"
dependencies = [
"cast",
"itertools",
]
[[package]]
name = "crossbeam-deque"
version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51"
dependencies = [
"crossbeam-epoch",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-epoch"
version = "0.9.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
dependencies = [
"crossbeam-utils",
]
[[package]]
name = "crossbeam-utils"
version = "0.8.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
[[package]]
name = "crunchy"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5"
[[package]] [[package]]
name = "crypto-common" name = "crypto-common"
version = "0.1.6" version = "0.1.6"
@ -626,6 +766,17 @@ dependencies = [
"tracing", "tracing",
] ]
[[package]]
name = "half"
version = "2.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b"
dependencies = [
"cfg-if",
"crunchy",
"zerocopy",
]
[[package]] [[package]]
name = "hashbrown" name = "hashbrown"
version = "0.12.3" version = "0.12.3"
@ -1048,6 +1199,15 @@ dependencies = [
"windows-sys 0.59.0", "windows-sys 0.59.0",
] ]
[[package]]
name = "itertools"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186"
dependencies = [
"either",
]
[[package]] [[package]]
name = "itoa" name = "itoa"
version = "1.0.15" version = "1.0.15"
@ -1308,6 +1468,12 @@ version = "1.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
[[package]]
name = "oorandom"
version = "11.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e"
[[package]] [[package]]
name = "openssl" name = "openssl"
version = "0.10.73" version = "0.10.73"
@ -1454,6 +1620,34 @@ version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c"
[[package]]
name = "plotters"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5aeb6f403d7a4911efb1e33402027fc44f29b5bf6def3effcc22d7bb75f2b747"
dependencies = [
"num-traits",
"plotters-backend",
"plotters-svg",
"wasm-bindgen",
"web-sys",
]
[[package]]
name = "plotters-backend"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df42e13c12958a16b3f7f4386b9ab1f3e7933914ecea48da7139435263a4172a"
[[package]]
name = "plotters-svg"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51bae2ac328883f7acdfea3d66a7c35751187f870bc81f94563733a154d7a670"
dependencies = [
"plotters-backend",
]
[[package]] [[package]]
name = "potential_utf" name = "potential_utf"
version = "0.1.2" version = "0.1.2"
@ -1572,6 +1766,26 @@ dependencies = [
"getrandom 0.2.16", "getrandom 0.2.16",
] ]
[[package]]
name = "rayon"
version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f"
dependencies = [
"either",
"rayon-core",
]
[[package]]
name = "rayon-core"
version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91"
dependencies = [
"crossbeam-deque",
"crossbeam-utils",
]
[[package]] [[package]]
name = "rc4" name = "rc4"
version = "0.1.0" version = "0.1.0"
@ -1714,9 +1928,11 @@ dependencies = [
name = "rnex-core" name = "rnex-core"
version = "0.1.1" version = "0.1.1"
dependencies = [ dependencies = [
"anyhow",
"async-trait", "async-trait",
"bytemuck", "bytemuck",
"chrono", "chrono",
"criterion",
"ctrlc", "ctrlc",
"dotenv", "dotenv",
"hex", "hex",
@ -1885,6 +2101,15 @@ version = "1.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
[[package]]
name = "same-file"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
dependencies = [
"winapi-util",
]
[[package]] [[package]]
name = "schannel" name = "schannel"
version = "0.1.27" version = "0.1.27"
@ -2242,6 +2467,16 @@ dependencies = [
"zerovec", "zerovec",
] ]
[[package]]
name = "tinytemplate"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc"
dependencies = [
"serde",
"serde_json",
]
[[package]] [[package]]
name = "tokio" name = "tokio"
version = "1.47.1" version = "1.47.1"
@ -2607,6 +2842,16 @@ version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
[[package]]
name = "walkdir"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
dependencies = [
"same-file",
"winapi-util",
]
[[package]] [[package]]
name = "want" name = "want"
version = "0.3.1" version = "0.3.1"

View file

@ -48,7 +48,7 @@ impl Parse for ProtoInputParams {
fn gen_serialize_data_struct( fn gen_serialize_data_struct(
s: DataStruct, s: DataStruct,
struct_attr: Option<&Attribute>, struct_attr: Option<&Attribute>,
) -> (proc_macro2::TokenStream, proc_macro2::TokenStream) { ) -> (proc_macro2::TokenStream, proc_macro2::TokenStream, proc_macro2::TokenStream) {
let serialize_base_content = { let serialize_base_content = {
let mut serialize_content = quote! {}; let mut serialize_content = quote! {};
@ -119,6 +119,29 @@ fn gen_serialize_data_struct(
} }
}; };
let write_size = {
let mut size_content = quote! { 0 };
for f in &s.fields {
let ident = f.ident.as_ref().unwrap();
let ty = &f.ty;
size_content.append_all(quote! {
+ rnex_core::rmc::structures::RmcSerialize::serialize_write_size(&self.#ident)?
})
}
size_content
};
let write_size = if let Some(_) = struct_attr {
quote!{ #write_size + if rnex_core::config::FEATURE_HAS_STRUCT_HEADER{ 5 } else { 0 } }
} else {
write_size
};
// generate base with extends stuff // generate base with extends stuff
let serialize_base_content = if let Some(attr) = struct_attr { let serialize_base_content = if let Some(attr) = struct_attr {
@ -143,9 +166,18 @@ fn gen_serialize_data_struct(
quote! { quote! {
#pre_inner #pre_inner
rnex_core::rmc::structures::rmc_struct::write_struct(writer, #version, |mut writer|{ rnex_core::rmc::structures::rmc_struct::write_struct(
#serialize_base_content writer,
})?; #version,
rnex_core::rmc::structures::helpers::len_of_write(
|writer|{
#serialize_base_content
}
),
|writer|{
#serialize_base_content
}
)?;
Ok(()) Ok(())
} }
@ -184,7 +216,13 @@ fn gen_serialize_data_struct(
deserialize_base_content deserialize_base_content
}; };
(serialize_base_content, deserialize_base_content) let write_size = quote!{
fn serialize_write_size(&self) -> rnex_core::rmc::structures::Result<u32>{
Ok(#write_size)
}
};
(serialize_base_content, deserialize_base_content, write_size)
} }
#[proc_macro_derive(RmcSerialize, attributes(extends, rmc_struct))] #[proc_macro_derive(RmcSerialize, attributes(extends, rmc_struct))]
@ -210,7 +248,7 @@ pub fn rmc_serialize(input: TokenStream) -> TokenStream {
panic!("rmc struct type MUST be a struct"); panic!("rmc struct type MUST be a struct");
};*/ };*/
let (serialize_base_content, deserialize_base_content) = match derive_input.data { let (serialize_base_content, deserialize_base_content, write_size) = match derive_input.data {
Data::Struct(s) => gen_serialize_data_struct(s, struct_attr), Data::Struct(s) => gen_serialize_data_struct(s, struct_attr),
Data::Enum(e) => { Data::Enum(e) => {
let Some(repr_attr) = repr_attr else { let Some(repr_attr) = repr_attr else {
@ -221,6 +259,7 @@ pub fn rmc_serialize(input: TokenStream) -> TokenStream {
let mut inner_match_de = quote! {}; let mut inner_match_de = quote! {};
let mut inner_match_se = quote! {}; let mut inner_match_se = quote! {};
let mut inner_match_len = quote!{};
for variant in e.variants { for variant in e.variants {
let Some((_, val)) = variant.discriminant else { let Some((_, val)) = variant.discriminant else {
@ -352,7 +391,7 @@ pub fn rmc_serialize(input: TokenStream) -> TokenStream {
Ok(val) Ok(val)
}; };
(serialize_base_content, deserialize_base_content) (serialize_base_content, deserialize_base_content, quote!{})
} }
Data::Union(_) => { Data::Union(_) => {
unimplemented!() unimplemented!()
@ -365,15 +404,16 @@ pub fn rmc_serialize(input: TokenStream) -> TokenStream {
let tokens = quote! { let tokens = quote! {
impl rnex_core::rmc::structures::RmcSerialize for #ident{ impl rnex_core::rmc::structures::RmcSerialize for #ident{
fn serialize(&self, writer: &mut dyn ::std::io::Write) -> rnex_core::rmc::structures::Result<()>{ #[inline(always)]
fn serialize(&self, writer: &mut impl ::std::io::Write) -> rnex_core::rmc::structures::Result<()>{
#serialize_base_content #serialize_base_content
} }
#[inline(always)]
fn deserialize(reader: &mut dyn ::std::io::Read) -> rnex_core::rmc::structures::Result<Self>{ fn deserialize(reader: &mut impl ::std::io::Read) -> rnex_core::rmc::structures::Result<Self>{
#deserialize_base_content #deserialize_base_content
} }
#write_size
} }
}; };

View file

@ -55,6 +55,7 @@ impl RmcProtocolData{
let raw_name = Ident::new(&format!("raw_{}", name), name.span()); let raw_name = Ident::new(&format!("raw_{}", name), name.span());
quote!{ quote!{
#[inline(always)]
async fn #raw_name async fn #raw_name
}.to_tokens(tokens); }.to_tokens(tokens);
@ -125,6 +126,7 @@ impl RmcProtocolData{
} }
quote!{ quote!{
#[inline(always)]
async fn rmc_call_proto( async fn rmc_call_proto(
&self, &self,
remote_response_connection: &rnex_core::util::SendingBufferConnection, remote_response_connection: &rnex_core::util::SendingBufferConnection,

View file

@ -31,7 +31,7 @@ async fn main() {
let conn: SplittableBufferConnection = conn.into(); let conn: SplittableBufferConnection = conn.into();
conn.send(Register(SocketAddrV4::new(*OWN_IP_PUBLIC, *SERVER_PORT)).to_data()).await; conn.send(Register(SocketAddrV4::new(*OWN_IP_PUBLIC, *SERVER_PORT)).to_data().unwrap()).await;
let conn = new_rmc_gateway_connection(conn, |r| Arc::new(OnlyRemote::<RemoteEdgeNodeHolder>::new(r))); let conn = new_rmc_gateway_connection(conn, |r| Arc::new(OnlyRemote::<RemoteEdgeNodeHolder>::new(r)));
@ -67,7 +67,7 @@ async fn main() {
if let Err(e) = stream.send_buffer(&ConnectionInitData{ if let Err(e) = stream.send_buffer(&ConnectionInitData{
prudpsock_addr: conn.socket_addr, prudpsock_addr: conn.socket_addr,
pid: conn.user_id pid: conn.user_id
}.to_data()).await{ }.to_data().unwrap()).await{
error!("error connecting to backend: {}", e); error!("error connecting to backend: {}", e);
return; return;
}; };

View file

@ -28,7 +28,7 @@ async fn main() {
let conn: SplittableBufferConnection = conn.into(); let conn: SplittableBufferConnection = conn.into();
conn.send(Register(SocketAddrV4::new(*OWN_IP_PUBLIC, *SERVER_PORT)).to_data()).await; conn.send(Register(SocketAddrV4::new(*OWN_IP_PUBLIC, *SERVER_PORT)).to_data().unwrap()).await;
let conn = new_rmc_gateway_connection(conn, |r| Arc::new(OnlyRemote::<RemoteEdgeNodeHolder>::new(r))); let conn = new_rmc_gateway_connection(conn, |r| Arc::new(OnlyRemote::<RemoteEdgeNodeHolder>::new(r)));
@ -67,7 +67,7 @@ async fn main() {
if let Err(e) = stream.send_buffer(&ConnectionInitData{ if let Err(e) = stream.send_buffer(&ConnectionInitData{
prudpsock_addr: conn.socket_addr, prudpsock_addr: conn.socket_addr,
pid: conn.user_id pid: conn.user_id
}.to_data()).await{ }.to_data().unwrap()).await{
error!("error connecting to backend: {}", e); error!("error connecting to backend: {}", e);
return; return;
}; };

View file

@ -29,9 +29,15 @@ typenum = "1.18.0"
reqwest = { version= "0.12.18", features = ["blocking"]} reqwest = { version= "0.12.18", features = ["blocking"]}
json = "0.12.4" json = "0.12.4"
ctrlc = "3.4.7" ctrlc = "3.4.7"
criterion = "0.7.0"
anyhow = "1.0.100"
[features]
rmc_struct_header = []
[[bench]]
name = "rmc_serialization"
harness = false
[[bin]] [[bin]]
name = "backend_server_insecure" name = "backend_server_insecure"

View file

@ -0,0 +1,99 @@
use std::hint::black_box;
use std::io::Cursor;
use std::ops::Deref;
use criterion::{criterion_group, criterion_main, Criterion};
use once_cell::sync::Lazy;
use rnex_core::kerberos::KerberosDateTime;
use rnex_core::rmc::structures::matchmake::{AutoMatchmakeParam, Gathering, MatchmakeParam, MatchmakeSession, MatchmakeSessionSearchCriteria};
use rnex_core::rmc::structures::RmcSerialize;
use rnex_core::rmc::structures::variant::Variant;
static DUMMY: Lazy<AutoMatchmakeParam> = Lazy::new(|| AutoMatchmakeParam{
additional_participants: vec![1,2,3,4],
auto_matchmake_option: 10,
gid_for_participation_check: 9,
join_message: "hi".to_string(),
participation_count: 32,
target_gids: vec![45,2,51,1,1,1,1],
search_criteria: vec![MatchmakeSessionSearchCriteria{
attribs: vec!["hi".to_string(), "ig".to_string(), "gotta put data here".to_string()],
exclude_locked: true,
exclude_non_host_pid: false,
exclude_system_password_set: true,
exclude_user_password_set: false,
game_mode: "some gamemode".to_string(),
matchmake_param: MatchmakeParam{
params: vec![
("SR".to_string(), Variant::Bool(true)),
("SR2".to_string(), Variant::Double(1.0)),
("SR3".to_string(), Variant::SInt64(42)),
("SR4".to_string(), Variant::String("test".to_string()))
]
},
matchmake_system_type: "some type".to_string(),
maximum_participants: "???".to_string(),
minimum_participants: "-99".to_string(),
refer_gid: 123,
selection_method: 9999999,
vacant_only: true,
vacant_participants: 1000
}],
matchmake_session: MatchmakeSession{
refer_gid: 10,
matchmake_system_type: 139,
matchmake_param: MatchmakeParam{
params: vec![
("QSR".to_string(), Variant::Bool(false)),
("SRQ2".to_string(), Variant::Double(1.1)),
("SQR3".to_string(), Variant::SInt64(422)),
("SDR4".to_string(), Variant::String("tetst".to_string()))
]
},
participation_count: 99,
application_buffer: vec![1,2,3,4,5,6,7,8,9],
attributes: vec![10,20,99,100000],
datetime: KerberosDateTime::now(),
gamemode: 111,
open_participation: false,
option0: 100,
progress_score: 1,
system_password_enabled: false,
user_password: "aaa".to_string(),
session_key: vec![91,123,5,2,1,2,4,124,4],
user_password_enabled: false,
gathering: Gathering{
minimum_participants: 1,
maximum_participants: 12,
description: "aaargh".to_string(),
flags: 100,
host_pid: 999999919,
owner_pid: 138830,
participant_policy: 1,
policy_argument: 99837,
self_gid: 129,
state: 1389488
}
}
});
static DUMMY_SER: Lazy<Vec<u8>> = Lazy::new(|| serialize_to_vec(DUMMY.deref()));
fn serialize_to_vec(r: &impl RmcSerialize) -> Vec<u8>{
let mut vec = r.to_data();
vec.unwrap()
}
fn read_struct<T: RmcSerialize>(r: &[u8]) -> T{
T::deserialize(&mut Cursor::new(r)).unwrap()
}
fn matchmake_with_param(c: &mut Criterion) {
let raw = DUMMY.deref();
let ser = DUMMY_SER.deref().as_slice();
c.bench_function("mmparam: ser", |b| b.iter(move || serialize_to_vec(black_box(raw))));
c.bench_function("mmparam: de", |b| b.iter(move || read_struct::<AutoMatchmakeParam>(black_box(ser))));
}
criterion_group!(benches, matchmake_with_param);
criterion_main!(benches);

View file

@ -30,7 +30,7 @@ async fn main() {
let conn: SplittableBufferConnection = conn.into(); let conn: SplittableBufferConnection = conn.into();
conn.send(DontRegister.to_data()).await; conn.send(DontRegister.to_data().unwrap()).await;
let conn = new_rmc_gateway_connection(conn, |r| Arc::new(OnlyRemote::<RemoteEdgeNodeHolder>::new(r))); let conn = new_rmc_gateway_connection(conn, |r| Arc::new(OnlyRemote::<RemoteEdgeNodeHolder>::new(r)));

View file

@ -83,11 +83,11 @@ impl KerberosDateTime{
} }
impl RmcSerialize for KerberosDateTime{ impl RmcSerialize for KerberosDateTime{
fn serialize(&self, writer: &mut dyn Write) -> crate::rmc::structures::Result<()> { fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> {
Ok(self.0.serialize(writer)?) Ok(self.0.serialize(writer)?)
} }
fn deserialize(reader: &mut dyn Read) -> crate::rmc::structures::Result<Self> { fn deserialize(reader: &mut impl Read) -> crate::rmc::structures::Result<Self> {
Ok(Self(u64::deserialize(reader)?)) Ok(Self(u64::deserialize(reader)?))
} }
} }

View file

@ -24,3 +24,7 @@ pub mod rnex_proxy_common;
pub mod util; pub mod util;
pub mod executables; pub mod executables;
pub use macros::*; pub use macros::*;
pub mod config{
pub const FEATURE_HAS_STRUCT_HEADER: bool = cfg!(feature = "rmc_struct_header");
}

View file

@ -20,6 +20,8 @@ use std::fs::File;
use std::net::{Ipv4Addr}; use std::net::{Ipv4Addr};
use std::sync::Once; use std::sync::Once;
use std::{env, fs}; use std::{env, fs};
use std::hint::black_box;
use criterion::{criterion_group, criterion_main, Criterion};
mod prudp; mod prudp;
pub mod rmc; pub mod rmc;
@ -35,360 +37,111 @@ pub mod reggie;
pub mod util; pub mod util;
pub mod common; pub mod common;
pub mod config{
pub const FEATURE_HAS_STRUCT_HEADER: bool = cfg!(feature = "rmc_struct_header");
static KERBEROS_SERVER_PASSWORD: Lazy<String> = Lazy::new(|| {
env::var("AUTH_SERVER_PASSWORD")
.ok()
.unwrap_or("password".to_owned())
});
static AUTH_SERVER_ACCOUNT: Lazy<Account> =
Lazy::new(|| Account::new(1, "Quazal Authentication", &KERBEROS_SERVER_PASSWORD));
static SECURE_SERVER_ACCOUNT: Lazy<Account> =
Lazy::new(|| Account::new(2, "Quazal Rendez-Vous", &KERBEROS_SERVER_PASSWORD));
static AUTH_SERVER_PORT: Lazy<u16> = Lazy::new(|| {
env::var("AUTH_SERVER_PORT")
.ok()
.and_then(|s| s.parse().ok())
.unwrap_or(10000)
});
static SECURE_SERVER_PORT: Lazy<u16> = Lazy::new(|| {
env::var("SECURE_SERVER_PORT")
.ok()
.and_then(|s| s.parse().ok())
.unwrap_or(10001)
});
static OWN_IP_PRIVATE: Lazy<Ipv4Addr> = Lazy::new(|| {
env::var("SERVER_IP")
.ok()
.and_then(|s| s.parse().ok())
.expect("no private ip specified")
});
static OWN_IP_PUBLIC: Lazy<String> =
Lazy::new(|| env::var("SERVER_IP_PUBLIC").unwrap_or(OWN_IP_PRIVATE.to_string()));
static SECURE_STATION_URL: Lazy<String> = Lazy::new(|| {
format!(
"prudps:/PID=2;sid=1;stream=10;type=2;address={};port={};CID=1",
*OWN_IP_PUBLIC, *SECURE_SERVER_PORT
)
});
static FORCE_EXIT: Once = Once::new();
#[tokio::main]
async fn main() {
CombinedLogger::init(vec![
TermLogger::new(
LevelFilter::Info,
Config::default(),
TerminalMode::Mixed,
ColorChoice::Auto,
),
WriteLogger::new(LevelFilter::max(), Config::default(), {
fs::create_dir_all("log").unwrap();
let date = Local::now().to_rfc3339_opts(SecondsFormat::Secs, false);
// this fixes windows being windows
let date = date.replace(":", "-");
let filename = format!("{}.log", date);
if cfg!(windows) {
File::create(format!("log\\{}", filename)).unwrap()
} else {
File::create(format!("log/{}", filename)).unwrap()
}
}),
])
.unwrap();
ctrlc::set_handler(||{
FORCE_EXIT.call_once_force(|_|{
println!("attempting exit");
});
}).unwrap();
dotenv::dotenv().ok();
//start_servers().await;
}
/*
struct AuthServer{
router: Arc<Router>,
join_handle: JoinHandle<()>,
socket: Socket
} }
async fn start_auth_server() -> AuthServer{ use std::io::Cursor;
info!("starting auth server on {}:{}", *OWN_IP_PRIVATE, *AUTH_SERVER_PORT); use std::ops::Deref;
use rnex_core::kerberos::KerberosDateTime;
use rnex_core::rmc::structures::matchmake::{AutoMatchmakeParam, Gathering, MatchmakeParam, MatchmakeSession, MatchmakeSessionSearchCriteria};
use rnex_core::rmc::structures::RmcSerialize;
use rnex_core::rmc::structures::variant::Variant;
let (router, join_handle) = static DUMMY: Lazy<AutoMatchmakeParam> = Lazy::new(|| AutoMatchmakeParam{
Router::new(SocketAddrV4::new(*OWN_IP_PRIVATE, *AUTH_SERVER_PORT)).await additional_participants: vec![1,2,3,4],
.expect("unable to startauth server"); auto_matchmake_option: 10,
gid_for_participation_check: 9,
join_message: "hi".to_string(),
participation_count: 32,
target_gids: vec![45,2,51,1,1,1,1],
search_criteria: vec![MatchmakeSessionSearchCriteria{
attribs: vec!["hi".to_string(), "ig".to_string(), "gotta put data here".to_string()],
exclude_locked: true,
exclude_non_host_pid: false,
exclude_system_password_set: true,
exclude_user_password_set: false,
game_mode: "some gamemode".to_string(),
matchmake_param: MatchmakeParam{
params: vec![
("SR".to_string(), Variant::Bool(true)),
("SR2".to_string(), Variant::Double(1.0)),
("SR3".to_string(), Variant::SInt64(42)),
("SR4".to_string(), Variant::String("test".to_string()))
]
},
matchmake_system_type: "some type".to_string(),
maximum_participants: "???".to_string(),
minimum_participants: "-99".to_string(),
refer_gid: 123,
selection_method: 9999999,
vacant_only: true,
vacant_participants: 1000
}],
matchmake_session: MatchmakeSession{
refer_gid: 10,
matchmake_system_type: 139,
matchmake_param: MatchmakeParam{
params: vec![
("QSR".to_string(), Variant::Bool(false)),
("SRQ2".to_string(), Variant::Double(1.1)),
("SQR3".to_string(), Variant::SInt64(422)),
("SDR4".to_string(), Variant::String("tetst".to_string()))
]
},
participation_count: 99,
application_buffer: vec![1,2,3,4,5,6,7,8,9],
attributes: vec![10,20,99,100000],
datetime: KerberosDateTime::now(),
gamemode: 111,
open_participation: false,
option0: 100,
progress_score: 1,
system_password_enabled: false,
user_password: "aaa".to_string(),
session_key: vec![91,123,5,2,1,2,4,124,4],
user_password_enabled: false,
gathering: Gathering{
minimum_participants: 1,
maximum_participants: 12,
description: "aaargh".to_string(),
flags: 100,
host_pid: 999999919,
owner_pid: 138830,
participant_policy: 1,
policy_argument: 99837,
self_gid: 129,
state: 1389488
}
}
});
info!("setting up endpoints"); static DUMMY_SER: Lazy<Vec<u8>> = Lazy::new(|| serialize_to_vec(DUMMY.deref()));
// dont assign it to the name _ as that will make it drop right here and now fn serialize_to_vec(r: &impl RmcSerialize) -> Vec<u8>{
let mut vec = r.to_data();
let auth_protocol_config = AuthProtocolConfig{ vec.unwrap()
secure_server_account: &SECURE_SERVER_ACCOUNT, }
build_name: "branch:origin/project/wup-agmj build:3_8_15_2004_0",
station_url: &SECURE_STATION_URL
};
let rmcserver = RMCProtocolServer::new(Box::new([ fn read_struct<T: RmcSerialize>(r: &[u8]) -> T{
Box::new(auth::bound_protocol(auth_protocol_config)) T::deserialize(&mut Cursor::new(r)).unwrap()
])); }
fn matchmake_with_param(c: &mut Criterion) {
let raw = DUMMY.deref();
let ser = DUMMY_SER.deref().as_slice();
c.bench_function("mmparam: ser", |b| b.iter(move || serialize_to_vec(black_box(raw))));
c.bench_function("mmparam: de", |b| b.iter(move || read_struct::<AutoMatchmakeParam>(black_box(ser))));
}
let socket = criterion_group!(benches, matchmake_with_param);
Socket::new( //criterion_main!(benches);
router.clone(),
VirtualPort::new(1,10),
"6f599f81",
Box::new(|_, count|{
Box::pin(
async move {
fn main(){
let encryption_pairs = Vec::from_iter((0..=count).map(|_v| { for _ in 0..10000000 {
let rc4: Rc4<U5> = Rc4::new_from_slice( "CD&ML".as_bytes()).unwrap(); let v = serialize_to_vec(black_box(DUMMY.deref()));
let cypher = Box::new(rc4); let u = read_struct::<AutoMatchmakeParam>(black_box(DUMMY_SER.deref().as_slice()));
let server_cypher: Box<dyn StreamCipher + Send> = cypher; black_box(v);
black_box(u);
let rc4: Rc4<U5> = Rc4::new_from_slice( "CD&ML".as_bytes()).unwrap();
let cypher = Box::new(rc4);
let client_cypher: Box<dyn StreamCipher + Send> = cypher;
EncryptionPair{
recv: client_cypher,
send: server_cypher
}
}));
Some((Vec::new(), encryption_pairs, None))
}
)
}),
Box::new(move |packet, socket, connection|{
let rmcserver = rmcserver.clone();
Box::pin(async move { rmcserver.process_message(packet, socket, connection).await; })
})
).await.expect("unable to create socket");
AuthServer{
join_handle,
router,
socket,
} }
} }
struct SecureServer{
router: Arc<Router>,
join_handle: JoinHandle<()>,
socket: Socket
}
async fn start_secure_server() -> SecureServer{
info!("starting secure server on {}:{}", *OWN_IP_PRIVATE, *SECURE_SERVER_PORT);
let (router, join_handle) =
Router::new(SocketAddrV4::new(*OWN_IP_PRIVATE, *SECURE_SERVER_PORT)).await
.expect("unable to startauth server");
info!("setting up endpoints");
let matchmake_data = Arc::new(RwLock::new(
MatchmakeData{
matchmake_sessions: BTreeMap::new()
}
));
let rmcserver = RMCProtocolServer::new(Box::new([
Box::new(block_if_maintenance),
Box::new(protocols::secure::bound_protocol()),
Box::new(protocols::matchmake::bound_protocol(matchmake_data.clone())),
Box::new(protocols::matchmake_extension::bound_protocol(matchmake_data)),
Box::new(protocols::nat_traversal::bound_protocol())
]));
let socket =
Socket::new(
router.clone(),
VirtualPort::new(1,10),
"6f599f81",
Box::new(|p, count|{
Box::pin(
async move {
let (session_key, pid, check_value) = read_secure_connection_data(&p.payload, &SECURE_SERVER_ACCOUNT)?;
let check_value_response = check_value + 1;
let data = bytemuck::bytes_of(&check_value_response);
let mut response = Vec::new();
data.serialize(&mut response).ok()?;
let encryption_pairs = generate_secure_encryption_pairs(session_key, count);
Some((response, encryption_pairs, Some(
ActiveSecureConnectionData{
pid,
session_key
}
)))
}
)
}),
Box::new(move |packet, socket, connection|{
let rmcserver = rmcserver.clone();
Box::pin(async move { rmcserver.process_message(packet, socket, connection).await; })
})
).await.expect("unable to create socket");
SecureServer{
join_handle,
router,
socket,
}
}*/
/*
async fn start_auth() -> JoinHandle<()> {
tokio::spawn(async {
let (router_secure, _) = Router::new(SocketAddrV4::new(*OWN_IP_PRIVATE, *AUTH_SERVER_PORT))
.await
.expect("unable to start router");
let mut socket_secure = router_secure
.add_socket(VirtualPort::new(1, 10), Unsecure(
"6f599f81"
))
.await
.expect("unable to add socket");
// let conn = socket_secure.connect(auth_sockaddr).await.unwrap();
while !FORCE_EXIT.is_completed() {
let Some(conn) = socket_secure.accept().await else {
error!("server crashed");
return;
};
info!("new connected user!");
let _ = new_rmc_gateway_connection(conn, |_| {
Arc::new(AuthHandler {
destination_server_acct: &SECURE_SERVER_ACCOUNT,
build_name: "branch:origin/project/wup-agmj build:3_8_15_2004_0",
station_url: &SECURE_STATION_URL,
})
});
}
})
}
async fn start_secure() -> JoinHandle<()> {
tokio::spawn(async {
let mmm = Arc::new(MatchmakeManager{
gid_counter: AtomicU32::new(1),
sessions: Default::default(),
users: Default::default(),
rv_cid_counter: AtomicU32::new(1),
});
let weak_mmm = Arc::downgrade(&mmm);
MatchmakeManager::initialize_garbage_collect_thread(weak_mmm).await;
let web_server = web::start_web(mmm.clone()).await;
let (router_secure, _) =
Router::new(SocketAddrV4::new(*OWN_IP_PRIVATE, *SECURE_SERVER_PORT))
.await
.expect("unable to start router");
let mut socket_secure = router_secure
.add_socket(
VirtualPort::new(1, 10),
Secure(
"6f599f81",
&SECURE_SERVER_ACCOUNT
),
)
.await
.expect("unable to add socket");
// let conn = socket_secure.connect(auth_sockaddr).await.unwrap();
while !FORCE_EXIT.is_completed() {
let Some(conn) = socket_secure.accept().await else {
error!("server crashed");
return;
};
info!("new connected user on secure :D!");
let ip = conn.socket_addr;
let pid = conn.user_id;
let _ = new_rmc_gateway_connection(conn, |r| {
Arc::new_cyclic(|w| User {
ip,
pid,
this: w.clone(),
remote: RemoteConsole::new(r),
station_url: Default::default(),
matchmake_manager: mmm.clone()
})
});
}
})
}
async fn start_test() {
let addr = SocketAddrV4::new(*OWN_IP_PRIVATE, *SECURE_SERVER_PORT);
let virt_addr = VirtualPort::new(1, 10);
let prudp_addr = PRUDPSockAddr::new(addr, virt_addr);
let (router_test, _) = Router::new(SocketAddrV4::new(*OWN_IP_PRIVATE, 26969))
.await
.expect("unable to start router");
let mut socket_secure = router_test
.add_socket(VirtualPort::new(1, 10), Unsecure("6f599f81"))
.await
.expect("unable to add socket");
let conn = socket_secure.connect(prudp_addr).await.unwrap();
let remote = new_rmc_gateway_connection(conn, |r| {
Arc::new(OnlyRemote::<RemoteUserProtocol>::new(r))
});
tokio::time::sleep(Duration::from_secs(1)).await;
let urls = vec!["prudp:/address=192.168.178.45;port=60146;Pl=2;natf=0;natm=0;pmp=0;sid=15;upnp=0".to_owned()];
}
async fn start_servers() {
#[cfg(feature = "auth")]
let auth_server = start_auth().await;
#[cfg(feature = "secure")]
let secure_server = start_secure().await;
tokio::time::sleep(Duration::from_secs(1)).await;
//start_test().await;
#[cfg(feature = "auth")]
auth_server.await.expect("auth server crashed");
#[cfg(feature = "secure")]
secure_server.await.expect("auth server crashed");
}
*/

View file

@ -163,6 +163,8 @@ mod test {
use rnex_core::rmc::response::RMCResponse; use rnex_core::rmc::response::RMCResponse;
use std::io::Cursor; use std::io::Cursor;
#[test] #[test]
fn test() { fn test() {

View file

@ -5,6 +5,7 @@ use std::io::Read;
use crate::prudp::station_url::Type::{PRUDP, PRUDPS, UDP}; use crate::prudp::station_url::Type::{PRUDP, PRUDPS, UDP};
use crate::prudp::station_url::UrlOptions::{Address, ConnectionID, NatFiltering, NatMapping, NatType, Platform, PMP, Port, PrincipalID, RVConnectionID, StreamID, StreamType, UPNP, PID}; use crate::prudp::station_url::UrlOptions::{Address, ConnectionID, NatFiltering, NatMapping, NatType, Platform, PMP, Port, PrincipalID, RVConnectionID, StreamID, StreamType, UPNP, PID};
use crate::rmc::structures::Error::StationUrlInvalid; use crate::rmc::structures::Error::StationUrlInvalid;
use crate::rmc::structures::helpers::DummyFormatWriter;
use crate::rmc::structures::RmcSerialize; use crate::rmc::structures::RmcSerialize;
#[derive(Clone, Copy, PartialEq, Eq)] #[derive(Clone, Copy, PartialEq, Eq)]
pub enum Type{ pub enum Type{
@ -135,59 +136,66 @@ impl TryFrom<&str> for StationUrl{
} }
} }
impl<'a> Into<String> for &'a StationUrl{ impl Display for StationUrl{
fn into(self) -> String { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let mut url = match self.url_type{ let url_type_str = match self.url_type{
UDP => "udp:/", UDP => "udp:/",
PRUDP => "prudp:/", PRUDP => "prudp:/",
PRUDPS => "prudps:/" PRUDPS => "prudps:/"
}.to_owned(); };
write!(f, "{}",url_type_str)?;
for option in &self.options{ for option in &self.options{
match option{ match option{
Address(v) => write!(url, "address={}", v).expect("failed to write"), Address(v) => write!(f, "address={}", v)?,
Port(v) => write!(url, "port={}", v).expect("failed to write"), Port(v) => write!(f, "port={}", v)?,
StreamType(v) => write!(url, "stream={}", v).expect("failed to write"), StreamType(v) => write!(f, "stream={}", v)?,
StreamID(v) => write!(url, "sid={}", v).expect("failed to write"), StreamID(v) => write!(f, "sid={}", v)?,
ConnectionID(v) => write!(url, "CID={}", v).expect("failed to write"), ConnectionID(v) => write!(f, "CID={}", v)?,
PrincipalID(v) => write!(url, "PID={}", v).expect("failed to write"), PrincipalID(v) => write!(f, "PID={}", v)?,
NatType(v) => write!(url, "type={}", v).expect("failed to write"), NatType(v) => write!(f, "type={}", v)?,
NatMapping(v) => write!(url, "natm={}", v).expect("failed to write"), NatMapping(v) => write!(f, "natm={}", v)?,
NatFiltering(v) => write!(url, "natf={}", v).expect("failed to write"), NatFiltering(v) => write!(f, "natf={}", v)?,
UPNP(v) => write!(url, "upnp={}", v).expect("failed to write"), UPNP(v) => write!(f, "upnp={}", v)?,
RVConnectionID(v) => write!(url, "RVCID={}", v).expect("failed to write"), RVConnectionID(v) => write!(f, "RVCID={}", v)?,
Platform(v) => write!(url, "pl={}", v).expect("failed to write"), Platform(v) => write!(f, "pl={}", v)?,
PMP(v) => write!(url, "pmp={}", v).expect("failed to write"), PMP(v) => write!(f, "pmp={}", v)?,
PID(v) => write!(url, "PID={}", v).expect("failed to write"), PID(v) => write!(f, "PID={}", v)?,
} }
write!(url, ";").expect("failed to write"); write!(f, ";")?;
} }
Ok(())
}
}
impl<'a> Into<String> for &'a StationUrl{
fn into(self) -> String {
let mut url = self.to_string();
url[0..url.len()-1].into() url[0..url.len()-1].into()
} }
} }
impl Display for StationUrl{
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let str: String = self.into();
write!(f, "{}", str)
}
}
impl RmcSerialize for StationUrl{ impl RmcSerialize for StationUrl{
fn deserialize(reader: &mut dyn Read) -> crate::rmc::structures::Result<Self> { fn deserialize(reader: &mut impl Read) -> crate::rmc::structures::Result<Self> {
let str = String::deserialize(reader)?; let str = String::deserialize(reader)?;
Self::try_from(str.as_str()).map_err(|_| StationUrlInvalid) Self::try_from(str.as_str()).map_err(|_| StationUrlInvalid)
} }
fn serialize(&self, writer: &mut dyn std::io::Write) -> crate::rmc::structures::Result<()> { fn serialize(&self, writer: &mut impl std::io::Write) -> crate::rmc::structures::Result<()> {
let str: String = self.into(); let str: String = self.into();
str.serialize(writer) str.serialize(writer)
} }
fn serialize_write_size(&self) -> crate::rmc::structures::Result<u32> {
let mut dummy = DummyFormatWriter::new();
write!(&mut dummy, "{}", self)?;
Ok(dummy.serialize_str_len())
}
} }
impl Debug for StationUrl{ impl Debug for StationUrl{

View file

@ -9,7 +9,7 @@ pub struct Any{
} }
impl RmcSerialize for Any{ impl RmcSerialize for Any{
fn serialize(&self, writer: &mut dyn Write) -> Result<()> { fn serialize(&self, writer: &mut impl Write) -> Result<()> {
self.name.serialize(writer)?; self.name.serialize(writer)?;
let u32_len = self.data.len() as u32; let u32_len = self.data.len() as u32;
@ -21,7 +21,7 @@ impl RmcSerialize for Any{
Ok(()) Ok(())
} }
fn deserialize(mut reader: &mut dyn Read) -> Result<Self> { fn deserialize(mut reader: &mut impl Read) -> Result<Self> {
let name = String::deserialize(reader)?; let name = String::deserialize(reader)?;
// also length ? // also length ?

View file

@ -4,7 +4,7 @@ use crate::rmc::structures::RmcSerialize;
impl<'a> RmcSerialize for &'a [u8]{ impl<'a> RmcSerialize for &'a [u8]{
fn serialize(&self, writer: &mut dyn Write) -> crate::rmc::structures::Result<()> { fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> {
let u32_size = self.len() as u32; let u32_size = self.len() as u32;
writer.write(bytemuck::bytes_of(&u32_size))?; writer.write(bytemuck::bytes_of(&u32_size))?;
writer.write(self)?; writer.write(self)?;
@ -13,17 +13,25 @@ impl<'a> RmcSerialize for &'a [u8]{
} }
/// DO NOT USE (also maybe split off the serialize and deserialize functions at some point) /// DO NOT USE (also maybe split off the serialize and deserialize functions at some point)
fn deserialize(_reader: &mut dyn Read) -> crate::rmc::structures::Result<Self> { fn deserialize(_reader: &mut impl Read) -> crate::rmc::structures::Result<Self> {
panic!("cannot deserialize to a u8 slice reference (use this ONLY for writing)") panic!("cannot deserialize to a u8 slice reference (use this ONLY for writing)")
} }
fn serialize_write_size(&self) -> crate::rmc::structures::Result<u32> {
Ok(4 + self.len() as u32)
}
} }
impl RmcSerialize for Box<[u8]>{ impl RmcSerialize for Box<[u8]>{
fn serialize(&self, writer: &mut dyn Write) -> crate::rmc::structures::Result<()> { fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> {
(&self[..]).serialize(writer) (&self[..]).serialize(writer)
} }
fn deserialize(reader: &mut dyn Read) -> crate::rmc::structures::Result<Self> { fn deserialize(reader: &mut impl Read) -> crate::rmc::structures::Result<Self> {
Vec::deserialize(reader).map(|v| v.into_boxed_slice()) Vec::deserialize(reader).map(|v| v.into_boxed_slice())
} }
fn serialize_write_size(&self) -> crate::rmc::structures::Result<u32> {
(&self[..]).serialize_write_size()
}
} }

View file

@ -0,0 +1,48 @@
use std::{fmt, io};
pub struct DummyFormatWriter(u32);
impl fmt::Write for DummyFormatWriter{
fn write_str(&mut self, s: &str) -> fmt::Result {
self.0 += s.as_bytes().len() as u32;
Ok(())
}
}
impl DummyFormatWriter{
pub const fn new() -> Self{ Self(0) }
pub const fn serialize_str_len(&self) -> u32 {
2 + self.0 + 1
}
}
pub struct DummyWriter(u32);
impl io::Write for DummyWriter{
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.0 += buf.len() as u32;
Ok(buf.len())
}
fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
self.0 += buf.len() as u32;
Ok(())
}
fn flush(&mut self) -> io::Result<()> {
Ok(())
}
}
impl DummyWriter{
pub const fn new() -> Self{ Self(0) }
pub const fn get_total_len(&self) -> u32{
self.0
}
}
pub fn len_of_write(f: impl FnOnce(&mut DummyWriter) -> anyhow::Result<()>) -> u32{
let mut dummy = DummyWriter::new();
f(&mut dummy).ok();
dummy.get_total_len()
}

View file

@ -9,7 +9,7 @@ use crate::rmc::structures::RmcSerialize;
// this is also for implementing `Buffer` this is tecnically not the same as its handled internaly // this is also for implementing `Buffer` this is tecnically not the same as its handled internaly
// probably but as it has the same mapping it doesn't matter and simplifies things // probably but as it has the same mapping it doesn't matter and simplifies things
impl<T: RmcSerialize> RmcSerialize for Vec<T>{ impl<T: RmcSerialize> RmcSerialize for Vec<T>{
fn serialize(&self, writer: &mut dyn Write) -> crate::rmc::structures::Result<()> { fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> {
let u32_len = self.len() as u32; let u32_len = self.len() as u32;
writer.write_all(bytes_of(&u32_len))?; writer.write_all(bytes_of(&u32_len))?;
@ -20,21 +20,27 @@ impl<T: RmcSerialize> RmcSerialize for Vec<T>{
Ok(()) Ok(())
} }
fn deserialize(mut reader: &mut dyn Read) -> crate::rmc::structures::Result<Self> { fn deserialize(mut reader: &mut impl Read) -> crate::rmc::structures::Result<Self> {
let len: u32 = reader.read_struct(IS_BIG_ENDIAN)?; let len: u32 = reader.read_struct(IS_BIG_ENDIAN)?;
let mut vec = Vec::with_capacity(len as usize); //let mut vec = Vec::with_capacity(len as usize);
for _ in 0..len{ let vec = (0..len).map(|_| T::deserialize(reader)).collect::<Result<Vec<_>, _>>()?;
vec.push(T::deserialize(reader)?);
}
Ok(vec) Ok(vec)
} }
fn serialize_write_size(&self) -> crate::rmc::structures::Result<u32> {
let mut val = 0u32;
for i in self{
val += i.serialize_write_size()?;
}
Ok(4 + val)
}
} }
impl<const LEN: usize, T: RmcSerialize> RmcSerialize for [T; LEN]{ impl<const LEN: usize, T: RmcSerialize> RmcSerialize for [T; LEN]{
fn serialize(&self, writer: &mut dyn Write) -> crate::rmc::structures::Result<()> { fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> {
for i in 0..LEN{ for i in 0..LEN{
self[i].serialize(writer)?; self[i].serialize(writer)?;
} }
@ -42,7 +48,7 @@ impl<const LEN: usize, T: RmcSerialize> RmcSerialize for [T; LEN]{
Ok(()) Ok(())
} }
fn deserialize(reader: &mut dyn Read) -> crate::rmc::structures::Result<Self> { fn deserialize(reader: &mut impl Read) -> crate::rmc::structures::Result<Self> {
let mut arr = [const { MaybeUninit::<T>::uninit() }; LEN]; let mut arr = [const { MaybeUninit::<T>::uninit() }; LEN];
for i in 0..LEN{ for i in 0..LEN{
@ -55,4 +61,12 @@ impl<const LEN: usize, T: RmcSerialize> RmcSerialize for [T; LEN]{
Ok(arr) Ok(arr)
} }
#[inline(always)]
fn serialize_write_size(&self) -> crate::rmc::structures::Result<u32> {
let mut val = 0u32;
for i in self{
val += i.serialize_write_size()?;
}
Ok(val)
}
} }

View file

@ -1,8 +1,8 @@
use std::io; use std::{fmt, io};
use std::io::{Read, Write}; use std::io::{Read, Write};
use std::string::FromUtf8Error; use std::string::FromUtf8Error;
use thiserror::Error; use thiserror::Error;
use crate::rmc::structures::helpers::DummyWriter;
//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
#[derive(Error, Debug)] #[derive(Error, Debug)]
@ -16,7 +16,9 @@ pub enum Error{
#[error("version mismatch: {0}")] #[error("version mismatch: {0}")]
VersionMismatch(u8), VersionMismatch(u8),
#[error("an error occurred reading the station url")] #[error("an error occurred reading the station url")]
StationUrlInvalid StationUrlInvalid,
#[error("error formatting text: {0}")]
FormatError(#[from] fmt::Error)
} }
pub type Result<T> = std::result::Result<T, Error>; pub type Result<T> = std::result::Result<T, Error>;
@ -33,28 +35,43 @@ pub mod primitives;
pub mod matchmake; pub mod matchmake;
pub mod variant; pub mod variant;
pub mod ranking; pub mod ranking;
mod networking; pub mod networking;
pub mod helpers;
pub trait RmcSerialize{ pub trait RmcSerialize{
fn serialize(&self, writer: &mut dyn Write) -> Result<()>; fn serialize(&self, writer: &mut impl Write) -> Result<()>;
fn deserialize(reader: &mut dyn Read) -> Result<Self> where Self: Sized; fn serialize_write_size(&self) -> Result<u32>{
let mut dummy = DummyWriter::new();
fn to_data(&self) -> Vec<u8>{ self.serialize(&mut dummy)?;
let mut data = Vec::new();
self.serialize(&mut data).expect("out of memory or something"); Ok(dummy.get_total_len())
}
fn deserialize(reader: &mut impl Read) -> Result<Self> where Self: Sized;
data fn to_data(&self) -> Result<Vec<u8>>{
let mut data = Vec::with_capacity(
self.serialize_write_size()? as usize
);
self.serialize(&mut data)?;
debug_assert_eq!(self.serialize_write_size().unwrap(), data.len() as u32);
Ok(data)
} }
} }
impl RmcSerialize for (){ impl RmcSerialize for (){
fn serialize(&self, _writer: &mut dyn Write) -> Result<()> { fn serialize(&self, _writer: &mut impl Write) -> Result<()> {
Ok(()) Ok(())
} }
fn deserialize(_reader: &mut dyn Read) -> Result<Self> { fn deserialize(_reader: &mut impl Read) -> Result<Self> {
Ok(()) Ok(())
} }
fn serialize_write_size(&self) -> Result<u32> {
Ok(0)
}
} }

View file

@ -4,30 +4,36 @@ use rnex_core::prudp::virtual_port::VirtualPort;
use crate::rmc::structures::RmcSerialize; use crate::rmc::structures::RmcSerialize;
impl RmcSerialize for SocketAddrV4{ impl RmcSerialize for SocketAddrV4{
fn serialize(&self, writer: &mut dyn Write) -> crate::rmc::structures::Result<()> { fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> {
self.ip().to_bits().serialize(writer)?; self.ip().to_bits().serialize(writer)?;
self.port().serialize(writer)?; self.port().serialize(writer)?;
Ok(()) Ok(())
} }
fn deserialize(reader: &mut dyn Read) -> crate::rmc::structures::Result<Self> { fn deserialize(reader: &mut impl Read) -> crate::rmc::structures::Result<Self> {
let ip = u32::deserialize(reader)?; let ip = u32::deserialize(reader)?;
let port = u16::deserialize(reader)?; let port = u16::deserialize(reader)?;
Ok(SocketAddrV4::new(Ipv4Addr::from_bits(ip), port)) Ok(SocketAddrV4::new(Ipv4Addr::from_bits(ip), port))
} }
fn serialize_write_size(&self) -> crate::rmc::structures::Result<u32> {
Ok(6)
}
} }
impl RmcSerialize for VirtualPort{ impl RmcSerialize for VirtualPort{
fn serialize(&self, writer: &mut dyn Write) -> crate::rmc::structures::Result<()> { fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> {
self.0.serialize(writer)?; self.0.serialize(writer)?;
Ok(()) Ok(())
} }
fn deserialize(reader: &mut dyn Read) -> crate::rmc::structures::Result<Self> { fn deserialize(reader: &mut impl Read) -> crate::rmc::structures::Result<Self> {
Ok(Self(u8::deserialize(reader)?)) Ok(Self(u8::deserialize(reader)?))
} }
fn serialize_write_size(&self) -> crate::rmc::structures::Result<u32> {
Ok(1)
}
} }

View file

@ -4,97 +4,146 @@ use v_byte_helpers::{IS_BIG_ENDIAN, ReadExtensions};
use crate::rmc::structures::RmcSerialize; use crate::rmc::structures::RmcSerialize;
impl RmcSerialize for u8{ impl RmcSerialize for u8{
fn serialize(&self, writer: &mut dyn Write) -> crate::rmc::structures::Result<()> { #[inline(always)]
fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> {
Ok(writer.write_all(bytes_of(self))?) Ok(writer.write_all(bytes_of(self))?)
} }
fn deserialize(mut reader: &mut dyn Read) -> crate::rmc::structures::Result<Self> { #[inline(always)]
fn deserialize(mut reader: &mut impl Read) -> crate::rmc::structures::Result<Self> {
Ok(reader.read_struct(IS_BIG_ENDIAN)?) Ok(reader.read_struct(IS_BIG_ENDIAN)?)
} }
#[inline(always)]
fn serialize_write_size(&self) -> crate::rmc::structures::Result<u32> {
Ok(1)
}
} }
impl RmcSerialize for i8{ impl RmcSerialize for i8{
fn serialize(&self, writer: &mut dyn Write) -> crate::rmc::structures::Result<()> { #[inline(always)]
fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> {
Ok(writer.write_all(bytes_of(self))?) Ok(writer.write_all(bytes_of(self))?)
} }
fn deserialize(mut reader: &mut dyn Read) -> crate::rmc::structures::Result<Self> { #[inline(always)]
fn deserialize(mut reader: &mut impl Read) -> crate::rmc::structures::Result<Self> {
Ok(reader.read_struct(IS_BIG_ENDIAN)?) Ok(reader.read_struct(IS_BIG_ENDIAN)?)
} }
#[inline(always)]
fn serialize_write_size(&self) -> crate::rmc::structures::Result<u32> {
Ok(1)
}
} }
impl RmcSerialize for u16{ impl RmcSerialize for u16{
fn serialize(&self, writer: &mut dyn Write) -> crate::rmc::structures::Result<()> { #[inline(always)]
fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> {
Ok(writer.write_all(bytes_of(self))?) Ok(writer.write_all(bytes_of(self))?)
} }
#[inline(always)]
fn deserialize(mut reader: &mut dyn Read) -> crate::rmc::structures::Result<Self> { fn deserialize(mut reader: &mut impl Read) -> crate::rmc::structures::Result<Self> {
Ok(reader.read_struct(IS_BIG_ENDIAN)?) Ok(reader.read_struct(IS_BIG_ENDIAN)?)
} }
#[inline(always)]
fn serialize_write_size(&self) -> crate::rmc::structures::Result<u32> {
Ok(2)
}
} }
impl RmcSerialize for i16{ impl RmcSerialize for i16{
fn serialize(&self, writer: &mut dyn Write) -> crate::rmc::structures::Result<()> { #[inline(always)]
fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> {
Ok(writer.write_all(bytes_of(self))?) Ok(writer.write_all(bytes_of(self))?)
} }
#[inline(always)]
fn deserialize(mut reader: &mut dyn Read) -> crate::rmc::structures::Result<Self> { fn deserialize(mut reader: &mut impl Read) -> crate::rmc::structures::Result<Self> {
Ok(reader.read_struct(IS_BIG_ENDIAN)?) Ok(reader.read_struct(IS_BIG_ENDIAN)?)
} }
#[inline(always)]
fn serialize_write_size(&self) -> crate::rmc::structures::Result<u32> {
Ok(2)
}
} }
impl RmcSerialize for u32{ impl RmcSerialize for u32{
fn serialize(&self, writer: &mut dyn Write) -> crate::rmc::structures::Result<()> { #[inline(always)]
fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> {
Ok(writer.write_all(bytes_of(self))?) Ok(writer.write_all(bytes_of(self))?)
} }
#[inline(always)]
fn deserialize(mut reader: &mut dyn Read) -> crate::rmc::structures::Result<Self> { fn deserialize(mut reader: &mut impl Read) -> crate::rmc::structures::Result<Self> {
Ok(reader.read_struct(IS_BIG_ENDIAN)?) Ok(reader.read_struct(IS_BIG_ENDIAN)?)
} }
#[inline(always)]
fn serialize_write_size(&self) -> crate::rmc::structures::Result<u32> {
Ok(4)
}
} }
impl RmcSerialize for i32{ impl RmcSerialize for i32{
fn serialize(&self, writer: &mut dyn Write) -> crate::rmc::structures::Result<()> { #[inline(always)]
fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> {
Ok(writer.write_all(bytes_of(self))?) Ok(writer.write_all(bytes_of(self))?)
} }
#[inline(always)]
fn deserialize(mut reader: &mut dyn Read) -> crate::rmc::structures::Result<Self> { fn deserialize(mut reader: &mut impl Read) -> crate::rmc::structures::Result<Self> {
Ok(reader.read_struct(IS_BIG_ENDIAN)?) Ok(reader.read_struct(IS_BIG_ENDIAN)?)
} }
#[inline(always)]
fn serialize_write_size(&self) -> crate::rmc::structures::Result<u32> {
Ok(4)
}
} }
impl RmcSerialize for u64{ impl RmcSerialize for u64{
fn serialize(&self, writer: &mut dyn Write) -> crate::rmc::structures::Result<()> { #[inline(always)]
fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> {
Ok(writer.write_all(bytes_of(self))?) Ok(writer.write_all(bytes_of(self))?)
} }
#[inline(always)]
fn deserialize(mut reader: &mut dyn Read) -> crate::rmc::structures::Result<Self> { fn deserialize(mut reader: &mut impl Read) -> crate::rmc::structures::Result<Self> {
Ok(reader.read_struct(IS_BIG_ENDIAN)?) Ok(reader.read_struct(IS_BIG_ENDIAN)?)
} }
#[inline(always)]
fn serialize_write_size(&self) -> crate::rmc::structures::Result<u32> {
Ok(8)
}
} }
impl RmcSerialize for i64{ impl RmcSerialize for i64{
fn serialize(&self, writer: &mut dyn Write) -> crate::rmc::structures::Result<()> { #[inline(always)]
fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> {
Ok(writer.write_all(bytes_of(self))?) Ok(writer.write_all(bytes_of(self))?)
} }
#[inline(always)]
fn deserialize(mut reader: &mut dyn Read) -> crate::rmc::structures::Result<Self> { fn deserialize(mut reader: &mut impl Read) -> crate::rmc::structures::Result<Self> {
Ok(reader.read_struct(IS_BIG_ENDIAN)?) Ok(reader.read_struct(IS_BIG_ENDIAN)?)
} }
#[inline(always)]
fn serialize_write_size(&self) -> crate::rmc::structures::Result<u32> {
Ok(8)
}
} }
impl RmcSerialize for f64{ impl RmcSerialize for f64{
fn serialize(&self, writer: &mut dyn Write) -> crate::rmc::structures::Result<()> { #[inline(always)]
fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> {
Ok(writer.write_all(bytes_of(self))?) Ok(writer.write_all(bytes_of(self))?)
} }
fn deserialize(mut reader: &mut dyn Read) -> crate::rmc::structures::Result<Self> { #[inline(always)]
fn deserialize(mut reader: &mut impl Read) -> crate::rmc::structures::Result<Self> {
Ok(reader.read_struct(IS_BIG_ENDIAN)?) Ok(reader.read_struct(IS_BIG_ENDIAN)?)
} }
#[inline(always)]
fn serialize_write_size(&self) -> crate::rmc::structures::Result<u32> {
Ok(8)
}
} }
impl RmcSerialize for bool{ impl RmcSerialize for bool{
fn serialize(&self, writer: &mut dyn Write) -> crate::rmc::structures::Result<()> { #[inline(always)]
fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> {
match self{ match self{
true => writer.write_all(&[1])?, true => writer.write_all(&[1])?,
false => writer.write_all(&[0])?, false => writer.write_all(&[0])?,
@ -102,54 +151,77 @@ impl RmcSerialize for bool{
Ok(()) Ok(())
} }
fn deserialize(reader: &mut dyn Read) -> crate::rmc::structures::Result<Self> { #[inline(always)]
fn deserialize(reader: &mut impl Read) -> crate::rmc::structures::Result<Self> {
Ok(u8::deserialize(reader)? != 0) Ok(u8::deserialize(reader)? != 0)
} }
#[inline(always)]
fn serialize_write_size(&self) -> crate::rmc::structures::Result<u32> {
Ok(1)
}
} }
impl<T: RmcSerialize, U: RmcSerialize> RmcSerialize for (T, U){ impl<T: RmcSerialize, U: RmcSerialize> RmcSerialize for (T, U){
fn serialize(&self, writer: &mut dyn Write) -> crate::rmc::structures::Result<()> { #[inline(always)]
fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> {
self.0.serialize(writer)?; self.0.serialize(writer)?;
self.1.serialize(writer)?; self.1.serialize(writer)?;
Ok(()) Ok(())
} }
#[inline(always)]
fn deserialize(reader: &mut dyn Read) -> crate::rmc::structures::Result<Self> { fn deserialize(reader: &mut impl Read) -> crate::rmc::structures::Result<Self> {
let first = T::deserialize(reader)?; let first = T::deserialize(reader)?;
let second = U::deserialize(reader)?; let second = U::deserialize(reader)?;
Ok((first, second)) Ok((first, second))
} }
#[inline(always)]
fn serialize_write_size(&self) -> crate::rmc::structures::Result<u32> {
Ok(
self.0.serialize_write_size()? +
self.1.serialize_write_size()?
)
}
} }
impl<T: RmcSerialize, U: RmcSerialize, V: RmcSerialize> RmcSerialize for (T, U, V){ impl<T: RmcSerialize, U: RmcSerialize, V: RmcSerialize> RmcSerialize for (T, U, V){
fn serialize(&self, writer: &mut dyn Write) -> crate::rmc::structures::Result<()> { #[inline(always)]
fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> {
self.0.serialize(writer)?; self.0.serialize(writer)?;
self.1.serialize(writer)?; self.1.serialize(writer)?;
self.2.serialize(writer)?; self.2.serialize(writer)?;
Ok(()) Ok(())
} }
#[inline(always)]
fn deserialize(reader: &mut dyn Read) -> crate::rmc::structures::Result<Self> { fn deserialize(reader: &mut impl Read) -> crate::rmc::structures::Result<Self> {
let first = T::deserialize(reader)?; let first = T::deserialize(reader)?;
let second = U::deserialize(reader)?; let second = U::deserialize(reader)?;
let third = V::deserialize(reader)?; let third = V::deserialize(reader)?;
Ok((first, second, third)) Ok((first, second, third))
} }
#[inline(always)]
fn serialize_write_size(&self) -> crate::rmc::structures::Result<u32> {
Ok(
self.0.serialize_write_size()? +
self.1.serialize_write_size()? +
self.2.serialize_write_size()?
)
}
} }
impl<T: RmcSerialize, U: RmcSerialize, V: RmcSerialize, W: RmcSerialize> RmcSerialize for (T, U, V, W){ impl<T: RmcSerialize, U: RmcSerialize, V: RmcSerialize, W: RmcSerialize> RmcSerialize for (T, U, V, W){
fn serialize(&self, writer: &mut dyn Write) -> crate::rmc::structures::Result<()> { #[inline(always)]
fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> {
self.0.serialize(writer)?; self.0.serialize(writer)?;
self.1.serialize(writer)?; self.1.serialize(writer)?;
self.2.serialize(writer)?; self.2.serialize(writer)?;
self.3.serialize(writer)?; self.3.serialize(writer)?;
Ok(()) Ok(())
} }
#[inline(always)]
fn deserialize(reader: &mut dyn Read) -> crate::rmc::structures::Result<Self> { fn deserialize(reader: &mut impl Read) -> crate::rmc::structures::Result<Self> {
let first = T::deserialize(reader)?; let first = T::deserialize(reader)?;
let second = U::deserialize(reader)?; let second = U::deserialize(reader)?;
let third = V::deserialize(reader)?; let third = V::deserialize(reader)?;
@ -157,10 +229,20 @@ impl<T: RmcSerialize, U: RmcSerialize, V: RmcSerialize, W: RmcSerialize> RmcSeri
Ok((first, second, third, fourth)) Ok((first, second, third, fourth))
} }
#[inline(always)]
fn serialize_write_size(&self) -> crate::rmc::structures::Result<u32> {
Ok(
self.0.serialize_write_size()? +
self.1.serialize_write_size()? +
self.2.serialize_write_size()? +
self.3.serialize_write_size()?
)
}
} }
impl<T: RmcSerialize, U: RmcSerialize, V: RmcSerialize, W: RmcSerialize, X: RmcSerialize> RmcSerialize for (T, U, V, W, X){ impl<T: RmcSerialize, U: RmcSerialize, V: RmcSerialize, W: RmcSerialize, X: RmcSerialize> RmcSerialize for (T, U, V, W, X){
fn serialize(&self, writer: &mut dyn Write) -> crate::rmc::structures::Result<()> { #[inline(always)]
fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> {
self.0.serialize(writer)?; self.0.serialize(writer)?;
self.1.serialize(writer)?; self.1.serialize(writer)?;
self.2.serialize(writer)?; self.2.serialize(writer)?;
@ -170,7 +252,8 @@ impl<T: RmcSerialize, U: RmcSerialize, V: RmcSerialize, W: RmcSerialize, X: RmcS
Ok(()) Ok(())
} }
fn deserialize(reader: &mut dyn Read) -> crate::rmc::structures::Result<Self> { #[inline(always)]
fn deserialize(reader: &mut impl Read) -> crate::rmc::structures::Result<Self> {
let first = T::deserialize(reader)?; let first = T::deserialize(reader)?;
let second = U::deserialize(reader)?; let second = U::deserialize(reader)?;
let third = V::deserialize(reader)?; let third = V::deserialize(reader)?;
@ -179,10 +262,21 @@ impl<T: RmcSerialize, U: RmcSerialize, V: RmcSerialize, W: RmcSerialize, X: RmcS
Ok((first, second, third, fourth, fifth)) Ok((first, second, third, fourth, fifth))
} }
#[inline(always)]
fn serialize_write_size(&self) -> crate::rmc::structures::Result<u32> {
Ok(
self.0.serialize_write_size()? +
self.1.serialize_write_size()? +
self.2.serialize_write_size()? +
self.2.serialize_write_size()? +
self.3.serialize_write_size()?
)
}
} }
impl<T: RmcSerialize, U: RmcSerialize, V: RmcSerialize, W: RmcSerialize, X: RmcSerialize, Y: RmcSerialize> RmcSerialize for (T, U, V, W, X, Y){ impl<T: RmcSerialize, U: RmcSerialize, V: RmcSerialize, W: RmcSerialize, X: RmcSerialize, Y: RmcSerialize> RmcSerialize for (T, U, V, W, X, Y){
fn serialize(&self, writer: &mut dyn Write) -> crate::rmc::structures::Result<()> { #[inline(always)]
fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> {
self.0.serialize(writer)?; self.0.serialize(writer)?;
self.1.serialize(writer)?; self.1.serialize(writer)?;
self.2.serialize(writer)?; self.2.serialize(writer)?;
@ -193,7 +287,8 @@ impl<T: RmcSerialize, U: RmcSerialize, V: RmcSerialize, W: RmcSerialize, X: RmcS
Ok(()) Ok(())
} }
fn deserialize(reader: &mut dyn Read) -> crate::rmc::structures::Result<Self> { #[inline(always)]
fn deserialize(reader: &mut impl Read) -> crate::rmc::structures::Result<Self> {
let first = T::deserialize(reader)?; let first = T::deserialize(reader)?;
let second = U::deserialize(reader)?; let second = U::deserialize(reader)?;
let third = V::deserialize(reader)?; let third = V::deserialize(reader)?;
@ -203,10 +298,22 @@ impl<T: RmcSerialize, U: RmcSerialize, V: RmcSerialize, W: RmcSerialize, X: RmcS
Ok((first, second, third, fourth, fifth, sixth)) Ok((first, second, third, fourth, fifth, sixth))
} }
#[inline(always)]
fn serialize_write_size(&self) -> crate::rmc::structures::Result<u32> {
Ok(
self.0.serialize_write_size()? +
self.1.serialize_write_size()? +
self.2.serialize_write_size()? +
self.3.serialize_write_size()? +
self.4.serialize_write_size()? +
self.5.serialize_write_size()?
)
}
} }
impl<T: RmcSerialize, U: RmcSerialize, V: RmcSerialize, W: RmcSerialize, X: RmcSerialize, Y: RmcSerialize, Z: RmcSerialize> RmcSerialize for (T, U, V, W, X, Y, Z){ impl<T: RmcSerialize, U: RmcSerialize, V: RmcSerialize, W: RmcSerialize, X: RmcSerialize, Y: RmcSerialize, Z: RmcSerialize> RmcSerialize for (T, U, V, W, X, Y, Z){
fn serialize(&self, writer: &mut dyn Write) -> crate::rmc::structures::Result<()> { #[inline(always)]
fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> {
self.0.serialize(writer)?; self.0.serialize(writer)?;
self.1.serialize(writer)?; self.1.serialize(writer)?;
self.2.serialize(writer)?; self.2.serialize(writer)?;
@ -217,8 +324,8 @@ impl<T: RmcSerialize, U: RmcSerialize, V: RmcSerialize, W: RmcSerialize, X: RmcS
Ok(()) Ok(())
} }
#[inline(always)]
fn deserialize(reader: &mut dyn Read) -> crate::rmc::structures::Result<Self> { fn deserialize(reader: &mut impl Read) -> crate::rmc::structures::Result<Self> {
let first = T::deserialize(reader)?; let first = T::deserialize(reader)?;
let second = U::deserialize(reader)?; let second = U::deserialize(reader)?;
let third = V::deserialize(reader)?; let third = V::deserialize(reader)?;
@ -229,13 +336,31 @@ impl<T: RmcSerialize, U: RmcSerialize, V: RmcSerialize, W: RmcSerialize, X: RmcS
Ok((first, second, third, fourth, fifth, sixth, seventh)) Ok((first, second, third, fourth, fifth, sixth, seventh))
} }
#[inline(always)]
fn serialize_write_size(&self) -> crate::rmc::structures::Result<u32> {
Ok(
self.0.serialize_write_size()? +
self.1.serialize_write_size()? +
self.2.serialize_write_size()? +
self.3.serialize_write_size()? +
self.4.serialize_write_size()? +
self.5.serialize_write_size()? +
self.6.serialize_write_size()?
)
}
} }
impl<T: RmcSerialize> RmcSerialize for Box<T>{ impl<T: RmcSerialize> RmcSerialize for Box<T>{
fn serialize(&self, writer: &mut dyn Write) -> crate::rmc::structures::Result<()> { #[inline(always)]
fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> {
self.as_ref().serialize(writer) self.as_ref().serialize(writer)
} }
fn deserialize(reader: &mut dyn Read) -> crate::rmc::structures::Result<Self> { #[inline(always)]
fn deserialize(reader: &mut impl Read) -> crate::rmc::structures::Result<Self> {
T::deserialize(reader).map(Box::new) T::deserialize(reader).map(Box::new)
} }
#[inline(always)]
fn serialize_write_size(&self) -> crate::rmc::structures::Result<u32> {
T::serialize_write_size(self.as_ref())
}
} }

View file

@ -8,7 +8,7 @@ use crate::rmc::structures::{Result, RmcSerialize};
pub struct QBuffer(pub Vec<u8>); pub struct QBuffer(pub Vec<u8>);
impl RmcSerialize for QBuffer{ impl RmcSerialize for QBuffer{
fn serialize(&self, writer: &mut dyn Write) -> Result<()> { fn serialize(&self, writer: &mut impl Write) -> Result<()> {
let len_u16 = self.0.len() as u16; let len_u16 = self.0.len() as u16;
writer.write(bytes_of(&len_u16))?; writer.write(bytes_of(&len_u16))?;
@ -17,7 +17,7 @@ impl RmcSerialize for QBuffer{
Ok(()) Ok(())
} }
fn deserialize(mut reader: &mut dyn Read) -> Result<Self> { fn deserialize(mut reader: &mut impl Read) -> Result<Self> {
let size: u16 = reader.read_struct(IS_BIG_ENDIAN)?; let size: u16 = reader.read_struct(IS_BIG_ENDIAN)?;
let mut vec = vec![0; size as usize]; let mut vec = vec![0; size as usize];

View file

@ -26,12 +26,12 @@ impl QResult{
} }
impl RmcSerialize for QResult{ impl RmcSerialize for QResult{
fn serialize(&self, writer: &mut dyn Write) -> Result<()> { fn serialize(&self, writer: &mut impl Write) -> Result<()> {
writer.write(bytes_of(self))?; writer.write(bytes_of(self))?;
Ok(()) Ok(())
} }
fn deserialize(mut reader: &mut dyn Read) -> Result<Self> { fn deserialize(mut reader: &mut impl Read) -> Result<Self> {
Ok(reader.read_struct(IS_BIG_ENDIAN)?) Ok(reader.read_struct(IS_BIG_ENDIAN)?)
} }
} }

View file

@ -1,6 +1,12 @@
use std::io::{Cursor, Read, Write}; use std::any::Any;
use std::cmp::max;
use std::fmt::Arguments;
use std::io;
use std::io::{Cursor, ErrorKind, IoSlice, Read, Write};
use std::ops::Sub;
use bytemuck::bytes_of; use bytemuck::bytes_of;
use v_byte_helpers::{IS_BIG_ENDIAN, ReadExtensions}; use v_byte_helpers::{IS_BIG_ENDIAN, ReadExtensions};
use crate::rmc::structures;
use crate::rmc::structures::Error::VersionMismatch; use crate::rmc::structures::Error::VersionMismatch;
use crate::rmc::structures::Result; use crate::rmc::structures::Result;
@ -10,35 +16,97 @@ struct StructureHeader{
length: u32 length: u32
} }
pub fn write_struct(writer: &mut dyn Write, version: u8, pred: impl FnOnce(&mut Vec<u8>) -> Result<()> ) -> Result<()> { #[cfg(feature = "rmc_struct_header")]
pub const HEADER_SIZE: u32 = 0;
#[cfg(not(feature = "rmc_struct_header"))]
pub const HEADER_SIZE: u32 = 5;
pub struct OnlyWriteVec<'a>(&'a mut Vec<u8>);
impl Write for OnlyWriteVec<'_> {
fn flush(&mut self) -> io::Result<()> {
self.0.flush()
}
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.0.write(buf)
}
fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
self.0.write_all(buf)
}
fn write_fmt(&mut self, args: Arguments<'_>) -> io::Result<()> {
self.0.write_fmt(args)
}
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
self.0.write_vectored(bufs)
}
}
#[cfg(feature = "rmc_struct_header")]
pub fn write_struct<T: Write>(writer: &mut T, version: u8, inner_size: u32, pred: impl FnOnce(&mut T) -> Result<()> ) -> Result<()> {
writer.write_all(&[version])?; writer.write_all(&[version])?;
let mut scratch_space: Vec<u8> = Vec::new(); writer.write_all(bytes_of(&inner_size))?;
(pred)(&mut scratch_space)?; (pred)(writer)?;
let u32_size = scratch_space.len() as u32;
writer.write_all(bytes_of(&u32_size))?;
writer.write_all(&scratch_space)?;
Ok(()) Ok(())
} }
pub fn read_struct<T: Sized>(mut reader: &mut dyn Read, version: u8, pred: impl FnOnce(&mut Cursor<Vec<u8>>) -> Result<T>) -> Result<T> {
#[cfg(not(feature = "rmc_struct_header"))]
pub fn write_struct<T: Write>(writer: &mut T, version: u8, _inner_size: u32, pred: impl FnOnce(&mut T) -> Result<()> ) -> Result<()> {
pred(writer)
}
pub struct SubRead<'a, T: Read>{
left_to_read: usize,
origin: &'a mut T
}
impl<'a, T: Read> SubRead<'a, T>{
pub const fn new(origin: &'a mut T, left_to_read: usize) -> Self{
Self{
left_to_read,
origin
}
}
}
impl<T: Read> Read for SubRead<'_, T>{
#[inline(always)]
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
let max_read = max(self.left_to_read, buf.len());
let read = self.origin.read(&mut buf[..max_read])?;
self.left_to_read -= read;
Ok(read)
}
#[inline(always)]
fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
if buf.len() > self.left_to_read{
return Err(io::Error::new(ErrorKind::UnexpectedEof, "Would run over end of SubRead"));
}
self.left_to_read -= buf.len();
self.origin.read_exact(buf)
}
}
#[cfg(feature = "rmc_struct_header")]
pub fn read_struct<T: Sized, R: Read>(mut reader: &mut R, version: u8, pred: impl FnOnce(&mut SubRead<R>) -> Result<T>) -> Result<T> {
let ver: u8 = reader.read_struct(IS_BIG_ENDIAN)?; let ver: u8 = reader.read_struct(IS_BIG_ENDIAN)?;
if ver != version{ if ver != version {
return Err(VersionMismatch(ver)); return Err(VersionMismatch(ver));
} }
let size: u32 = reader.read_struct(IS_BIG_ENDIAN)?; let size: u32 = reader.read_struct(IS_BIG_ENDIAN)?;
let mut vec = vec![0u8; size as usize]; Ok(pred(&mut SubRead::new(reader, size as usize))?)
}
reader.read_exact(&mut vec)?;
#[cfg(not(feature = "rmc_struct_header"))]
let mut cursor = Cursor::new(vec); pub fn read_struct<T: Sized, R: Read>(mut reader: &mut R, version: u8, pred: impl FnOnce(&mut R) -> Result<T>) -> Result<T> {
Ok(pred(&mut reader)?)
Ok(pred(&mut cursor)?)
} }

View file

@ -1,39 +1,49 @@
use std::io::{Read, Write}; use std::io::{Read, Write};
use bytemuck::bytes_of; use bytemuck::bytes_of;
use log::error; use log::error;
use rocket::form::validate::Len;
use v_byte_helpers::{IS_BIG_ENDIAN, ReadExtensions}; use v_byte_helpers::{IS_BIG_ENDIAN, ReadExtensions};
use super::{Result, RmcSerialize}; use super::{Result, RmcSerialize};
impl RmcSerialize for String{ impl RmcSerialize for String{
fn deserialize(mut reader: &mut dyn Read) -> Result<Self> { fn deserialize(mut reader: &mut impl Read) -> Result<Self> {
let len: u16 = reader.read_struct(IS_BIG_ENDIAN)?; let len: u16 = reader.read_struct(IS_BIG_ENDIAN)?;
let mut data = vec![0; len as usize - 1]; if len == 0{
return Ok("".to_string());
}
let mut data = vec![0; len as usize];
reader.read_exact(&mut data)?; reader.read_exact(&mut data)?;
if *data.last().unwrap() != 0{
let null: u8 = reader.read_struct(IS_BIG_ENDIAN)?;
if null != 0{
error!("unable to find null terminator... continuing anyways"); error!("unable to find null terminator... continuing anyways");
} }
data.pop();
Ok(String::from_utf8(data)?) Ok(String::from_utf8(data)?)
} }
fn serialize(&self, writer: &mut dyn Write) -> Result<()> { fn serialize(&self, writer: &mut impl Write) -> Result<()> {
(&self[..]).serialize(writer) (&self[..]).serialize(writer)
} }
fn serialize_write_size(&self) -> Result<u32> {
(&self[..]).serialize_write_size()
}
} }
impl RmcSerialize for &str{ impl RmcSerialize for &str{
fn deserialize(_reader: &mut dyn Read) -> Result<Self> { fn deserialize(_reader: &mut impl Read) -> Result<Self> {
panic!("cannot serialize to &str") panic!("cannot serialize to &str")
} }
fn serialize(&self, writer: &mut dyn Write) -> Result<()> { fn serialize(&self, writer: &mut impl Write) -> Result<()> {
let u16_len: u16 = (self.len() + 1) as u16; let u16_len: u16 = (self.len() + 1) as u16;
writer.write(bytes_of(&u16_len))?; writer.write_all(bytes_of(&u16_len))?;
writer.write(self.as_bytes())?; writer.write_all(self.as_bytes())?;
writer.write(&[0])?; writer.write_all(&[0])?;
Ok(()) Ok(())
} }
#[inline(always)]
fn serialize_write_size(&self) -> Result<u32> {
Ok(2 + self.as_bytes().len() as u32 + 1)
}
} }

View file

@ -16,7 +16,7 @@ pub enum Variant{
} }
impl RmcSerialize for Variant{ impl RmcSerialize for Variant{
fn serialize(&self, writer: &mut dyn Write) -> crate::rmc::structures::Result<()> { fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> {
match self{ match self{
Variant::None => { Variant::None => {
writer.write_all(&[0])?; writer.write_all(&[0])?;
@ -50,7 +50,7 @@ impl RmcSerialize for Variant{
Ok(()) Ok(())
} }
fn deserialize(reader: &mut dyn Read) -> crate::rmc::structures::Result<Self> { fn deserialize(reader: &mut impl Read) -> crate::rmc::structures::Result<Self> {
match u8::deserialize(reader)?{ match u8::deserialize(reader)?{
0 => Ok(Variant::None), 0 => Ok(Variant::None),
1 => Ok(Variant::SInt64(i64::deserialize(reader)?)), 1 => Ok(Variant::SInt64(i64::deserialize(reader)?)),