1 use super::*; 2 3 /// An enum variant. 4 #[derive(Debug, Clone, Eq, PartialEq, Hash)] 5 pub struct Variant { 6 /// Name of the variant. 7 pub ident: Ident, 8 9 /// Attributes tagged on the variant. 10 pub attrs: Vec<Attribute>, 11 12 /// Type of variant. 13 pub data: VariantData, 14 15 /// Explicit discriminant, e.g. `Foo = 1` 16 pub discriminant: Option<ConstExpr>, 17 } 18 19 /// Data stored within an enum variant or struct. 20 #[derive(Debug, Clone, Eq, PartialEq, Hash)] 21 pub enum VariantData { 22 /// Struct variant, e.g. `Point { x: f64, y: f64 }`. 23 Struct(Vec<Field>), 24 25 /// Tuple variant, e.g. `Some(T)`. 26 Tuple(Vec<Field>), 27 28 /// Unit variant, e.g. `None`. 29 Unit, 30 } 31 32 impl VariantData { 33 /// Slice containing the fields stored in the variant. fields(&self) -> &[Field]34 pub fn fields(&self) -> &[Field] { 35 match *self { 36 VariantData::Struct(ref fields) | 37 VariantData::Tuple(ref fields) => fields, 38 VariantData::Unit => &[], 39 } 40 } 41 42 /// Mutable slice containing the fields stored in the variant. fields_mut(&mut self) -> &mut [Field]43 pub fn fields_mut(&mut self) -> &mut [Field] { 44 match *self { 45 VariantData::Struct(ref mut fields) | 46 VariantData::Tuple(ref mut fields) => fields, 47 VariantData::Unit => &mut [], 48 } 49 } 50 } 51 52 /// A field of a struct or enum variant. 53 #[derive(Debug, Clone, Eq, PartialEq, Hash)] 54 pub struct Field { 55 /// Name of the field, if any. 56 /// 57 /// Fields of tuple structs have no names. 58 pub ident: Option<Ident>, 59 60 /// Visibility of the field. 61 pub vis: Visibility, 62 63 /// Attributes tagged on the field. 64 pub attrs: Vec<Attribute>, 65 66 /// Type of the field. 67 pub ty: Ty, 68 } 69 70 71 /// Visibility level of an item. 72 #[derive(Debug, Clone, Eq, PartialEq, Hash)] 73 pub enum Visibility { 74 /// Public, i.e. `pub`. 75 Public, 76 77 /// Crate-visible, i.e. `pub(crate)`. 78 Crate, 79 80 /// Restricted, e.g. `pub(some::module)`. 81 Restricted(Box<Path>), 82 83 /// Inherited, i.e. private. 84 Inherited, 85 } 86 87 #[cfg(feature = "parsing")] 88 pub mod parsing { 89 use super::*; 90 use WhereClause; 91 #[cfg(feature = "full")] 92 use ConstExpr; 93 use attr::parsing::outer_attr; 94 #[cfg(feature = "full")] 95 use constant::parsing::const_expr; 96 #[cfg(feature = "full")] 97 use expr::parsing::expr; 98 use generics::parsing::where_clause; 99 use ident::parsing::ident; 100 use ty::parsing::{path, ty}; 101 102 named!(pub struct_body -> (WhereClause, VariantData), alt!( 103 do_parse!( 104 wh: where_clause >> 105 body: struct_like_body >> 106 (wh, VariantData::Struct(body)) 107 ) 108 | 109 do_parse!( 110 body: tuple_like_body >> 111 wh: where_clause >> 112 punct!(";") >> 113 (wh, VariantData::Tuple(body)) 114 ) 115 | 116 do_parse!( 117 wh: where_clause >> 118 punct!(";") >> 119 (wh, VariantData::Unit) 120 ) 121 )); 122 123 named!(pub enum_body -> (WhereClause, Vec<Variant>), do_parse!( 124 wh: where_clause >> 125 punct!("{") >> 126 variants: terminated_list!(punct!(","), variant) >> 127 punct!("}") >> 128 (wh, variants) 129 )); 130 131 named!(variant -> Variant, do_parse!( 132 attrs: many0!(outer_attr) >> 133 id: ident >> 134 data: alt!( 135 struct_like_body => { VariantData::Struct } 136 | 137 tuple_like_body => { VariantData::Tuple } 138 | 139 epsilon!() => { |_| VariantData::Unit } 140 ) >> 141 disr: option!(preceded!(punct!("="), discriminant)) >> 142 (Variant { 143 ident: id, 144 attrs: attrs, 145 data: data, 146 discriminant: disr, 147 }) 148 )); 149 150 #[cfg(not(feature = "full"))] 151 use constant::parsing::const_expr as discriminant; 152 153 #[cfg(feature = "full")] 154 named!(discriminant -> ConstExpr, alt!( 155 terminated!(const_expr, after_discriminant) 156 | 157 terminated!(expr, after_discriminant) => { ConstExpr::Other } 158 )); 159 160 #[cfg(feature = "full")] 161 named!(after_discriminant -> &str, peek!(alt!(punct!(",") | punct!("}")))); 162 163 named!(pub struct_like_body -> Vec<Field>, do_parse!( 164 punct!("{") >> 165 fields: terminated_list!(punct!(","), struct_field) >> 166 punct!("}") >> 167 (fields) 168 )); 169 170 named!(tuple_like_body -> Vec<Field>, do_parse!( 171 punct!("(") >> 172 fields: terminated_list!(punct!(","), tuple_field) >> 173 punct!(")") >> 174 (fields) 175 )); 176 177 named!(struct_field -> Field, do_parse!( 178 attrs: many0!(outer_attr) >> 179 vis: visibility >> 180 id: ident >> 181 punct!(":") >> 182 ty: ty >> 183 (Field { 184 ident: Some(id), 185 vis: vis, 186 attrs: attrs, 187 ty: ty, 188 }) 189 )); 190 191 named!(tuple_field -> Field, do_parse!( 192 attrs: many0!(outer_attr) >> 193 vis: visibility >> 194 ty: ty >> 195 (Field { 196 ident: None, 197 vis: vis, 198 attrs: attrs, 199 ty: ty, 200 }) 201 )); 202 203 named!(pub visibility -> Visibility, alt!( 204 do_parse!( 205 keyword!("pub") >> 206 punct!("(") >> 207 keyword!("crate") >> 208 punct!(")") >> 209 (Visibility::Crate) 210 ) 211 | 212 do_parse!( 213 keyword!("pub") >> 214 punct!("(") >> 215 restricted: path >> 216 punct!(")") >> 217 (Visibility::Restricted(Box::new(restricted))) 218 ) 219 | 220 keyword!("pub") => { |_| Visibility::Public } 221 | 222 epsilon!() => { |_| Visibility::Inherited } 223 )); 224 } 225 226 #[cfg(feature = "printing")] 227 mod printing { 228 use super::*; 229 use quote::{Tokens, ToTokens}; 230 231 impl ToTokens for Variant { to_tokens(&self, tokens: &mut Tokens)232 fn to_tokens(&self, tokens: &mut Tokens) { 233 for attr in &self.attrs { 234 attr.to_tokens(tokens); 235 } 236 self.ident.to_tokens(tokens); 237 self.data.to_tokens(tokens); 238 if let Some(ref disr) = self.discriminant { 239 tokens.append("="); 240 disr.to_tokens(tokens); 241 } 242 } 243 } 244 245 impl ToTokens for VariantData { to_tokens(&self, tokens: &mut Tokens)246 fn to_tokens(&self, tokens: &mut Tokens) { 247 match *self { 248 VariantData::Struct(ref fields) => { 249 tokens.append("{"); 250 tokens.append_separated(fields, ","); 251 tokens.append("}"); 252 } 253 VariantData::Tuple(ref fields) => { 254 tokens.append("("); 255 tokens.append_separated(fields, ","); 256 tokens.append(")"); 257 } 258 VariantData::Unit => {} 259 } 260 } 261 } 262 263 impl ToTokens for Field { to_tokens(&self, tokens: &mut Tokens)264 fn to_tokens(&self, tokens: &mut Tokens) { 265 for attr in &self.attrs { 266 attr.to_tokens(tokens); 267 } 268 self.vis.to_tokens(tokens); 269 if let Some(ref ident) = self.ident { 270 ident.to_tokens(tokens); 271 tokens.append(":"); 272 } 273 self.ty.to_tokens(tokens); 274 } 275 } 276 277 impl ToTokens for Visibility { to_tokens(&self, tokens: &mut Tokens)278 fn to_tokens(&self, tokens: &mut Tokens) { 279 match *self { 280 Visibility::Public => tokens.append("pub"), 281 Visibility::Crate => { 282 tokens.append("pub"); 283 tokens.append("("); 284 tokens.append("crate"); 285 tokens.append(")"); 286 } 287 Visibility::Restricted(ref path) => { 288 tokens.append("pub"); 289 tokens.append("("); 290 path.to_tokens(tokens); 291 tokens.append(")"); 292 } 293 Visibility::Inherited => {} 294 } 295 } 296 } 297 } 298