1use field::FieldAugment;
2use generators::{
3 generate_builder_struct, generate_impl_for_all_states, generate_state_struct_declarations,
4 generate_trait_implementation,
5};
6
7use quote::{format_ident, quote};
8
9use state::State;
10use syn::Field;
11
12mod attribute;
13mod field;
14mod generators;
15mod path;
16mod state;
17
18const DEFAULT_OUTER_TYPE: &str = "Arc<Mutex<(.*)>>";
19const OUTER_TYPE: &str = "outer_type";
20const INNER_TYPE: &str = "inner_type";
21const ASYNC: &str = "async_lock";
22const RESULT: &str = "result";
23const LOCK_METHOD: &str = "lock_method";
24const INCLUDE: &str = "include";
25const EXCLUDE: &str = "exclude";
26
27#[proc_macro_derive(
28 Locker,
29 attributes(
30 outer_type,
31 inner_type,
32 async_lock,
33 lock_method,
34 result,
35 include,
36 exclude
37 )
38)]
39pub fn locker_macro_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
40 let ast = syn::parse(input).unwrap();
41
42 impl_locker_macro(&ast)
43}
44
45fn impl_locker_macro(ast: &syn::DeriveInput) -> proc_macro::TokenStream {
47 let ident = &ast.ident;
48
49 let fields = if let syn::Data::Struct(parsed_struct) = &ast.data {
50 &parsed_struct.fields
51 } else {
52 panic!("Only applicable to structs")
53 };
54
55 let all_ordered = if fields.iter().any(Field::is_included) {
56 fields
57 .iter()
58 .filter(|f| f.is_included())
59 .map(Field::to_owned)
60 .collect::<Vec<Field>>()
61 } else {
62 fields
63 .iter()
64 .filter(|f| !f.is_excluded())
65 .map(Field::to_owned)
66 .collect::<Vec<Field>>()
67 };
68
69 let empty = State {
70 struct_ident: ident.clone(),
71 active: Vec::new(),
72 complements: all_ordered.clone(),
73 all_ordered: all_ordered.clone(),
74 };
75
76 let empty_name = empty.ident();
77 let states = empty.into_substates();
78
79 let name = format_ident!("{}Locker", ident);
80
81 let state_struct_declarations = generate_state_struct_declarations(&states);
82 let builder_struct = generate_builder_struct(&name, fields.iter());
83 let impl_states = generate_impl_for_all_states(&name, &states, fields);
84 let trait_implementation = generate_trait_implementation(ident, &name, &empty_name, fields);
85
86 quote! {
87 #state_struct_declarations
88 #builder_struct
89 #impl_states
90 #trait_implementation
91 }
92 .into()
93}