1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
extern crate proc_macro;
use proc_macro::{TokenStream};
use syn::{DeriveInput, Data};
use quote::quote;
#[proc_macro_derive(Parsable)]
pub fn derive_parsable(struc: TokenStream) -> TokenStream {
let ast: &DeriveInput = &syn::parse(struc).unwrap();
let name = &ast.ident;
if let Data::Struct(data_struct) = &ast.data {
let mut p_fields_gen = vec![];
let mut d_fields_gen = vec![];
for field in &data_struct.fields {
let field_ident = &field.ident.clone().expect("Expected named field");
let field_type = &field.ty;
p_fields_gen.push(
quote! {
#field_ident: <#field_type>::parse(data)?
}
);
d_fields_gen.push(
quote! {
self.#field_ident.dump(data)?;
}
);
}
let final_gen = quote! {
impl Parsable for #name {
fn parse(data: &mut dyn std::io::Read) -> std::io::Result<Self> {
Ok(Self{
#(#p_fields_gen),*
})
}
fn dump(&self, data: &mut dyn std::io::Write) -> std::io::Result<usize> {
let mut write_count: usize = 0;
#(write_count += #d_fields_gen;)*
Ok(write_count)
}
}
};
return final_gen.into();
} else {
panic!("Expected Parsable auto-trait to be applied to struct");
}
}