1 | use quote::ToTokens; |
2 | |
3 | use crate::{ast::Data, codegen::FromAttributesImpl, Error, Result}; |
4 | |
5 | use super::{OuterFrom, ParseAttribute, ParseData}; |
6 | |
7 | /// Receiver for derived `FromAttributes` impls. |
8 | pub struct FromAttributesOptions { |
9 | // Note: FromAttributes has no behaviors beyond those common |
10 | // to all the `OuterFrom` traits. |
11 | pub base: OuterFrom, |
12 | } |
13 | |
14 | impl 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 | |
40 | impl ParseAttribute for FromAttributesOptions { |
41 | fn parse_nested(&mut self, mi: &syn::Meta) -> Result<()> { |
42 | self.base.parse_nested(mi) |
43 | } |
44 | } |
45 | |
46 | impl 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 | |
56 | impl<'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 | |
65 | impl ToTokens for FromAttributesOptions { |
66 | fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { |
67 | FromAttributesImpl::from(self).to_tokens(tokens) |
68 | } |
69 | } |
70 | |