deadlocker_derive/
lib.rs

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
45/// Main driver function extracting fields and generating states to use in invocation of the generator functions
46fn 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}