|
|
@ -16,6 +16,8 @@ enum AttrMeta { |
|
|
|
Utf8,
|
|
|
|
Utf16,
|
|
|
|
NoDebug,
|
|
|
|
LengthIs(syn::Ident),
|
|
|
|
LengthOf(syn::Ident),
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
@ -237,9 +239,9 @@ fn generate_debug_impl(name: syn::Ident, attrs: &Vec<AttrType>) -> proc_macro2:: |
|
|
|
AttrMeta::NoDebug => quote! {
|
|
|
|
write!(f, " {} [{}; {}]: [...]\n", #ident_str, #type_str, #len)?;
|
|
|
|
},
|
|
|
|
AttrMeta::None => quote! {
|
|
|
|
_ => quote! {
|
|
|
|
write!(f, " {} [{}; {}]: {:?}\n", #ident_str, #type_str, #len, self.#name.to_vec())?;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
@ -306,6 +308,8 @@ fn get_struct_fields(fields: Iter<Field>) -> Result<Vec<AttrType>, TokenStream> |
|
|
|
"utf8" => AttrMeta::Utf8,
|
|
|
|
"utf16" => AttrMeta::Utf16,
|
|
|
|
"nodebug" => AttrMeta::NoDebug,
|
|
|
|
"length_is" => AttrMeta::LengthIs(attr.parse_args::<syn::Ident>().unwrap()),
|
|
|
|
"length_of" => AttrMeta::LengthOf(attr.parse_args::<syn::Ident>().unwrap()),
|
|
|
|
_ => AttrMeta::None
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -404,9 +408,130 @@ pub fn pso_packet(attr: TokenStream, item: TokenStream) -> TokenStream { |
|
|
|
q.into()
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn generate_psomessage_from_bytes(attrs: &Vec<AttrType>) -> (Vec<proc_macro2::TokenStream>, Vec<proc_macro2::TokenStream>) {
|
|
|
|
//let mut from_bytes = Vec::new();
|
|
|
|
let mut assignment = Vec::new();
|
|
|
|
let mut structure_creation = Vec::new();
|
|
|
|
for attr in attrs {
|
|
|
|
let (assignment_element, creation_element) = match attr {
|
|
|
|
AttrType::Value(ty, name, meta) => {
|
|
|
|
let temp_name = syn::Ident::new(&("_".to_string() + &name.to_string()), name.span());
|
|
|
|
let type_str = ty.path.segments[0].ident.to_string();
|
|
|
|
if type_str == "Vec" {
|
|
|
|
let vec_type = match &ty.path.segments[0].arguments {
|
|
|
|
syn::PathArguments::AngleBracketed(arg) => {
|
|
|
|
match &arg.args[0] {
|
|
|
|
syn::GenericArgument::Type(typ) => {
|
|
|
|
match &typ {
|
|
|
|
syn::Type::Path(path) => {
|
|
|
|
Some(path.path.segments[0].ident.clone())
|
|
|
|
}
|
|
|
|
_ => None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => None
|
|
|
|
}.unwrap();
|
|
|
|
|
|
|
|
let length_variable = match meta {
|
|
|
|
AttrMeta::LengthIs(ident) => syn::Ident::new(&("_".to_string() + &ident.to_string()), ident.span()),
|
|
|
|
_ => panic!("{} does not have a length specified", name),
|
|
|
|
};
|
|
|
|
let assignment = quote! {
|
|
|
|
let mut #temp_name = Vec::new();
|
|
|
|
|
|
|
|
for _ in 0..#length_variable {
|
|
|
|
#temp_name.push(<#vec_type as PSOPacketData>::from_bytes(&mut cur)?);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
let creation = quote! {
|
|
|
|
#name: #temp_name,
|
|
|
|
};
|
|
|
|
|
|
|
|
(assignment, creation)
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
let assignment = quote! {
|
|
|
|
let #temp_name = <#ty as PSOPacketData>::from_bytes(&mut cur)?;
|
|
|
|
};
|
|
|
|
let creation = quote! {
|
|
|
|
#name: #temp_name,
|
|
|
|
};
|
|
|
|
|
|
|
|
(assignment, creation)
|
|
|
|
}
|
|
|
|
},
|
|
|
|
AttrType::Array(ty, name, len, _) => {
|
|
|
|
let temp_name = syn::Ident::new(&("_".to_string() + &name.to_string()), name.span());
|
|
|
|
let assignment = quote! {
|
|
|
|
let #temp_name = {
|
|
|
|
let mut arr = [#ty::default(); #len];
|
|
|
|
for e in arr.iter_mut() {
|
|
|
|
*e = #ty::from_bytes(&mut cur)?
|
|
|
|
}
|
|
|
|
arr
|
|
|
|
};
|
|
|
|
};
|
|
|
|
let creation = quote! {
|
|
|
|
#name: #temp_name,
|
|
|
|
};
|
|
|
|
(assignment, creation)
|
|
|
|
}
|
|
|
|
};
|
|
|
|
assignment.push(assignment_element);
|
|
|
|
structure_creation.push(creation_element);
|
|
|
|
}
|
|
|
|
(assignment, structure_creation)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn generate_psomessage_as_bytes(attrs: &Vec<AttrType>) -> Vec<proc_macro2::TokenStream> {
|
|
|
|
let mut as_bytes = Vec::new();
|
|
|
|
for attr in attrs {
|
|
|
|
let element = match attr {
|
|
|
|
AttrType::Value(ty, name, meta) => {
|
|
|
|
let type_str = ty.path.segments[0].ident.to_string();
|
|
|
|
if type_str == "Vec" {
|
|
|
|
quote! {
|
|
|
|
for i in self.#name.iter() {
|
|
|
|
buf.extend_from_slice(&PSOPacketData::as_bytes(i));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if let AttrMeta::LengthOf(ident) = meta {
|
|
|
|
quote! {
|
|
|
|
buf.extend_from_slice(&PSOPacketData::as_bytes(&(self.#ident.len() as #ty)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
quote! {
|
|
|
|
buf.extend_from_slice(&PSOPacketData::as_bytes(&self.#name));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
AttrType::Array(_ty, name, len, _) => {
|
|
|
|
quote! {
|
|
|
|
for i in 0..#len {
|
|
|
|
buf.extend_from_slice(&self.#name[i].as_bytes());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
as_bytes.push(element);
|
|
|
|
}
|
|
|
|
as_bytes
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fn generate_psomessage_impl(msg_cmd: u8, name: syn::Ident, attrs: &Vec<AttrType>) -> proc_macro2::TokenStream {
|
|
|
|
let from_bytes = generate_from_bytes(&attrs);
|
|
|
|
let as_bytes = generate_as_bytes(&attrs);
|
|
|
|
let (assignment, struct_creation)= generate_psomessage_from_bytes(&attrs);
|
|
|
|
let as_bytes = generate_psomessage_as_bytes(&attrs);
|
|
|
|
|
|
|
|
quote! {
|
|
|
|
impl PSOMessage for #name {
|
|
|
@ -430,8 +555,9 @@ fn generate_psomessage_impl(msg_cmd: u8, name: syn::Ident, attrs: &Vec<AttrType> |
|
|
|
}
|
|
|
|
|
|
|
|
let mut cur = std::io::Cursor::new(subbuf);
|
|
|
|
#(#assignment)*
|
|
|
|
let result = Ok(#name {
|
|
|
|
#(#from_bytes)*
|
|
|
|
#(#struct_creation)*
|
|
|
|
});
|
|
|
|
|
|
|
|
result
|
|
|
|