From 4d1353afd260f06d5845ac5a5469a0b0f99de63f Mon Sep 17 00:00:00 2001 From: Wyatt Herkamp Date: Thu, 23 Jun 2022 07:33:30 -0400 Subject: [PATCH] Improving the packet mapping --- src/api/tests/protocol.rs | 2 ++ src/models/protocol/mod.rs | 38 +++++++++++++++++++++++----- src/models/protocol/packet_mapper.rs | 29 +++++++++++++++++---- src/models/protocol/types.rs | 5 +++- 4 files changed, 62 insertions(+), 12 deletions(-) diff --git a/src/api/tests/protocol.rs b/src/api/tests/protocol.rs index 73e562e..250bd54 100644 --- a/src/api/tests/protocol.rs +++ b/src/api/tests/protocol.rs @@ -1,3 +1,5 @@ +use std::collections::HashMap; +use std::convert::TryInto; use crate::api::protocol::Protocol; use crate::api::tests::get_test_versions; use crate::models::protocol::{PacketDataType}; diff --git a/src/models/protocol/mod.rs b/src/models/protocol/mod.rs index cd0d608..120af8d 100644 --- a/src/models/protocol/mod.rs +++ b/src/models/protocol/mod.rs @@ -1,6 +1,7 @@ pub mod types; pub mod packet_mapper; +use std::borrow::Cow; use std::fmt; use serde::{de, Deserialize, Deserializer}; use serde::de::{MapAccess, Visitor}; @@ -8,7 +9,7 @@ use serde_json::Value; pub use packet_mapper::{PacketMapper, PacketSwitch, PacketMapperSwitch}; pub use types::{BitField, NativeType, PacketDataType, PacketDataTypes}; -#[derive(Deserialize, Debug)] +#[derive(Deserialize, Debug, Clone)] pub struct Protocol { pub types: PacketDataTypes, pub handshaking: PacketGrouping, @@ -17,7 +18,7 @@ pub struct Protocol { pub play: PacketGrouping, } -#[derive(Deserialize, Debug)] +#[derive(Deserialize, Debug, Clone)] pub struct PacketGrouping { #[serde(rename = "toServer")] pub to_server: PacketTypes, @@ -25,7 +26,7 @@ pub struct PacketGrouping { pub to_client: PacketTypes, } -#[derive(Debug)] +#[derive(Debug, Clone)] pub enum DataTypeReference { Simple(String), Complex { @@ -34,13 +35,38 @@ pub enum DataTypeReference { }, } -#[derive(Debug)] +impl Into for DataTypeReference { + fn into(self) -> PacketDataType { + let (name, properties) = match self { + DataTypeReference::Simple(simple) => { + (simple, Value::Null) + } + DataTypeReference::Complex { name, properties } => { + (name, properties) + } + }; + + PacketDataType::new(name.as_str(), Cow::Borrowed(&properties)). + or_else(|| { + let option = NativeType::new(name.as_str(), Cow::Borrowed(&properties)); + option.map(PacketDataType::Native) + }) + .unwrap_or_else(|| { + PacketDataType::Other { + name: Some(name.into()), + value: properties, + } + }) + } +} + +#[derive(Debug, Clone)] pub struct Packet { pub name: String, pub data: Vec<(String, DataTypeReference)>, } -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct PacketTypes { pub packet_mapper: PacketMapperSwitch, pub types: Vec, @@ -89,7 +115,7 @@ impl<'de> Deserialize<'de> for PacketTypes { let name = obj.remove("name"); let name = if let Some(name) = name { name.to_string() - }else{ + } else { "anon".to_string() }; let value = obj.remove("type").ok_or_else(|| de::Error::custom(format!("Packet ID {} missing type", key)))?; diff --git a/src/models/protocol/packet_mapper.rs b/src/models/protocol/packet_mapper.rs index 27bda65..0649fe6 100644 --- a/src/models/protocol/packet_mapper.rs +++ b/src/models/protocol/packet_mapper.rs @@ -1,26 +1,45 @@ use std::collections::HashMap; +use std::convert::TryInto; use std::fmt; +use std::iter::Map; +use std::num::ParseIntError; use serde::de::{SeqAccess, Visitor}; use serde::{de, Deserialize, Deserializer}; use serde_json::Value; -#[derive(Deserialize, Debug)] +#[derive(Deserialize, Debug, Clone)] pub struct PacketMapper { /// A Type #[serde(rename = "type")] pub map_type: String, + /// The first Value is a Hex value of the packet id. That is a string in the JSON. You can convert the map with the `i32::from_str_radix` (The ids do start with 0x) function. You can also just do try_into::() on the PacketMapper + /// The second Value is the name of the packet pub mappings: HashMap, } -#[derive(Deserialize, Debug)] +impl TryInto> for PacketMapper { + type Error = ParseIntError; + + fn try_into(self) -> Result, Self::Error> { + let mut map = HashMap::with_capacity(self.mappings.len()); + for (key, value) in self.mappings.into_iter() { + let key = i32::from_str_radix(key.trim_start_matches("0x"), 16)?; + map.insert(key, value); + } + Ok(map) + } +} + +#[derive(Deserialize, Debug, Clone)] pub struct PacketSwitch { #[serde(rename = "compareTo")] pub compare_to: String, + /// First value is the name of the packet. Second is the name of the JSON object for the packet. pub fields: HashMap, } -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct PacketMapperSwitch { pub mapper: PacketMapper, pub switch: PacketSwitch, @@ -59,10 +78,10 @@ impl<'de> Deserialize<'de> for PacketMapperSwitch { } else if key.eq("switch") { let value: PacketSwitch = serde_json::from_value(value).map_err(de::Error::custom)?; switch = Some(value); - }else{ + } else { return Err(de::Error::custom("unknown key")); } - }else{ + } else { return Err(de::Error::custom("unknown key")); } } else { diff --git a/src/models/protocol/types.rs b/src/models/protocol/types.rs index ad6b040..8914128 100644 --- a/src/models/protocol/types.rs +++ b/src/models/protocol/types.rs @@ -435,6 +435,9 @@ pub enum PacketDataType { }, /// A Type that could not be built or parsed. This is a fallback for when we don't know what the type is /// This type is usually a reference to a built type + /// + /// If this is a reference you you will want to push any data within Value to the reference. + /// For example the Packet type references another type called "PacketData" that has a variable within it for the compareTo value. You will want to take the value from the Value and push it to the PacketData type. Other { // The name of the type if found name: Option, @@ -492,7 +495,7 @@ impl PacketDataType { } } -#[derive(Debug)] +#[derive(Debug,Clone)] pub struct PacketDataTypes { pub types: Vec, }