1 //! Utility types for working with the AST.
2 
3 use syn;
4 
5 use {Error, FromField, FromVariant, Result};
6 
7 /// A struct or enum body.
8 ///
9 /// `V` is the type which receives any encountered variants, and `F` receives struct fields.
10 #[derive(Debug, Clone, PartialEq, Eq)]
11 pub enum Data<V, F> {
12     Enum(Vec<V>),
13     Struct(Fields<F>),
14 }
15 
16 #[deprecated(since="0.3", note="this has been renamed to Data")]
17 pub type Body<V, F> = Data<V, F>;
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.into_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) -> U38     pub fn map_enum_variants<T, U>(self, map: T) -> Data<U, F>
39         where T: FnMut(V) -> U
40     {
41         match self {
42             Data::Enum(v) => Data::Enum(v.into_iter().map(map).collect()),
43             Data::Struct(f) => Data::Struct(f),
44         }
45     }
46 
47     /// 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) -> U48     pub fn map_struct_fields<T, U>(self, map: T) -> Data<V, U>
49         where T: FnMut(F) -> U
50     {
51         match self {
52             Data::Enum(v) => Data::Enum(v),
53             Data::Struct(f) => Data::Struct(f.map(map)),
54         }
55     }
56 
57     /// 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>58     pub fn map_struct<T, U>(self, mut map: T) -> Data<V, U>
59         where T: FnMut(Fields<F>) -> Fields<U>
60     {
61         match self {
62             Data::Enum(v) => Data::Enum(v),
63             Data::Struct(f) => Data::Struct(map(f)),
64         }
65     }
66 
67     /// Consumes the `Data`, returning `Fields<F>` if it was a struct.
take_struct(self) -> Option<Fields<F>>68     pub fn take_struct(self) -> Option<Fields<F>> {
69         match self {
70             Data::Enum(_) => None,
71             Data::Struct(f) => Some(f),
72         }
73     }
74 
75     /// Consumes the `Data`, returning `Vec<V>` if it was an enum.
take_enum(self) -> Option<Vec<V>>76     pub fn take_enum(self) -> Option<Vec<V>> {
77         match self {
78             Data::Enum(v) => Some(v),
79             Data::Struct(_) => None,
80         }
81     }
82 
83     /// Returns `true` if this instance is `Data::Enum`.
is_enum(&self) -> bool84     pub fn is_enum(&self) -> bool {
85         match *self {
86             Data::Enum(_) => true,
87             Data::Struct(_) => false,
88         }
89     }
90 
91     /// Returns `true` if this instance is `Data::Struct`.
is_struct(&self) -> bool92     pub fn is_struct(&self) -> bool {
93         !self.is_enum()
94     }
95 }
96 
97 impl<V: FromVariant, F: FromField> Data<V, F> {
98     /// Attempt to convert from a `syn::Data` instance.
try_from(body: &syn::Data) -> Result<Self>99     pub fn try_from(body: &syn::Data) -> Result<Self> {
100         match *body {
101             syn::Data::Enum(ref data) => {
102                 let mut items = Vec::with_capacity(data.variants.len());
103                 let mut errors = Vec::new();
104                 for v_result in data.variants.clone().into_iter().map(|v| FromVariant::from_variant(&v)) {
105                     match v_result {
106                         Ok(val) => items.push(val),
107                         Err(err) => errors.push(err)
108                     }
109                 }
110 
111                 if !errors.is_empty() {
112                     Err(Error::multiple(errors))
113                 } else {
114                     Ok(Data::Enum(items))
115                 }
116             }
117             syn::Data::Struct(ref data) => Ok(Data::Struct(Fields::try_from(&data.fields)?)),
118             syn::Data::Union(_) => unreachable!(),
119         }
120     }
121 }
122 
123 #[derive(Debug, Clone, PartialEq, Eq)]
124 pub struct Fields<T> {
125     pub style: Style,
126     pub fields: Vec<T>,
127 }
128 
129 #[deprecated(since="0.3", note="this has been renamed to Fields")]
130 pub type VariantData<T> = Fields<T>;
131 
132 impl<T> Fields<T> {
empty_from(vd: &syn::Fields) -> Self133     pub fn empty_from(vd: &syn::Fields) -> Self {
134         Fields {
135             style: vd.into(),
136             fields: Vec::new(),
137         }
138     }
139 
140     /// Splits the `Fields` into its style and fields for further processing.
141     /// Returns an empty `Vec` for `Unit` data.
split(self) -> (Style, Vec<T>)142     pub fn split(self) -> (Style, Vec<T>) {
143         (self.style, self.fields)
144     }
145 
146     /// Returns true if this variant's data makes it a newtype.
is_newtype(&self) -> bool147     pub fn is_newtype(&self) -> bool {
148         self.style == Style::Tuple && self.fields.len() == 1
149     }
150 
is_unit(&self) -> bool151     pub fn is_unit(&self) -> bool {
152         self.style.is_unit()
153     }
154 
is_tuple(&self) -> bool155     pub fn is_tuple(&self) -> bool {
156         self.style.is_tuple()
157     }
158 
is_struct(&self) -> bool159     pub fn is_struct(&self) -> bool {
160         self.style.is_struct()
161     }
162 
as_ref<'a>(&'a self) -> Fields<&'a T>163     pub fn as_ref<'a>(&'a self) -> Fields<&'a T> {
164         Fields {
165             style: self.style,
166             fields: self.fields.iter().collect(),
167         }
168     }
169 
map<F, U>(self, map: F) -> Fields<U> where F: FnMut(T) -> U170     pub fn map<F, U>(self, map: F) -> Fields<U> where F: FnMut(T) -> U {
171         Fields {
172             style: self.style,
173             fields: self.fields.into_iter().map(map).collect()
174         }
175     }
176 }
177 
178 impl<F: FromField> Fields<F> {
try_from(fields: &syn::Fields) -> Result<Self>179     pub fn try_from(fields: &syn::Fields) -> Result<Self> {
180         let (items, errors) = match *fields {
181             syn::Fields::Named(ref fields) => {
182                 let mut items = Vec::with_capacity(fields.named.len());
183                 let mut errors = Vec::new();
184 
185                 for field in &fields.named {
186                     let f_result = FromField::from_field(field);
187                     match f_result {
188                         Ok(val) => items.push(val),
189                         Err(err) => errors.push(if let Some(ref ident) = field.ident {
190                             err.at(ident.as_ref())
191                         } else {
192                             err
193                         })
194                     }
195                 }
196 
197                 (items, errors)
198             }
199             syn::Fields::Unnamed(ref fields) => {
200                 let mut items = Vec::with_capacity(fields.unnamed.len());
201                 let mut errors = Vec::new();
202 
203                 for field in &fields.unnamed {
204                     let f_result = FromField::from_field(field);
205                     match f_result {
206                         Ok(val) => items.push(val),
207                         Err(err) => errors.push(if let Some(ref ident) = field.ident {
208                             err.at(ident.as_ref())
209                         } else {
210                             err
211                         })
212                     }
213                 }
214 
215                 (items, errors)
216             }
217             syn::Fields::Unit => (vec![], vec![]),
218         };
219 
220 
221         if !errors.is_empty() {
222             Err(Error::multiple(errors))
223         } else {
224             Ok(Fields {
225                 style: fields.into(),
226                 fields: items,
227             })
228         }
229     }
230 }
231 
232 impl<T> From<Style> for Fields<T> {
from(style: Style) -> Self233     fn from(style: Style) -> Self {
234         Fields {
235             style,
236             fields: Vec::new(),
237         }
238     }
239 }
240 
241 impl<T, U: Into<Vec<T>>> From<(Style, U)> for Fields<T> {
from((style, fields): (Style, U)) -> Self242     fn from((style, fields): (Style, U)) -> Self {
243         style.with_fields(fields)
244     }
245 }
246 
247 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
248 pub enum Style {
249     Tuple,
250     Struct,
251     Unit,
252 }
253 
254 impl Style {
is_unit(&self) -> bool255     pub fn is_unit(&self) -> bool {
256         *self == Style::Unit
257     }
258 
is_tuple(&self) -> bool259     pub fn is_tuple(&self) -> bool {
260         *self == Style::Tuple
261     }
262 
is_struct(&self) -> bool263     pub fn is_struct(&self) -> bool {
264         *self == Style::Struct
265     }
266 
267     /// 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>268     fn with_fields<T, U: Into<Vec<T>>>(self, fields: U) -> Fields<T> {
269         Fields {
270             style: self,
271             fields: fields.into(),
272         }
273     }
274 }
275 
276 impl From<syn::Fields> for Style {
from(vd: syn::Fields) -> Self277     fn from(vd: syn::Fields) -> Self {
278         (&vd).into()
279     }
280 }
281 
282 impl<'a> From<&'a syn::Fields> for Style {
from(vd: &syn::Fields) -> Self283     fn from(vd: &syn::Fields) -> Self {
284         match *vd {
285             syn::Fields::Named(_) => Style::Struct,
286             syn::Fields::Unnamed(_) => Style::Tuple,
287             syn::Fields::Unit => Style::Unit,
288         }
289     }
290 }
291