• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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