Skip to main content

virtue_next/parse/
mod.rs

1//! Module for parsing code. The main enum is [`Parse`].
2
3use crate::prelude::*;
4
5mod attributes;
6mod body;
7mod data_type;
8mod generics;
9mod utils;
10mod visibility;
11
12pub use self::attributes::Attribute;
13pub use self::attributes::AttributeAccess;
14pub use self::attributes::AttributeLocation;
15pub use self::attributes::FromAttribute;
16pub use self::body::EnumBody;
17pub use self::body::EnumVariant;
18pub use self::body::Fields;
19pub use self::body::IdentOrIndex;
20pub use self::body::StructBody;
21pub use self::body::UnnamedField;
22pub(crate) use self::data_type::DataType;
23pub use self::generics::ConstGeneric;
24pub use self::generics::Generic;
25pub use self::generics::GenericConstraints;
26pub use self::generics::Generics;
27pub use self::generics::Lifetime;
28pub use self::generics::SimpleGeneric;
29pub use self::visibility::Visibility;
30
31use crate::generate::Generator;
32
33/// Parser for Enum and Struct derives.
34///
35/// You can generate this enum by calling
36///
37/// ```ignore
38/// use virtue::prelude::*;
39///
40/// #[proc_macro_derive(YourDerive)]
41/// pub fn derive_your_derive(input: TokenStream) -> TokenStream {
42///     let parse = Parse::new(input).unwrap();
43///     // rest
44/// # unimplemented!()
45/// }
46/// ```
47#[non_exhaustive]
48pub enum Parse {
49    /// The given input is a struct
50    Struct {
51        /// The attributes of the struct
52        attributes: Vec<Attribute>,
53        /// The visibility of the struct
54        visibility: Visibility,
55        /// The name of the struct
56        name: Ident,
57        /// The generics of the struct, e.g. `struct Foo<F> { ... }` will be `F`
58        generics: Option<Generics>,
59        /// The generic constraits of the struct, e.g. `struct Foo<F> { ... } where F: Display` will be `F: Display`
60        generic_constraints: Option<GenericConstraints>,
61        /// The body of the struct
62        body: StructBody,
63    },
64    /// The given input is an enum
65    Enum {
66        /// The attributes of the enum
67        attributes: Vec<Attribute>,
68        /// The visibility of the enum
69        visibility: Visibility,
70        /// The name of the enum
71        name: Ident,
72        /// The generics of the enum, e.g. `enum Foo<F> { ... }` will be `F`
73        generics: Option<Generics>,
74        /// The generic constraits of the enum, e.g. `enum Foo<F> { ... } where F: Display` will be `F: Display`
75        generic_constraints: Option<GenericConstraints>,
76        /// The body of the enum
77        body: EnumBody,
78    },
79}
80
81impl Parse {
82    /// Parse the given [`TokenStream`] and return the result.
83    ///
84    /// # Errors
85    ///
86    /// Returns an error if the operation fails.
87    pub fn new(input: TokenStream) -> Result<Self> {
88        let source = &mut input.into_iter().peekable();
89
90        let attributes = Attribute::try_take(AttributeLocation::Container, source)?;
91        let visibility = Visibility::try_take(source)?;
92        let (datatype, name) = DataType::take(source)?;
93        let generics = Generics::try_take(source)?;
94        let generic_constraints = GenericConstraints::try_take(source)?;
95        match datatype {
96            | DataType::Struct => {
97                let body = StructBody::take(source)?;
98                Ok(Self::Struct {
99                    attributes,
100                    visibility,
101                    name,
102                    generics,
103                    generic_constraints,
104                    body,
105                })
106            },
107            | DataType::Enum => {
108                let body = EnumBody::take(source)?;
109                Ok(Self::Enum {
110                    attributes,
111                    visibility,
112                    name,
113                    generics,
114                    generic_constraints,
115                    body,
116                })
117            },
118        }
119    }
120
121    /// Split this struct or enum into a [`Generator`], list of [`Attribute`] and [`Body`].
122    pub fn into_generator(self) -> (Generator, Vec<Attribute>, Body) {
123        match self {
124            | Self::Struct {
125                name,
126                generics,
127                generic_constraints,
128                body,
129                attributes,
130                ..
131            } => {
132                (
133                    Generator::new(name, generics, generic_constraints),
134                    attributes,
135                    Body::Struct(body),
136                )
137            },
138            | Self::Enum {
139                name,
140                generics,
141                generic_constraints,
142                body,
143                attributes,
144                ..
145            } => {
146                (
147                    Generator::new(name, generics, generic_constraints),
148                    attributes,
149                    Body::Enum(body),
150                )
151            },
152        }
153    }
154}
155
156/// The body of the enum or struct
157#[allow(missing_docs)]
158pub enum Body {
159    Struct(StructBody),
160    Enum(EnumBody),
161}