Files
exe-parse/src-tauri/pe_serialize_proc_macro/src/lib.rs
T

86 lines
3.5 KiB
Rust

use proc_macro::TokenStream;
use quote::quote;
use syn::Data;
fn impl_serialize_ex(ast: &syn::DeriveInput) -> TokenStream {
let name = &ast.ident;
let fields = match ast.data {
Data::Struct(ref data) => &data.fields,
_ => panic!("CustomSerialize 只能用于结构体!"),
};
let field_len = fields.len();
// 迭代器,为每一个字段实现serialize_field
let serialize_fields = match fields {
syn::Fields::Named(ref fields) => {
fields.named.iter().map(|f| {
let name = &f.ident;
let ty = &f.ty;
let mut child_token_stream = proc_macro2::TokenStream::new();
// 如果字段是数组类型
if let syn::Type::Array(ref array) = ty {
let len = &array.len;
let child_ty = &array.elem;
// 类型所占字节
child_token_stream = quote! {
children = Some(Vec::new());
let field_size = std::mem::size_of::<#child_ty>();
for i in 0..#len {
let child_value = serde_json::json!({
"name": format!("{}[{}]", stringify!(#name), i),
"value": format!("0x{:0width$X}",self.#name[i], width=field_size),
"field_type": stringify!(#child_ty),
"size": field_size,
"offset": (&self.#name[i] as *const _ as usize) - (self as *const _ as usize),
"children": null
});
children.as_mut().unwrap().push(child_value);
}
};
}else{
child_token_stream = quote! {
let field_size = std::mem::size_of::<#ty>();
value = serde_json::json!(format!("0x{:0width$X}",&self.#name, width=field_size));
};
}
quote! {
let mut value = serde_json::Value::Null;
let mut children: Option<Vec<serde_json::Value>> = None;
#child_token_stream
let json_value = serde_json::json!({
"name": stringify!(#name),
"value": value,
"field_type": stringify!(#ty),
"size": std::mem::size_of::<#ty>(),
"offset": (&self.#name as *const _ as usize) - (self as *const _ as usize),
"children": &children
});
state.serialize_field(stringify!(#name), &json_value)?;
}
})
}
_ => panic!("CustomSerialize 只能用于结构体!"),
};
let gen = quote! {
impl serde::Serialize for #name {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer {
let mut state = serializer.serialize_struct(stringify!(#name), #field_len)?;
#(#serialize_fields)*
state.end()
}
}
};
gen.into()
}
// 拓展Serialize
#[proc_macro_derive(SerializeEX)]
pub fn serialize_ex(input: TokenStream) -> TokenStream {
let ast = syn::parse(input).unwrap();
impl_serialize_ex(&ast)
}