use super::*; /// An enum variant. #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub struct Variant { /// Name of the variant. pub ident: Ident, /// Attributes tagged on the variant. pub attrs: Vec, /// Type of variant. pub data: VariantData, /// Explicit discriminant, e.g. `Foo = 1` pub discriminant: Option, } /// Data stored within an enum variant or struct. #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub enum VariantData { /// Struct variant, e.g. `Point { x: f64, y: f64 }`. Struct(Vec), /// Tuple variant, e.g. `Some(T)`. Tuple(Vec), /// Unit variant, e.g. `None`. Unit, } impl VariantData { /// Slice containing the fields stored in the variant. pub fn fields(&self) -> &[Field] { match *self { VariantData::Struct(ref fields) | VariantData::Tuple(ref fields) => fields, VariantData::Unit => &[], } } /// Mutable slice containing the fields stored in the variant. pub fn fields_mut(&mut self) -> &mut [Field] { match *self { VariantData::Struct(ref mut fields) | VariantData::Tuple(ref mut fields) => fields, VariantData::Unit => &mut [], } } } /// A field of a struct or enum variant. #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub struct Field { /// Name of the field, if any. /// /// Fields of tuple structs have no names. pub ident: Option, /// Visibility of the field. pub vis: Visibility, /// Attributes tagged on the field. pub attrs: Vec, /// Type of the field. pub ty: Ty, } /// Visibility level of an item. #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub enum Visibility { /// Public, i.e. `pub`. Public, /// Crate-visible, i.e. `pub(crate)`. Crate, /// Restricted, e.g. `pub(some::module)`. Restricted(Box), /// Inherited, i.e. private. Inherited, } #[cfg(feature = "parsing")] pub mod parsing { use super::*; use WhereClause; #[cfg(feature = "full")] use ConstExpr; use attr::parsing::outer_attr; #[cfg(feature = "full")] use constant::parsing::const_expr; #[cfg(feature = "full")] use expr::parsing::expr; use generics::parsing::where_clause; use ident::parsing::ident; use ty::parsing::{path, ty}; named!(pub struct_body -> (WhereClause, VariantData), alt!( do_parse!( wh: where_clause >> body: struct_like_body >> (wh, VariantData::Struct(body)) ) | do_parse!( body: tuple_like_body >> wh: where_clause >> punct!(";") >> (wh, VariantData::Tuple(body)) ) | do_parse!( wh: where_clause >> punct!(";") >> (wh, VariantData::Unit) ) )); named!(pub enum_body -> (WhereClause, Vec), do_parse!( wh: where_clause >> punct!("{") >> variants: terminated_list!(punct!(","), variant) >> punct!("}") >> (wh, variants) )); named!(variant -> Variant, do_parse!( attrs: many0!(outer_attr) >> id: ident >> data: alt!( struct_like_body => { VariantData::Struct } | tuple_like_body => { VariantData::Tuple } | epsilon!() => { |_| VariantData::Unit } ) >> disr: option!(preceded!(punct!("="), discriminant)) >> (Variant { ident: id, attrs: attrs, data: data, discriminant: disr, }) )); #[cfg(not(feature = "full"))] use constant::parsing::const_expr as discriminant; #[cfg(feature = "full")] named!(discriminant -> ConstExpr, alt!( terminated!(const_expr, after_discriminant) | terminated!(expr, after_discriminant) => { ConstExpr::Other } )); #[cfg(feature = "full")] named!(after_discriminant -> &str, peek!(alt!(punct!(",") | punct!("}")))); named!(pub struct_like_body -> Vec, do_parse!( punct!("{") >> fields: terminated_list!(punct!(","), struct_field) >> punct!("}") >> (fields) )); named!(tuple_like_body -> Vec, do_parse!( punct!("(") >> fields: terminated_list!(punct!(","), tuple_field) >> punct!(")") >> (fields) )); named!(struct_field -> Field, do_parse!( attrs: many0!(outer_attr) >> vis: visibility >> id: ident >> punct!(":") >> ty: ty >> (Field { ident: Some(id), vis: vis, attrs: attrs, ty: ty, }) )); named!(tuple_field -> Field, do_parse!( attrs: many0!(outer_attr) >> vis: visibility >> ty: ty >> (Field { ident: None, vis: vis, attrs: attrs, ty: ty, }) )); named!(pub visibility -> Visibility, alt!( do_parse!( keyword!("pub") >> punct!("(") >> keyword!("crate") >> punct!(")") >> (Visibility::Crate) ) | do_parse!( keyword!("pub") >> punct!("(") >> restricted: path >> punct!(")") >> (Visibility::Restricted(Box::new(restricted))) ) | keyword!("pub") => { |_| Visibility::Public } | epsilon!() => { |_| Visibility::Inherited } )); } #[cfg(feature = "printing")] mod printing { use super::*; use quote::{Tokens, ToTokens}; impl ToTokens for Variant { fn to_tokens(&self, tokens: &mut Tokens) { for attr in &self.attrs { attr.to_tokens(tokens); } self.ident.to_tokens(tokens); self.data.to_tokens(tokens); if let Some(ref disr) = self.discriminant { tokens.append("="); disr.to_tokens(tokens); } } } impl ToTokens for VariantData { fn to_tokens(&self, tokens: &mut Tokens) { match *self { VariantData::Struct(ref fields) => { tokens.append("{"); tokens.append_separated(fields, ","); tokens.append("}"); } VariantData::Tuple(ref fields) => { tokens.append("("); tokens.append_separated(fields, ","); tokens.append(")"); } VariantData::Unit => {} } } } impl ToTokens for Field { fn to_tokens(&self, tokens: &mut Tokens) { for attr in &self.attrs { attr.to_tokens(tokens); } self.vis.to_tokens(tokens); if let Some(ref ident) = self.ident { ident.to_tokens(tokens); tokens.append(":"); } self.ty.to_tokens(tokens); } } impl ToTokens for Visibility { fn to_tokens(&self, tokens: &mut Tokens) { match *self { Visibility::Public => tokens.append("pub"), Visibility::Crate => { tokens.append("pub"); tokens.append("("); tokens.append("crate"); tokens.append(")"); } Visibility::Restricted(ref path) => { tokens.append("pub"); tokens.append("("); path.to_tokens(tokens); tokens.append(")"); } Visibility::Inherited => {} } } } }