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