quote_data_codegen/
lib.rs1extern crate proc_macro;
2
3mod r#enum;
4mod helper;
5mod r#struct;
6
7use helper::MOD_PATH;
8use proc_macro::TokenStream;
9use proc_macro2::TokenStream as TokenStream2;
10use r#enum::EnumStructure;
11use r#struct::StructStructure;
12use std::str::FromStr;
13use syn::{parse_macro_input, Data, DeriveInput, Error, Expr, Lit, Meta};
14
15#[proc_macro_derive(QuoteIt, attributes(mod_path))]
16pub fn derive_to_tokens(input: TokenStream) -> TokenStream {
17 let input = parse_macro_input! {input as DeriveInput};
18 let mut mod_path_tokens: Result<Option<TokenStream2>, Error> = Ok(None);
19
20 for attr in &input.attrs {
21 if attr.path() == MOD_PATH {
22 match &attr.meta {
23 Meta::NameValue(mod_path) => {
24 mod_path_tokens = match match &mod_path.value {
25 Expr::Lit(path_lit) => match &path_lit.lit {
26 Lit::Str(path_str) => Ok(path_str.value()),
27 _ => Err(Error::new_spanned(
28 mod_path,
29 "`mod_path` must be a string",
30 ))
31 },
32 _ => Err(Error::new_spanned(
33 mod_path,
34 "`mod_path` must be a string",
35 )),
36 }
37 .map(|path| {
38 TokenStream2::from_str(path.as_str()).map_err(|_| {
39 Error::new_spanned(
40 mod_path,
41 "Value of `mod_path` must be a path of mod",
42 )
43 })
44 }) {
45 Ok(Ok(tokens)) => Ok(Some(tokens)),
46 Ok(Err(e)) => Err(e),
47 Err(e) => Err(e),
48 }
49 }
50 _ => {
51 mod_path_tokens = Err(Error::new_spanned(
52 attr,
53 "Attribute `mod_path` must be a named value.",
54 ))
55 }
56 }
57 }
58 }
59
60 let mod_path_tokens = match mod_path_tokens {
61 Ok(result) => result,
62 Err(e) => return TokenStream::from(e.to_compile_error()),
63 };
64
65 let result = match &input.data {
66 Data::Enum(_) => {
67 EnumStructure::from_ast(&input, mod_path_tokens).map(|s| s.get_implement())
68 }
69 Data::Struct(_) => {
70 StructStructure::from_ast(&input, mod_path_tokens).map(|s| s.get_implement())
71 }
72 _ => Err(Error::new_spanned(&input, "Unknown data type")),
73 };
74
75 TokenStream::from(match result {
76 Ok(Ok(tokens)) => tokens,
77 Ok(Err(e)) => e.to_compile_error(),
78 Err(e) => e.to_compile_error(),
79 })
80}