1use quote::ToTokens;
2
3use crate::{ast::Data, codegen::FromAttributesImpl, Error, Result};
4
5use super::{OuterFrom, ParseAttribute, ParseData};
6
7/// Receiver for derived `FromAttributes` impls.
8pub struct FromAttributesOptions {
9 // Note: FromAttributes has no behaviors beyond those common
10 // to all the `OuterFrom` traits.
11 pub base: OuterFrom,
12}
13
14impl FromAttributesOptions {
15 pub fn new(di: &syn::DeriveInput) -> Result<Self> {
16 let opts = (Self {
17 base: OuterFrom::start(di)?,
18 })
19 .parse_attributes(&di.attrs)?
20 .parse_body(&di.data)?;
21
22 if !opts.is_newtype() && opts.base.attr_names.is_empty() {
23 Err(Error::custom(
24 "FromAttributes without attributes collects nothing",
25 ))
26 } else {
27 Ok(opts)
28 }
29 }
30
31 fn is_newtype(&self) -> bool {
32 if let Data::Struct(ref data) = self.base.container.data {
33 data.is_newtype()
34 } else {
35 false
36 }
37 }
38}
39
40impl ParseAttribute for FromAttributesOptions {
41 fn parse_nested(&mut self, mi: &syn::Meta) -> Result<()> {
42 self.base.parse_nested(mi)
43 }
44}
45
46impl ParseData for FromAttributesOptions {
47 fn parse_variant(&mut self, variant: &syn::Variant) -> Result<()> {
48 self.base.parse_variant(variant)
49 }
50
51 fn parse_field(&mut self, field: &syn::Field) -> Result<()> {
52 self.base.parse_field(field)
53 }
54}
55
56impl<'a> From<&'a FromAttributesOptions> for FromAttributesImpl<'a> {
57 fn from(v: &'a FromAttributesOptions) -> Self {
58 FromAttributesImpl {
59 base: (&v.base.container).into(),
60 attr_names: &v.base.attr_names,
61 }
62 }
63}
64
65impl ToTokens for FromAttributesOptions {
66 fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
67 FromAttributesImpl::from(self).to_tokens(tokens)
68 }
69}
70