feat: 写了一个派生宏,来简单的序列化一个结构体
This commit is contained in:
1
src-tauri/pe_serialize_proc_macro/.gitignore
vendored
Normal file
1
src-tauri/pe_serialize_proc_macro/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/target/
|
||||
68
src-tauri/pe_serialize_proc_macro/Cargo.lock
generated
Normal file
68
src-tauri/pe_serialize_proc_macro/Cargo.lock
generated
Normal file
@@ -0,0 +1,68 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "pe_serialize_proc_macro"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"serde",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.92"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.37"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.215"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.215"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.90"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"
|
||||
16
src-tauri/pe_serialize_proc_macro/Cargo.toml
Normal file
16
src-tauri/pe_serialize_proc_macro/Cargo.toml
Normal file
@@ -0,0 +1,16 @@
|
||||
[lib]
|
||||
proc-macro = true
|
||||
|
||||
[package]
|
||||
name = "pe_serialize_proc_macro"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
proc-macro2 = "1.0.92"
|
||||
quote = "1.0.37"
|
||||
serde = "1.0.215"
|
||||
syn = "2.0.90"
|
||||
|
||||
[serde.features]
|
||||
default = ["derive"]
|
||||
85
src-tauri/pe_serialize_proc_macro/src/lib.rs
Normal file
85
src-tauri/pe_serialize_proc_macro/src/lib.rs
Normal file
@@ -0,0 +1,85 @@
|
||||
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)
|
||||
}
|
||||
Reference in New Issue
Block a user