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}