1use crate::attr::{self, Attrs};
2use crate::generics::ParamsInScope;
3use proc_macro2::Span;
4use syn::{
5 Data, DataEnum, DataStruct, DeriveInput, Error, Fields, Generics, Ident, Index, Member, Result,
6 Type,
7};
8
9pub enum Input<'a> {
10 Struct(Struct<'a>),
11 Enum(Enum<'a>),
12}
13
14pub struct Struct<'a> {
15 pub original: &'a DeriveInput,
16 pub attrs: Attrs<'a>,
17 pub ident: Ident,
18 pub generics: &'a Generics,
19 pub fields: Vec<Field<'a>>,
20}
21
22pub struct Enum<'a> {
23 pub original: &'a DeriveInput,
24 pub attrs: Attrs<'a>,
25 pub ident: Ident,
26 pub generics: &'a Generics,
27 pub variants: Vec<Variant<'a>>,
28}
29
30pub struct Variant<'a> {
31 pub original: &'a syn::Variant,
32 pub attrs: Attrs<'a>,
33 pub ident: Ident,
34 pub fields: Vec<Field<'a>>,
35}
36
37pub struct Field<'a> {
38 pub original: &'a syn::Field,
39 pub attrs: Attrs<'a>,
40 pub member: Member,
41 pub ty: &'a Type,
42 pub contains_generic: bool,
43}
44
45impl<'a> Input<'a> {
46 pub fn from_syn(node: &'a DeriveInput) -> Result<Self> {
47 match &node.data {
48 Data::Struct(data: &DataStruct) => Struct::from_syn(node, data).map(op:Input::Struct),
49 Data::Enum(data: &DataEnum) => Enum::from_syn(node, data).map(op:Input::Enum),
50 Data::Union(_) => Err(Error::new_spanned(
51 tokens:node,
52 message:"union as errors are not supported",
53 )),
54 }
55 }
56}
57
58impl<'a> Struct<'a> {
59 fn from_syn(node: &'a DeriveInput, data: &'a DataStruct) -> Result<Self> {
60 let mut attrs: Attrs<'_> = attr::get(&node.attrs)?;
61 let scope: ParamsInScope<'_> = ParamsInScope::new(&node.generics);
62 let span: Span = attrs.span().unwrap_or_else(Span::call_site);
63 let fields: Vec> = Field::multiple_from_syn(&data.fields, &scope, span)?;
64 if let Some(display: &mut Display<'_>) = &mut attrs.display {
65 display.expand_shorthand(&fields);
66 }
67 Ok(Struct {
68 original: node,
69 attrs,
70 ident: node.ident.clone(),
71 generics: &node.generics,
72 fields,
73 })
74 }
75}
76
77impl<'a> Enum<'a> {
78 fn from_syn(node: &'a DeriveInput, data: &'a DataEnum) -> Result<Self> {
79 let attrs = attr::get(&node.attrs)?;
80 let scope = ParamsInScope::new(&node.generics);
81 let span = attrs.span().unwrap_or_else(Span::call_site);
82 let variants = data
83 .variants
84 .iter()
85 .map(|node| {
86 let mut variant = Variant::from_syn(node, &scope, span)?;
87 if let display @ None = &mut variant.attrs.display {
88 *display = attrs.display.clone();
89 }
90 if let Some(display) = &mut variant.attrs.display {
91 display.expand_shorthand(&variant.fields);
92 } else if variant.attrs.transparent.is_none() {
93 variant.attrs.transparent = attrs.transparent;
94 }
95 Ok(variant)
96 })
97 .collect::<Result<_>>()?;
98 Ok(Enum {
99 original: node,
100 attrs,
101 ident: node.ident.clone(),
102 generics: &node.generics,
103 variants,
104 })
105 }
106}
107
108impl<'a> Variant<'a> {
109 fn from_syn(node: &'a syn::Variant, scope: &ParamsInScope<'a>, span: Span) -> Result<Self> {
110 let attrs: Attrs<'_> = attr::get(&node.attrs)?;
111 let span: Span = attrs.span().unwrap_or(default:span);
112 Ok(Variant {
113 original: node,
114 attrs,
115 ident: node.ident.clone(),
116 fields: Field::multiple_from_syn(&node.fields, scope, span)?,
117 })
118 }
119}
120
121impl<'a> Field<'a> {
122 fn multiple_from_syn(
123 fields: &'a Fields,
124 scope: &ParamsInScope<'a>,
125 span: Span,
126 ) -> Result<Vec<Self>> {
127 fields
128 .iter()
129 .enumerate()
130 .map(|(i, field)| Field::from_syn(i, field, scope, span))
131 .collect()
132 }
133
134 fn from_syn(
135 i: usize,
136 node: &'a syn::Field,
137 scope: &ParamsInScope<'a>,
138 span: Span,
139 ) -> Result<Self> {
140 Ok(Field {
141 original: node,
142 attrs: attr::get(&node.attrs)?,
143 member: node.ident.clone().map(Member::Named).unwrap_or_else(|| {
144 Member::Unnamed(Index {
145 index: i as u32,
146 span,
147 })
148 }),
149 ty: &node.ty,
150 contains_generic: scope.intersects(&node.ty),
151 })
152 }
153}
154
155impl Attrs<'_> {
156 pub fn span(&self) -> Option<Span> {
157 if let Some(display: &Display<'_>) = &self.display {
158 Some(display.fmt.span())
159 } else if let Some(transparent: &Transparent<'_>) = &self.transparent {
160 Some(transparent.span)
161 } else {
162 None
163 }
164 }
165}
166