use manyhow::bail;
use proc_macro2::{Ident, TokenStream};
use quote::quote;
use syn::{Data, Fields};
use crate::shared::{self, unreachable};
pub(super) fn debug_bits(item: TokenStream) -> manyhow::Result {
let derive_input = shared::parse_derive(item);
let name = &derive_input.ident;
let name_str = name.to_string();
let struct_data = match derive_input.data {
Data::Struct(s) => s,
Data::Enum(_) => bail!("use derive(Debug) for enums"),
Data::Union(_) => unreachable(()),
};
let fmt_impl = match struct_data.fields {
Fields::Named(fields) => {
let calls = fields.named.iter().map(|f| {
let call = f.ident.as_ref().unwrap();
let name = call.to_string();
quote!(.field(#name, &self.#call()))
});
quote! {
f.debug_struct(#name_str)
#(#calls)*.finish()
}
}
Fields::Unnamed(fields) => {
let calls = fields.unnamed.iter().enumerate().map(|(i, _)| {
let call: Ident = syn::parse_str(&format!("val_{i}")).unwrap_or_else(unreachable);
quote!(.field(&self.#call()))
});
quote! {
f.debug_tuple(#name_str)
#(#calls)*.finish()
}
}
Fields::Unit => bail!("unit structs are not supported"),
};
Ok(quote! {
impl ::core::fmt::Debug for #name {
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
#fmt_impl
}
}
})
}