Replaced `PacketArray` trait with `McType` macro

This commit is contained in:
Kyler Olsen 2025-09-14 21:46:57 -06:00
parent 90f2270c78
commit 17c7360c76
4 changed files with 87 additions and 40 deletions

View File

@ -107,3 +107,51 @@ pub fn derive_packet(input: TokenStream) -> TokenStream {
expanded.into() 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<u8>) -> Result<Self> {
Ok(Self {
#(#read_fields),*
})
}
fn convert(&self) -> Vec<u8> {
let mut out = Vec::new();
#(#write_fields)*
out
}
}
};
expanded.into()
}

View File

@ -10,7 +10,7 @@ use serde::{Serialize, Deserialize};
pub use crate::mc_types::error::PacketError; pub use crate::mc_types::error::PacketError;
pub use crate::mc_types::protocol::{ProtocolRead, ProtocolConnection}; 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::*; use crate::mc_types::helpers::*;
pub const VERSION_NAME: &str = "1.21"; pub const VERSION_NAME: &str = "1.21";
@ -120,7 +120,42 @@ impl McType for String {
fn convert(&self) -> Vec<u8> { convert_string(*self) } fn convert(&self) -> Vec<u8> { convert_string(*self) }
} }
impl McType for Vec<u8> { impl<T: McType> McType for Vec<T> {
fn get(data: &mut Vec<u8>) -> Result<Self> { Ok(get_byte_array(data)) } fn get(data: &mut Vec<u8>) -> Result<Self> {
fn convert(&self) -> Vec<u8> { convert_byte_array(*self) } 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<u8> {
let mut data = convert_var_int(self.len() as i32);
for el in self {
data.extend(el.convert());
}
data
}
}
impl<T: McType> McType for Option<T> {
fn get(data: &mut Vec<u8>) -> Result<Self> {
if get_bool(data) {
Ok(Some(T::get(data)?))
} else {
Ok(None)
}
}
fn convert(&self) -> Vec<u8> {
match self {
Some(v) => {
let mut data = convert_bool(true);
data.extend(v.convert());
data
}
None => convert_bool(false),
}
}
} }

View File

@ -242,16 +242,3 @@ pub fn convert_string(s: &str) -> Vec<u8> {
data.append(&mut s.as_bytes().to_vec()); data.append(&mut s.as_bytes().to_vec());
data data
} }
pub fn get_byte_array(data: &mut Vec<u8>) -> Result<Vec<u8>> {
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<u8>) -> Vec<u8> {
let length = s.len() as i32;
let mut data = convert_var_int(length);
data.append(&mut s);
data
}

View File

@ -30,26 +30,3 @@ pub trait Packet: Sized {
conn.write_data(&mut self.convert()).await conn.write_data(&mut self.convert()).await
} }
} }
pub trait PacketArray: Sized {
fn get(data: &mut Vec<u8>) -> Result<Self>;
fn convert(&self) -> Vec<u8>;
fn get_array(data: &mut Vec<u8>) -> Result<Vec<Self>> {
let length = get_var_int(data)?;
let mut out_data: Vec<Self> = vec![];
for _ in 0..length {
out_data.push(Self::get(data)?);
}
Ok(out_data)
}
fn convert_array(array: &mut Vec<Self>) -> Vec<u8> {
let length = array.len() as i32;
let mut data: Vec<u8> = convert_var_int(length);
for element in array {
data.append(&mut Self::convert(element));
}
data
}
}