Skip to content

Commit

Permalink
Implement Debug and defmt::Format for enums and fieldsets.
Browse files Browse the repository at this point in the history
  • Loading branch information
de-vri-es committed Jan 1, 2025
1 parent 30e78c3 commit 7af7ceb
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 2 deletions.
32 changes: 31 additions & 1 deletion src/generate/enumm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,16 @@ pub fn render(_opts: &super::Options, _ir: &IR, e: &Enum, path: &str) -> Result<

if newtype {
let mut items = TokenStream::new();
let mut item_names_str = Vec::with_capacity(e.variants.len());
let mut item_values = Vec::with_capacity(e.variants.len());

for f in sorted(&e.variants, |f| (f.value, f.name.clone())) {
let name = Ident::new(&f.name, span);
let value = util::hex(f.value);

item_names_str.push(&f.name);
item_values.push(value.clone());

let doc = util::doc(&f.description);
items.extend(quote!(
#doc
Expand All @@ -63,6 +69,29 @@ pub fn render(_opts: &super::Options, _ir: &IR, e: &Enum, path: &str) -> Result<
self.0
}
}

impl core::fmt::Debug for #name {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
match self.0 {
#(
#item_values => f.write_str(#item_names_str),
)*
other => core::write!(f, "0x{:02X}", other),
}
}
}

#[cfg(feature = "defmt")]
impl defmt::Format for #name {
fn format(&self, f: defmt::Formatter) {
match self.0 {
#(
#item_values => defmt::write!("{}", #item_names_str),
)*
other => defmt::write!(f, "0x{:02X}", other),
}
}
}
});
} else {
let variants: BTreeMap<_, _> = e.variants.iter().map(|v| (v.value, v)).collect();
Expand All @@ -88,7 +117,8 @@ pub fn render(_opts: &super::Options, _ir: &IR, e: &Enum, path: &str) -> Result<
out.extend(quote! {
#doc
#[repr(#ty)]
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum #name {
#items
}
Expand Down
51 changes: 50 additions & 1 deletion src/generate/fieldset.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use anyhow::Result;
use proc_macro2::TokenStream;
use proc_macro2::{Ident, Span};
use proc_macro2::{Ident, Literal, Span};
use quote::quote;

use crate::ir::*;
Expand All @@ -11,6 +11,10 @@ use super::sorted;
pub fn render(_opts: &super::Options, ir: &IR, fs: &FieldSet, path: &str) -> Result<TokenStream> {
let span = Span::call_site();
let mut items = TokenStream::new();
let mut field_names = Vec::with_capacity(fs.fields.len());
let mut field_names_str = Vec::with_capacity(fs.fields.len());
let mut field_getters = Vec::with_capacity(fs.fields.len());
let mut field_types = Vec::with_capacity(fs.fields.len());

let ty = match fs.bit_size {
1..=8 => quote!(u8),
Expand Down Expand Up @@ -64,6 +68,18 @@ pub fn render(_opts: &super::Options, ir: &IR, fs: &FieldSet, path: &str) -> Res
}
}

field_names.push(name.clone());
field_names_str.push(f.name.as_str());
if let Some(array) = &f.array {
let len = array.len();
let i = 0..len;
field_types.push(quote!([#field_ty; #len]));
field_getters.push(quote!([#( self.#name(#i), )*]));
} else {
field_types.push(field_ty.clone());
field_getters.push(quote!(self.#name()));
}

match off_in_reg {
BitOffset::Regular(off_in_reg) => {
let off_in_reg = off_in_reg as usize;
Expand Down Expand Up @@ -165,6 +181,11 @@ pub fn render(_opts: &super::Options, ir: &IR, fs: &FieldSet, path: &str) -> Res
}

let (_, name) = super::split_path(path);
let name_str = {
let mut literal = Literal::string(name);
literal.set_span(span);
literal
};
let name = Ident::new(name, span);
let doc = util::doc(&fs.description);

Expand All @@ -184,6 +205,34 @@ pub fn render(_opts: &super::Options, ir: &IR, fs: &FieldSet, path: &str) -> Res
#name(0)
}
}

impl core::fmt::Debug for #name {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
f.debug_struct(#name_str)
#(
.field(#field_names_str, &#field_getters)
)*
.finish()
}
}

#[cfg(feature = "defmt")]
impl defmt::Format for #name {
fn format(&self, f: defmt::Formatter) {
#[derive(defmt::Format)]
struct #name {
#(
#field_names: #field_types,
)*
}
let proxy = #name {
#(
#field_names: #field_getters,
)*
};
defmt::write!(f, "{}", proxy)
}
}
};

Ok(out)
Expand Down
10 changes: 10 additions & 0 deletions src/ir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,16 @@ pub enum Array {
Cursed(CursedArray),
}

impl Array {
/// Get the number of elements in the array.
pub fn len(&self) -> usize {
match self {
Self::Regular(x) => x.len as usize,
Self::Cursed(x) => x.offsets.len(),
}
}
}

#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct RegularArray {
pub len: u32,
Expand Down

0 comments on commit 7af7ceb

Please sign in to comment.