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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
|
use crate::info_structures::{Derive, StructInfo};
use proc_macro2::TokenStream;
use quote::quote;
use syn::{Error, GenericParam, TypeParamBound};
fn add_trait_bound(param: &GenericParam, bound: &TypeParamBound) -> GenericParam {
let mut new = param.clone();
match &mut new {
GenericParam::Type(t) => t.bounds.push(bound.clone()),
_ => (),
}
new
}
fn impl_trait(info: &StructInfo, trait_name: TypeParamBound, body: TokenStream) -> TokenStream {
let generic_params = info.generic_params();
let generic_params = generic_params
.into_iter()
.map(|i| add_trait_bound(i, &trait_name))
.collect::<Vec<_>>();
let generic_args = info.generic_arguments();
let generic_where = &info.generics.where_clause;
let struct_name = &info.ident;
quote! {
impl <#(#generic_params),*> #trait_name for #struct_name <#(#generic_args),*> #generic_where {
#body
}
}
}
fn impl_debug(info: &StructInfo) -> Result<TokenStream, Error> {
let fields = info
.fields
.iter()
.filter(|field| !field.is_mutably_borrowed())
.map(|field| {
let name = &field.name;
quote! {
field(stringify!(#name), &safe_self.#name)
}
})
.collect::<Vec<_>>();
let trait_name = syn::parse_quote! { ::core::fmt::Debug };
let struct_name = &info.ident;
let body = quote! {
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
self.with(|safe_self| {
f.debug_struct(stringify!(#struct_name))
#(.#fields)*
.finish()
})
}
};
Ok(impl_trait(info, trait_name, body))
}
fn impl_partial_eq(info: &StructInfo) -> Result<TokenStream, Error> {
let fields = info
.fields
.iter()
.filter(|field| !field.is_mutably_borrowed())
.map(|field| {
let name = &field.name;
quote! {
&*safe_self.#name == &*safe_other.#name
}
})
.collect::<Vec<_>>();
let trait_name = syn::parse_quote! { ::core::cmp::PartialEq };
let body = quote! {
fn eq(&self, other: &Self) -> bool {
self.with(|safe_self| {
other.with(|safe_other| {
#(#fields)&&*
})
})
}
};
Ok(impl_trait(info, trait_name, body))
}
fn impl_eq(info: &StructInfo) -> Result<TokenStream, Error> {
let trait_name = syn::parse_quote! { ::core::cmp::Eq };
let body = quote! {};
Ok(impl_trait(info, trait_name, body))
}
pub fn create_derives(info: &StructInfo) -> Result<TokenStream, Error> {
let mut impls = Vec::new();
for derive in &info.derives {
match derive {
Derive::Debug => impls.push(impl_debug(info)?),
Derive::PartialEq => impls.push(impl_partial_eq(info)?),
Derive::Eq => impls.push(impl_eq(info)?),
}
}
Ok(quote! { #(#impls)* })
}
|