diff --git a/Cargo.toml b/Cargo.toml index 94aecbc..6a1f0ca 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,8 +19,8 @@ darling_core = { version = "=0.2.2", path = "core" } darling_macro = { version = "=0.2.2", path = "macro" } [dev-dependencies] -syn = "0.11.11" -quote = "0.3.15" +syn = "0.12.10" +quote = "0.4" [workspace] members = ["macro", "core"] diff --git a/core/Cargo.toml b/core/Cargo.toml index df84e88..4e5d4c4 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -16,6 +16,5 @@ default = ["syn/full"] [dependencies] ident_case = "1.0.0" -lazy_static = "1.0.0" -syn = "0.11.11" -quote = "0.3.15" +syn = { version = "0.12.10", features = ["extra-traits"] } +quote = "0.4" diff --git a/core/src/ast.rs b/core/src/ast.rs index 4f25bed..a0b68fa 100644 --- a/core/src/ast.rs +++ b/core/src/ast.rs @@ -8,96 +8,100 @@ use {Error, FromField, FromVariant, Result}; /// /// `V` is the type which receives any encountered variants, and `F` receives struct fields. #[derive(Debug, Clone, PartialEq, Eq)] -pub enum Body { +pub enum Data { Enum(Vec), - Struct(VariantData), + Struct(Fields), } -impl Body { +#[deprecated(since="0.3", note="this has been renamed to Data")] +pub type Body = Data; + +impl Data { /// Creates an empty body of the same shape as the passed-in body. - pub fn empty_from(src: &syn::Body) -> Self { + pub fn empty_from(src: &syn::Data) -> Self { match *src { - syn::Body::Enum(_) => Body::Enum(vec![]), - syn::Body::Struct(ref vd) => Body::Struct(VariantData::empty_from(vd)), + syn::Data::Enum(_) => Data::Enum(vec![]), + syn::Data::Struct(ref vd) => Data::Struct(Fields::empty_from(&vd.fields)), + syn::Data::Union(_) => unreachable!(), } } - /// Creates a new `Body<&'a V, &'a F>` instance from `Body`. - pub fn as_ref<'a>(&'a self) -> Body<&'a V, &'a F> { + /// Creates a new `Data<&'a V, &'a F>` instance from `Data`. + pub fn as_ref<'a>(&'a self) -> Data<&'a V, &'a F> { match *self { - Body::Enum(ref variants) => Body::Enum(variants.into_iter().collect()), - Body::Struct(ref data) => Body::Struct(data.as_ref()), + Data::Enum(ref variants) => Data::Enum(variants.into_iter().collect()), + Data::Struct(ref data) => Data::Struct(data.as_ref()), } } /// Applies a function `V -> U` on enum variants, if this is an enum. - pub fn map_enum_variants(self, map: T) -> Body + pub fn map_enum_variants(self, map: T) -> Data where T: FnMut(V) -> U { match self { - Body::Enum(v) => Body::Enum(v.into_iter().map(map).collect()), - Body::Struct(f) => Body::Struct(f), + Data::Enum(v) => Data::Enum(v.into_iter().map(map).collect()), + Data::Struct(f) => Data::Struct(f), } } /// Applies a function `F -> U` on struct fields, if this is a struct. - pub fn map_struct_fields(self, map: T) -> Body + pub fn map_struct_fields(self, map: T) -> Data where T: FnMut(F) -> U { match self { - Body::Enum(v) => Body::Enum(v), - Body::Struct(f) => Body::Struct(f.map(map)), + Data::Enum(v) => Data::Enum(v), + Data::Struct(f) => Data::Struct(f.map(map)), } } - /// Applies a function to the `VariantData` if this is a struct. - pub fn map_struct(self, mut map: T) -> Body - where T: FnMut(VariantData) -> VariantData + /// Applies a function to the `Fields` if this is a struct. + pub fn map_struct(self, mut map: T) -> Data + where T: FnMut(Fields) -> Fields { match self { - Body::Enum(v) => Body::Enum(v), - Body::Struct(f) => Body::Struct(map(f)), + Data::Enum(v) => Data::Enum(v), + Data::Struct(f) => Data::Struct(map(f)), } } - /// Consumes the `Body`, returning `VariantData` if it was a struct. - pub fn take_struct(self) -> Option> { + /// Consumes the `Data`, returning `Fields` if it was a struct. + pub fn take_struct(self) -> Option> { match self { - Body::Enum(_) => None, - Body::Struct(f) => Some(f), + Data::Enum(_) => None, + Data::Struct(f) => Some(f), } } - /// Consumes the `Body`, returning `Vec` if it was an enum. + /// Consumes the `Data`, returning `Vec` if it was an enum. pub fn take_enum(self) -> Option> { match self { - Body::Enum(v) => Some(v), - Body::Struct(_) => None, + Data::Enum(v) => Some(v), + Data::Struct(_) => None, } } - /// Returns `true` if this instance is `Body::Enum`. + /// Returns `true` if this instance is `Data::Enum`. pub fn is_enum(&self) -> bool { match *self { - Body::Enum(_) => true, - Body::Struct(_) => false, + Data::Enum(_) => true, + Data::Struct(_) => false, } } - /// Returns `true` if this instance is `Body::Struct`. + /// Returns `true` if this instance is `Data::Struct`. pub fn is_struct(&self) -> bool { !self.is_enum() } } -impl Body { - /// Attempt to convert from a `syn::Body` instance. - pub fn try_from(body: &syn::Body) -> Result { +impl Data { + /// Attempt to convert from a `syn::Data` instance. + pub fn try_from(body: &syn::Data) -> Result { match *body { - syn::Body::Enum(ref variants) => { - let mut items = Vec::with_capacity(variants.len()); + syn::Data::Enum(ref data) => { + let mut items = Vec::with_capacity(data.variants.len()); let mut errors = Vec::new(); - for v_result in variants.into_iter().map(FromVariant::from_variant) { + for v_result in data.variants.clone().into_iter().map(|v| FromVariant::from_variant(&v)) { match v_result { Ok(val) => items.push(val), Err(err) => errors.push(err) @@ -107,29 +111,33 @@ impl Body { if !errors.is_empty() { Err(Error::multiple(errors)) } else { - Ok(Body::Enum(items)) + Ok(Data::Enum(items)) } } - syn::Body::Struct(ref data) => Ok(Body::Struct(VariantData::try_from(data)?)), + syn::Data::Struct(ref data) => Ok(Data::Struct(Fields::try_from(&data.fields)?)), + syn::Data::Union(_) => unreachable!(), } } } #[derive(Debug, Clone, PartialEq, Eq)] -pub struct VariantData { +pub struct Fields { pub style: Style, pub fields: Vec, } -impl VariantData { - pub fn empty_from(vd: &syn::VariantData) -> Self { - VariantData { +#[deprecated(since="0.3", note="this has been renamed to Fields")] +pub type VariantData = Fields; + +impl Fields { + pub fn empty_from(vd: &syn::Fields) -> Self { + Fields { style: vd.into(), fields: Vec::new(), } } - /// Splits the `VariantData` into its style and fields for further processing. + /// Splits the `Fields` into its style and fields for further processing. /// Returns an empty `Vec` for `Unit` data. pub fn split(self) -> (Style, Vec) { (self.style, self.fields) @@ -152,60 +160,85 @@ impl VariantData { self.style.is_struct() } - pub fn as_ref<'a>(&'a self) -> VariantData<&'a T> { - VariantData { + pub fn as_ref<'a>(&'a self) -> Fields<&'a T> { + Fields { style: self.style, fields: self.fields.iter().collect(), } } - pub fn map(self, map: F) -> VariantData where F: FnMut(T) -> U { - VariantData { + pub fn map(self, map: F) -> Fields where F: FnMut(T) -> U { + Fields { style: self.style, fields: self.fields.into_iter().map(map).collect() } } } -impl VariantData { - pub fn try_from(data: &syn::VariantData) -> Result { - let fields = data.fields(); - let mut items = Vec::with_capacity(fields.len()); - let mut errors = Vec::new(); - - for field in fields { - let f_result = FromField::from_field(field); - match f_result { - Ok(val) => items.push(val), - Err(err) => errors.push(if let Some(ref ident) = field.ident { - err.at(ident.as_ref()) - } else { - err - }) +impl Fields { + pub fn try_from(fields: &syn::Fields) -> Result { + let (items, errors) = match *fields { + syn::Fields::Named(ref fields) => { + let mut items = Vec::with_capacity(fields.named.len()); + let mut errors = Vec::new(); + + for field in &fields.named { + let f_result = FromField::from_field(field); + match f_result { + Ok(val) => items.push(val), + Err(err) => errors.push(if let Some(ref ident) = field.ident { + err.at(ident.as_ref()) + } else { + err + }) + } + } + + (items, errors) } - } + syn::Fields::Unnamed(ref fields) => { + let mut items = Vec::with_capacity(fields.unnamed.len()); + let mut errors = Vec::new(); + + for field in &fields.unnamed { + let f_result = FromField::from_field(field); + match f_result { + Ok(val) => items.push(val), + Err(err) => errors.push(if let Some(ref ident) = field.ident { + err.at(ident.as_ref()) + } else { + err + }) + } + } + + (items, errors) + } + syn::Fields::Unit => (vec![], vec![]), + }; + if !errors.is_empty() { Err(Error::multiple(errors)) } else { - Ok(VariantData { - style: data.into(), + Ok(Fields { + style: fields.into(), fields: items, - }) + }) } } } -impl From