educe/trait_handlers/deref/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_meta(&self, meta: &Meta) -> FieldAttribute {
19        let flag;
20
21        let correct_usage_for_deref_attribute = {
22            let mut usage = vec![];
23
24            if self.enable_flag {
25                usage.push(stringify!(#[educe(Deref)]));
26            }
27
28            usage
29        };
30
31        match meta {
32            Meta::List(_) => {
33                panic::attribute_incorrect_format("Deref", &correct_usage_for_deref_attribute)
34            },
35            Meta::NameValue(_) => {
36                panic::attribute_incorrect_format("Deref", &correct_usage_for_deref_attribute)
37            },
38            Meta::Path(_) => {
39                if !self.enable_flag {
40                    panic::attribute_incorrect_format("Deref", &correct_usage_for_deref_attribute);
41                }
42
43                flag = true;
44            },
45        }
46
47        FieldAttribute {
48            flag,
49        }
50    }
51
52    #[allow(clippy::wrong_self_convention)]
53    pub fn from_attributes(self, attributes: &[Attribute], traits: &[Trait]) -> FieldAttribute {
54        let mut result = None;
55
56        for attribute in attributes.iter() {
57            if attribute.path.is_ident("educe") {
58                let meta = attribute.parse_meta().unwrap();
59
60                match meta {
61                    Meta::List(list) => {
62                        for p in list.nested.iter() {
63                            match p {
64                                NestedMeta::Meta(meta) => {
65                                    let meta_name = meta.path().into_token_stream().to_string();
66
67                                    let t = Trait::from_str(meta_name);
68
69                                    if traits.binary_search(&t).is_err() {
70                                        panic::trait_not_used(t);
71                                    }
72
73                                    if t == Trait::Deref {
74                                        if result.is_some() {
75                                            panic::reuse_a_trait(t);
76                                        }
77
78                                        result = Some(self.from_deref_meta(meta));
79                                    }
80                                },
81                                _ => panic::educe_format_incorrect(),
82                            }
83                        }
84                    },
85                    _ => panic::educe_format_incorrect(),
86                }
87            }
88        }
89
90        result.unwrap_or(FieldAttribute {
91            flag: false
92        })
93    }
94}