educe/trait_handlers/deref_mut/models/
field_attribute.rs

1use quote::ToTokens;
2use syn::{Attribute, Meta, NestedMeta};
3
4use crate::{panic, Trait};
5
6#[derive(Clone)]
7pub struct FieldAttribute {
8    pub flag: bool,
9}
10
11#[derive(Debug, Clone)]
12pub struct FieldAttributeBuilder {
13    pub enable_flag: bool,
14}
15
16impl FieldAttributeBuilder {
17    #[allow(clippy::wrong_self_convention)]
18    pub fn from_deref_mut_meta(&self, meta: &Meta) -> FieldAttribute {
19        let correct_usage_for_deref_mut_attribute = {
20            let mut usage = vec![];
21
22            if self.enable_flag {
23                usage.push(stringify!(#[educe(DerefMut)]));
24            }
25
26            usage
27        };
28
29        match meta {
30            Meta::List(_) => panic::attribute_incorrect_format(
31                "DerefMut",
32                &correct_usage_for_deref_mut_attribute,
33            ),
34            Meta::NameValue(_) => panic::attribute_incorrect_format(
35                "DerefMut",
36                &correct_usage_for_deref_mut_attribute,
37            ),
38            Meta::Path(_) => {
39                if !self.enable_flag {
40                    panic::attribute_incorrect_format(
41                        "DerefMut",
42                        &correct_usage_for_deref_mut_attribute,
43                    );
44                }
45
46                true
47            },
48        };
49
50        FieldAttribute {
51            flag: true
52        }
53    }
54
55    #[allow(clippy::wrong_self_convention)]
56    pub fn from_attributes(self, attributes: &[Attribute], traits: &[Trait]) -> FieldAttribute {
57        let mut result = None;
58
59        for attribute in attributes.iter() {
60            if attribute.path.is_ident("educe") {
61                let meta = attribute.parse_meta().unwrap();
62
63                match meta {
64                    Meta::List(list) => {
65                        for p in list.nested.iter() {
66                            match p {
67                                NestedMeta::Meta(meta) => {
68                                    let meta_name = meta.path().into_token_stream().to_string();
69
70                                    let t = Trait::from_str(meta_name);
71
72                                    if traits.binary_search(&t).is_err() {
73                                        panic::trait_not_used(t);
74                                    }
75
76                                    if t == Trait::DerefMut {
77                                        if result.is_some() {
78                                            panic::reuse_a_trait(t);
79                                        }
80
81                                        result = Some(self.from_deref_mut_meta(meta));
82                                    }
83                                },
84                                _ => panic::educe_format_incorrect(),
85                            }
86                        }
87                    },
88                    _ => panic::educe_format_incorrect(),
89                }
90            }
91        }
92
93        result.unwrap_or(FieldAttribute {
94            flag: false
95        })
96    }
97}