1 use std::{slice, vec};
2 
3 use syn;
4 
5 use usage::{
6     self, IdentRefSet, IdentSet, LifetimeRefSet, LifetimeSet, UsesLifetimes, UsesTypeParams,
7 };
8 use {Error, FromField, FromVariant, Result};
9 
10 /// A struct or enum body.
11 ///
12 /// `V` is the type which receives any encountered variants, and `F` receives struct fields.
13 #[derive(Debug, Clone, PartialEq, Eq)]
14 pub enum Data<V, F> {
15     Enum(Vec<V>),
16     Struct(Fields<F>),
17 }
18 
19 impl<V, F> Data<V, F> {
20     /// Creates an empty body of the same shape as the passed-in body.
empty_from(src: &syn::Data) -> Self21     pub fn empty_from(src: &syn::Data) -> Self {
22         match *src {
23             syn::Data::Enum(_) => Data::Enum(vec![]),
24             syn::Data::Struct(ref vd) => Data::Struct(Fields::empty_from(&vd.fields)),
25             syn::Data::Union(_) => unreachable!(),
26         }
27     }
28 
29     /// Creates a new `Data<&'a V, &'a F>` instance from `Data<V, F>`.
as_ref<'a>(&'a self) -> Data<&'a V, &'a F>30     pub fn as_ref<'a>(&'a self) -> Data<&'a V, &'a F> {
31         match *self {
32             Data::Enum(ref variants) => Data::Enum(variants.iter().collect()),
33             Data::Struct(ref data) => Data::Struct(data.as_ref()),
34         }
35     }
36 
37     /// Applies a function `V -> U` on enum variants, if this is an enum.
map_enum_variants<T, U>(self, map: T) -> Data<U, F> where T: FnMut(V) -> U,38     pub fn map_enum_variants<T, U>(self, map: T) -> Data<U, F>
39     where
40         T: FnMut(V) -> U,
41     {
42         match self {
43             Data::Enum(v) => Data::Enum(v.into_iter().map(map).collect()),
44             Data::Struct(f) => Data::Struct(f),
45         }
46     }
47 
48     /// Applies a function `F -> U` on struct fields, if this is a struct.
map_struct_fields<T, U>(self, map: T) -> Data<V, U> where T: FnMut(F) -> U,49     pub fn map_struct_fields<T, U>(self, map: T) -> Data<V, U>
50     where
51         T: FnMut(F) -> U,
52     {
53         match self {
54             Data::Enum(v) => Data::Enum(v),
55             Data::Struct(f) => Data::Struct(f.map(map)),
56         }
57     }
58 
59     /// Applies a function to the `Fields` if this is a struct.
map_struct<T, U>(self, mut map: T) -> Data<V, U> where T: FnMut(Fields<F>) -> Fields<U>,60     pub fn map_struct<T, U>(self, mut map: T) -> Data<V, U>
61     where
62         T: FnMut(Fields<F>) -> Fields<U>,
63     {
64         match self {
65             Data::Enum(v) => Data::Enum(v),
66             Data::Struct(f) => Data::Struct(map(f)),
67         }
68     }
69 
70     /// Consumes the `Data`, returning `Fields<F>` if it was a struct.
take_struct(self) -> Option<Fields<F>>71     pub fn take_struct(self) -> Option<Fields<F>> {
72         match self {
73             Data::Enum(_) => None,
74             Data::Struct(f) => Some(f),
75         }
76     }
77 
78     /// Consumes the `Data`, returning `Vec<V>` if it was an enum.
take_enum(self) -> Option<Vec<V>>79     pub fn take_enum(self) -> Option<Vec<V>> {
80         match self {
81             Data::Enum(v) => Some(v),
82             Data::Struct(_) => None,
83         }
84     }
85 
86     /// Returns `true` if this instance is `Data::Enum`.
is_enum(&self) -> bool87     pub fn is_enum(&self) -> bool {
88         match *self {
89             Data::Enum(_) => true,
90             Data::Struct(_) => false,
91         }
92     }
93 
94     /// Returns `true` if this instance is `Data::Struct`.
is_struct(&self) -> bool95     pub fn is_struct(&self) -> bool {
96         !self.is_enum()
97     }
98 }
99 
100 impl<V: FromVariant, F: FromField> Data<V, F> {
101     /// Attempt to convert from a `syn::Data` instance.
try_from(body: &syn::Data) -> Result<Self>102     pub fn try_from(body: &syn::Data) -> Result<Self> {
103         match *body {
104             syn::Data::Enum(ref data) => {
105                 let mut items = Vec::with_capacity(data.variants.len());
106                 let mut errors = Vec::new();
107                 for v_result in data.variants.iter().map(FromVariant::from_variant) {
108                     match v_result {
109                         Ok(val) => items.push(val),
110                         Err(err) => errors.push(err),
111                     }
112                 }
113 
114                 if !errors.is_empty() {
115                     Err(Error::multiple(errors))
116                 } else {
117                     Ok(Data::Enum(items))
118                 }
119             }
120             syn::Data::Struct(ref data) => Ok(Data::Struct(Fields::try_from(&data.fields)?)),
121             syn::Data::Union(_) => unreachable!(),
122         }
123     }
124 }
125 
126 impl<V: UsesTypeParams, F: UsesTypeParams> UsesTypeParams for Data<V, F> {
uses_type_params<'a>( &self, options: &usage::Options, type_set: &'a IdentSet, ) -> IdentRefSet<'a>127     fn uses_type_params<'a>(
128         &self,
129         options: &usage::Options,
130         type_set: &'a IdentSet,
131     ) -> IdentRefSet<'a> {
132         match *self {
133             Data::Struct(ref v) => v.uses_type_params(options, type_set),
134             Data::Enum(ref v) => v.uses_type_params(options, type_set),
135         }
136     }
137 }
138 
139 impl<V: UsesLifetimes, F: UsesLifetimes> UsesLifetimes for Data<V, F> {
uses_lifetimes<'a>( &self, options: &usage::Options, lifetimes: &'a LifetimeSet, ) -> LifetimeRefSet<'a>140     fn uses_lifetimes<'a>(
141         &self,
142         options: &usage::Options,
143         lifetimes: &'a LifetimeSet,
144     ) -> LifetimeRefSet<'a> {
145         match *self {
146             Data::Struct(ref v) => v.uses_lifetimes(options, lifetimes),
147             Data::Enum(ref v) => v.uses_lifetimes(options, lifetimes),
148         }
149     }
150 }
151 
152 /// Equivalent to `syn::Fields`, but replaces the AST element with a generic.
153 #[derive(Debug, Clone, PartialEq, Eq)]
154 pub struct Fields<T> {
155     pub style: Style,
156     pub fields: Vec<T>,
157 }
158 
159 impl<T> Fields<T> {
empty_from(vd: &syn::Fields) -> Self160     pub fn empty_from(vd: &syn::Fields) -> Self {
161         Fields {
162             style: vd.into(),
163             fields: Vec::new(),
164         }
165     }
166 
167     /// Splits the `Fields` into its style and fields for further processing.
168     /// Returns an empty `Vec` for `Unit` data.
split(self) -> (Style, Vec<T>)169     pub fn split(self) -> (Style, Vec<T>) {
170         (self.style, self.fields)
171     }
172 
173     /// Returns true if this variant's data makes it a newtype.
is_newtype(&self) -> bool174     pub fn is_newtype(&self) -> bool {
175         self.style == Style::Tuple && self.len() == 1
176     }
177 
is_unit(&self) -> bool178     pub fn is_unit(&self) -> bool {
179         self.style.is_unit()
180     }
181 
is_tuple(&self) -> bool182     pub fn is_tuple(&self) -> bool {
183         self.style.is_tuple()
184     }
185 
is_struct(&self) -> bool186     pub fn is_struct(&self) -> bool {
187         self.style.is_struct()
188     }
189 
as_ref<'a>(&'a self) -> Fields<&'a T>190     pub fn as_ref<'a>(&'a self) -> Fields<&'a T> {
191         Fields {
192             style: self.style,
193             fields: self.fields.iter().collect(),
194         }
195     }
196 
map<F, U>(self, map: F) -> Fields<U> where F: FnMut(T) -> U,197     pub fn map<F, U>(self, map: F) -> Fields<U>
198     where
199         F: FnMut(T) -> U,
200     {
201         Fields {
202             style: self.style,
203             fields: self.fields.into_iter().map(map).collect(),
204         }
205     }
206 
iter(&self) -> slice::Iter<T>207     pub fn iter(&self) -> slice::Iter<T> {
208         self.fields.iter()
209     }
210 
211     /// Returns the number of fields in the structure.
len(&self) -> usize212     pub fn len(&self) -> usize {
213         self.fields.len()
214     }
215 
216     /// Returns `true` if the `Fields` contains no fields.
is_empty(&self) -> bool217     pub fn is_empty(&self) -> bool {
218         self.fields.is_empty()
219     }
220 }
221 
222 impl<F: FromField> Fields<F> {
try_from(fields: &syn::Fields) -> Result<Self>223     pub fn try_from(fields: &syn::Fields) -> Result<Self> {
224         let (items, errors) = match *fields {
225             syn::Fields::Named(ref fields) => {
226                 let mut items = Vec::with_capacity(fields.named.len());
227                 let mut errors = Vec::new();
228 
229                 for field in &fields.named {
230                     match FromField::from_field(field) {
231                         Ok(val) => items.push(val),
232                         Err(err) => errors.push(if let Some(ref ident) = field.ident {
233                             err.at(ident)
234                         } else {
235                             err
236                         }),
237                     }
238                 }
239 
240                 (items, errors)
241             }
242             syn::Fields::Unnamed(ref fields) => {
243                 let mut items = Vec::with_capacity(fields.unnamed.len());
244                 let mut errors = Vec::new();
245 
246                 for field in &fields.unnamed {
247                     match FromField::from_field(field) {
248                         Ok(val) => items.push(val),
249                         Err(err) => errors.push(if let Some(ref ident) = field.ident {
250                             err.at(ident)
251                         } else {
252                             err
253                         }),
254                     }
255                 }
256 
257                 (items, errors)
258             }
259             syn::Fields::Unit => (vec![], vec![]),
260         };
261 
262         if !errors.is_empty() {
263             Err(Error::multiple(errors))
264         } else {
265             Ok(Fields {
266                 style: fields.into(),
267                 fields: items,
268             })
269         }
270     }
271 }
272 
273 impl<T> IntoIterator for Fields<T> {
274     type Item = T;
275     type IntoIter = vec::IntoIter<T>;
276 
into_iter(self) -> Self::IntoIter277     fn into_iter(self) -> Self::IntoIter {
278         self.fields.into_iter()
279     }
280 }
281 
282 impl<T> From<Style> for Fields<T> {
from(style: Style) -> Self283     fn from(style: Style) -> Self {
284         Fields {
285             style,
286             fields: Vec::new(),
287         }
288     }
289 }
290 
291 impl<T, U: Into<Vec<T>>> From<(Style, U)> for Fields<T> {
from((style, fields): (Style, U)) -> Self292     fn from((style, fields): (Style, U)) -> Self {
293         style.with_fields(fields)
294     }
295 }
296 
297 impl<T: UsesTypeParams> UsesTypeParams for Fields<T> {
uses_type_params<'a>( &self, options: &usage::Options, type_set: &'a IdentSet, ) -> IdentRefSet<'a>298     fn uses_type_params<'a>(
299         &self,
300         options: &usage::Options,
301         type_set: &'a IdentSet,
302     ) -> IdentRefSet<'a> {
303         self.fields.uses_type_params(options, type_set)
304     }
305 }
306 
307 impl<T: UsesLifetimes> UsesLifetimes for Fields<T> {
uses_lifetimes<'a>( &self, options: &usage::Options, lifetimes: &'a LifetimeSet, ) -> LifetimeRefSet<'a>308     fn uses_lifetimes<'a>(
309         &self,
310         options: &usage::Options,
311         lifetimes: &'a LifetimeSet,
312     ) -> LifetimeRefSet<'a> {
313         self.fields.uses_lifetimes(options, lifetimes)
314     }
315 }
316 
317 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
318 pub enum Style {
319     Tuple,
320     Struct,
321     Unit,
322 }
323 
324 impl Style {
is_unit(self) -> bool325     pub fn is_unit(self) -> bool {
326         self == Style::Unit
327     }
328 
is_tuple(self) -> bool329     pub fn is_tuple(self) -> bool {
330         self == Style::Tuple
331     }
332 
is_struct(self) -> bool333     pub fn is_struct(self) -> bool {
334         self == Style::Struct
335     }
336 
337     /// Creates a new `Fields` of the specified style with the passed-in fields.
with_fields<T, U: Into<Vec<T>>>(self, fields: U) -> Fields<T>338     fn with_fields<T, U: Into<Vec<T>>>(self, fields: U) -> Fields<T> {
339         Fields {
340             style: self,
341             fields: fields.into(),
342         }
343     }
344 }
345 
346 impl From<syn::Fields> for Style {
from(vd: syn::Fields) -> Self347     fn from(vd: syn::Fields) -> Self {
348         (&vd).into()
349     }
350 }
351 
352 impl<'a> From<&'a syn::Fields> for Style {
from(vd: &syn::Fields) -> Self353     fn from(vd: &syn::Fields) -> Self {
354         match *vd {
355             syn::Fields::Named(_) => Style::Struct,
356             syn::Fields::Unnamed(_) => Style::Tuple,
357             syn::Fields::Unit => Style::Unit,
358         }
359     }
360 }
361