From 17c7360c76c580befd679043075346733c7e717b Mon Sep 17 00:00:00 2001 From: Kyler Date: Sun, 14 Sep 2025 21:46:57 -0600 Subject: [PATCH] Replaced `PacketArray` trait with `McType` macro --- purple_cello_mc_derive/src/lib.rs | 48 +++++++++++++++++++++++++++++++ src/mc_types.rs | 43 ++++++++++++++++++++++++--- src/mc_types/helpers.rs | 13 --------- src/mc_types/packet.rs | 23 --------------- 4 files changed, 87 insertions(+), 40 deletions(-) diff --git a/purple_cello_mc_derive/src/lib.rs b/purple_cello_mc_derive/src/lib.rs index b89f595..3867a04 100644 --- a/purple_cello_mc_derive/src/lib.rs +++ b/purple_cello_mc_derive/src/lib.rs @@ -107,3 +107,51 @@ pub fn derive_packet(input: TokenStream) -> TokenStream { expanded.into() } + +#[proc_macro_derive(McType)] +pub fn derive_mctype_struct(input: TokenStream) -> TokenStream { + let input = parse_macro_input!(input as DeriveInput); + let name = &input.ident; + + let Data::Struct(data_struct) = input.data else { + return syn::Error::new_spanned(name, "McType can only be derived for structs") + .to_compile_error() + .into(); + }; + + let Fields::Named(fields) = data_struct.fields else { + return syn::Error::new_spanned(name, "McType requires named fields") + .to_compile_error() + .into(); + }; + + // build field accessors + let read_fields = fields.named.iter().map(|f| { + let fname = &f.ident; + let fty = &f.ty; + quote! { #fname: <#fty as McType>::get(data)? } + }); + + let write_fields = fields.named.iter().map(|f| { + let fname = &f.ident; + quote! { out.extend(self.#fname.convert()); } + }); + + let expanded = quote! { + impl McType for #name { + fn get(data: &mut Vec) -> Result { + Ok(Self { + #(#read_fields),* + }) + } + + fn convert(&self) -> Vec { + let mut out = Vec::new(); + #(#write_fields)* + out + } + } + }; + + expanded.into() +} diff --git a/src/mc_types.rs b/src/mc_types.rs index 3cd4be9..5778e37 100644 --- a/src/mc_types.rs +++ b/src/mc_types.rs @@ -10,7 +10,7 @@ use serde::{Serialize, Deserialize}; pub use crate::mc_types::error::PacketError; pub use crate::mc_types::protocol::{ProtocolRead, ProtocolConnection}; -pub use crate::mc_types::packet::{Result, Packet, PacketArray}; +pub use crate::mc_types::packet::{Result, Packet}; use crate::mc_types::helpers::*; pub const VERSION_NAME: &str = "1.21"; @@ -120,7 +120,42 @@ impl McType for String { fn convert(&self) -> Vec { convert_string(*self) } } -impl McType for Vec { - fn get(data: &mut Vec) -> Result { Ok(get_byte_array(data)) } - fn convert(&self) -> Vec { convert_byte_array(*self) } +impl McType for Vec { + fn get(data: &mut Vec) -> Result { + let length = get_var_int(data)?; + let mut out = Vec::with_capacity(length as usize); + for _ in 0..length { + out.push(T::get(data)?); + } + Ok(out) + } + + fn convert(&self) -> Vec { + let mut data = convert_var_int(self.len() as i32); + for el in self { + data.extend(el.convert()); + } + data + } +} + +impl McType for Option { + fn get(data: &mut Vec) -> Result { + if get_bool(data) { + Ok(Some(T::get(data)?)) + } else { + Ok(None) + } + } + + fn convert(&self) -> Vec { + match self { + Some(v) => { + let mut data = convert_bool(true); + data.extend(v.convert()); + data + } + None => convert_bool(false), + } + } } diff --git a/src/mc_types/helpers.rs b/src/mc_types/helpers.rs index d73e481..30202f4 100644 --- a/src/mc_types/helpers.rs +++ b/src/mc_types/helpers.rs @@ -242,16 +242,3 @@ pub fn convert_string(s: &str) -> Vec { data.append(&mut s.as_bytes().to_vec()); data } - -pub fn get_byte_array(data: &mut Vec) -> Result> { - let length = get_var_int(data)? as usize; - let buffer = data[..length].to_vec(); - for _ in 0..length { data.remove(0); } - Ok(buffer) -} -pub fn convert_byte_array(mut s: &mut Vec) -> Vec { - let length = s.len() as i32; - let mut data = convert_var_int(length); - data.append(&mut s); - data -} diff --git a/src/mc_types/packet.rs b/src/mc_types/packet.rs index 70843be..74b825f 100644 --- a/src/mc_types/packet.rs +++ b/src/mc_types/packet.rs @@ -30,26 +30,3 @@ pub trait Packet: Sized { conn.write_data(&mut self.convert()).await } } - -pub trait PacketArray: Sized { - fn get(data: &mut Vec) -> Result; - fn convert(&self) -> Vec; - - fn get_array(data: &mut Vec) -> Result> { - let length = get_var_int(data)?; - let mut out_data: Vec = vec![]; - for _ in 0..length { - out_data.push(Self::get(data)?); - } - Ok(out_data) - } - - fn convert_array(array: &mut Vec) -> Vec { - let length = array.len() as i32; - let mut data: Vec = convert_var_int(length); - for element in array { - data.append(&mut Self::convert(element)); - } - data - } -}