1 use super::*; 2 use crate::punctuated::Punctuated; 3 4 ast_struct! { 5 /// An enum variant. 6 #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] 7 pub struct Variant { 8 pub attrs: Vec<Attribute>, 9 10 /// Name of the variant. 11 pub ident: Ident, 12 13 /// Content stored in the variant. 14 pub fields: Fields, 15 16 /// Explicit discriminant: `Variant = 1` 17 pub discriminant: Option<(Token![=], Expr)>, 18 } 19 } 20 21 ast_enum_of_structs! { 22 /// Data stored within an enum variant or struct. 23 /// 24 /// # Syntax tree enum 25 /// 26 /// This type is a [syntax tree enum]. 27 /// 28 /// [syntax tree enum]: Expr#syntax-tree-enums 29 #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] 30 pub enum Fields { 31 /// Named fields of a struct or struct variant such as `Point { x: f64, 32 /// y: f64 }`. 33 Named(FieldsNamed), 34 35 /// Unnamed fields of a tuple struct or tuple variant such as `Some(T)`. 36 Unnamed(FieldsUnnamed), 37 38 /// Unit struct or unit variant such as `None`. 39 Unit, 40 } 41 } 42 43 ast_struct! { 44 /// Named fields of a struct or struct variant such as `Point { x: f64, 45 /// y: f64 }`. 46 #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] 47 pub struct FieldsNamed { 48 pub brace_token: token::Brace, 49 pub named: Punctuated<Field, Token![,]>, 50 } 51 } 52 53 ast_struct! { 54 /// Unnamed fields of a tuple struct or tuple variant such as `Some(T)`. 55 #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] 56 pub struct FieldsUnnamed { 57 pub paren_token: token::Paren, 58 pub unnamed: Punctuated<Field, Token![,]>, 59 } 60 } 61 62 impl Fields { 63 /// Get an iterator over the borrowed [`Field`] items in this object. This 64 /// iterator can be used to iterate over a named or unnamed struct or 65 /// variant's fields uniformly. iter(&self) -> punctuated::Iter<Field>66 pub fn iter(&self) -> punctuated::Iter<Field> { 67 match self { 68 Fields::Unit => crate::punctuated::empty_punctuated_iter(), 69 Fields::Named(f) => f.named.iter(), 70 Fields::Unnamed(f) => f.unnamed.iter(), 71 } 72 } 73 74 /// Get an iterator over the mutably borrowed [`Field`] items in this 75 /// object. This iterator can be used to iterate over a named or unnamed 76 /// struct or variant's fields uniformly. iter_mut(&mut self) -> punctuated::IterMut<Field>77 pub fn iter_mut(&mut self) -> punctuated::IterMut<Field> { 78 match self { 79 Fields::Unit => crate::punctuated::empty_punctuated_iter_mut(), 80 Fields::Named(f) => f.named.iter_mut(), 81 Fields::Unnamed(f) => f.unnamed.iter_mut(), 82 } 83 } 84 85 /// Returns the number of fields. len(&self) -> usize86 pub fn len(&self) -> usize { 87 match self { 88 Fields::Unit => 0, 89 Fields::Named(f) => f.named.len(), 90 Fields::Unnamed(f) => f.unnamed.len(), 91 } 92 } 93 94 /// Returns `true` if there are zero fields. is_empty(&self) -> bool95 pub fn is_empty(&self) -> bool { 96 match self { 97 Fields::Unit => true, 98 Fields::Named(f) => f.named.is_empty(), 99 Fields::Unnamed(f) => f.unnamed.is_empty(), 100 } 101 } 102 } 103 104 impl IntoIterator for Fields { 105 type Item = Field; 106 type IntoIter = punctuated::IntoIter<Field>; 107 into_iter(self) -> Self::IntoIter108 fn into_iter(self) -> Self::IntoIter { 109 match self { 110 Fields::Unit => Punctuated::<Field, ()>::new().into_iter(), 111 Fields::Named(f) => f.named.into_iter(), 112 Fields::Unnamed(f) => f.unnamed.into_iter(), 113 } 114 } 115 } 116 117 impl<'a> IntoIterator for &'a Fields { 118 type Item = &'a Field; 119 type IntoIter = punctuated::Iter<'a, Field>; 120 into_iter(self) -> Self::IntoIter121 fn into_iter(self) -> Self::IntoIter { 122 self.iter() 123 } 124 } 125 126 impl<'a> IntoIterator for &'a mut Fields { 127 type Item = &'a mut Field; 128 type IntoIter = punctuated::IterMut<'a, Field>; 129 into_iter(self) -> Self::IntoIter130 fn into_iter(self) -> Self::IntoIter { 131 self.iter_mut() 132 } 133 } 134 135 ast_struct! { 136 /// A field of a struct or enum variant. 137 #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] 138 pub struct Field { 139 pub attrs: Vec<Attribute>, 140 141 pub vis: Visibility, 142 143 pub mutability: FieldMutability, 144 145 /// Name of the field, if any. 146 /// 147 /// Fields of tuple structs have no names. 148 pub ident: Option<Ident>, 149 150 pub colon_token: Option<Token![:]>, 151 152 pub ty: Type, 153 } 154 } 155 156 #[cfg(feature = "parsing")] 157 pub(crate) mod parsing { 158 use super::*; 159 use crate::ext::IdentExt; 160 use crate::parse::{Parse, ParseStream, Result}; 161 162 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] 163 impl Parse for Variant { parse(input: ParseStream) -> Result<Self>164 fn parse(input: ParseStream) -> Result<Self> { 165 let attrs = input.call(Attribute::parse_outer)?; 166 let _visibility: Visibility = input.parse()?; 167 let ident: Ident = input.parse()?; 168 let fields = if input.peek(token::Brace) { 169 Fields::Named(input.parse()?) 170 } else if input.peek(token::Paren) { 171 Fields::Unnamed(input.parse()?) 172 } else { 173 Fields::Unit 174 }; 175 let discriminant = if input.peek(Token![=]) { 176 let eq_token: Token![=] = input.parse()?; 177 let discriminant: Expr = input.parse()?; 178 Some((eq_token, discriminant)) 179 } else { 180 None 181 }; 182 Ok(Variant { 183 attrs, 184 ident, 185 fields, 186 discriminant, 187 }) 188 } 189 } 190 191 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] 192 impl Parse for FieldsNamed { parse(input: ParseStream) -> Result<Self>193 fn parse(input: ParseStream) -> Result<Self> { 194 let content; 195 Ok(FieldsNamed { 196 brace_token: braced!(content in input), 197 named: content.parse_terminated(Field::parse_named, Token![,])?, 198 }) 199 } 200 } 201 202 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] 203 impl Parse for FieldsUnnamed { parse(input: ParseStream) -> Result<Self>204 fn parse(input: ParseStream) -> Result<Self> { 205 let content; 206 Ok(FieldsUnnamed { 207 paren_token: parenthesized!(content in input), 208 unnamed: content.parse_terminated(Field::parse_unnamed, Token![,])?, 209 }) 210 } 211 } 212 213 impl Field { 214 /// Parses a named (braced struct) field. 215 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] parse_named(input: ParseStream) -> Result<Self>216 pub fn parse_named(input: ParseStream) -> Result<Self> { 217 let attrs = input.call(Attribute::parse_outer)?; 218 let vis: Visibility = input.parse()?; 219 220 let unnamed_field = cfg!(feature = "full") && input.peek(Token![_]); 221 let ident = if unnamed_field { 222 input.call(Ident::parse_any) 223 } else { 224 input.parse() 225 }?; 226 227 let colon_token: Token![:] = input.parse()?; 228 229 let ty: Type = if unnamed_field 230 && (input.peek(Token![struct]) 231 || input.peek(Token![union]) && input.peek2(token::Brace)) 232 { 233 let begin = input.fork(); 234 input.call(Ident::parse_any)?; 235 input.parse::<FieldsNamed>()?; 236 Type::Verbatim(verbatim::between(&begin, input)) 237 } else { 238 input.parse()? 239 }; 240 241 Ok(Field { 242 attrs, 243 vis, 244 mutability: FieldMutability::None, 245 ident: Some(ident), 246 colon_token: Some(colon_token), 247 ty, 248 }) 249 } 250 251 /// Parses an unnamed (tuple struct) field. 252 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] parse_unnamed(input: ParseStream) -> Result<Self>253 pub fn parse_unnamed(input: ParseStream) -> Result<Self> { 254 Ok(Field { 255 attrs: input.call(Attribute::parse_outer)?, 256 vis: input.parse()?, 257 mutability: FieldMutability::None, 258 ident: None, 259 colon_token: None, 260 ty: input.parse()?, 261 }) 262 } 263 } 264 } 265 266 #[cfg(feature = "printing")] 267 mod printing { 268 use super::*; 269 use crate::print::TokensOrDefault; 270 use proc_macro2::TokenStream; 271 use quote::{ToTokens, TokenStreamExt}; 272 273 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 274 impl ToTokens for Variant { to_tokens(&self, tokens: &mut TokenStream)275 fn to_tokens(&self, tokens: &mut TokenStream) { 276 tokens.append_all(&self.attrs); 277 self.ident.to_tokens(tokens); 278 self.fields.to_tokens(tokens); 279 if let Some((eq_token, disc)) = &self.discriminant { 280 eq_token.to_tokens(tokens); 281 disc.to_tokens(tokens); 282 } 283 } 284 } 285 286 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 287 impl ToTokens for FieldsNamed { to_tokens(&self, tokens: &mut TokenStream)288 fn to_tokens(&self, tokens: &mut TokenStream) { 289 self.brace_token.surround(tokens, |tokens| { 290 self.named.to_tokens(tokens); 291 }); 292 } 293 } 294 295 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 296 impl ToTokens for FieldsUnnamed { to_tokens(&self, tokens: &mut TokenStream)297 fn to_tokens(&self, tokens: &mut TokenStream) { 298 self.paren_token.surround(tokens, |tokens| { 299 self.unnamed.to_tokens(tokens); 300 }); 301 } 302 } 303 304 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 305 impl ToTokens for Field { to_tokens(&self, tokens: &mut TokenStream)306 fn to_tokens(&self, tokens: &mut TokenStream) { 307 tokens.append_all(&self.attrs); 308 self.vis.to_tokens(tokens); 309 if let Some(ident) = &self.ident { 310 ident.to_tokens(tokens); 311 TokensOrDefault(&self.colon_token).to_tokens(tokens); 312 } 313 self.ty.to_tokens(tokens); 314 } 315 } 316 } 317