1use crate::attr::Attribute;
2use crate::expr::{Expr, Index, Member};
3use crate::ident::Ident;
4use crate::punctuated::{self, Punctuated};
5use crate::restriction::{FieldMutability, Visibility};
6use crate::token;
7use crate::ty::Type;
8
9ast_struct! {
10 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
12 pub struct Variant {
13 pub attrs: Vec<Attribute>,
14
15 pub ident: Ident,
17
18 pub fields: Fields,
20
21 pub discriminant: Option<(Token![=], Expr)>,
23 }
24}
25
26ast_enum_of_structs! {
27 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
35 pub enum Fields {
36 Named(FieldsNamed),
39
40 Unnamed(FieldsUnnamed),
42
43 Unit,
45 }
46}
47
48ast_struct! {
49 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
52 pub struct FieldsNamed {
53 pub brace_token: token::Brace,
54 pub named: Punctuated<Field, Token![,]>,
55 }
56}
57
58ast_struct! {
59 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
61 pub struct FieldsUnnamed {
62 pub paren_token: token::Paren,
63 pub unnamed: Punctuated<Field, Token![,]>,
64 }
65}
66
67impl Fields {
68 pub fn iter(&self) -> punctuated::Iter<Field> {
72 match self {
73 Fields::Unit => crate::punctuated::empty_punctuated_iter(),
74 Fields::Named(f) => f.named.iter(),
75 Fields::Unnamed(f) => f.unnamed.iter(),
76 }
77 }
78
79 pub fn iter_mut(&mut self) -> punctuated::IterMut<Field> {
83 match self {
84 Fields::Unit => crate::punctuated::empty_punctuated_iter_mut(),
85 Fields::Named(f) => f.named.iter_mut(),
86 Fields::Unnamed(f) => f.unnamed.iter_mut(),
87 }
88 }
89
90 pub fn len(&self) -> usize {
92 match self {
93 Fields::Unit => 0,
94 Fields::Named(f) => f.named.len(),
95 Fields::Unnamed(f) => f.unnamed.len(),
96 }
97 }
98
99 pub fn is_empty(&self) -> bool {
101 match self {
102 Fields::Unit => true,
103 Fields::Named(f) => f.named.is_empty(),
104 Fields::Unnamed(f) => f.unnamed.is_empty(),
105 }
106 }
107
108 return_impl_trait! {
109 pub fn members(&self) -> impl Iterator<Item = Member> + Clone + '_ [Members] {
142 Members {
143 fields: self.iter(),
144 index: 0,
145 }
146 }
147 }
148}
149
150impl IntoIterator for Fields {
151 type Item = Field;
152 type IntoIter = punctuated::IntoIter<Field>;
153
154 fn into_iter(self) -> Self::IntoIter {
155 match self {
156 Fields::Unit => Punctuated::<Field, ()>::new().into_iter(),
157 Fields::Named(f) => f.named.into_iter(),
158 Fields::Unnamed(f) => f.unnamed.into_iter(),
159 }
160 }
161}
162
163impl<'a> IntoIterator for &'a Fields {
164 type Item = &'a Field;
165 type IntoIter = punctuated::Iter<'a, Field>;
166
167 fn into_iter(self) -> Self::IntoIter {
168 self.iter()
169 }
170}
171
172impl<'a> IntoIterator for &'a mut Fields {
173 type Item = &'a mut Field;
174 type IntoIter = punctuated::IterMut<'a, Field>;
175
176 fn into_iter(self) -> Self::IntoIter {
177 self.iter_mut()
178 }
179}
180
181ast_struct! {
182 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
184 pub struct Field {
185 pub attrs: Vec<Attribute>,
186
187 pub vis: Visibility,
188
189 pub mutability: FieldMutability,
190
191 pub ident: Option<Ident>,
195
196 pub colon_token: Option<Token![:]>,
197
198 pub ty: Type,
199 }
200}
201
202pub struct Members<'a> {
203 fields: punctuated::Iter<'a, Field>,
204 index: u32,
205}
206
207impl<'a> Iterator for Members<'a> {
208 type Item = Member;
209
210 fn next(&mut self) -> Option<Self::Item> {
211 let field = self.fields.next()?;
212 let member = match &field.ident {
213 Some(ident) => Member::Named(ident.clone()),
214 None => {
215 #[cfg(all(feature = "parsing", feature = "printing"))]
216 let span = crate::spanned::Spanned::span(&field.ty);
217 #[cfg(not(all(feature = "parsing", feature = "printing")))]
218 let span = proc_macro2::Span::call_site();
219 Member::Unnamed(Index {
220 index: self.index,
221 span,
222 })
223 }
224 };
225 self.index += 1;
226 Some(member)
227 }
228}
229
230impl<'a> Clone for Members<'a> {
231 fn clone(&self) -> Self {
232 Members {
233 fields: self.fields.clone(),
234 index: self.index,
235 }
236 }
237}
238
239#[cfg(feature = "parsing")]
240pub(crate) mod parsing {
241 use crate::attr::Attribute;
242 use crate::data::{Field, Fields, FieldsNamed, FieldsUnnamed, Variant};
243 use crate::error::Result;
244 use crate::expr::Expr;
245 use crate::ext::IdentExt as _;
246 use crate::ident::Ident;
247 #[cfg(not(feature = "full"))]
248 use crate::parse::discouraged::Speculative as _;
249 use crate::parse::{Parse, ParseStream};
250 use crate::restriction::{FieldMutability, Visibility};
251 #[cfg(not(feature = "full"))]
252 use crate::scan_expr::scan_expr;
253 use crate::token;
254 use crate::ty::Type;
255 use crate::verbatim;
256
257 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
258 impl Parse for Variant {
259 fn parse(input: ParseStream) -> Result<Self> {
260 let attrs = input.call(Attribute::parse_outer)?;
261 let _visibility: Visibility = input.parse()?;
262 let ident: Ident = input.parse()?;
263 let fields = if input.peek(token::Brace) {
264 Fields::Named(input.parse()?)
265 } else if input.peek(token::Paren) {
266 Fields::Unnamed(input.parse()?)
267 } else {
268 Fields::Unit
269 };
270 let discriminant = if input.peek(Token![=]) {
271 let eq_token: Token![=] = input.parse()?;
272 #[cfg(feature = "full")]
273 let discriminant: Expr = input.parse()?;
274 #[cfg(not(feature = "full"))]
275 let discriminant = {
276 let begin = input.fork();
277 let ahead = input.fork();
278 let mut discriminant: Result<Expr> = ahead.parse();
279 if discriminant.is_ok() {
280 input.advance_to(&ahead);
281 } else if scan_expr(input).is_ok() {
282 discriminant = Ok(Expr::Verbatim(verbatim::between(&begin, input)));
283 }
284 discriminant?
285 };
286 Some((eq_token, discriminant))
287 } else {
288 None
289 };
290 Ok(Variant {
291 attrs,
292 ident,
293 fields,
294 discriminant,
295 })
296 }
297 }
298
299 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
300 impl Parse for FieldsNamed {
301 fn parse(input: ParseStream) -> Result<Self> {
302 let content;
303 Ok(FieldsNamed {
304 brace_token: braced!(content in input),
305 named: content.parse_terminated(Field::parse_named, Token![,])?,
306 })
307 }
308 }
309
310 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
311 impl Parse for FieldsUnnamed {
312 fn parse(input: ParseStream) -> Result<Self> {
313 let content;
314 Ok(FieldsUnnamed {
315 paren_token: parenthesized!(content in input),
316 unnamed: content.parse_terminated(Field::parse_unnamed, Token![,])?,
317 })
318 }
319 }
320
321 impl Field {
322 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
324 pub fn parse_named(input: ParseStream) -> Result<Self> {
325 let attrs = input.call(Attribute::parse_outer)?;
326 let vis: Visibility = input.parse()?;
327
328 let unnamed_field = cfg!(feature = "full") && input.peek(Token![_]);
329 let ident = if unnamed_field {
330 input.call(Ident::parse_any)
331 } else {
332 input.parse()
333 }?;
334
335 let colon_token: Token![:] = input.parse()?;
336
337 let ty: Type = if unnamed_field
338 && (input.peek(Token![struct])
339 || input.peek(Token![union]) && input.peek2(token::Brace))
340 {
341 let begin = input.fork();
342 input.call(Ident::parse_any)?;
343 input.parse::<FieldsNamed>()?;
344 Type::Verbatim(verbatim::between(&begin, input))
345 } else {
346 input.parse()?
347 };
348
349 Ok(Field {
350 attrs,
351 vis,
352 mutability: FieldMutability::None,
353 ident: Some(ident),
354 colon_token: Some(colon_token),
355 ty,
356 })
357 }
358
359 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
361 pub fn parse_unnamed(input: ParseStream) -> Result<Self> {
362 Ok(Field {
363 attrs: input.call(Attribute::parse_outer)?,
364 vis: input.parse()?,
365 mutability: FieldMutability::None,
366 ident: None,
367 colon_token: None,
368 ty: input.parse()?,
369 })
370 }
371 }
372}
373
374#[cfg(feature = "printing")]
375mod printing {
376 use crate::data::{Field, FieldsNamed, FieldsUnnamed, Variant};
377 use crate::print::TokensOrDefault;
378 use proc_macro2::TokenStream;
379 use quote::{ToTokens, TokenStreamExt};
380
381 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
382 impl ToTokens for Variant {
383 fn to_tokens(&self, tokens: &mut TokenStream) {
384 tokens.append_all(&self.attrs);
385 self.ident.to_tokens(tokens);
386 self.fields.to_tokens(tokens);
387 if let Some((eq_token, disc)) = &self.discriminant {
388 eq_token.to_tokens(tokens);
389 disc.to_tokens(tokens);
390 }
391 }
392 }
393
394 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
395 impl ToTokens for FieldsNamed {
396 fn to_tokens(&self, tokens: &mut TokenStream) {
397 self.brace_token.surround(tokens, |tokens| {
398 self.named.to_tokens(tokens);
399 });
400 }
401 }
402
403 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
404 impl ToTokens for FieldsUnnamed {
405 fn to_tokens(&self, tokens: &mut TokenStream) {
406 self.paren_token.surround(tokens, |tokens| {
407 self.unnamed.to_tokens(tokens);
408 });
409 }
410 }
411
412 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
413 impl ToTokens for Field {
414 fn to_tokens(&self, tokens: &mut TokenStream) {
415 tokens.append_all(&self.attrs);
416 self.vis.to_tokens(tokens);
417 if let Some(ident) = &self.ident {
418 ident.to_tokens(tokens);
419 TokensOrDefault(&self.colon_token).to_tokens(tokens);
420 }
421 self.ty.to_tokens(tokens);
422 }
423 }
424}