1
1
use anyhow:: Result ;
2
2
use proc_macro2:: TokenStream ;
3
- use proc_macro2:: { Ident , Literal , Span } ;
3
+ use proc_macro2:: { Ident , Span } ;
4
4
use quote:: quote;
5
5
6
6
use crate :: ir:: * ;
@@ -12,7 +12,6 @@ pub fn render(opts: &super::Options, ir: &IR, fs: &FieldSet, path: &str) -> Resu
12
12
let span = Span :: call_site ( ) ;
13
13
let mut items = TokenStream :: new ( ) ;
14
14
let mut field_names = Vec :: with_capacity ( fs. fields . len ( ) ) ;
15
- let mut field_names_str = Vec :: with_capacity ( fs. fields . len ( ) ) ;
16
15
let mut field_getters = Vec :: with_capacity ( fs. fields . len ( ) ) ;
17
16
let mut field_types = Vec :: with_capacity ( fs. fields . len ( ) ) ;
18
17
@@ -68,14 +67,16 @@ pub fn render(opts: &super::Options, ir: &IR, fs: &FieldSet, path: &str) -> Resu
68
67
}
69
68
}
70
69
71
- field_names. push ( name. clone ( ) ) ;
72
- field_names_str. push ( f. name . as_str ( ) ) ;
73
70
if let Some ( array) = & f. array {
74
- let len = array. len ( ) ;
75
- let i = 0 ..len;
76
- field_types. push ( quote ! ( [ #field_ty; #len] ) ) ;
77
- field_getters. push ( quote ! ( [ #( self . #name( #i) , ) * ] ) ) ;
71
+ // Print array fields using array indexing: "field[0]"
72
+ for i in 0 ..array. len ( ) {
73
+ let debug_name = format ! ( "{}[{i}]" , f. name) ;
74
+ field_names. push ( debug_name) ;
75
+ field_types. push ( field_ty. clone ( ) ) ;
76
+ field_getters. push ( quote ! ( self . #name( #i) ) ) ;
77
+ }
78
78
} else {
79
+ field_names. push ( f. name . clone ( ) ) ;
79
80
field_types. push ( field_ty. clone ( ) ) ;
80
81
field_getters. push ( quote ! ( self . #name( ) ) ) ;
81
82
}
@@ -181,31 +182,37 @@ pub fn render(opts: &super::Options, ir: &IR, fs: &FieldSet, path: &str) -> Resu
181
182
}
182
183
183
184
let ( _, name) = super :: split_path ( path) ;
184
- let name_str = {
185
- let mut literal = Literal :: string ( name) ;
186
- literal. set_span ( span) ;
187
- literal
188
- } ;
185
+ let name_str = name;
189
186
let name = Ident :: new ( name, span) ;
190
187
let doc = util:: doc ( & fs. description ) ;
191
188
192
189
let impl_defmt_format = opts. defmt_feature . as_ref ( ) . map ( |defmt_feature| {
190
+ let mut defmt_format_string = String :: new ( ) ;
191
+ defmt_format_string. push_str ( name_str) ;
192
+ defmt_format_string. push_str ( " {{" ) ;
193
+ for ( i, ( field_name, field_type) ) in field_names. iter ( ) . zip ( & field_types) . enumerate ( ) {
194
+ if i > 0 {
195
+ defmt_format_string. push_str ( ", " ) ;
196
+ } else {
197
+ defmt_format_string. push_str ( " " ) ;
198
+ }
199
+ defmt_format_string. push_str ( field_name) ;
200
+
201
+ if is_defmt_primitive_type ( field_type) {
202
+ defmt_format_string. push_str ( ": {=" ) ;
203
+ defmt_format_string. push_str ( & field_type. to_string ( ) ) ;
204
+ defmt_format_string. push_str ( ":?}" ) ;
205
+ } else {
206
+ defmt_format_string. push_str ( ": {:?}" ) ;
207
+ }
208
+ }
209
+ defmt_format_string. push_str ( " }}" ) ;
210
+
193
211
quote ! {
194
212
#[ cfg( feature = #defmt_feature) ]
195
213
impl defmt:: Format for #name {
196
214
fn format( & self , f: defmt:: Formatter ) {
197
- #[ derive( defmt:: Format ) ]
198
- struct #name {
199
- #(
200
- #field_names: #field_types,
201
- ) *
202
- }
203
- let proxy = #name {
204
- #(
205
- #field_names: #field_getters,
206
- ) *
207
- } ;
208
- defmt:: write!( f, "{}" , proxy)
215
+ defmt:: write!( f, #defmt_format_string, #( #field_getters) , * )
209
216
}
210
217
}
211
218
}
@@ -232,7 +239,7 @@ pub fn render(opts: &super::Options, ir: &IR, fs: &FieldSet, path: &str) -> Resu
232
239
fn fmt( & self , f: & mut core:: fmt:: Formatter ) -> core:: fmt:: Result {
233
240
f. debug_struct( #name_str)
234
241
#(
235
- . field( #field_names_str , & #field_getters)
242
+ . field( #field_names , & #field_getters)
236
243
) *
237
244
. finish( )
238
245
}
@@ -243,3 +250,14 @@ pub fn render(opts: &super::Options, ir: &IR, fs: &FieldSet, path: &str) -> Resu
243
250
244
251
Ok ( out)
245
252
}
253
+
254
+ fn is_defmt_primitive_type ( ty : & TokenStream ) -> bool {
255
+ // Supported by defmt but not included: [u8; N], [u8] and str.
256
+ // Parsing these types is more complicated, so we skip them.
257
+ // They should never occur as the field of a fieldset,
258
+ // so this should not be a problem.
259
+ let primitives = [
260
+ "bool" , "u8" , "i8" , "u16" , "i16" , "u32" , "i32" , "u64" , "i64" , "u128" , "i128" , "f32" , "f64" ,
261
+ ] ;
262
+ primitives. as_slice ( ) . contains ( & ty. to_string ( ) . as_str ( ) )
263
+ }
0 commit comments