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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
use proc_macro::TokenStream;
use quote::quote;
use syn::{self, Fields, Item};
#[proc_macro_attribute]
pub fn serializable(attr: TokenStream, input: TokenStream) -> TokenStream {
if !attr.is_empty() {
panic!("No attributes expected")
}
let ast = syn::parse(input).unwrap();
impl_serialize(ast)
}
fn impl_serialize(ast: Item) -> TokenStream {
match &ast {
Item::Struct(s) => {
let ident = &s.ident;
let (serializers, deserializers) = match &s.fields {
Fields::Unit => (quote! { }, quote! { Self }),
Fields::Named(fields) => {
let serializers = fields.named.iter().map(|field| {
let fident = field.ident.as_ref().unwrap();
quote! { binverse::serialize::Serialize::serialize(&self.#fident, s)?; }
});
let deserializers = fields.named.iter().map(|field| {
let fident = field.ident.as_ref().unwrap();
quote! { #fident: binverse::serialize::Deserialize::deserialize(d)? }
});
(
quote! { #(#serializers)* },
quote! {
Self {
#(#deserializers,)*
}
}
)
},
Fields::Unnamed(fields) => {
let serializers = fields.unnamed.iter().enumerate().map(|(i, _)| {
quote! { binverse::serialize::Serialize::serialize(&self.#i, s)?; }
});
let deserializers = fields.unnamed.iter().map(|_| {
quote! { binverse::serialize::Deserialize::deserialize(d)? }
});
(
quote! { #(#serializers)* },
quote! { Self(#(#deserializers,)*) }
)
}
};
quote! {
#ast
impl binverse::serialize::Serialize for #ident {
fn serialize<W: std::io::Write>(&self, s: &mut binverse::streams::Serializer<W>) -> binverse::error::BinverseResult<()> {
#serializers
Ok(())
}
}
impl binverse::serialize::Deserialize for #ident {
fn deserialize<R: std::io::Read>(d: &mut binverse::streams::Deserializer<R>) -> binverse::error::BinverseResult<Self> {
Ok(#deserializers)
}
}
}.into()
},
Item::Enum(_e) => {
todo!("Enums are not yet implemented")
},
_ => panic!("Only structs and enums are supported by serialize/deserialize attribute!")
}
}