1//! Types holding data of items.
2
3mod field;
4mod fields;
5
6use proc_macro2::Span;
7use syn::{Expr, FieldsNamed, Ident, Pat, PatPath, Path, Result, Variant};
8
9pub use self::{
10 field::{Field, Member},
11 fields::Fields,
12};
13use crate::{util, Default, DeriveWhere, Either, Error, Incomparable, Skip, Trait, VariantAttr};
14
15/// Holds all relevant data of a struct, union or variant.
16#[cfg_attr(test, derive(Debug))]
17pub struct Data<'a> {
18 /// [`Skip`] attribute of this struct, union or variant.
19 skip_inner: Skip,
20 /// [`Incomparable`] attribute of this struct, union or variant.
21 pub incomparable: Incomparable,
22 /// [`struct@Ident`] of this struct, union or variant, used for implementing
23 /// [`Debug`](std::fmt::Debug).
24 pub ident: &'a Ident,
25 /// [`Path`] of this struct, union or variant, used to construct new
26 /// instances of that item, for example when implementing [`Clone`].
27 pub path: Path,
28 /// [Type](DataType) of this struct, union or variant.
29 pub type_: DataType<'a>,
30 /// Discriminant of this variant.
31 pub discriminant: Option<&'a Expr>,
32}
33
34/// Type of this data.
35#[cfg_attr(test, derive(Debug))]
36pub enum DataType<'a> {
37 /// Struct.
38 Struct(Fields<'a>),
39 /// Tuple.
40 Tuple(Fields<'a>),
41 /// Union.
42 Union(Fields<'a>),
43 /// Variant.
44 Variant {
45 /// [`struct@Default`] attribute of this variant.
46 default: Default,
47 /// [Type](VariantType) of this variant.
48 type_: VariantType<'a>,
49 },
50 /// Unit.
51 Unit(Pat),
52}
53
54/// Type of [`Data`].
55#[cfg_attr(test, derive(Debug))]
56pub enum VariantType<'a> {
57 /// Struct variant.
58 Struct(Fields<'a>),
59 /// Tuple variant.
60 Tuple(Fields<'a>),
61 /// Unit variant.
62 Unit(Pat),
63}
64
65/// Type to enable simplified matching.
66pub enum SimpleType<'a> {
67 /// Struct, struct variant.
68 Struct(&'a Fields<'a>),
69 /// Tuple struct or tuple variant.
70 Tuple(&'a Fields<'a>),
71 /// Union.
72 Union(&'a Fields<'a>),
73 /// Unit variant.
74 Unit(&'a Pat),
75}
76
77impl<'a> Data<'a> {
78 /// Create [`Data`]s from [`syn::Fields`] of a struct.
79 pub fn from_struct(
80 span: Span,
81 derive_wheres: &[DeriveWhere],
82 skip_inner: Skip,
83 incomparable: Incomparable,
84 ident: &'a Ident,
85 fields: &'a syn::Fields,
86 ) -> Result<Self> {
87 let path = util::path_from_idents(&[ident]);
88
89 match fields {
90 syn::Fields::Named(fields) => {
91 if fields.named.is_empty() && incomparable.0.is_none() {
92 Err(Error::item_empty(span))
93 } else {
94 let fields =
95 Fields::from_named(derive_wheres, &skip_inner, path.clone(), fields)?;
96
97 Ok(Self {
98 skip_inner,
99 incomparable,
100 ident,
101 path,
102 type_: DataType::Struct(fields),
103 discriminant: None,
104 })
105 }
106 }
107 syn::Fields::Unnamed(fields) => {
108 if fields.unnamed.is_empty() && incomparable.0.is_none() {
109 Err(Error::item_empty(span))
110 } else {
111 let fields =
112 Fields::from_unnamed(derive_wheres, &skip_inner, path.clone(), fields)?;
113
114 Ok(Self {
115 skip_inner,
116 incomparable,
117 ident,
118 path,
119 type_: DataType::Tuple(fields),
120 discriminant: None,
121 })
122 }
123 }
124 syn::Fields::Unit if incomparable.0.is_some() => Ok(Self {
125 skip_inner,
126 incomparable,
127 ident,
128 path: path.clone(),
129 type_: DataType::Unit(Pat::Path(PatPath {
130 attrs: Vec::new(),
131 qself: None,
132 path,
133 })),
134 discriminant: None,
135 }),
136 syn::Fields::Unit => Err(Error::item_empty(span)),
137 }
138 }
139
140 /// Create [`Data`]s from [`FieldsNamed`] of an union.
141 pub fn from_union(
142 span: Span,
143 derive_wheres: &[DeriveWhere],
144 skip_inner: Skip,
145 incomparable: Incomparable,
146 ident: &'a Ident,
147 fields: &'a FieldsNamed,
148 ) -> Result<Self> {
149 if fields.named.is_empty() && incomparable.0.is_none() {
150 Err(Error::item_empty(span))
151 } else {
152 let path = util::path_from_idents(&[ident]);
153 let fields = Fields::from_named(derive_wheres, &skip_inner, path.clone(), fields)?;
154
155 Ok(Self {
156 skip_inner,
157 incomparable,
158 ident,
159 path,
160 type_: DataType::Union(fields),
161 discriminant: None,
162 })
163 }
164 }
165
166 /// Create [`Data`]s from [`syn::Fields`] of a variant.
167 pub fn from_variant(
168 item_ident: &'a Ident,
169 derive_wheres: &[DeriveWhere],
170 variant: &'a Variant,
171 ) -> Result<Self> {
172 // Parse `Attribute`s on variant.
173 let VariantAttr {
174 default,
175 skip_inner,
176 incomparable,
177 } = VariantAttr::from_attrs(&variant.attrs, derive_wheres, variant)?;
178
179 let path = util::path_from_idents(&[item_ident, &variant.ident]);
180
181 match &variant.fields {
182 syn::Fields::Named(fields) => {
183 let fields = Fields::from_named(derive_wheres, &skip_inner, path.clone(), fields)?;
184
185 Ok(Self {
186 skip_inner,
187 incomparable,
188 ident: &variant.ident,
189 path,
190 type_: DataType::Variant {
191 default,
192 type_: VariantType::Struct(fields),
193 },
194 discriminant: variant.discriminant.as_ref().map(|(_, expr)| expr),
195 })
196 }
197 syn::Fields::Unnamed(fields) => {
198 let fields =
199 Fields::from_unnamed(derive_wheres, &skip_inner, path.clone(), fields)?;
200
201 Ok(Self {
202 skip_inner,
203 incomparable,
204 ident: &variant.ident,
205 path,
206 type_: DataType::Variant {
207 default,
208 type_: VariantType::Tuple(fields),
209 },
210 discriminant: variant.discriminant.as_ref().map(|(_, expr)| expr),
211 })
212 }
213 syn::Fields::Unit => {
214 let pattern = Pat::Path(PatPath {
215 attrs: Vec::new(),
216 qself: None,
217 path: path.clone(),
218 });
219
220 Ok(Self {
221 skip_inner,
222 incomparable,
223 ident: &variant.ident,
224 path,
225 type_: DataType::Variant {
226 default,
227 type_: VariantType::Unit(pattern),
228 },
229 discriminant: variant.discriminant.as_ref().map(|(_, expr)| expr),
230 })
231 }
232 }
233 }
234
235 /// Returns the [`Fields`] of this [`Data`]. If [`Data`] is a unit variant
236 /// or struct returns [`Pat`] instead.
237 pub fn fields(&self) -> Either<&Fields, &Pat> {
238 match &self.type_ {
239 DataType::Struct(fields)
240 | DataType::Tuple(fields)
241 | DataType::Union(fields)
242 | DataType::Variant {
243 type_: VariantType::Struct(fields),
244 ..
245 }
246 | DataType::Variant {
247 type_: VariantType::Tuple(fields),
248 ..
249 } => Either::Left(fields),
250 DataType::Unit(pattern)
251 | DataType::Variant {
252 type_: VariantType::Unit(pattern),
253 ..
254 } => Either::Right(pattern),
255 }
256 }
257
258 /// Returns the destructuring `self` pattern of this [`Data`].
259 pub fn self_pattern(&self) -> &Pat {
260 match self.fields() {
261 Either::Left(fields) => &fields.self_pattern,
262 Either::Right(pattern) => pattern,
263 }
264 }
265
266 /// Returns `true` if this variant is marked as the [`struct@Default`]. If
267 /// not a variant, always returns `true`.
268 pub fn is_default(&self) -> bool {
269 match self.type_ {
270 DataType::Variant { default, .. } => default.0.is_some(),
271 _ => true,
272 }
273 }
274
275 /// Returns `true` if this item or variant is marked as [`Incomparable`].
276 pub fn is_incomparable(&self) -> bool {
277 self.incomparable.0.is_some()
278 }
279
280 /// Returns [`Some`] if this variant has a [`struct@Default`]. If
281 /// not a variant, always returns [`None`].
282 pub fn default_span(&self) -> Option<Span> {
283 match &self.type_ {
284 DataType::Variant { default, .. } => default.0,
285 _ => None,
286 }
287 }
288
289 /// Returns `true` if this [`Data`] has no [`Fields`].
290 pub fn is_empty(&self, trait_: Trait) -> bool {
291 self.iter_fields(trait_).count() == 0
292 }
293
294 /// Returns `true` if a field is skipped with that [`Trait`].
295 pub fn any_skip_trait(&self, trait_: Trait) -> bool {
296 self.skip_inner.trait_skipped(trait_)
297 || match self.fields() {
298 Either::Left(fields) => fields.any_skip_trait(trait_),
299 Either::Right(_) => false,
300 }
301 }
302
303 /// Returns `true` if all fields are skipped with that [`Trait`].
304 fn skip(&self, trait_: Trait) -> bool {
305 self.skip_inner.trait_skipped(trait_)
306 || match self.fields() {
307 Either::Left(fields) => fields.skip(trait_),
308 Either::Right(_) => false,
309 }
310 }
311
312 /// Return a [`SimpleType`].
313 pub fn simple_type(&self) -> SimpleType {
314 match &self.type_ {
315 DataType::Struct(fields)
316 | DataType::Variant {
317 type_: VariantType::Struct(fields),
318 ..
319 } => SimpleType::Struct(fields),
320 DataType::Tuple(fields)
321 | DataType::Variant {
322 type_: VariantType::Tuple(fields),
323 ..
324 } => SimpleType::Tuple(fields),
325 DataType::Unit(pattern)
326 | DataType::Variant {
327 type_: VariantType::Unit(pattern),
328 ..
329 } => SimpleType::Unit(pattern),
330 DataType::Union(fields) => SimpleType::Union(fields),
331 }
332 }
333
334 /// Returns an [`Iterator`] over [`Field`]s.
335 pub fn iter_fields(
336 &self,
337 trait_: Trait,
338 ) -> impl '_ + Iterator<Item = &'_ Field> + DoubleEndedIterator {
339 if self.skip(trait_) {
340 [].iter()
341 } else {
342 match self.fields() {
343 Either::Left(fields) => fields.fields.iter(),
344 Either::Right(_) => [].iter(),
345 }
346 }
347 .filter(move |field| !field.skip(trait_))
348 }
349
350 /// Returns an [`Iterator`] over [`Member`]s.
351 pub fn iter_field_ident(&self, trait_: Trait) -> impl '_ + Iterator<Item = &'_ Member> {
352 self.iter_fields(trait_).map(|field| &field.member)
353 }
354
355 /// Returns an [`Iterator`] over [`struct@Ident`]s used as temporary
356 /// variables for destructuring `self`.
357 pub fn iter_self_ident(
358 &self,
359 trait_: Trait,
360 ) -> impl Iterator<Item = &'_ Ident> + DoubleEndedIterator {
361 self.iter_fields(trait_).map(|field| &field.self_ident)
362 }
363
364 /// Returns an [`Iterator`] over [`struct@Ident`]s used as temporary
365 /// variables for destructuring `other`.
366 pub fn iter_other_ident(
367 &self,
368 trait_: Trait,
369 ) -> impl Iterator<Item = &'_ Ident> + DoubleEndedIterator {
370 self.iter_fields(trait_).map(|field| &field.other_ident)
371 }
372}
373