• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use crate::attr::{self, Attrs};
2 use crate::generics::ParamsInScope;
3 use crate::unraw::{IdentUnraw, MemberUnraw};
4 use proc_macro2::Span;
5 use std::fmt::{self, Display};
6 use syn::{
7     Data, DataEnum, DataStruct, DeriveInput, Error, Fields, Generics, Ident, Index, Result, Type,
8 };
9 
10 pub enum Input<'a> {
11     Struct(Struct<'a>),
12     Enum(Enum<'a>),
13 }
14 
15 pub 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 
22 pub 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 
29 pub 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 
36 pub 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)]
45 pub enum ContainerKind {
46     Struct,
47     TupleStruct,
48     UnitStruct,
49     StructVariant,
50     TupleVariant,
51     UnitVariant,
52 }
53 
54 impl<'a> Input<'a> {
from_syn(node: &'a DeriveInput) -> Result<Self>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 
67 impl<'a> Struct<'a> {
from_syn(node: &'a DeriveInput, data: &'a DataStruct) -> Result<Self>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 
85 impl<'a> Enum<'a> {
from_syn(node: &'a DeriveInput, data: &'a DataEnum) -> Result<Self>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 
118 impl<'a> Variant<'a> {
from_syn(node: &'a syn::Variant, scope: &ParamsInScope<'a>) -> Result<Self>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 
130 impl<'a> Field<'a> {
multiple_from_syn(fields: &'a Fields, scope: &ParamsInScope<'a>) -> Result<Vec<Self>>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 
from_syn(i: usize, node: &'a syn::Field, scope: &ParamsInScope<'a>) -> Result<Self>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 
156 impl ContainerKind {
from_struct(node: &DataStruct) -> Self157     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 
from_variant(node: &syn::Variant) -> Self165     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 
174 impl Display for ContainerKind {
fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result175     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 }
186