1use proc_macro::TokenStream;
2use syn::{parse_macro_input, DeriveInput};
3
4extern crate proc_macro;
5#[macro_use]
6extern crate quote;
7
8struct GFFStructId(syn::LitInt);
11
12impl syn::parse::Parse for GFFStructId {
13 fn parse(input: syn::parse::ParseStream) -> syn::parse::Result<Self> {
14 let content;
15 syn::parenthesized!(content in input);
16 let st_id = content.parse()?;
17 Ok(GFFStructId(st_id))
18 }
19}
20
21#[proc_macro_derive(GFFStruct, attributes(GFFStructId))]
22pub fn derive_gff_struct(input: TokenStream) -> TokenStream {
23 let input = parse_macro_input!(input as DeriveInput);
25
26 let attribute = input.attrs.iter().find(
28 |a| a.path.segments.len() == 1 && a.path.segments[0].ident == "GFFStructId"
29 ).expect("GFFStructId attribute required for deriving GFFStruct");
30 let parameters: GFFStructId = syn::parse2(attribute.tokens.clone())
31 .expect("Invalid GFFStructId attribute!");
32
33 let struct_name = &input.ident;
34 let input = input.data;
35 let struct_id = parameters.0;
36
37 match input {
38 syn::Data::Enum(_) => { panic!("Expected struct, got enum"); }
39 syn::Data::Union(_) => { panic!("Expected struct, got union"); }
40 syn::Data::Struct(data_struct) => {
41 match data_struct.fields {
42 syn::Fields::Unnamed(_) => { panic!("Expected named fields, got unnamed"); }
43 syn::Fields::Unit => { panic!("Expected named fields, got unit"); }
44 syn::Fields::Named(named_fields) => {
45 let fields : Vec<&syn::Ident> = named_fields.named.iter().map(|field| {
46 field.ident.as_ref().unwrap()
47 }).collect();
48 let keys : Vec<String> = fields.iter().map(|ident| {
49 ident.to_string()
50 }).collect();
51
52 let expanded = quote! {
54 impl std::convert::TryFrom<&GffFieldValue> for #struct_name {
56 type Error = &'static str;
57
58 fn try_from(value: &GffFieldValue) -> Result<Self, self::Error> {
59 match value {
60 ::gff::common::GffFieldValue::Struct(s) =>
61 ::gff::common::Deserialize::deserialize(s),
62 _ => Err("Expected Struct"),
63 }
64 }
65 }
66 impl ::gff::common::Deserialize for #struct_name {
67 fn deserialize(s: &::gff::common::GffStruct)
68 -> Result<Self, &'static str> where Self: std::marker::Sized {
69 Ok(#struct_name {
70 #(
71 #fields : std::convert::TryFrom::try_from(
72 s.fields.get(#keys)
73 .ok_or("key not found")?
74 )?
75 ),*
76 })
77 }
78 }
79
80 impl ::gff::common::Serialize for #struct_name {
82 fn serialize(&self) -> Result<GffStruct, &'static str> {
83 Ok(GffStruct {
84 st_type: #struct_id,
85 fields: HashMap::from([
86 #(
87 (#keys.to_string(), (&self.#fields).try_into()?)
88 ),*
89 ])
90 })
91 }
92 }
93 impl std::convert::TryInto<GffFieldValue> for &#struct_name {
94 type Error = &'static str;
95
96 fn try_into(self) -> Result<GffFieldValue, self::Error> {
97 Ok(GffFieldValue::Struct(::gff::common::Serialize::serialize(self)?))
98 }
99 }
100 };
101
102 TokenStream::from(expanded)
104 }
105 }
106 }
107 }
108}
109
110#[proc_macro_derive(GFFStructPack, attributes(GFFStructId))]
111pub fn derive_gff_struct_pack(input: TokenStream) -> TokenStream {
112 let input = parse_macro_input!(input as DeriveInput);
114
115 let attribute = input.attrs.iter().find(
117 |a| a.path.segments.len() == 1 && a.path.segments[0].ident == "GFFStructId"
118 ).expect("GFFStructId attribute required for deriving GFFStruct");
119 let parameters: GFFStructId = syn::parse2(attribute.tokens.clone())
120 .expect("Invalid GFFStructId attribute!");
121
122 let struct_name = &input.ident;
123 let input = input.data;
124 let struct_id = parameters.0;
125
126 match input {
127 syn::Data::Enum(_) => { panic!("Expected struct, got enum"); }
128 syn::Data::Union(_) => { panic!("Expected struct, got union"); }
129 syn::Data::Struct(data_struct) => {
130 let field_count = data_struct.fields.len();
131 match data_struct.fields {
132 syn::Fields::Unnamed(_) => { panic!("Expected named fields, got unnamed"); }
133 syn::Fields::Unit => { panic!("Expected named fields, got unit"); }
134 syn::Fields::Named(named_fields) => {
135 let fields : Vec<&syn::Ident> = named_fields.named.iter().map(|field| {
136 field.ident.as_ref().unwrap()
137 }).collect();
138 let keys : Vec<String> = fields.iter().map(|ident| {
139 ident.to_string()
140 }).collect();
141
142 let pack_field_idx = match field_count {
143 0..=1 => quote! {
144 packer.data.structs.extend_from_slice(
145 &(packer.data.header.fields.1 as u32).to_le_bytes()
146 );
147 },
148 _ => quote! {
149 packer.data.structs.extend_from_slice(
150 &(packer.data.header.field_indices.1 as u32).to_le_bytes()
151 );
152 },
153 };
154
155 let expanded = quote! {
157 impl <'a, W: std::io::Write> gff::packer::PackField<'a, W> for #struct_name {
158 fn pack_field(&'a self, label: String, packer: &mut gff::packer::Packer<W>,
159 structs: &mut Vec<&'a dyn gff::packer::PackStruct<W>>, st_idx: &mut u32)
160 -> ()
161 {
162 let label_idx = packer.pack_label(&label).unwrap();
163
164 *st_idx += 1;
165 packer.pack_val_4(14, label_idx, &(*st_idx).to_le_bytes());
166 structs.push(self);
167 }
168 }
169
170 impl<'a, W: std::io::Write> ::gff::packer::PackStruct<'a, W> for #struct_name {
172 fn pack(&'a self, packer: &mut ::gff::packer::Packer<W>,
173 structs: &mut Vec<&'a dyn ::gff::packer::PackStruct<W>>,
174 st_idx: &mut u32)
175 -> ()
176 {
177 packer.data.structs.extend_from_slice(
179 &(#struct_id as u32).to_le_bytes()
180 );
181 #pack_field_idx
183 packer.data.structs.extend_from_slice(
185 &(#field_count as u32).to_le_bytes()
186 );
187 #(
189 gff::packer::PackField::pack_field(
190 &self.#fields, #keys.to_string(),
191 packer, structs, st_idx
192 );
193 )*;
194 }
196 }
197 };
198
199 TokenStream::from(expanded)
201 }
202 }
203 }
204 }
205}
206
207