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