diff --git a/psopacket/Cargo.toml b/psopacket/Cargo.toml index fe5cafa..2bf042f 100644 --- a/psopacket/Cargo.toml +++ b/psopacket/Cargo.toml @@ -8,6 +8,6 @@ edition = "2018" proc-macro = true [dependencies] -syn = {version = "1.0", features=["full", "extra-traits", "parsing"]} +syn = {version = "2.0.39", features=["full", "extra-traits", "parsing"]} quote = "1.0" proc-macro2 = "1.0" diff --git a/psopacket/src/lib.rs b/psopacket/src/lib.rs index fa93e38..344ed2d 100644 --- a/psopacket/src/lib.rs +++ b/psopacket/src/lib.rs @@ -6,8 +6,10 @@ extern crate proc_macro; use proc_macro::TokenStream; -use syn::{parse_macro_input, ItemStruct, NestedMeta, DeriveInput, Field}; +use syn::{parse_macro_input, ItemStruct, DeriveInput, Field}; use syn::punctuated::Iter; +use syn::punctuated::Punctuated; +use syn::parse::Parse; use quote::quote; #[derive(Debug, PartialEq)] @@ -308,7 +310,7 @@ fn get_struct_fields(fields: Iter) -> Result, TokenStream> } let mut attr_meta = AttrMeta::None; for attr in &field.attrs { - attr_meta = match attr.path.segments[0].ident.to_string().as_str() { + attr_meta = match attr.path().segments[0].ident.to_string().as_str() { "utf8" => AttrMeta::Utf8, "utf16" => AttrMeta::Utf16, "nodebug" => AttrMeta::NoDebug, @@ -345,35 +347,51 @@ fn get_struct_fields(fields: Iter) -> Result, TokenStream> } -#[proc_macro_attribute] -pub fn pso_packet(attr: TokenStream, item: TokenStream) -> TokenStream { - let args = parse_macro_input!(attr as syn::AttributeArgs); - let mut cmd = 0; - let mut flag = true; - let mut manual_flag = false; - for a in args { - match &a { - NestedMeta::Lit(lit) => { - if let syn::Lit::Int(litint) = lit { - cmd = litint.base10_parse().unwrap(); - } - }, - NestedMeta::Meta(k) => { - if let syn::Meta::Path(syn::Path {segments, ..}) = k { - match segments[0].ident.to_string().as_str() { - "no_flag" => flag = false, - "manual_flag" => { - flag = false; - manual_flag = true; - }, - _ => { - return syn::Error::new(segments[0].ident.span(), "unknown macro param").to_compile_error().into(); +#[derive(Debug)] +struct PSOPacketAttrs { + cmd: u16, + flag: bool, + manual_flag: bool, +} + +impl Parse for PSOPacketAttrs { + fn parse(input: syn::parse::ParseStream) -> syn::Result { + let vars = Punctuated::::parse_terminated(input)?; + + let (cmd, flag, manual_flag) = vars + .into_iter() + .fold((None, true, false), |mut acc, attr| { + match attr { + syn::Expr::Lit(lit) => { + if let syn::Lit::Int(int) = lit.lit { + acc.0 = int.base10_parse().ok(); + } + }, + syn::Expr::Path(path) => { + if path.path.is_ident("no_flag") { + acc.1 = false; + } + if path.path.is_ident("manual_flag") { + acc.2 = true; } } + _ => {}, } - }, - } + acc + }); + Ok(PSOPacketAttrs { + cmd: cmd.unwrap(), + flag, + manual_flag + }) } +} + + + +#[proc_macro_attribute] +pub fn pso_packet(attr: TokenStream, item: TokenStream) -> TokenStream { + let args = parse_macro_input!(attr as PSOPacketAttrs); let pkt_struct = parse_macro_input!(item as ItemStruct); let attrs = match get_struct_fields(pkt_struct.fields.iter()) { @@ -381,7 +399,7 @@ pub fn pso_packet(attr: TokenStream, item: TokenStream) -> TokenStream { Err(err) => return err }; - if manual_flag { + if args.manual_flag { match &attrs[0] { AttrType::Array(_, ident, _, _) => { if ident.to_string() != "flag" { @@ -397,7 +415,7 @@ pub fn pso_packet(attr: TokenStream, item: TokenStream) -> TokenStream { } let struct_def = generate_struct_def(pkt_struct.ident.clone(), &attrs); - let psopacket_impl = generate_psopacket_impl(cmd, pkt_struct.ident.clone(), &attrs, flag); + let psopacket_impl = generate_psopacket_impl(args.cmd, pkt_struct.ident.clone(), &attrs, args.flag); let debug_impl = generate_debug_impl(pkt_struct.ident.clone(), &attrs); let partialeq_impl = generate_partialeq_impl(pkt_struct.ident.clone(), &attrs); @@ -588,18 +606,10 @@ fn generate_psomessage_impl(msg_cmd: u8, name: syn::Ident, attrs: &Vec #[proc_macro_attribute] pub fn pso_message(attr: TokenStream, item: TokenStream) -> TokenStream { - let args = parse_macro_input!(attr as syn::AttributeArgs); - let mut cmd = 0; - for a in args { - if let NestedMeta::Lit(lit) = a { - if let syn::Lit::Int(litint) = lit { - cmd = litint.base10_parse().unwrap(); - } - } - } - + let cmd = parse_macro_input!(attr as syn::LitInt).base10_parse().unwrap(); let pkt_struct = parse_macro_input!(item as ItemStruct); - let mut attrs = match get_struct_fields(pkt_struct.fields.iter()) { + + let mut fields = match get_struct_fields(pkt_struct.fields.iter()) { Ok(a) => a, Err(err) => return err }; @@ -617,13 +627,13 @@ pub fn pso_message(attr: TokenStream, item: TokenStream) -> TokenStream { segments: punctuated } }; - attrs.insert(0, AttrType::Value(u8tpath.clone(), syn::Ident::new("target", proc_macro2::Span::call_site()), AttrMeta::None)); - attrs.insert(0, AttrType::Value(u8tpath, syn::Ident::new("client", proc_macro2::Span::call_site()), AttrMeta::None)); + fields.insert(0, AttrType::Value(u8tpath.clone(), syn::Ident::new("target", proc_macro2::Span::call_site()), AttrMeta::None)); + fields.insert(0, AttrType::Value(u8tpath, syn::Ident::new("client", proc_macro2::Span::call_site()), AttrMeta::None)); - let struct_def = generate_struct_def(pkt_struct.ident.clone(), &attrs); - let psopacket_impl = generate_psomessage_impl(cmd, pkt_struct.ident.clone(), &attrs); - let debug_impl = generate_debug_impl(pkt_struct.ident.clone(), &attrs); - let partialeq_impl = generate_partialeq_impl(pkt_struct.ident.clone(), &attrs); + let struct_def = generate_struct_def(pkt_struct.ident.clone(), &fields); + let psopacket_impl = generate_psomessage_impl(cmd, pkt_struct.ident.clone(), &fields); + let debug_impl = generate_debug_impl(pkt_struct.ident.clone(), &fields); + let partialeq_impl = generate_partialeq_impl(pkt_struct.ident.clone(), &fields); let q = quote!{ #[derive(Clone)]