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