Skip to content

Commit 5b8ea81

Browse files
authored
Merge pull request #45 from de-vri-es/better-array-debug
Print array fields separate instead of as array in `Debug` and `defmt::Format` impls.
2 parents 2d0b3cc + 34fc0dc commit 5b8ea81

File tree

1 file changed

+44
-26
lines changed

1 file changed

+44
-26
lines changed

src/generate/fieldset.rs

+44-26
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use anyhow::Result;
22
use proc_macro2::TokenStream;
3-
use proc_macro2::{Ident, Literal, Span};
3+
use proc_macro2::{Ident, Span};
44
use quote::quote;
55

66
use crate::ir::*;
@@ -12,7 +12,6 @@ pub fn render(opts: &super::Options, ir: &IR, fs: &FieldSet, path: &str) -> Resu
1212
let span = Span::call_site();
1313
let mut items = TokenStream::new();
1414
let mut field_names = Vec::with_capacity(fs.fields.len());
15-
let mut field_names_str = Vec::with_capacity(fs.fields.len());
1615
let mut field_getters = Vec::with_capacity(fs.fields.len());
1716
let mut field_types = Vec::with_capacity(fs.fields.len());
1817

@@ -68,14 +67,16 @@ pub fn render(opts: &super::Options, ir: &IR, fs: &FieldSet, path: &str) -> Resu
6867
}
6968
}
7069

71-
field_names.push(name.clone());
72-
field_names_str.push(f.name.as_str());
7370
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+
}
7878
} else {
79+
field_names.push(f.name.clone());
7980
field_types.push(field_ty.clone());
8081
field_getters.push(quote!(self.#name()));
8182
}
@@ -181,31 +182,37 @@ pub fn render(opts: &super::Options, ir: &IR, fs: &FieldSet, path: &str) -> Resu
181182
}
182183

183184
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;
189186
let name = Ident::new(name, span);
190187
let doc = util::doc(&fs.description);
191188

192189
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+
193211
quote! {
194212
#[cfg(feature = #defmt_feature)]
195213
impl defmt::Format for #name {
196214
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),*)
209216
}
210217
}
211218
}
@@ -232,7 +239,7 @@ pub fn render(opts: &super::Options, ir: &IR, fs: &FieldSet, path: &str) -> Resu
232239
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
233240
f.debug_struct(#name_str)
234241
#(
235-
.field(#field_names_str, &#field_getters)
242+
.field(#field_names, &#field_getters)
236243
)*
237244
.finish()
238245
}
@@ -243,3 +250,14 @@ pub fn render(opts: &super::Options, ir: &IR, fs: &FieldSet, path: &str) -> Resu
243250

244251
Ok(out)
245252
}
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

Comments
 (0)