80 lines
2.2 KiB
Rust
80 lines
2.2 KiB
Rust
|
extern crate proc_macro;
|
||
|
|
||
|
use proc_macro::TokenStream;
|
||
|
use quote::{quote, ToTokens};
|
||
|
use syn::{parse_macro_input, Expr, Fields, Item, Lit};
|
||
|
|
||
|
// TODO: clean up this mess.
|
||
|
|
||
|
/// Helps read and write serialized structs. These are structs that have named fields with known types.
|
||
|
/// Note: This adds a hidden "None" at the end of the struct as well.
|
||
|
#[proc_macro_attribute]
|
||
|
pub fn serialized_struct(_metadata: TokenStream, input: TokenStream)
|
||
|
-> TokenStream {
|
||
|
let mut input = syn::parse_macro_input!(input as syn::ItemStruct);
|
||
|
|
||
|
for mut field in &mut input.fields {
|
||
|
let our_custom = &field.attrs[0];
|
||
|
let our_custom_name = our_custom.meta.require_name_value().unwrap();
|
||
|
let our_custom_name = match &our_custom_name.value {
|
||
|
Expr::Lit(_0) => {
|
||
|
match &_0.lit {
|
||
|
Lit::Str(_0) => {
|
||
|
Some(_0.value())
|
||
|
}
|
||
|
_ => None
|
||
|
}
|
||
|
}
|
||
|
_ => None
|
||
|
}.unwrap();
|
||
|
field.attrs.clear();
|
||
|
let field_tokens = field.to_token_stream();
|
||
|
let new_field_token_stream = quote! {
|
||
|
#[br(parse_with = crate::structs::read_struct_field, args(#our_custom_name))]
|
||
|
#field_tokens
|
||
|
};
|
||
|
let buffer = ::syn::parse::Parser::parse2(
|
||
|
syn::Field::parse_named,
|
||
|
new_field_token_stream,
|
||
|
).unwrap();
|
||
|
*field = buffer;
|
||
|
}
|
||
|
|
||
|
// Add "None" field
|
||
|
let none_field_stream = quote! {
|
||
|
#[br(temp)]
|
||
|
#[bw(ignore)]
|
||
|
none_field: crate::structs::PrimaryAssetNameProperty
|
||
|
};
|
||
|
let buffer = ::syn::parse::Parser::parse2(
|
||
|
syn::Field::parse_named,
|
||
|
none_field_stream,
|
||
|
).unwrap();
|
||
|
match &mut input.fields {
|
||
|
Fields::Named(_0) => {
|
||
|
_0.named.push(buffer)
|
||
|
}
|
||
|
_ => {}
|
||
|
}
|
||
|
|
||
|
let output = quote! {
|
||
|
#[binrw]
|
||
|
#input
|
||
|
};
|
||
|
|
||
|
output.into_token_stream().into()
|
||
|
}
|
||
|
|
||
|
/// Denotes a field with a known name.
|
||
|
#[proc_macro_attribute]
|
||
|
pub fn serialized_field(attr: TokenStream, input: TokenStream) -> TokenStream {
|
||
|
let input2 = parse_macro_input!(input as Item);
|
||
|
|
||
|
let output = quote! {
|
||
|
#[binrw]
|
||
|
#input2
|
||
|
};
|
||
|
|
||
|
output.into_token_stream().into()
|
||
|
}
|