ireko/paramacro/src/lib.rs

80 lines
2.2 KiB
Rust
Raw Normal View History

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()
}