1extern crate proc_macro;
2
3use darling::FromMeta;
4use proc_macro::TokenStream;
5use quote::quote;
6use syn::{parse_macro_input, AttributeArgs, DeriveInput, Ident};
7
8#[derive(Debug, FromMeta)]
9struct MacroArgs {
10 #[darling(default)]
11 serialization: Option<Ident>,
12}
13
14#[proc_macro_attribute]
46pub fn track(_attr: TokenStream, unparsed_input: TokenStream) -> TokenStream {
47 let attr_args = parse_macro_input!(_attr as AttributeArgs);
48 let input: DeriveInput = parse_macro_input!(unparsed_input as syn::DeriveInput);
49
50 let _args = match MacroArgs::from_list(&attr_args) {
51 Ok(v) => v,
52 Err(e) => {
53 return proc_macro::TokenStream::from(e.write_errors());
54 }
55 };
56
57 let serialization = if let Some(ser) = _args.serialization {
58 ser
59 } else {
60 Ident::from_string("Bincode").unwrap()
61 };
62
63 let name = input.ident.clone();
64
65 let implementation = quote! {
66 #[derive(Clone, SerdeDiff, Serialize, Deserialize)]
67 #input
68
69 impl Trackable<#name, #serialization> for #name {
70 fn track<'notifier, I: Identifier>(&mut self, sender: &'notifier Sender<ModificationEvent<I>>, identifier: I) -> Tracker<'_, 'notifier, #name, #serialization, I> {
71 Tracker::new(self, sender, #serialization, identifier)
72 }
73 }
74
75 impl TrackableMarker for #name { }
76 };
77
78 proc_macro::TokenStream::from(implementation)
79}