ion_proc/attribute/
value.rs

1/*
2 * This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
5 */
6
7use 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}