1use core::iter;
2use core::slice;
3
4use crate::ast::prelude::*;
5
6#[derive(Debug, TryClone, PartialEq, Eq, ToTokens, OptionSpanned)]
8#[non_exhaustive]
9pub enum Fields {
10 Named(ast::Braced<ast::Field, T![,]>),
12 Unnamed(ast::Parenthesized<ast::Field, T![,]>),
14 Empty,
16}
17
18impl Fields {
19 pub(crate) fn needs_semi_colon(&self) -> bool {
21 matches!(self, Self::Empty | Self::Unnamed(..))
22 }
23}
24
25impl Parse for Fields {
26 fn parse(p: &mut Parser<'_>) -> Result<Self> {
27 Ok(match p.nth(0)? {
28 K!['('] => Self::Unnamed(p.parse()?),
29 K!['{'] => Self::Named(p.parse()?),
30 _ => Self::Empty,
31 })
32 }
33}
34
35type ToField = fn(&(ast::Field, Option<T![,]>)) -> &ast::Field;
36
37fn to_field((field, _): &(ast::Field, Option<T![,]>)) -> &ast::Field {
38 field
39}
40
41impl<'a> IntoIterator for &'a Fields {
42 type Item = &'a ast::Field;
43 type IntoIter = iter::Map<slice::Iter<'a, (ast::Field, Option<T![,]>)>, ToField>;
44
45 fn into_iter(self) -> Self::IntoIter {
46 static STATIC: &[(ast::Field, Option<T![,]>); 0] = &[];
47
48 match self {
49 Fields::Named(fields) => fields.iter().map(to_field as ToField),
50 Fields::Unnamed(fields) => fields.iter().map(to_field as ToField),
51 Fields::Empty => STATIC.iter().map(to_field as ToField),
52 }
53 }
54}