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