86 lines
3.5 KiB
Rust
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)
|
||
}
|