palette_derive/meta/
field_attributes.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
use std::collections::{HashMap, HashSet};

use syn::{spanned::Spanned, Expr, ExprLit};
use syn::{Lit, Meta, MetaNameValue, Type};

use super::{assert_path_meta, FieldAttributeArgumentParser, IdentOrIndex};

#[derive(Default)]
pub struct FieldAttributes {
    pub alpha_property: Option<(IdentOrIndex, Type)>,
    pub zero_size_fields: HashSet<IdentOrIndex>,
    pub type_substitutes: HashMap<IdentOrIndex, Type>,
}

impl FieldAttributeArgumentParser for FieldAttributes {
    fn argument(
        &mut self,
        field_name: &IdentOrIndex,
        ty: &Type,
        argument: Meta,
    ) -> Result<(), Vec<syn::Error>> {
        let argument_name = argument.path().get_ident().map(ToString::to_string);

        match argument_name.as_deref() {
            Some("alpha") => {
                assert_path_meta(&argument).map_err(|error| vec![error])?;
                self.alpha_property = Some((field_name.clone(), ty.clone()));
            }
            Some("unsafe_same_layout_as") => {
                let substitute = if let Meta::NameValue(MetaNameValue {
                    value:
                        Expr::Lit(ExprLit {
                            lit: Lit::Str(string),
                            ..
                        }),
                    ..
                }) = argument
                {
                    string.parse().map_err(|error| vec![error])?
                } else {
                    return Err(vec![::syn::parse::Error::new(
                        argument.span(),
                        "expected `unsafe_same_layout_as = \"SomeType\"`",
                    )]);
                };

                self.type_substitutes.insert(field_name.clone(), substitute);
            }
            Some("unsafe_zero_sized") => {
                assert_path_meta(&argument).map_err(|error| vec![error])?;
                self.zero_size_fields.insert(field_name.clone());
            }
            _ => {
                return Err(vec![::syn::parse::Error::new(
                    argument.span(),
                    "unknown field attribute",
                )]);
            }
        }

        Ok(())
    }
}