1- use std:: fmt:: Display ;
2- use std:: io:: Write ;
3-
4- use anyhow:: { Error , Result } ;
1+ use proc_macro2:: TokenStream ;
2+ use template_quote:: quote;
53
64/// Configuration for including features in the code generator.
75///
@@ -20,31 +18,41 @@ pub enum FeatureConfig<'a> {
2018}
2119
2220impl FeatureConfig < ' _ > {
23- pub ( crate ) fn fmt_attr ( & self , w : & mut impl Write , attr : impl Display ) -> Result < ( ) > {
21+ /// Generate an attribute token stream (like `#[derive(Debug)]`).
22+ /// The closure is only called when the feature is enabled, so expensive codegen can be skipped when `Never`.
23+ pub ( crate ) fn attr < F > ( & self , f : F ) -> TokenStream
24+ where
25+ F : FnOnce ( ) -> TokenStream ,
26+ {
2427 match self {
25- FeatureConfig :: Always => writeln ! ( w, "#[{attr}]" ) ?,
26- FeatureConfig :: Gated ( gate) => writeln ! ( w, "#[cfg_attr(feature = {gate:?}, {attr})]" ) ?,
27- FeatureConfig :: Never => { }
28+ FeatureConfig :: Always => {
29+ let tokens = f ( ) ;
30+ quote ! { #[ #tokens] }
31+ }
32+ FeatureConfig :: Gated ( gate) => {
33+ let tokens = f ( ) ;
34+ quote ! { #[ cfg_attr( feature = #gate, #tokens) ] }
35+ }
36+ FeatureConfig :: Never => quote ! { } ,
2837 }
29- Ok ( ( ) )
3038 }
3139
32- pub ( crate ) fn fmt_cfg < W : Write , E : Into < Error > > (
33- & self ,
34- mut w : W ,
35- f : impl FnOnce ( W ) -> Result < ( ) , E > ,
36- ) -> Result < ( ) > {
40+ /// Generate a token stream optionally wrapped in a cfg attribute.
41+ /// The closure is only called when the feature is enabled, so expensive codegen can be skipped when `Never`.
42+ pub ( crate ) fn if_cfg < F > ( & self , f : F ) -> TokenStream
43+ where
44+ F : FnOnce ( ) -> TokenStream ,
45+ {
3746 match self {
38- // If config is Never, return immediately without calling `f`
39- FeatureConfig :: Never => return Ok ( ( ) ) ,
40- // If config is Gated, prepend `f` with a cfg guard
47+ FeatureConfig :: Always => f ( ) ,
4148 FeatureConfig :: Gated ( gate) => {
42- writeln ! ( w, "#[cfg(feature = {gate:?})]" ) ?;
49+ let tokens = f ( ) ;
50+ quote ! {
51+ #[ cfg( feature = #gate) ]
52+ #tokens
53+ }
4354 }
44- // Otherwise, just call `f`
45- FeatureConfig :: Always => { }
55+ FeatureConfig :: Never => quote ! { } ,
4656 }
47-
48- f ( w) . map_err ( Into :: into)
4957 }
5058}
0 commit comments