@@ -15,7 +15,7 @@ mod format_syntax;
15
15
16
16
use crate :: { format_syntax:: * , regex_utils:: * , syn_utils:: * } ;
17
17
use proc_macro2:: { Span , TokenStream } ;
18
- use quote:: { format_ident, quote} ;
18
+ use quote:: { format_ident, quote, ToTokens } ;
19
19
use regex:: { Captures , Regex } ;
20
20
use regex_syntax:: hir:: Hir ;
21
21
use std:: {
@@ -62,7 +62,9 @@ fn derive_display_for_struct(input: &DeriveInput, data: &DataStruct) -> Result<T
62
62
)
63
63
} ;
64
64
let mut bounds = Bounds :: from_data ( hattrs. bound_display ) ;
65
- let args = format. format_args ( context, & None , & mut bounds, & generics) ?;
65
+ let write = format
66
+ . format_args ( context, & None , & mut bounds, & generics) ?
67
+ . build_write ( quote ! ( f) ) ?;
66
68
let trait_path = parse_quote ! ( :: core:: fmt:: Display ) ;
67
69
let wheres = bounds. build_wheres ( & trait_path) ;
68
70
impl_trait_result (
@@ -71,7 +73,7 @@ fn derive_display_for_struct(input: &DeriveInput, data: &DataStruct) -> Result<T
71
73
& wheres,
72
74
quote ! {
73
75
fn fmt( & self , f: & mut :: core:: fmt:: Formatter ) -> :: core:: fmt:: Result {
74
- :: core :: write! ( f , #args )
76
+ #write
75
77
}
76
78
} ,
77
79
hattrs. dump_display ,
@@ -117,19 +119,21 @@ fn derive_display_for_enum(input: &DeriveInput, data: &DataEnum) -> Result<Token
117
119
)
118
120
} ;
119
121
let variant_ident = & variant. ident ;
120
- let args = format. format_args (
121
- DisplayContext :: Variant {
122
- variant,
123
- style,
124
- crate_path : & hattrs_enum. crate_path ,
125
- } ,
126
- & None ,
127
- & mut bounds. child ( hattrs_variant. bound_display ) ,
128
- generics,
129
- ) ?;
122
+ let write = format
123
+ . format_args (
124
+ DisplayContext :: Variant {
125
+ variant,
126
+ style,
127
+ crate_path : & hattrs_enum. crate_path ,
128
+ } ,
129
+ & None ,
130
+ & mut bounds. child ( hattrs_variant. bound_display ) ,
131
+ generics,
132
+ ) ?
133
+ . build_write ( quote ! ( f) ) ?;
130
134
Ok ( quote ! {
131
135
& Self :: #variant_ident #fields => {
132
- :: core :: write! ( f , #args )
136
+ #write
133
137
} ,
134
138
} )
135
139
}
@@ -1080,7 +1084,7 @@ impl DisplayFormat {
1080
1084
with : & Option < Expr > ,
1081
1085
bounds : & mut Bounds ,
1082
1086
generics : & GenericParamSet ,
1083
- ) -> Result < TokenStream > {
1087
+ ) -> Result < FormatArgs > {
1084
1088
let mut format_str = String :: new ( ) ;
1085
1089
let mut format_args = Vec :: new ( ) ;
1086
1090
for p in & self . parts {
@@ -1102,8 +1106,42 @@ impl DisplayFormat {
1102
1106
}
1103
1107
}
1104
1108
}
1105
- let format_str = LitStr :: new ( & format_str, self . span ) ;
1106
- Ok ( quote ! { #format_str #( , #format_args) * } )
1109
+ Ok ( FormatArgs {
1110
+ format_str,
1111
+ format_args,
1112
+ span : self . span ,
1113
+ } )
1114
+ }
1115
+
1116
+ fn try_unescape ( & self ) -> Option < String > {
1117
+ let mut s = String :: new ( ) ;
1118
+ for p in & self . parts {
1119
+ s. push_str ( p. try_unescape ( ) ?) ;
1120
+ }
1121
+ Some ( s)
1122
+ }
1123
+ }
1124
+
1125
+ struct FormatArgs {
1126
+ format_str : String ,
1127
+ format_args : Vec < TokenStream > ,
1128
+ span : Span ,
1129
+ }
1130
+ impl FormatArgs {
1131
+ fn build_write ( & self , f : TokenStream ) -> Result < TokenStream > {
1132
+ if self . format_args . is_empty ( ) {
1133
+ if let Some ( s) = DisplayFormat :: parse ( & self . format_str , self . span ) ?. try_unescape ( ) {
1134
+ return Ok ( quote ! { #f. write_str( #s) } ) ;
1135
+ }
1136
+ }
1137
+ Ok ( quote ! { :: core:: write!( #f, #self ) } )
1138
+ }
1139
+ }
1140
+ impl ToTokens for FormatArgs {
1141
+ fn to_tokens ( & self , tokens : & mut TokenStream ) {
1142
+ let format_str = LitStr :: new ( & self . format_str , self . span ) ;
1143
+ let format_args = & self . format_args ;
1144
+ tokens. extend ( quote ! ( #format_str #( , #format_args) * ) ) ;
1107
1145
}
1108
1146
}
1109
1147
@@ -1114,6 +1152,16 @@ enum DisplayFormatPart {
1114
1152
EscapedEndBracket ,
1115
1153
Var { arg : String , format_spec : String } ,
1116
1154
}
1155
+ impl DisplayFormatPart {
1156
+ fn try_unescape ( & self ) -> Option < & str > {
1157
+ match self {
1158
+ Self :: Str ( value) => Some ( value) ,
1159
+ Self :: EscapedBeginBracket => Some ( "{" ) ,
1160
+ Self :: EscapedEndBracket => Some ( "}" ) ,
1161
+ Self :: Var { .. } => None ,
1162
+ }
1163
+ }
1164
+ }
1117
1165
1118
1166
enum DisplayContext < ' a > {
1119
1167
Struct {
@@ -1542,7 +1590,7 @@ impl std::fmt::Display for FieldKey {
1542
1590
}
1543
1591
}
1544
1592
}
1545
- impl quote :: ToTokens for FieldKey {
1593
+ impl ToTokens for FieldKey {
1546
1594
fn to_tokens ( & self , tokens : & mut TokenStream ) {
1547
1595
self . to_member ( ) . to_tokens ( tokens) ;
1548
1596
}
0 commit comments