refactor
This commit is contained in:
parent
a4ccc96ed0
commit
aab4414904
71 changed files with 293 additions and 4316 deletions
42
rnex-core/src/rmc/structures/any.rs
Normal file
42
rnex-core/src/rmc/structures/any.rs
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
use std::io::{Read, Write};
|
||||
use v_byte_helpers::{IS_BIG_ENDIAN, ReadExtensions};
|
||||
use super::{Result, RmcSerialize};
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct Any{
|
||||
pub name: String,
|
||||
pub data: Vec<u8>
|
||||
}
|
||||
|
||||
impl RmcSerialize for Any{
|
||||
fn serialize(&self, writer: &mut dyn Write) -> Result<()> {
|
||||
self.name.serialize(writer)?;
|
||||
|
||||
let u32_len = self.data.len() as u32;
|
||||
|
||||
u32_len.serialize(writer)?;
|
||||
u32_len.serialize(writer)?;
|
||||
|
||||
self.data.serialize(writer)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
fn deserialize(mut reader: &mut dyn Read) -> Result<Self> {
|
||||
let name = String::deserialize(reader)?;
|
||||
|
||||
// also length ?
|
||||
let _len2: u32 = reader.read_struct(IS_BIG_ENDIAN)?;
|
||||
let length: u32 = reader.read_struct(IS_BIG_ENDIAN)?;
|
||||
|
||||
let mut data = vec![0; length as usize];
|
||||
|
||||
reader.read_exact(&mut data)?;
|
||||
|
||||
Ok(
|
||||
Any{
|
||||
name,
|
||||
data
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
29
rnex-core/src/rmc/structures/buffer.rs
Normal file
29
rnex-core/src/rmc/structures/buffer.rs
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
use std::io::{Read, Write};
|
||||
use crate::rmc::structures::RmcSerialize;
|
||||
|
||||
|
||||
|
||||
impl<'a> RmcSerialize for &'a [u8]{
|
||||
fn serialize(&self, writer: &mut dyn Write) -> crate::rmc::structures::Result<()> {
|
||||
let u32_size = self.len() as u32;
|
||||
writer.write(bytemuck::bytes_of(&u32_size))?;
|
||||
writer.write(self)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// 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> {
|
||||
panic!("cannot deserialize to a u8 slice reference (use this ONLY for writing)")
|
||||
}
|
||||
}
|
||||
|
||||
impl RmcSerialize for Box<[u8]>{
|
||||
fn serialize(&self, writer: &mut dyn Write) -> crate::rmc::structures::Result<()> {
|
||||
(&self[..]).serialize(writer)
|
||||
}
|
||||
|
||||
fn deserialize(reader: &mut dyn Read) -> crate::rmc::structures::Result<Self> {
|
||||
Vec::deserialize(reader).map(|v| v.into_boxed_slice())
|
||||
}
|
||||
}
|
||||
13
rnex-core/src/rmc/structures/connection_data.rs
Normal file
13
rnex-core/src/rmc/structures/connection_data.rs
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
|
||||
use macros::RmcSerialize;
|
||||
use rnex_core::kerberos::KerberosDateTime;
|
||||
|
||||
#[derive(Debug, RmcSerialize)]
|
||||
#[rmc_struct(1)]
|
||||
pub struct ConnectionData{
|
||||
pub station_url: String,
|
||||
pub special_protocols: Vec<u8>,
|
||||
pub special_station_url: String,
|
||||
pub date_time: KerberosDateTime
|
||||
}
|
||||
|
||||
60
rnex-core/src/rmc/structures/list.rs
Normal file
60
rnex-core/src/rmc/structures/list.rs
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
use std::array::from_fn;
|
||||
use std::io::{Read, Write};
|
||||
use std::mem::MaybeUninit;
|
||||
use bytemuck::bytes_of;
|
||||
use serde::Serialize;
|
||||
use v_byte_helpers::{IS_BIG_ENDIAN, ReadExtensions};
|
||||
use crate::rmc::structures::RmcSerialize;
|
||||
|
||||
|
||||
|
||||
// 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
|
||||
impl<T: RmcSerialize> RmcSerialize for Vec<T>{
|
||||
fn serialize(&self, writer: &mut dyn Write) -> crate::rmc::structures::Result<()> {
|
||||
let u32_len = self.len() as u32;
|
||||
|
||||
writer.write_all(bytes_of(&u32_len))?;
|
||||
for e in self{
|
||||
e.serialize(writer)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn deserialize(mut reader: &mut dyn Read) -> crate::rmc::structures::Result<Self> {
|
||||
let len: u32 = reader.read_struct(IS_BIG_ENDIAN)?;
|
||||
|
||||
let mut vec = Vec::with_capacity(len as usize);
|
||||
|
||||
for _ in 0..len{
|
||||
vec.push(T::deserialize(reader)?);
|
||||
}
|
||||
|
||||
Ok(vec)
|
||||
}
|
||||
}
|
||||
|
||||
impl<const LEN: usize, T: RmcSerialize> RmcSerialize for [T; LEN]{
|
||||
fn serialize(&self, writer: &mut dyn Write) -> crate::rmc::structures::Result<()> {
|
||||
for i in 0..LEN{
|
||||
self[i].serialize(writer)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn deserialize(reader: &mut dyn Read) -> crate::rmc::structures::Result<Self> {
|
||||
let mut arr = [const { MaybeUninit::<T>::uninit() }; LEN];
|
||||
|
||||
for i in 0..LEN{
|
||||
arr[i] = MaybeUninit::new(T::deserialize(reader)?);
|
||||
}
|
||||
|
||||
// all of the elements are now initialized so it is safe to assume they are initialized
|
||||
|
||||
let arr = arr.map(|v| unsafe{ v.assume_init() });
|
||||
|
||||
Ok(arr)
|
||||
}
|
||||
}
|
||||
126
rnex-core/src/rmc/structures/matchmake.rs
Normal file
126
rnex-core/src/rmc/structures/matchmake.rs
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
use rnex_core::kerberos::KerberosDateTime;
|
||||
use rnex_core::rmc::structures::variant::Variant;
|
||||
use macros::RmcSerialize;
|
||||
|
||||
// rmc structure
|
||||
#[derive(RmcSerialize, Debug, Clone, Default)]
|
||||
#[rmc_struct(0)]
|
||||
pub struct Gathering {
|
||||
pub self_gid: u32,
|
||||
pub owner_pid: u32,
|
||||
pub host_pid: u32,
|
||||
pub minimum_participants: u16,
|
||||
pub maximum_participants: u16,
|
||||
pub participant_policy: u32,
|
||||
pub policy_argument: u32,
|
||||
pub flags: u32,
|
||||
pub state: u32,
|
||||
pub description: String,
|
||||
}
|
||||
|
||||
// rmc structure
|
||||
#[derive(RmcSerialize, Debug, Clone, Default)]
|
||||
#[rmc_struct(0)]
|
||||
pub struct MatchmakeParam {
|
||||
pub params: Vec<(String, Variant)>,
|
||||
}
|
||||
|
||||
// rmc structure
|
||||
#[derive(RmcSerialize, Debug, Clone, Default)]
|
||||
#[rmc_struct(3)]
|
||||
pub struct MatchmakeSession {
|
||||
//inherits from
|
||||
#[extends]
|
||||
pub gathering: Gathering,
|
||||
|
||||
pub gamemode: u32,
|
||||
pub attributes: Vec<u32>,
|
||||
pub open_participation: bool,
|
||||
pub matchmake_system_type: u32,
|
||||
pub application_buffer: Vec<u8>,
|
||||
pub participation_count: u32,
|
||||
pub progress_score: u8,
|
||||
pub session_key: Vec<u8>,
|
||||
pub option0: u32,
|
||||
pub matchmake_param: MatchmakeParam,
|
||||
pub datetime: KerberosDateTime,
|
||||
pub user_password: String,
|
||||
pub refer_gid: u32,
|
||||
pub user_password_enabled: bool,
|
||||
pub system_password_enabled: bool,
|
||||
}
|
||||
|
||||
#[derive(RmcSerialize, Debug, Clone)]
|
||||
#[rmc_struct(3)]
|
||||
pub struct MatchmakeSessionSearchCriteria {
|
||||
pub attribs: Vec<String>,
|
||||
pub game_mode: String,
|
||||
pub minimum_participants: String,
|
||||
pub maximum_participants: String,
|
||||
pub matchmake_system_type: String,
|
||||
pub vacant_only: bool,
|
||||
pub exclude_locked: bool,
|
||||
pub exclude_non_host_pid: bool,
|
||||
pub selection_method: u32,
|
||||
pub vacant_participants: u16,
|
||||
pub matchmake_param: MatchmakeParam,
|
||||
pub exclude_user_password_set: bool,
|
||||
pub exclude_system_password_set: bool,
|
||||
pub refer_gid: u32,
|
||||
}
|
||||
|
||||
#[derive(RmcSerialize, Debug, Clone)]
|
||||
#[rmc_struct(0)]
|
||||
pub struct AutoMatchmakeParam {
|
||||
pub matchmake_session: MatchmakeSession,
|
||||
pub additional_participants: Vec<u32>,
|
||||
pub gid_for_participation_check: u32,
|
||||
pub auto_matchmake_option: u32,
|
||||
pub join_message: String,
|
||||
pub participation_count: u16,
|
||||
pub search_criteria: Vec<MatchmakeSessionSearchCriteria>,
|
||||
pub target_gids: Vec<u32>,
|
||||
}
|
||||
|
||||
#[derive(RmcSerialize, Debug, Clone)]
|
||||
#[rmc_struct(0)]
|
||||
pub struct CreateMatchmakeSessionParam {
|
||||
pub matchmake_session: MatchmakeSession,
|
||||
pub additional_participants: Vec<u32>,
|
||||
pub gid_for_participation_check: u32,
|
||||
pub create_matchmake_session_option: u32,
|
||||
pub join_message: String,
|
||||
pub participation_count: u16,
|
||||
}
|
||||
|
||||
#[derive(RmcSerialize, Debug, Clone)]
|
||||
#[rmc_struct(0)]
|
||||
pub struct MatchmakeBlockListParam {
|
||||
option_flag: u32,
|
||||
}
|
||||
|
||||
#[derive(RmcSerialize, Debug, Clone)]
|
||||
#[rmc_struct(0)]
|
||||
pub struct JoinMatchmakeSessionParam {
|
||||
pub gid: u32,
|
||||
pub additional_participants: Vec<u32>,
|
||||
pub gid_for_participation_check: u32,
|
||||
pub join_matchmake_session_open: u32,
|
||||
pub join_matchmake_session_behavior: u8,
|
||||
pub user_password: String,
|
||||
pub system_password: String,
|
||||
pub join_message: String,
|
||||
pub participation_count: u16,
|
||||
//pub extra_participant: u16,
|
||||
//pub block_list_param: MatchmakeBlockListParam
|
||||
}
|
||||
|
||||
pub mod gathering_flags {
|
||||
pub const PERSISTENT_GATHERING: u32 = 0x1;
|
||||
pub const DISCONNECT_CHANGE_OWNER: u32 = 0x10;
|
||||
pub const PERSISTENT_GATHERING_LEAVE_PARTICIPATION: u32 = 0x40;
|
||||
pub const PERSISTENT_GATHERING_ALLOW_ZERO_USERS: u32 = 0x80;
|
||||
pub const PARTICIPANTS_CHANGE_OWNER: u32 = 0x200;
|
||||
pub const VERBOSE_PARTICIPANTS: u32 = 0x400;
|
||||
pub const VERBOSE_PARTICIPANTS_EX: u32 = 0x800;
|
||||
}
|
||||
60
rnex-core/src/rmc/structures/mod.rs
Normal file
60
rnex-core/src/rmc/structures/mod.rs
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
use std::io;
|
||||
use std::io::{Read, Write};
|
||||
use std::string::FromUtf8Error;
|
||||
use thiserror::Error;
|
||||
|
||||
//ideas for the future: make a proc macro library which allows generation of struct reads
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum Error{
|
||||
#[error("Io Error: {0}")]
|
||||
Io(#[from] io::Error),
|
||||
#[error("UTF8 conversion Error: {0}")]
|
||||
Utf8(#[from] FromUtf8Error),
|
||||
#[error("unexpected value: {0}")]
|
||||
UnexpectedValue(u64),
|
||||
#[error("version mismatch: {0}")]
|
||||
VersionMismatch(u8),
|
||||
#[error("an error occurred reading the station url")]
|
||||
StationUrlInvalid
|
||||
}
|
||||
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
|
||||
pub mod string;
|
||||
pub mod any;
|
||||
pub mod qresult;
|
||||
pub mod buffer;
|
||||
pub mod connection_data;
|
||||
pub mod rmc_struct;
|
||||
pub mod list;
|
||||
pub mod qbuffer;
|
||||
pub mod primitives;
|
||||
pub mod matchmake;
|
||||
pub mod variant;
|
||||
pub mod ranking;
|
||||
mod networking;
|
||||
|
||||
pub trait RmcSerialize{
|
||||
fn serialize(&self, writer: &mut dyn Write) -> Result<()>;
|
||||
fn deserialize(reader: &mut dyn Read) -> Result<Self> where Self: Sized;
|
||||
|
||||
fn to_data(&self) -> Vec<u8>{
|
||||
let mut data = Vec::new();
|
||||
|
||||
self.serialize(&mut data).expect("out of memory or something");
|
||||
|
||||
data
|
||||
}
|
||||
}
|
||||
|
||||
impl RmcSerialize for (){
|
||||
fn serialize(&self, writer: &mut dyn Write) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
fn deserialize(reader: &mut dyn Read) -> Result<Self> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
33
rnex-core/src/rmc/structures/networking.rs
Normal file
33
rnex-core/src/rmc/structures/networking.rs
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
use std::io::{Read, Write};
|
||||
use std::net::{Ipv4Addr, SocketAddrV4};
|
||||
use rnex_core::prudp::virtual_port::VirtualPort;
|
||||
use crate::rmc::structures::RmcSerialize;
|
||||
|
||||
impl RmcSerialize for SocketAddrV4{
|
||||
fn serialize(&self, writer: &mut dyn Write) -> crate::rmc::structures::Result<()> {
|
||||
self.ip().to_bits().serialize(writer)?;
|
||||
self.port().serialize(writer)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn deserialize(reader: &mut dyn Read) -> crate::rmc::structures::Result<Self> {
|
||||
let ip = u32::deserialize(reader)?;
|
||||
let port = u16::deserialize(reader)?;
|
||||
|
||||
Ok(SocketAddrV4::new(Ipv4Addr::from_bits(ip), port))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl RmcSerialize for VirtualPort{
|
||||
fn serialize(&self, writer: &mut dyn Write) -> crate::rmc::structures::Result<()> {
|
||||
self.0.serialize(writer)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn deserialize(reader: &mut dyn Read) -> crate::rmc::structures::Result<Self> {
|
||||
Ok(Self(u8::deserialize(reader)?))
|
||||
}
|
||||
}
|
||||
241
rnex-core/src/rmc/structures/primitives.rs
Normal file
241
rnex-core/src/rmc/structures/primitives.rs
Normal file
|
|
@ -0,0 +1,241 @@
|
|||
use std::io::{Read, Write};
|
||||
use bytemuck::bytes_of;
|
||||
use v_byte_helpers::{IS_BIG_ENDIAN, ReadExtensions};
|
||||
use crate::rmc::structures::RmcSerialize;
|
||||
|
||||
impl RmcSerialize for u8{
|
||||
fn serialize(&self, writer: &mut dyn Write) -> crate::rmc::structures::Result<()> {
|
||||
Ok(writer.write_all(bytes_of(self))?)
|
||||
}
|
||||
|
||||
fn deserialize(mut reader: &mut dyn Read) -> crate::rmc::structures::Result<Self> {
|
||||
Ok(reader.read_struct(IS_BIG_ENDIAN)?)
|
||||
}
|
||||
}
|
||||
|
||||
impl RmcSerialize for i8{
|
||||
fn serialize(&self, writer: &mut dyn Write) -> crate::rmc::structures::Result<()> {
|
||||
Ok(writer.write_all(bytes_of(self))?)
|
||||
}
|
||||
|
||||
fn deserialize(mut reader: &mut dyn Read) -> crate::rmc::structures::Result<Self> {
|
||||
Ok(reader.read_struct(IS_BIG_ENDIAN)?)
|
||||
}
|
||||
}
|
||||
|
||||
impl RmcSerialize for u16{
|
||||
fn serialize(&self, writer: &mut dyn Write) -> crate::rmc::structures::Result<()> {
|
||||
Ok(writer.write_all(bytes_of(self))?)
|
||||
}
|
||||
|
||||
fn deserialize(mut reader: &mut dyn Read) -> crate::rmc::structures::Result<Self> {
|
||||
Ok(reader.read_struct(IS_BIG_ENDIAN)?)
|
||||
}
|
||||
}
|
||||
|
||||
impl RmcSerialize for i16{
|
||||
fn serialize(&self, writer: &mut dyn Write) -> crate::rmc::structures::Result<()> {
|
||||
Ok(writer.write_all(bytes_of(self))?)
|
||||
}
|
||||
|
||||
fn deserialize(mut reader: &mut dyn Read) -> crate::rmc::structures::Result<Self> {
|
||||
Ok(reader.read_struct(IS_BIG_ENDIAN)?)
|
||||
}
|
||||
}
|
||||
|
||||
impl RmcSerialize for u32{
|
||||
fn serialize(&self, writer: &mut dyn Write) -> crate::rmc::structures::Result<()> {
|
||||
Ok(writer.write_all(bytes_of(self))?)
|
||||
}
|
||||
|
||||
fn deserialize(mut reader: &mut dyn Read) -> crate::rmc::structures::Result<Self> {
|
||||
Ok(reader.read_struct(IS_BIG_ENDIAN)?)
|
||||
}
|
||||
}
|
||||
|
||||
impl RmcSerialize for i32{
|
||||
fn serialize(&self, writer: &mut dyn Write) -> crate::rmc::structures::Result<()> {
|
||||
Ok(writer.write_all(bytes_of(self))?)
|
||||
}
|
||||
|
||||
fn deserialize(mut reader: &mut dyn Read) -> crate::rmc::structures::Result<Self> {
|
||||
Ok(reader.read_struct(IS_BIG_ENDIAN)?)
|
||||
}
|
||||
}
|
||||
|
||||
impl RmcSerialize for u64{
|
||||
fn serialize(&self, writer: &mut dyn Write) -> crate::rmc::structures::Result<()> {
|
||||
Ok(writer.write_all(bytes_of(self))?)
|
||||
}
|
||||
|
||||
fn deserialize(mut reader: &mut dyn Read) -> crate::rmc::structures::Result<Self> {
|
||||
Ok(reader.read_struct(IS_BIG_ENDIAN)?)
|
||||
}
|
||||
}
|
||||
|
||||
impl RmcSerialize for i64{
|
||||
fn serialize(&self, writer: &mut dyn Write) -> crate::rmc::structures::Result<()> {
|
||||
Ok(writer.write_all(bytes_of(self))?)
|
||||
}
|
||||
|
||||
fn deserialize(mut reader: &mut dyn Read) -> crate::rmc::structures::Result<Self> {
|
||||
Ok(reader.read_struct(IS_BIG_ENDIAN)?)
|
||||
}
|
||||
}
|
||||
|
||||
impl RmcSerialize for f64{
|
||||
fn serialize(&self, writer: &mut dyn Write) -> crate::rmc::structures::Result<()> {
|
||||
Ok(writer.write_all(bytes_of(self))?)
|
||||
}
|
||||
|
||||
fn deserialize(mut reader: &mut dyn Read) -> crate::rmc::structures::Result<Self> {
|
||||
Ok(reader.read_struct(IS_BIG_ENDIAN)?)
|
||||
}
|
||||
}
|
||||
|
||||
impl RmcSerialize for bool{
|
||||
fn serialize(&self, writer: &mut dyn Write) -> crate::rmc::structures::Result<()> {
|
||||
match self{
|
||||
true => writer.write_all(&[1])?,
|
||||
false => writer.write_all(&[0])?,
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn deserialize(reader: &mut dyn Read) -> crate::rmc::structures::Result<Self> {
|
||||
Ok(u8::deserialize(reader)? != 0)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl<T: RmcSerialize, U: RmcSerialize> RmcSerialize for (T, U){
|
||||
fn serialize(&self, writer: &mut dyn Write) -> crate::rmc::structures::Result<()> {
|
||||
self.0.serialize(writer)?;
|
||||
self.1.serialize(writer)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn deserialize(reader: &mut dyn Read) -> crate::rmc::structures::Result<Self> {
|
||||
let first = T::deserialize(reader)?;
|
||||
let second = U::deserialize(reader)?;
|
||||
|
||||
Ok((first, second))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: RmcSerialize, U: RmcSerialize, V: RmcSerialize> RmcSerialize for (T, U, V){
|
||||
fn serialize(&self, writer: &mut dyn Write) -> crate::rmc::structures::Result<()> {
|
||||
self.0.serialize(writer)?;
|
||||
self.1.serialize(writer)?;
|
||||
self.2.serialize(writer)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn deserialize(reader: &mut dyn Read) -> crate::rmc::structures::Result<Self> {
|
||||
let first = T::deserialize(reader)?;
|
||||
let second = U::deserialize(reader)?;
|
||||
let third = V::deserialize(reader)?;
|
||||
|
||||
Ok((first, second, third))
|
||||
}
|
||||
}
|
||||
|
||||
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<()> {
|
||||
self.0.serialize(writer)?;
|
||||
self.1.serialize(writer)?;
|
||||
self.2.serialize(writer)?;
|
||||
self.3.serialize(writer)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn deserialize(reader: &mut dyn Read) -> crate::rmc::structures::Result<Self> {
|
||||
let first = T::deserialize(reader)?;
|
||||
let second = U::deserialize(reader)?;
|
||||
let third = V::deserialize(reader)?;
|
||||
let fourth = W::deserialize(reader)?;
|
||||
|
||||
Ok((first, second, third, fourth))
|
||||
}
|
||||
}
|
||||
|
||||
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<()> {
|
||||
self.0.serialize(writer)?;
|
||||
self.1.serialize(writer)?;
|
||||
self.2.serialize(writer)?;
|
||||
self.3.serialize(writer)?;
|
||||
self.4.serialize(writer)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn deserialize(reader: &mut dyn Read) -> crate::rmc::structures::Result<Self> {
|
||||
let first = T::deserialize(reader)?;
|
||||
let second = U::deserialize(reader)?;
|
||||
let third = V::deserialize(reader)?;
|
||||
let fourth = W::deserialize(reader)?;
|
||||
let fifth = X::deserialize(reader)?;
|
||||
|
||||
Ok((first, second, third, fourth, fifth))
|
||||
}
|
||||
}
|
||||
|
||||
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<()> {
|
||||
self.0.serialize(writer)?;
|
||||
self.1.serialize(writer)?;
|
||||
self.2.serialize(writer)?;
|
||||
self.3.serialize(writer)?;
|
||||
self.4.serialize(writer)?;
|
||||
self.5.serialize(writer)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn deserialize(reader: &mut dyn Read) -> crate::rmc::structures::Result<Self> {
|
||||
let first = T::deserialize(reader)?;
|
||||
let second = U::deserialize(reader)?;
|
||||
let third = V::deserialize(reader)?;
|
||||
let fourth = W::deserialize(reader)?;
|
||||
let fifth = X::deserialize(reader)?;
|
||||
let sixth = Y::deserialize(reader)?;
|
||||
|
||||
Ok((first, second, third, fourth, fifth, sixth))
|
||||
}
|
||||
}
|
||||
|
||||
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<()> {
|
||||
self.0.serialize(writer)?;
|
||||
self.1.serialize(writer)?;
|
||||
self.2.serialize(writer)?;
|
||||
self.3.serialize(writer)?;
|
||||
self.4.serialize(writer)?;
|
||||
self.5.serialize(writer)?;
|
||||
self.6.serialize(writer)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn deserialize(reader: &mut dyn Read) -> crate::rmc::structures::Result<Self> {
|
||||
let first = T::deserialize(reader)?;
|
||||
let second = U::deserialize(reader)?;
|
||||
let third = V::deserialize(reader)?;
|
||||
let fourth = W::deserialize(reader)?;
|
||||
let fifth = X::deserialize(reader)?;
|
||||
let sixth = Y::deserialize(reader)?;
|
||||
let seventh = Z::deserialize(reader)?;
|
||||
|
||||
Ok((first, second, third, fourth, fifth, sixth, seventh))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: RmcSerialize> RmcSerialize for Box<T>{
|
||||
fn serialize(&self, writer: &mut dyn Write) -> crate::rmc::structures::Result<()> {
|
||||
self.as_ref().serialize(writer)
|
||||
}
|
||||
fn deserialize(reader: &mut dyn Read) -> crate::rmc::structures::Result<Self> {
|
||||
T::deserialize(reader).map(Box::new)
|
||||
}
|
||||
}
|
||||
29
rnex-core/src/rmc/structures/qbuffer.rs
Normal file
29
rnex-core/src/rmc/structures/qbuffer.rs
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
use std::io::{Read, Write};
|
||||
use bytemuck::bytes_of;
|
||||
use v_byte_helpers::{IS_BIG_ENDIAN, ReadExtensions};
|
||||
use crate::rmc::structures::{Result, RmcSerialize};
|
||||
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct QBuffer(pub Vec<u8>);
|
||||
|
||||
impl RmcSerialize for QBuffer{
|
||||
fn serialize(&self, writer: &mut dyn Write) -> Result<()> {
|
||||
let len_u16 = self.0.len() as u16;
|
||||
|
||||
writer.write(bytes_of(&len_u16))?;
|
||||
writer.write(&self.0)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn deserialize(mut reader: &mut dyn Read) -> Result<Self> {
|
||||
let size: u16 = reader.read_struct(IS_BIG_ENDIAN)?;
|
||||
|
||||
let mut vec = vec![0; size as usize];
|
||||
|
||||
reader.read_exact(&mut vec)?;
|
||||
|
||||
Ok(Self(vec))
|
||||
}
|
||||
}
|
||||
37
rnex-core/src/rmc/structures/qresult.rs
Normal file
37
rnex-core/src/rmc/structures/qresult.rs
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
use std::io::{Read, Write};
|
||||
use bytemuck::{bytes_of, Pod, Zeroable};
|
||||
use v_byte_helpers::SwapEndian;
|
||||
use v_byte_helpers::{IS_BIG_ENDIAN, ReadExtensions};
|
||||
use crate::rmc::response::ErrorCode;
|
||||
use crate::rmc::structures::{RmcSerialize, Result};
|
||||
|
||||
pub const ERROR_MASK: u32 = 1 << 31;
|
||||
|
||||
#[derive(Pod, Zeroable, Copy, Clone, SwapEndian, Debug)]
|
||||
#[repr(transparent)]
|
||||
pub struct QResult(u32);
|
||||
|
||||
impl QResult{
|
||||
pub fn success(error_code: ErrorCode) -> Self{
|
||||
let val: u32 = error_code.into();
|
||||
|
||||
Self(val & (!ERROR_MASK))
|
||||
}
|
||||
|
||||
pub fn error(error_code: ErrorCode) -> Self{
|
||||
let val: u32 = error_code.into();
|
||||
|
||||
Self(val | ERROR_MASK)
|
||||
}
|
||||
}
|
||||
|
||||
impl RmcSerialize for QResult{
|
||||
fn serialize(&self, writer: &mut dyn Write) -> Result<()> {
|
||||
writer.write(bytes_of(self))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn deserialize(mut reader: &mut dyn Read) -> Result<Self> {
|
||||
Ok(reader.read_struct(IS_BIG_ENDIAN)?)
|
||||
}
|
||||
}
|
||||
69
rnex-core/src/rmc/structures/ranking.rs
Normal file
69
rnex-core/src/rmc/structures/ranking.rs
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
use bytemuck::{Pod, Zeroable};
|
||||
use macros::RmcSerialize;
|
||||
use rnex_core::rmc::structures::qbuffer::QBuffer;
|
||||
|
||||
#[derive(RmcSerialize, Debug)]
|
||||
#[rmc_struct(0)]
|
||||
struct UploadCompetitionData{
|
||||
winning_team/*?*/: u32,
|
||||
splatfest_id/*?*/: u32,
|
||||
unk_2/*?*/: u32,
|
||||
unk_3: u32,
|
||||
team_id_1: u8,
|
||||
team_id_2: u8,
|
||||
unk_5: u32,
|
||||
player_data/*?*/: QBuffer,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Pod, Zeroable)]
|
||||
#[repr(C)]
|
||||
struct UserData{
|
||||
name: [u16; 0x10],
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test{
|
||||
use std::io::Cursor;
|
||||
use bytemuck::from_bytes;
|
||||
use tokio::io::AsyncReadExt;
|
||||
use crate::rmc::structures::ranking::{UploadCompetitionData, UserData};
|
||||
use rnex_core::rmc::structures::RmcSerialize;
|
||||
|
||||
#[test]
|
||||
fn test() {
|
||||
let data: [u8; 0xBD] = [
|
||||
0x00, 0xB8, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFC, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00,
|
||||
0x00, 0x1F, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0xA0, 0x00, 0x00, 0x49, 0x00,
|
||||
0x7A, 0x00, 0x7A, 0x00, 0x79, 0x00, 0x53, 0x00, 0x50, 0x00, 0x46, 0x00, 0x4E, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0xF2, 0x00, 0x00, 0x00,
|
||||
0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x1F, 0x5E, 0x00, 0x00, 0x00,
|
||||
0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x90, 0x00, 0x00, 0x00,
|
||||
0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x0A, 0x00, 0x00, 0x14, 0x87, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
|
||||
0x02, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x4C, 0x00, 0x00, 0x00,
|
||||
];
|
||||
|
||||
let mut cursor = Cursor::new(data);
|
||||
|
||||
let data = UploadCompetitionData::deserialize(&mut cursor).expect("unable to deserialize data");
|
||||
|
||||
let user_data: &UserData = from_bytes(&data.player_data.0[..size_of::<UserData>()]);
|
||||
|
||||
let pos = user_data.name.iter()
|
||||
.position(|v| *v == 0x0000)
|
||||
.unwrap_or(0x10);
|
||||
|
||||
let mut name = user_data.name[0..pos].to_vec();
|
||||
|
||||
name.iter_mut().for_each(|v| *v = v.swap_bytes());
|
||||
|
||||
let name = String::from_utf16(&name).expect("unable to get name");
|
||||
|
||||
println!("{:?}", name);
|
||||
|
||||
assert!(u8::deserialize(&mut cursor).is_err())
|
||||
}
|
||||
}
|
||||
44
rnex-core/src/rmc/structures/rmc_struct.rs
Normal file
44
rnex-core/src/rmc/structures/rmc_struct.rs
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
use std::io::{Cursor, Read, Write};
|
||||
use bytemuck::bytes_of;
|
||||
use v_byte_helpers::{IS_BIG_ENDIAN, ReadExtensions};
|
||||
use crate::rmc::structures::Error::VersionMismatch;
|
||||
use crate::rmc::structures::Result;
|
||||
|
||||
#[repr(C, packed)]
|
||||
struct StructureHeader{
|
||||
version: u8,
|
||||
length: u32
|
||||
}
|
||||
|
||||
pub fn write_struct(writer: &mut dyn Write, version: u8, pred: impl FnOnce(&mut Vec<u8>) -> Result<()> ) -> Result<()> {
|
||||
writer.write_all(&[version])?;
|
||||
|
||||
let mut scratch_space: Vec<u8> = Vec::new();
|
||||
|
||||
(pred)(&mut scratch_space)?;
|
||||
|
||||
let u32_size = scratch_space.len() as u32;
|
||||
|
||||
writer.write_all(bytes_of(&u32_size))?;
|
||||
writer.write_all(&scratch_space)?;
|
||||
|
||||
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> {
|
||||
let ver: u8 = reader.read_struct(IS_BIG_ENDIAN)?;
|
||||
|
||||
if ver != version{
|
||||
return Err(VersionMismatch(ver));
|
||||
}
|
||||
|
||||
let size: u32 = reader.read_struct(IS_BIG_ENDIAN)?;
|
||||
|
||||
let mut vec = vec![0u8; size as usize];
|
||||
|
||||
reader.read_exact(&mut vec)?;
|
||||
|
||||
let mut cursor = Cursor::new(vec);
|
||||
|
||||
Ok(pred(&mut cursor)?)
|
||||
}
|
||||
39
rnex-core/src/rmc/structures/string.rs
Normal file
39
rnex-core/src/rmc/structures/string.rs
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
use std::io::{Read, Write};
|
||||
use bytemuck::bytes_of;
|
||||
use log::error;
|
||||
use v_byte_helpers::{IS_BIG_ENDIAN, ReadExtensions};
|
||||
use super::{Result, RmcSerialize};
|
||||
|
||||
impl RmcSerialize for String{
|
||||
fn deserialize(mut reader: &mut dyn Read) -> Result<Self> {
|
||||
let len: u16 = reader.read_struct(IS_BIG_ENDIAN)?;
|
||||
let mut data = vec![0; len as usize - 1];
|
||||
reader.read_exact(&mut data)?;
|
||||
|
||||
let null: u8 = reader.read_struct(IS_BIG_ENDIAN)?;
|
||||
if null != 0{
|
||||
error!("unable to find null terminator... continuing anyways");
|
||||
}
|
||||
|
||||
Ok(String::from_utf8(data)?)
|
||||
}
|
||||
fn serialize(&self, writer: &mut dyn Write) -> Result<()> {
|
||||
(&self[..]).serialize(writer)
|
||||
}
|
||||
}
|
||||
|
||||
impl RmcSerialize for &str{
|
||||
fn deserialize(_reader: &mut dyn Read) -> Result<Self> {
|
||||
panic!("cannot serialize to &str")
|
||||
}
|
||||
fn serialize(&self, writer: &mut dyn Write) -> Result<()> {
|
||||
let u16_len: u16 = (self.len() + 1) as u16;
|
||||
writer.write(bytes_of(&u16_len))?;
|
||||
|
||||
writer.write(self.as_bytes())?;
|
||||
writer.write(&[0])?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
65
rnex-core/src/rmc/structures/variant.rs
Normal file
65
rnex-core/src/rmc/structures/variant.rs
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
use std::io::{Read, Write};
|
||||
use crate::kerberos::KerberosDateTime;
|
||||
use crate::rmc::structures;
|
||||
use crate::rmc::structures::RmcSerialize;
|
||||
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub enum Variant{
|
||||
#[default]
|
||||
None,
|
||||
SInt64(i64),
|
||||
Double(f64),
|
||||
Bool(bool),
|
||||
String(String),
|
||||
DateTime(KerberosDateTime),
|
||||
UInt64(u64),
|
||||
}
|
||||
|
||||
impl RmcSerialize for Variant{
|
||||
fn serialize(&self, writer: &mut dyn Write) -> crate::rmc::structures::Result<()> {
|
||||
match self{
|
||||
Variant::None => {
|
||||
writer.write_all(&[0])?;
|
||||
}
|
||||
Variant::SInt64(v) => {
|
||||
writer.write_all(&[1])?;
|
||||
v.serialize(writer)?;
|
||||
}
|
||||
Variant::Double(v) => {
|
||||
writer.write_all(&[2])?;
|
||||
v.serialize(writer)?;
|
||||
}
|
||||
Variant::Bool(v) => {
|
||||
writer.write_all(&[3])?;
|
||||
v.serialize(writer)?;
|
||||
}
|
||||
Variant::String(v) => {
|
||||
writer.write_all(&[4])?;
|
||||
v.serialize(writer)?;
|
||||
}
|
||||
Variant::DateTime(v) => {
|
||||
writer.write_all(&[5])?;
|
||||
v.serialize(writer)?;
|
||||
}
|
||||
Variant::UInt64(v) => {
|
||||
writer.write_all(&[6])?;
|
||||
v.serialize(writer)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn deserialize(reader: &mut dyn Read) -> crate::rmc::structures::Result<Self> {
|
||||
match u8::deserialize(reader)?{
|
||||
0 => Ok(Variant::None),
|
||||
1 => Ok(Variant::SInt64(i64::deserialize(reader)?)),
|
||||
2 => Ok(Variant::Double(f64::deserialize(reader)?)),
|
||||
3 => Ok(Variant::Bool(bool::deserialize(reader)?)),
|
||||
4 => Ok(Variant::String(String::deserialize(reader)?)),
|
||||
5 => Ok(Variant::DateTime(KerberosDateTime::deserialize(reader)?)),
|
||||
6 => Ok(Variant::UInt64(u64::deserialize(reader)?)),
|
||||
v => Err(structures::Error::UnexpectedValue(v as u64))
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue