palette_derive/meta/
field_attributes.rs

1use std::collections::{HashMap, HashSet};
2
3use syn::{spanned::Spanned, Expr, ExprLit};
4use syn::{Lit, Meta, MetaNameValue, Type};
5
6use super::{assert_path_meta, FieldAttributeArgumentParser, IdentOrIndex};
7
8#[derive(Default)]
9pub struct FieldAttributes {
10    pub alpha_property: Option<(IdentOrIndex, Type)>,
11    pub zero_size_fields: HashSet<IdentOrIndex>,
12    pub type_substitutes: HashMap<IdentOrIndex, Type>,
13}
14
15impl FieldAttributeArgumentParser for FieldAttributes {
16    fn argument(
17        &mut self,
18        field_name: &IdentOrIndex,
19        ty: &Type,
20        argument: Meta,
21    ) -> Result<(), Vec<syn::Error>> {
22        let argument_name = argument.path().get_ident().map(ToString::to_string);
23
24        match argument_name.as_deref() {
25            Some("alpha") => {
26                assert_path_meta(&argument).map_err(|error| vec![error])?;
27                self.alpha_property = Some((field_name.clone(), ty.clone()));
28            }
29            Some("unsafe_same_layout_as") => {
30                let substitute = if let Meta::NameValue(MetaNameValue {
31                    value:
32                        Expr::Lit(ExprLit {
33                            lit: Lit::Str(string),
34                            ..
35                        }),
36                    ..
37                }) = argument
38                {
39                    string.parse().map_err(|error| vec![error])?
40                } else {
41                    return Err(vec![::syn::parse::Error::new(
42                        argument.span(),
43                        "expected `unsafe_same_layout_as = \"SomeType\"`",
44                    )]);
45                };
46
47                self.type_substitutes.insert(field_name.clone(), substitute);
48            }
49            Some("unsafe_zero_sized") => {
50                assert_path_meta(&argument).map_err(|error| vec![error])?;
51                self.zero_size_fields.insert(field_name.clone());
52            }
53            _ => {
54                return Err(vec![::syn::parse::Error::new(
55                    argument.span(),
56                    "unknown field attribute",
57                )]);
58            }
59        }
60
61        Ok(())
62    }
63}