1use crate::attr::Attribute;
2#[cfg(feature = "parsing")]
3use crate::error::Result;
4use crate::expr::{Expr, Index, Member};
5use crate::ident::Ident;
6use crate::punctuated::{self, Punctuated};
7use crate::restriction::Visibility;
8use crate::token;
9use crate::ty::Type;
10use alloc::vec::Vec;
11
12#[doc = r" An enum variant."]
#[doc(cfg(any(feature = "full", feature = "derive")))]
pub struct Variant {
pub attrs: Vec<Attribute>,
#[doc = r" Name of the variant."]
pub ident: Ident,
#[doc = r" Content stored in the variant."]
pub fields: Fields,
#[doc = r" Explicit discriminant: `Variant = 1`"]
pub discriminant: Option<(crate::token::Eq, Expr)>,
}ast_struct! {
13 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
15 pub struct Variant {
16 pub attrs: Vec<Attribute>,
17
18 pub ident: Ident,
20
21 pub fields: Fields,
23
24 pub discriminant: Option<(Token![=], Expr)>,
26 }
27}
28
29#[doc = r" Data stored within an enum variant or struct."]
#[doc = r""]
#[doc = r" # Syntax tree enum"]
#[doc = r""]
#[doc = r" This type is a [syntax tree enum]."]
#[doc = r""]
#[doc = r" [syntax tree enum]: crate::expr::Expr#syntax-tree-enums"]
#[doc(cfg(any(feature = "full", feature = "derive")))]
pub enum Fields {
#[doc =
r" Named fields of a struct or struct variant such as `Point { x: f64,"]
#[doc = r" y: f64 }`."]
Named(FieldsNamed),
#[doc =
r" Unnamed fields of a tuple struct or tuple variant such as `Some(T)`."]
Unnamed(FieldsUnnamed),
#[doc = r" Unit struct or unit variant such as `None`."]
Unit,
}
#[doc(cfg(feature = "printing"))]
impl ::quote::ToTokens for Fields {
fn to_tokens(&self, tokens: &mut ::proc_macro2::TokenStream) {
match self {
Fields::Named(_e) => _e.to_tokens(tokens),
Fields::Unnamed(_e) => _e.to_tokens(tokens),
Fields::Unit => {}
}
}
}ast_enum_of_structs! {
30 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
38 pub enum Fields {
39 Named(FieldsNamed),
42
43 Unnamed(FieldsUnnamed),
45
46 Unit,
48 }
49}
50
51#[doc =
r" Named fields of a struct or struct variant such as `Point { x: f64,"]
#[doc = r" y: f64 }`."]
#[doc(cfg(any(feature = "full", feature = "derive")))]
pub struct FieldsNamed {
pub brace_token: token::Brace,
pub named: Punctuated<Field, crate::token::Comma>,
}ast_struct! {
52 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
55 pub struct FieldsNamed {
56 pub brace_token: token::Brace,
57 pub named: Punctuated<Field, Token![,]>,
58 }
59}
60
61#[doc =
r" Unnamed fields of a tuple struct or tuple variant such as `Some(T)`."]
#[doc(cfg(any(feature = "full", feature = "derive")))]
pub struct FieldsUnnamed {
pub paren_token: token::Paren,
pub unnamed: Punctuated<Field, crate::token::Comma>,
}ast_struct! {
62 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
64 pub struct FieldsUnnamed {
65 pub paren_token: token::Paren,
66 pub unnamed: Punctuated<Field, Token![,]>,
67 }
68}
69
70impl Fields {
71 pub fn iter(&self) -> punctuated::Iter<Field> {
75 match self {
76 Fields::Unit => crate::punctuated::empty_punctuated_iter(),
77 Fields::Named(f) => f.named.iter(),
78 Fields::Unnamed(f) => f.unnamed.iter(),
79 }
80 }
81
82 pub fn iter_mut(&mut self) -> punctuated::IterMut<Field> {
86 match self {
87 Fields::Unit => crate::punctuated::empty_punctuated_iter_mut(),
88 Fields::Named(f) => f.named.iter_mut(),
89 Fields::Unnamed(f) => f.unnamed.iter_mut(),
90 }
91 }
92
93 pub fn len(&self) -> usize {
95 match self {
96 Fields::Unit => 0,
97 Fields::Named(f) => f.named.len(),
98 Fields::Unnamed(f) => f.unnamed.len(),
99 }
100 }
101
102 pub fn is_empty(&self) -> bool {
104 match self {
105 Fields::Unit => true,
106 Fields::Named(f) => f.named.is_empty(),
107 Fields::Unnamed(f) => f.unnamed.is_empty(),
108 }
109 }
110
111 #[doc =
r" Get an iterator over the fields of a struct or variant as [`Member`]s."]
#[doc =
r" This iterator can be used to iterate over a named or unnamed struct or"]
#[doc = r" variant's fields uniformly."]
#[doc = r""]
#[doc = r" # Example"]
#[doc = r""]
#[doc =
r" The following is a simplistic [`Clone`] derive for structs. (A more"]
#[doc =
r" complete implementation would additionally want to infer trait bounds on"]
#[doc = r" the generic type parameters.)"]
#[doc = r""]
#[doc = r" ```"]
#[doc = r" # use quote::quote;"]
#[doc = r" #"]
#[doc =
r" fn derive_clone(input: &syn::ItemStruct) -> proc_macro2::TokenStream {"]
#[doc = r" let ident = &input.ident;"]
#[doc = r" let members = input.fields.members();"]
#[doc =
r" let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();"]
#[doc = r" quote! {"]
#[doc =
r" impl #impl_generics Clone for #ident #ty_generics #where_clause {"]
#[doc = r" fn clone(&self) -> Self {"]
#[doc = r" Self {"]
#[doc = r" #(#members: self.#members.clone()),*"]
#[doc = r" }"]
#[doc = r" }"]
#[doc = r" }"]
#[doc = r" }"]
#[doc = r" }"]
#[doc = r" ```"]
#[doc = r""]
#[doc =
r" For structs with named fields, it produces an expression like `Self { a:"]
#[doc = r" self.a.clone() }`. For structs with unnamed fields, `Self { 0:"]
#[doc = r" self.0.clone() }`. And for unit structs, `Self {}`."]
pub fn members(&self) -> impl Iterator<Item = Member> + Clone + '_ {
Members { fields: self.iter(), index: 0 }
}return_impl_trait! {
112 pub fn members(&self) -> impl Iterator<Item = Member> + Clone + '_ [Members] {
145 Members {
146 fields: self.iter(),
147 index: 0,
148 }
149 }
150 }
151}
152
153impl IntoIterator for Fields {
154 type Item = Field;
155 type IntoIter = punctuated::IntoIter<Field>;
156
157 fn into_iter(self) -> Self::IntoIter {
158 match self {
159 Fields::Unit => Punctuated::<Field, ()>::new().into_iter(),
160 Fields::Named(f) => f.named.into_iter(),
161 Fields::Unnamed(f) => f.unnamed.into_iter(),
162 }
163 }
164}
165
166impl<'a> IntoIterator for &'a Fields {
167 type Item = &'a Field;
168 type IntoIter = punctuated::Iter<'a, Field>;
169
170 fn into_iter(self) -> Self::IntoIter {
171 self.iter()
172 }
173}
174
175impl<'a> IntoIterator for &'a mut Fields {
176 type Item = &'a mut Field;
177 type IntoIter = punctuated::IterMut<'a, Field>;
178
179 fn into_iter(self) -> Self::IntoIter {
180 self.iter_mut()
181 }
182}
183
184#[doc = r" A field of a struct or enum variant."]
#[doc(cfg(any(feature = "full", feature = "derive")))]
pub struct Field {
pub attrs: Vec<Attribute>,
pub vis: Visibility,
#[doc =
r" (Non-exhaustive) Additional optional information about a field."]
pub modifiers: FieldModifiers,
#[doc = r" Name of the field, if any."]
#[doc = r""]
#[doc = r" Fields of tuple structs have no names."]
pub ident: Option<Ident>,
pub colon_token: Option<crate::token::Colon>,
pub ty: Type,
pub default: Option<(crate::token::Eq, Expr)>,
}ast_struct! {
185 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
187 pub struct Field {
188 pub attrs: Vec<Attribute>,
189
190 pub vis: Visibility,
191
192 pub modifiers: FieldModifiers,
194
195 pub ident: Option<Ident>,
199
200 pub colon_token: Option<Token![:]>,
201
202 pub ty: Type,
203
204 pub default: Option<(Token![=], Expr)>,
205 }
206}
207
208#[doc = r" Additional optional information about a field."]
#[doc = r""]
#[doc = r" This data structure may grow to accommodate future Rust language"]
#[doc = r" changes, including the following in-progress RFCs:"]
#[doc = r""]
#[doc = r#" - [RFC 3323] "Restrictions", such as `mut(crate)`"#]
#[doc = r#" - [RFC 3458] "Unsafe fields""#]
#[doc = r""]
#[doc =
r" [RFC 3323]: https://rust-lang.github.io/rfcs/3323-restrictions.html"]
#[doc = r" [RFC 3458]: https://github.com/rust-lang/rfcs/pull/3458"]
#[doc(cfg(any(feature = "full", feature = "derive")))]
#[non_exhaustive]
pub struct FieldModifiers {}ast_struct! {
209 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
220 #[non_exhaustive]
221 pub struct FieldModifiers {}
222}
223
224impl Default for FieldModifiers {
225 fn default() -> Self {
226 FieldModifiers {}
227 }
228}
229
230impl FieldModifiers {
231 #[cfg(feature = "parsing")]
232 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
233 pub fn require_empty(&self) -> Result<()> {
234 Ok(())
235 }
236}
237
238pub struct Members<'a> {
239 fields: punctuated::Iter<'a, Field>,
240 index: u32,
241}
242
243impl<'a> Iterator for Members<'a> {
244 type Item = Member;
245
246 fn next(&mut self) -> Option<Self::Item> {
247 let field = self.fields.next()?;
248 let member = match &field.ident {
249 Some(ident) => Member::Named(ident.clone()),
250 None => {
251 #[cfg(all(feature = "parsing", feature = "printing"))]
252 let span = crate::spanned::Spanned::span(&field.ty);
253 #[cfg(not(all(feature = "parsing", feature = "printing")))]
254 let span = proc_macro2::Span::call_site();
255 Member::Unnamed(Index {
256 index: self.index,
257 span,
258 })
259 }
260 };
261 self.index += 1;
262 Some(member)
263 }
264}
265
266impl<'a> Clone for Members<'a> {
267 fn clone(&self) -> Self {
268 Members {
269 fields: self.fields.clone(),
270 index: self.index,
271 }
272 }
273}
274
275#[cfg(feature = "parsing")]
276pub(crate) mod parsing {
277 use crate::attr::Attribute;
278 use crate::data::{Field, FieldModifiers, Fields, FieldsNamed, FieldsUnnamed, Variant};
279 use crate::error::Result;
280 use crate::expr::Expr;
281 use crate::ext::IdentExt as _;
282 use crate::ident::Ident;
283 #[cfg(not(feature = "full"))]
284 use crate::parse::discouraged::Speculative as _;
285 use crate::parse::{Parse, ParseStream};
286 use crate::restriction::Visibility;
287 #[cfg(not(feature = "full"))]
288 use crate::scan_expr::scan_expr;
289 use crate::token;
290 use crate::ty::Type;
291 use crate::verbatim;
292
293 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
294 impl Parse for Variant {
295 fn parse(input: ParseStream) -> Result<Self> {
296 let attrs = input.call(Attribute::parse_outer)?;
297 let _visibility: Visibility = input.parse()?;
298 let ident: Ident = input.parse()?;
299 let fields = if input.peek(token::Brace) {
300 Fields::Named(input.parse()?)
301 } else if input.peek(token::Paren) {
302 Fields::Unnamed(input.parse()?)
303 } else {
304 Fields::Unit
305 };
306 let discriminant = if input.peek(crate::token::EqToken![=]) {
307 let eq_token: crate::token::EqToken![=] = input.parse()?;
308 #[cfg(feature = "full")]
309 let discriminant: Expr = input.parse()?;
310 #[cfg(not(feature = "full"))]
311 let discriminant = {
312 let begin = input.cursor();
313 let ahead = input.fork();
314 let mut discriminant: Result<Expr> = ahead.parse();
315 if discriminant.is_ok() {
316 input.advance_to(&ahead);
317 } else if scan_expr(input).is_ok() {
318 discriminant = Ok(Expr::Verbatim(verbatim::between(begin, input.cursor())));
319 }
320 discriminant?
321 };
322 Some((eq_token, discriminant))
323 } else {
324 None
325 };
326 Ok(Variant {
327 attrs,
328 ident,
329 fields,
330 discriminant,
331 })
332 }
333 }
334
335 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
336 impl Parse for FieldsNamed {
337 fn parse(input: ParseStream) -> Result<Self> {
338 let content;
339 Ok(FieldsNamed {
340 brace_token: match crate::__private::parse_braces(&input) {
crate::__private::Ok(braces) => {
content = braces.content;
_ = content;
braces.token
}
crate::__private::Err(error) => { return crate::__private::Err(error); }
}braced!(content in input),
341 named: content.parse_terminated(Field::parse_named, crate::token::CommaToken![,])?,
342 })
343 }
344 }
345
346 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
347 impl Parse for FieldsUnnamed {
348 fn parse(input: ParseStream) -> Result<Self> {
349 let content;
350 Ok(FieldsUnnamed {
351 paren_token: match crate::__private::parse_parens(&input) {
crate::__private::Ok(parens) => {
content = parens.content;
_ = content;
parens.token
}
crate::__private::Err(error) => { return crate::__private::Err(error); }
}parenthesized!(content in input),
352 unnamed: content.parse_terminated(Field::parse_unnamed, crate::token::CommaToken![,])?,
353 })
354 }
355 }
356
357 impl Field {
358 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
360 pub fn parse_named(input: ParseStream) -> Result<Self> {
361 let attrs = input.call(Attribute::parse_outer)?;
362 let vis: Visibility = input.parse()?;
363
364 let unnamed_field = truecfg!(feature = "full") && input.peek(crate::token::UnderscoreToken![_]);
365 let ident = if unnamed_field {
366 input.call(Ident::parse_any)
367 } else {
368 input.parse()
369 }?;
370
371 let colon_token: crate::token::ColonToken![:] = input.parse()?;
372
373 let ty: Type = if unnamed_field
374 && (input.peek(crate::token::StructToken![struct])
375 || input.peek(crate::token::UnionToken![union]) && input.peek2(token::Brace))
376 {
377 let begin = input.cursor();
378 input.call(Ident::parse_any)?;
379 input.parse::<FieldsNamed>()?;
380 Type::Verbatim(verbatim::between(begin, input.cursor()))
381 } else {
382 input.parse()?
383 };
384
385 let default = if input.peek(crate::token::EqToken![=]) {
386 let eq_token: crate::token::EqToken![=] = input.parse()?;
387 let expr: Expr = input.parse()?;
388 Some((eq_token, expr))
389 } else {
390 None
391 };
392
393 Ok(Field {
394 attrs,
395 vis,
396 modifiers: FieldModifiers {},
397 ident: Some(ident),
398 colon_token: Some(colon_token),
399 ty,
400 default,
401 })
402 }
403
404 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
406 pub fn parse_unnamed(input: ParseStream) -> Result<Self> {
407 let attrs = input.call(Attribute::parse_outer)?;
408 let vis: Visibility = input.parse()?;
409 let ty: Type = input.parse()?;
410
411 if input.peek(crate::token::EqToken![=]) {
412 input.parse::<crate::token::EqToken![=]>()?;
413 let start_span = input.span();
414 input.parse::<Expr>()?;
415 let end_span = input.cursor().prev_span();
416 return Err(crate::error::new2(
417 start_span,
418 end_span,
419 "field default value is only supported in structs with named fields",
420 ));
421 }
422
423 Ok(Field {
424 attrs,
425 vis,
426 modifiers: FieldModifiers {},
427 ident: None,
428 colon_token: None,
429 ty,
430 default: None,
431 })
432 }
433 }
434}
435
436#[cfg(feature = "printing")]
437mod printing {
438 use crate::data::{Field, FieldsNamed, FieldsUnnamed, Variant};
439 use crate::print::TokensOrDefault;
440 use proc_macro2::TokenStream;
441 use quote::{ToTokens, TokenStreamExt as _};
442
443 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
444 impl ToTokens for Variant {
445 fn to_tokens(&self, tokens: &mut TokenStream) {
446 tokens.append_all(&self.attrs);
447 self.ident.to_tokens(tokens);
448 self.fields.to_tokens(tokens);
449 if let Some((eq_token, disc)) = &self.discriminant {
450 eq_token.to_tokens(tokens);
451 disc.to_tokens(tokens);
452 }
453 }
454 }
455
456 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
457 impl ToTokens for FieldsNamed {
458 fn to_tokens(&self, tokens: &mut TokenStream) {
459 self.brace_token.surround(tokens, |tokens| {
460 self.named.to_tokens(tokens);
461 });
462 }
463 }
464
465 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
466 impl ToTokens for FieldsUnnamed {
467 fn to_tokens(&self, tokens: &mut TokenStream) {
468 self.paren_token.surround(tokens, |tokens| {
469 self.unnamed.to_tokens(tokens);
470 });
471 }
472 }
473
474 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
475 impl ToTokens for Field {
476 fn to_tokens(&self, tokens: &mut TokenStream) {
477 tokens.append_all(&self.attrs);
478 self.vis.to_tokens(tokens);
479 if let Some(ident) = &self.ident {
480 ident.to_tokens(tokens);
481 TokensOrDefault(&self.colon_token).to_tokens(tokens);
482 }
483 self.ty.to_tokens(tokens);
484 if let Some((eq_token, default)) = &self.default {
485 eq_token.to_tokens(tokens);
486 default.to_tokens(tokens);
487 }
488 }
489 }
490}