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
use proc_macro::TokenStream;
use quote::quote;
use syn::DeriveInput;
#[proc_macro_derive(LiveMod)]
pub fn livemod_derive(input: TokenStream) -> TokenStream {
let ast: DeriveInput = syn::parse(input).unwrap();
match ast.data {
syn::Data::Struct(st) => {
match st.fields {
syn::Fields::Named(fields) => {
let struct_name = ast.ident;
let (fields, matches) = fields.named.into_iter()
.filter_map(|field| {
if !field.attrs.into_iter().any(|attr| attr.path.is_ident("livemod")) {
let ident = field.ident.unwrap();
let name = {
let mut name = ident.to_string();
name.as_mut_str()[..1].make_ascii_uppercase();
name
};
Some((
quote! {
::livemod::TrackedData {
name: String::from(#name),
data_type: ::livemod::LiveMod::data_type(&self.#ident)
}
},
quote! {
#name => &mut self.#ident
}
))
} else {
None
}
})
.unzip::<_, _, Vec<_>, Vec<_>>();
let gen = quote! {
impl ::livemod::LiveMod for #struct_name {
fn data_type(&self) -> ::livemod::TrackedDataRepr {
::livemod::TrackedDataRepr::Struct {
name: String::from(stringify!(#struct_name)),
fields: vec![
#(#fields),*
]
}
}
fn get_named_value(&mut self, name: &str) -> &mut ::livemod::LiveMod {
match name {
#(#matches ,)*
_ => panic!("Unexpected value name!"),
}
}
fn set_self(&mut self, value: ::livemod::TrackedDataValue) {
panic!("Unexpected set operation!")
}
}
};
gen.into()
},
syn::Fields::Unnamed(fields) => todo!(),
syn::Fields::Unit => todo!(),
}
},
syn::Data::Enum(en) => todo!(),
syn::Data::Union(_) => todo!(),
}
}