portrait_framework/
derive_filler.rs1use proc_macro2::TokenStream;
2use syn::parse::{Parse, ParseStream};
3use syn::Result;
4
5pub trait FillDerive {
7 type Args: Parse;
9
10 fn fill(
12 self,
13 trait_path: &syn::Path,
14 portrait: &[syn::TraitItem],
15 args: Self::Args,
16 input: &syn::DeriveInput,
17 ) -> Result<TokenStream>;
18}
19
20pub fn derive_filler<FillerT: FillDerive>(
27 input: TokenStream,
28 filler: FillerT,
29) -> Result<TokenStream> {
30 let Input::<FillerT::Args> { trait_path, portrait, args, input, debug_print } =
31 syn::parse2(input)?;
32
33 let output = filler.fill(&trait_path, &portrait, args, &input)?;
34
35 if debug_print {
36 println!("{output}");
37 }
38
39 Ok(output)
40}
41
42mod kw {
43 syn::custom_keyword!(TRAIT_PORTRAIT);
44 syn::custom_keyword!(TRAIT_PATH);
45 syn::custom_keyword!(ARGS);
46 syn::custom_keyword!(INPUT);
47 syn::custom_keyword!(DEBUG_PRINT_FILLER_OUTPUT);
48}
49
50pub(crate) struct Input<ArgsT> {
51 pub(crate) trait_path: syn::Path,
52 pub(crate) portrait: Vec<syn::TraitItem>,
53 pub(crate) args: ArgsT,
54 pub(crate) input: syn::DeriveInput,
55 pub(crate) debug_print: bool,
56}
57
58impl<ArgsT: Parse> Parse for Input<ArgsT> {
59 fn parse(input: ParseStream) -> Result<Self> {
60 input.parse::<kw::TRAIT_PORTRAIT>()?;
61
62 let portrait_braced;
63 syn::braced!(portrait_braced in input);
64 let mut portrait = Vec::new();
65 while !portrait_braced.is_empty() {
66 let item_braced;
67 syn::braced!(item_braced in portrait_braced);
68 let item: syn::TraitItem = item_braced.parse()?;
69 if !item_braced.is_empty() {
70 return Err(item_braced.error("braces should only contain one trait item"));
71 }
72 portrait.push(item);
73 }
74
75 input.parse::<kw::TRAIT_PATH>()?;
76 let trait_path_braced;
77 syn::braced!(trait_path_braced in input);
78 let trait_path: syn::Path = trait_path_braced.parse()?;
79 if !trait_path_braced.is_empty() {
80 return Err(trait_path_braced.error("trait path not fully parsed"));
81 }
82
83 input.parse::<kw::ARGS>()?;
84 let args_braced;
85 syn::braced!(args_braced in input);
86 let args: ArgsT = args_braced.parse()?;
87 if !args_braced.is_empty() {
88 return Err(args_braced.error("args not fully parsed"));
89 }
90
91 input.parse::<kw::INPUT>()?;
92 let input_braced;
93 syn::braced!(input_braced in input);
94 let derive_input = input_braced.parse()?;
95 if !input_braced.is_empty() {
96 return Err(input_braced.error("trailing tokens after input block"));
97 }
98
99 input.parse::<kw::DEBUG_PRINT_FILLER_OUTPUT>()?;
100 let dpfo_braced;
101 syn::braced!(dpfo_braced in input);
102 let dpfo: syn::LitBool = dpfo_braced.parse()?;
103 if !dpfo_braced.is_empty() {
104 return Err(input_braced.error("trailing tokens after input block"));
105 }
106
107 if !input.is_empty() {
108 return Err(input.error("trailing tokens in macro input"));
109 }
110
111 Ok(Self { trait_path, portrait, args, input: derive_input, debug_print: dpfo.value })
112 }
113}