ion_proc/attribute/
value.rs1use either::Either;
8use syn::meta::ParseNestedMeta;
9use syn::parse::{Parse, ParseStream};
10use syn::{Expr, ExprClosure, Lit, LitStr, Result};
11
12use crate::attribute::{ArgumentError, Optional, ParseArgument as _, ParseArgumentWith as _, ParseAttribute};
13
14#[derive(Clone, Debug, Default)]
15pub(crate) enum Tag {
16 Untagged,
17 #[default]
18 External,
19 Internal(LitStr),
20}
21
22impl Parse for Tag {
23 fn parse(input: ParseStream) -> Result<Tag> {
24 let tag: Option<_> = input.parse()?;
25 Ok(tag.map_or(Tag::External, Tag::Internal))
26 }
27}
28
29#[derive(Default)]
30pub(crate) enum DefaultValue {
31 #[default]
32 Default,
33 Literal(Lit),
34 Closure(ExprClosure),
35 Expr(Box<Expr>),
36}
37
38impl Parse for DefaultValue {
39 fn parse(input: ParseStream) -> Result<DefaultValue> {
40 let expr: Expr = input.parse()?;
41 match expr {
42 Expr::Lit(lit) => Ok(DefaultValue::Literal(lit.lit)),
43 Expr::Closure(closure) => Ok(DefaultValue::Closure(closure)),
44 expr => Ok(DefaultValue::Expr(Box::new(expr))),
45 }
46 }
47}
48
49#[derive(Debug, Default)]
50pub(crate) struct DataAttribute {
51 pub(crate) tag: Optional<Tag>,
52 pub(crate) inherit: bool,
53}
54
55impl ParseAttribute for DataAttribute {
56 type Parent<'a> = ();
57
58 fn parse(&mut self, meta: &ParseNestedMeta) -> Result<bool> {
59 const TAG_ERROR: &str = "Data cannot have multiple `untagged`, or `tag` attributes.";
60
61 let success = self
62 .tag
63 .parse_argument_with(meta, Tag::Untagged, "untagged", ArgumentError::Full(TAG_ERROR))?
64 || self.tag.parse_argument(meta, "tag", ArgumentError::Full(TAG_ERROR))?
65 || self.inherit.parse_argument(meta, "inherit", "Data")?;
66
67 Ok(success)
68 }
69}
70
71#[derive(Debug, Default)]
72pub(crate) struct VariantAttribute {
73 pub(crate) tag: Optional<Tag>,
74 pub(crate) inherit: bool,
75 pub(crate) skip: bool,
76}
77
78impl ParseAttribute for VariantAttribute {
79 type Parent<'a> = &'a DataAttribute;
80
81 fn from_parent(parent: Self::Parent<'_>) -> VariantAttribute {
82 VariantAttribute {
83 inherit: parent.inherit,
84 ..VariantAttribute::default()
85 }
86 }
87
88 fn merge(&mut self, parent: Self::Parent<'_>) {
89 if self.tag.0.is_none() {
90 self.tag = parent.tag.clone();
91 }
92 }
93
94 fn parse(&mut self, meta: &ParseNestedMeta) -> Result<bool> {
95 const TAG_ERROR: &str = "Variant cannot have multiple `untagged`, or `tag` attributes.";
96
97 let success = self
98 .tag
99 .parse_argument_with(meta, Tag::Untagged, "untagged", ArgumentError::Full(TAG_ERROR))?
100 || self.tag.parse_argument(meta, "tag", ArgumentError::Full(TAG_ERROR))?
101 || self.inherit.parse_argument(meta, "inherit", "Variant")?
102 || self.skip.parse_argument(meta, "skip", "Variant")?;
103
104 Ok(success)
105 }
106}
107
108#[derive(Default)]
109pub(crate) struct FieldAttribute {
110 pub(crate) name: Option<LitStr>,
111 pub(crate) inherit: bool,
112 pub(crate) skip: bool,
113}
114
115impl ParseAttribute for FieldAttribute {
116 type Parent<'a> = Either<&'a DataAttribute, &'a VariantAttribute>;
117
118 fn from_parent(parent: Self::Parent<'_>) -> FieldAttribute {
119 let mut attribute = FieldAttribute::default();
120 match parent {
121 Either::Left(data) => {
122 attribute.inherit = data.inherit;
123 }
124 Either::Right(variant) => {
125 attribute.inherit = variant.inherit;
126 attribute.skip = variant.skip;
127 }
128 }
129 attribute
130 }
131
132 fn parse(&mut self, meta: &ParseNestedMeta) -> Result<bool> {
133 let success = self.name.parse_argument(meta, "name", "Field")?
134 || self.inherit.parse_argument(meta, "inherit", "Field")?
135 || self.skip.parse_argument(meta, "skip", "Field")?;
136
137 Ok(success)
138 }
139}
140
141#[derive(Default)]
142pub(crate) struct FieldFromAttribute {
143 pub(crate) base: FieldAttribute,
144 pub(crate) convert: Option<Box<Expr>>,
145 pub(crate) strict: bool,
146 pub(crate) default: Optional<DefaultValue>,
147 pub(crate) parser: Option<Box<Expr>>,
148}
149
150impl ParseAttribute for FieldFromAttribute {
151 type Parent<'a> = Either<&'a DataAttribute, &'a VariantAttribute>;
152
153 fn from_parent(parent: Self::Parent<'_>) -> Self {
154 FieldFromAttribute {
155 base: FieldAttribute::from_parent(parent),
156 ..FieldFromAttribute::default()
157 }
158 }
159
160 fn parse(&mut self, meta: &ParseNestedMeta) -> Result<bool> {
161 let success = self.base.parse(meta)?
162 || self.default.parse_argument(meta, "default", "Field")?
163 || self.convert.parse_argument(meta, "convert", "Field")?
164 || self.strict.parse_argument(meta, "strict", "Field")?
165 || self.parser.parse_argument(meta, "parser", "Field")?;
166
167 Ok(success)
168 }
169}