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