1use super::*;
2use crate::punctuated::Punctuated;
3
4ast_struct! {
5 pub struct Variant {
10 pub attrs: Vec<Attribute>,
12
13 pub ident: Ident,
15
16 pub fields: Fields,
18
19 pub discriminant: Option<(Token![=], Expr)>,
21 }
22}
23
24ast_enum_of_structs! {
25 pub enum Fields {
39 Named(FieldsNamed),
42
43 Unnamed(FieldsUnnamed),
45
46 Unit,
48 }
49}
50
51ast_struct! {
52 pub struct FieldsNamed {
58 pub brace_token: token::Brace,
59 pub named: Punctuated<Field, Token![,]>,
60 }
61}
62
63ast_struct! {
64 pub struct FieldsUnnamed {
69 pub paren_token: token::Paren,
70 pub unnamed: Punctuated<Field, Token![,]>,
71 }
72}
73
74impl Fields {
75 pub fn iter(&self) -> punctuated::Iter<Field> {
79 match self {
80 Fields::Unit => crate::punctuated::empty_punctuated_iter(),
81 Fields::Named(f) => f.named.iter(),
82 Fields::Unnamed(f) => f.unnamed.iter(),
83 }
84 }
85
86 pub fn iter_mut(&mut self) -> punctuated::IterMut<Field> {
90 match self {
91 Fields::Unit => crate::punctuated::empty_punctuated_iter_mut(),
92 Fields::Named(f) => f.named.iter_mut(),
93 Fields::Unnamed(f) => f.unnamed.iter_mut(),
94 }
95 }
96
97 pub fn len(&self) -> usize {
99 match self {
100 Fields::Unit => 0,
101 Fields::Named(f) => f.named.len(),
102 Fields::Unnamed(f) => f.unnamed.len(),
103 }
104 }
105
106 pub fn is_empty(&self) -> bool {
108 match self {
109 Fields::Unit => true,
110 Fields::Named(f) => f.named.is_empty(),
111 Fields::Unnamed(f) => f.unnamed.is_empty(),
112 }
113 }
114}
115
116impl IntoIterator for Fields {
117 type Item = Field;
118 type IntoIter = punctuated::IntoIter<Field>;
119
120 fn into_iter(self) -> Self::IntoIter {
121 match self {
122 Fields::Unit => Punctuated::<Field, ()>::new().into_iter(),
123 Fields::Named(f) => f.named.into_iter(),
124 Fields::Unnamed(f) => f.unnamed.into_iter(),
125 }
126 }
127}
128
129impl<'a> IntoIterator for &'a Fields {
130 type Item = &'a Field;
131 type IntoIter = punctuated::Iter<'a, Field>;
132
133 fn into_iter(self) -> Self::IntoIter {
134 self.iter()
135 }
136}
137
138impl<'a> IntoIterator for &'a mut Fields {
139 type Item = &'a mut Field;
140 type IntoIter = punctuated::IterMut<'a, Field>;
141
142 fn into_iter(self) -> Self::IntoIter {
143 self.iter_mut()
144 }
145}
146
147ast_struct! {
148 pub struct Field {
153 pub attrs: Vec<Attribute>,
155
156 pub vis: Visibility,
158
159 pub ident: Option<Ident>,
163
164 pub colon_token: Option<Token![:]>,
165
166 pub ty: Type,
168 }
169}
170
171ast_enum_of_structs! {
172 pub enum Visibility {
187 Public(VisPublic),
189
190 Crate(VisCrate),
192
193 Restricted(VisRestricted),
196
197 Inherited,
199 }
200}
201
202ast_struct! {
203 pub struct VisPublic {
208 pub pub_token: Token![pub],
209 }
210}
211
212ast_struct! {
213 pub struct VisCrate {
218 pub crate_token: Token![crate],
219 }
220}
221
222ast_struct! {
223 pub struct VisRestricted {
229 pub pub_token: Token![pub],
230 pub paren_token: token::Paren,
231 pub in_token: Option<Token![in]>,
232 pub path: Box<Path>,
233 }
234}
235
236#[cfg(feature = "parsing")]
237pub mod parsing {
238 use super::*;
239
240 use crate::ext::IdentExt;
241 use crate::parse::discouraged::Speculative;
242 use crate::parse::{Parse, ParseStream, Result};
243
244 impl Parse for Variant {
245 fn parse(input: ParseStream) -> Result<Self> {
246 Ok(Variant {
247 attrs: input.call(Attribute::parse_outer)?,
248 ident: input.parse()?,
249 fields: {
250 if input.peek(token::Brace) {
251 Fields::Named(input.parse()?)
252 } else if input.peek(token::Paren) {
253 Fields::Unnamed(input.parse()?)
254 } else {
255 Fields::Unit
256 }
257 },
258 discriminant: {
259 if input.peek(Token![=]) {
260 let eq_token: Token![=] = input.parse()?;
261 let discriminant: Expr = input.parse()?;
262 Some((eq_token, discriminant))
263 } else {
264 None
265 }
266 },
267 })
268 }
269 }
270
271 impl Parse for FieldsNamed {
272 fn parse(input: ParseStream) -> Result<Self> {
273 let content;
274 Ok(FieldsNamed {
275 brace_token: braced!(content in input),
276 named: content.parse_terminated(Field::parse_named)?,
277 })
278 }
279 }
280
281 impl Parse for FieldsUnnamed {
282 fn parse(input: ParseStream) -> Result<Self> {
283 let content;
284 Ok(FieldsUnnamed {
285 paren_token: parenthesized!(content in input),
286 unnamed: content.parse_terminated(Field::parse_unnamed)?,
287 })
288 }
289 }
290
291 impl Field {
292 pub fn parse_named(input: ParseStream) -> Result<Self> {
294 Ok(Field {
295 attrs: input.call(Attribute::parse_outer)?,
296 vis: input.parse()?,
297 ident: Some(input.parse()?),
298 colon_token: Some(input.parse()?),
299 ty: input.parse()?,
300 })
301 }
302
303 pub fn parse_unnamed(input: ParseStream) -> Result<Self> {
305 Ok(Field {
306 attrs: input.call(Attribute::parse_outer)?,
307 vis: input.parse()?,
308 ident: None,
309 colon_token: None,
310 ty: input.parse()?,
311 })
312 }
313 }
314
315 impl Parse for Visibility {
316 fn parse(input: ParseStream) -> Result<Self> {
317 if input.peek(Token![pub]) {
318 Self::parse_pub(input)
319 } else if input.peek(Token![crate]) {
320 Self::parse_crate(input)
321 } else {
322 Ok(Visibility::Inherited)
323 }
324 }
325 }
326
327 impl Visibility {
328 fn parse_pub(input: ParseStream) -> Result<Self> {
329 let pub_token = input.parse::<Token![pub]>()?;
330
331 if input.peek(token::Paren) {
332 let ahead = input.fork();
333
334 let content;
335 let paren_token = parenthesized!(content in ahead);
336 if content.peek(Token![crate])
337 || content.peek(Token![self])
338 || content.peek(Token![super])
339 {
340 let path = content.call(Ident::parse_any)?;
341
342 if content.is_empty() {
347 input.advance_to(&ahead);
348 return Ok(Visibility::Restricted(VisRestricted {
349 pub_token,
350 paren_token,
351 in_token: None,
352 path: Box::new(Path::from(path)),
353 }));
354 }
355 } else if content.peek(Token![in]) {
356 let in_token: Token![in] = content.parse()?;
357 let path = content.call(Path::parse_mod_style)?;
358
359 input.advance_to(&ahead);
360 return Ok(Visibility::Restricted(VisRestricted {
361 pub_token,
362 paren_token,
363 in_token: Some(in_token),
364 path: Box::new(path),
365 }));
366 }
367 }
368
369 Ok(Visibility::Public(VisPublic { pub_token }))
370 }
371
372 fn parse_crate(input: ParseStream) -> Result<Self> {
373 if input.peek2(Token![::]) {
374 Ok(Visibility::Inherited)
375 } else {
376 Ok(Visibility::Crate(VisCrate {
377 crate_token: input.parse()?,
378 }))
379 }
380 }
381 }
382}
383
384#[cfg(feature = "printing")]
385mod printing {
386 use super::*;
387
388 use proc_macro2::TokenStream;
389 use quote::{ToTokens, TokenStreamExt};
390
391 use crate::print::TokensOrDefault;
392
393 impl ToTokens for Variant {
394 fn to_tokens(&self, tokens: &mut TokenStream) {
395 tokens.append_all(&self.attrs);
396 self.ident.to_tokens(tokens);
397 self.fields.to_tokens(tokens);
398 if let Some((eq_token, disc)) = &self.discriminant {
399 eq_token.to_tokens(tokens);
400 disc.to_tokens(tokens);
401 }
402 }
403 }
404
405 impl ToTokens for FieldsNamed {
406 fn to_tokens(&self, tokens: &mut TokenStream) {
407 self.brace_token.surround(tokens, |tokens| {
408 self.named.to_tokens(tokens);
409 });
410 }
411 }
412
413 impl ToTokens for FieldsUnnamed {
414 fn to_tokens(&self, tokens: &mut TokenStream) {
415 self.paren_token.surround(tokens, |tokens| {
416 self.unnamed.to_tokens(tokens);
417 });
418 }
419 }
420
421 impl ToTokens for Field {
422 fn to_tokens(&self, tokens: &mut TokenStream) {
423 tokens.append_all(&self.attrs);
424 self.vis.to_tokens(tokens);
425 if let Some(ident) = &self.ident {
426 ident.to_tokens(tokens);
427 TokensOrDefault(&self.colon_token).to_tokens(tokens);
428 }
429 self.ty.to_tokens(tokens);
430 }
431 }
432
433 impl ToTokens for VisPublic {
434 fn to_tokens(&self, tokens: &mut TokenStream) {
435 self.pub_token.to_tokens(tokens)
436 }
437 }
438
439 impl ToTokens for VisCrate {
440 fn to_tokens(&self, tokens: &mut TokenStream) {
441 self.crate_token.to_tokens(tokens);
442 }
443 }
444
445 impl ToTokens for VisRestricted {
446 fn to_tokens(&self, tokens: &mut TokenStream) {
447 self.pub_token.to_tokens(tokens);
448 self.paren_token.surround(tokens, |tokens| {
449 self.in_token.to_tokens(tokens);
452 self.path.to_tokens(tokens);
453 });
454 }
455 }
456}