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