1use crate::attr::{self, Attrs};
2use crate::generics::ParamsInScope;
3use crate::unraw::{IdentUnraw, MemberUnraw};
4use proc_macro2::Span;
5use std::fmt::{self, Display};
6use syn::{
7 Data, DataEnum, DataStruct, DeriveInput, Error, Fields, Generics, Ident, Index, Result, Type,
8};
9
10pub enum Input<'a> {
11 Struct(Struct<'a>),
12 Enum(Enum<'a>),
13}
14
15pub struct Struct<'a> {
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 attrs: Attrs<'a>,
24 pub ident: Ident,
25 pub generics: &'a Generics,
26 pub variants: Vec<Variant<'a>>,
27}
28
29pub struct Variant<'a> {
30 pub original: &'a syn::Variant,
31 pub attrs: Attrs<'a>,
32 pub ident: Ident,
33 pub fields: Vec<Field<'a>>,
34}
35
36pub struct Field<'a> {
37 pub original: &'a syn::Field,
38 pub attrs: Attrs<'a>,
39 pub member: MemberUnraw,
40 pub ty: &'a Type,
41 pub contains_generic: bool,
42}
43
44#[derive(Copy, Clone)]
45pub enum ContainerKind {
46 Struct,
47 TupleStruct,
48 UnitStruct,
49 StructVariant,
50 TupleVariant,
51 UnitVariant,
52}
53
54impl<'a> Input<'a> {
55 pub fn from_syn(node: &'a DeriveInput) -> Result<Self> {
56 match &node.data {
57 Data::Struct(data) => Struct::from_syn(node, data).map(Input::Struct),
58 Data::Enum(data) => Enum::from_syn(node, data).map(Input::Enum),
59 Data::Union(_) => Err(Error::new_spanned(
60 node,
61 "union as errors are not supported",
62 )),
63 }
64 }
65}
66
67impl<'a> Struct<'a> {
68 fn from_syn(node: &'a DeriveInput, data: &'a DataStruct) -> Result<Self> {
69 let mut attrs = attr::get(&node.attrs)?;
70 let scope = ParamsInScope::new(&node.generics);
71 let fields = Field::multiple_from_syn(&data.fields, &scope)?;
72 if let Some(display) = &mut attrs.display {
73 let container = ContainerKind::from_struct(data);
74 display.expand_shorthand(&fields, container)?;
75 }
76 Ok(Struct {
77 attrs,
78 ident: node.ident.clone(),
79 generics: &node.generics,
80 fields,
81 })
82 }
83}
84
85impl<'a> Enum<'a> {
86 fn from_syn(node: &'a DeriveInput, data: &'a DataEnum) -> Result<Self> {
87 let attrs = attr::get(&node.attrs)?;
88 let scope = ParamsInScope::new(&node.generics);
89 let variants = data
90 .variants
91 .iter()
92 .map(|node| {
93 let mut variant = Variant::from_syn(node, &scope)?;
94 if variant.attrs.display.is_none()
95 && variant.attrs.transparent.is_none()
96 && variant.attrs.fmt.is_none()
97 {
98 variant.attrs.display.clone_from(&attrs.display);
99 variant.attrs.transparent = attrs.transparent;
100 variant.attrs.fmt.clone_from(&attrs.fmt);
101 }
102 if let Some(display) = &mut variant.attrs.display {
103 let container = ContainerKind::from_variant(node);
104 display.expand_shorthand(&variant.fields, container)?;
105 }
106 Ok(variant)
107 })
108 .collect::<Result<_>>()?;
109 Ok(Enum {
110 attrs,
111 ident: node.ident.clone(),
112 generics: &node.generics,
113 variants,
114 })
115 }
116}
117
118impl<'a> Variant<'a> {
119 fn from_syn(node: &'a syn::Variant, scope: &ParamsInScope<'a>) -> Result<Self> {
120 let attrs = attr::get(&node.attrs)?;
121 Ok(Variant {
122 original: node,
123 attrs,
124 ident: node.ident.clone(),
125 fields: Field::multiple_from_syn(&node.fields, scope)?,
126 })
127 }
128}
129
130impl<'a> Field<'a> {
131 fn multiple_from_syn(fields: &'a Fields, scope: &ParamsInScope<'a>) -> Result<Vec<Self>> {
132 fields
133 .iter()
134 .enumerate()
135 .map(|(i, field)| Field::from_syn(i, field, scope))
136 .collect()
137 }
138
139 fn from_syn(i: usize, node: &'a syn::Field, scope: &ParamsInScope<'a>) -> Result<Self> {
140 Ok(Field {
141 original: node,
142 attrs: attr::get(&node.attrs)?,
143 member: match &node.ident {
144 Some(name) => MemberUnraw::Named(IdentUnraw::new(name.clone())),
145 None => MemberUnraw::Unnamed(Index {
146 index: i as u32,
147 span: Span::call_site(),
148 }),
149 },
150 ty: &node.ty,
151 contains_generic: scope.intersects(&node.ty),
152 })
153 }
154}
155
156impl ContainerKind {
157 fn from_struct(node: &DataStruct) -> Self {
158 match node.fields {
159 Fields::Named(_) => ContainerKind::Struct,
160 Fields::Unnamed(_) => ContainerKind::TupleStruct,
161 Fields::Unit => ContainerKind::UnitStruct,
162 }
163 }
164
165 fn from_variant(node: &syn::Variant) -> Self {
166 match node.fields {
167 Fields::Named(_) => ContainerKind::StructVariant,
168 Fields::Unnamed(_) => ContainerKind::TupleVariant,
169 Fields::Unit => ContainerKind::UnitVariant,
170 }
171 }
172}
173
174impl Display for ContainerKind {
175 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
176 formatter.write_str(match self {
177 ContainerKind::Struct => "struct",
178 ContainerKind::TupleStruct => "tuple struct",
179 ContainerKind::UnitStruct => "unit struct",
180 ContainerKind::StructVariant => "struct variant",
181 ContainerKind::TupleVariant => "tuple variant",
182 ContainerKind::UnitVariant => "unit variant",
183 })
184 }
185}