summaryrefslogtreecommitdiff
path: root/vendor/educe/src/trait_handlers/debug/debug_struct.rs
diff options
context:
space:
mode:
authormo khan <mo@mokhan.ca>2025-07-02 18:36:06 -0600
committermo khan <mo@mokhan.ca>2025-07-02 18:36:06 -0600
commit8cdfa445d6629ffef4cb84967ff7017654045bc2 (patch)
tree22f0b0907c024c78d26a731e2e1f5219407d8102 /vendor/educe/src/trait_handlers/debug/debug_struct.rs
parent4351c74c7c5f97156bc94d3a8549b9940ac80e3f (diff)
chore: add vendor directory
Diffstat (limited to 'vendor/educe/src/trait_handlers/debug/debug_struct.rs')
-rw-r--r--vendor/educe/src/trait_handlers/debug/debug_struct.rs185
1 files changed, 185 insertions, 0 deletions
diff --git a/vendor/educe/src/trait_handlers/debug/debug_struct.rs b/vendor/educe/src/trait_handlers/debug/debug_struct.rs
new file mode 100644
index 00000000..6430480b
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/debug/debug_struct.rs
@@ -0,0 +1,185 @@
+use quote::{format_ident, quote};
+use syn::{Data, DeriveInput, Fields, Meta, Type};
+
+use super::{
+ models::{FieldAttributeBuilder, FieldName, TypeAttributeBuilder, TypeName},
+ TraitHandler,
+};
+use crate::{common::ident_index::IdentOrIndex, Trait};
+
+pub struct DebugStructHandler;
+
+impl TraitHandler for DebugStructHandler {
+ fn trait_meta_handler(
+ ast: &DeriveInput,
+ token_stream: &mut proc_macro2::TokenStream,
+ traits: &[Trait],
+ meta: &Meta,
+ ) -> syn::Result<()> {
+ let is_tuple = {
+ if let Data::Struct(data) = &ast.data {
+ matches!(data.fields, Fields::Unnamed(_))
+ } else {
+ true
+ }
+ };
+
+ let type_attribute = TypeAttributeBuilder {
+ enable_flag: true,
+ enable_unsafe: false,
+ enable_name: true,
+ enable_named_field: true,
+ enable_bound: true,
+ name: TypeName::Default,
+ named_field: !is_tuple,
+ }
+ .build_from_debug_meta(meta)?;
+
+ let name = type_attribute.name.to_ident_by_ident(&ast.ident);
+
+ let mut debug_types: Vec<&Type> = Vec::new();
+
+ let mut builder_token_stream = proc_macro2::TokenStream::new();
+ let mut has_fields = false;
+
+ if type_attribute.named_field {
+ builder_token_stream.extend(if let Some(name) = name {
+ quote!(let mut builder = f.debug_struct(stringify!(#name));)
+ } else {
+ super::common::create_debug_map_builder()
+ });
+
+ if let Data::Struct(data) = &ast.data {
+ for (index, field) in data.fields.iter().enumerate() {
+ let field_attribute = FieldAttributeBuilder {
+ enable_name: true,
+ enable_ignore: true,
+ enable_method: true,
+ name: FieldName::Default,
+ }
+ .build_from_attributes(&field.attrs, traits)?;
+
+ if field_attribute.ignore {
+ continue;
+ }
+
+ let (key, field_name) = match field_attribute.name {
+ FieldName::Custom(name) => {
+ (name, IdentOrIndex::from_ident_with_index(field.ident.as_ref(), index))
+ },
+ FieldName::Default => {
+ if let Some(ident) = field.ident.as_ref() {
+ (ident.clone(), IdentOrIndex::from(ident))
+ } else {
+ (format_ident!("_{}", index), IdentOrIndex::from(index))
+ }
+ },
+ };
+
+ let ty = &field.ty;
+
+ if let Some(method) = field_attribute.method {
+ builder_token_stream.extend(super::common::create_format_arg(
+ ast,
+ ty,
+ &method,
+ quote!(&self.#field_name),
+ ));
+
+ builder_token_stream.extend(if name.is_some() {
+ quote! (builder.field(stringify!(#key), &arg);)
+ } else {
+ quote! (builder.entry(&Educe__RawString(stringify!(#key)), &arg);)
+ });
+ } else {
+ debug_types.push(ty);
+
+ builder_token_stream.extend(if name.is_some() {
+ quote! (builder.field(stringify!(#key), &self.#field_name);)
+ } else {
+ quote! (builder.entry(&Educe__RawString(stringify!(#key)), &self.#field_name);)
+ });
+ }
+
+ has_fields = true;
+ }
+ }
+ } else {
+ builder_token_stream
+ .extend(quote!(let mut builder = f.debug_tuple(stringify!(#name));));
+
+ if let Data::Struct(data) = &ast.data {
+ for (index, field) in data.fields.iter().enumerate() {
+ let field_attribute = FieldAttributeBuilder {
+ enable_name: false,
+ enable_ignore: true,
+ enable_method: true,
+ name: FieldName::Default,
+ }
+ .build_from_attributes(&field.attrs, traits)?;
+
+ if field_attribute.ignore {
+ continue;
+ }
+
+ let field_name =
+ IdentOrIndex::from_ident_with_index(field.ident.as_ref(), index);
+
+ let ty = &field.ty;
+
+ if let Some(method) = field_attribute.method {
+ builder_token_stream.extend(super::common::create_format_arg(
+ ast,
+ ty,
+ &method,
+ quote!(&self.#field_name),
+ ));
+
+ builder_token_stream.extend(quote! (builder.field(&arg);));
+ } else {
+ debug_types.push(ty);
+
+ builder_token_stream.extend(quote! (builder.field(&self.#field_name);));
+ }
+
+ has_fields = true;
+ }
+ }
+ }
+
+ let ident = &ast.ident;
+
+ if !has_fields && name.is_none() {
+ return Err(super::panic::unit_struct_need_name(ident));
+ }
+
+ let bound = type_attribute.bound.into_where_predicates_by_generic_parameters_check_types(
+ &ast.generics.params,
+ &syn::parse2(quote!(::core::fmt::Debug)).unwrap(),
+ &debug_types,
+ &[],
+ );
+
+ let mut generics = ast.generics.clone();
+ let where_clause = generics.make_where_clause();
+
+ for where_predicate in bound {
+ where_clause.predicates.push(where_predicate);
+ }
+
+ let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
+
+ token_stream.extend(quote! {
+ impl #impl_generics ::core::fmt::Debug for #ident #ty_generics #where_clause {
+ #[inline]
+ fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
+ #builder_token_stream
+
+ builder.finish()
+ }
+ }
+ });
+
+ Ok(())
+ }
+}