educe/trait_handlers/debug/
debug_union.rs1use proc_macro2::TokenStream;
2use quote::quote;
3use syn::{Data, DeriveInput, Generics, Meta};
4
5use super::{
6 super::TraitHandler,
7 models::{FieldAttributeBuilder, FieldAttributeName, TypeAttributeBuilder, TypeAttributeName},
8};
9use crate::Trait;
10
11pub struct DebugUnionHandler;
12
13impl TraitHandler for DebugUnionHandler {
14 fn trait_meta_handler(
15 ast: &DeriveInput,
16 tokens: &mut TokenStream,
17 traits: &[Trait],
18 meta: &Meta,
19 ) {
20 let type_attribute = TypeAttributeBuilder {
21 enable_flag: true,
22 name: TypeAttributeName::Default,
23 enable_name: true,
24 named_field: false,
25 enable_named_field: false,
26 enable_bound: true,
27 }
28 .from_debug_meta(meta);
29
30 let name = type_attribute.name.into_string_by_ident(&ast.ident);
31
32 let bound = type_attribute
33 .bound
34 .into_punctuated_where_predicates_by_generic_parameters(&ast.generics.params);
35
36 let mut builder_tokens = TokenStream::new();
37
38 if let Data::Union(data) = &ast.data {
39 for field in data.fields.named.iter() {
40 let _ = FieldAttributeBuilder {
41 name: FieldAttributeName::Default,
42 enable_name: false,
43 enable_ignore: false,
44 enable_impl: false,
45 }
46 .from_attributes(&field.attrs, traits);
47 }
48
49 if name.is_empty() {
50 builder_tokens.extend(quote!(
51 let size = core::mem::size_of::<Self>();
52 let data = unsafe {{ core::slice::from_raw_parts(self as *const Self as *const u8, size) }};
53
54 core::fmt::Debug::fmt(data, formatter)
55 ));
56 } else {
57 builder_tokens.extend(quote!(
58 let mut builder = formatter.debug_tuple(#name);
59
60 let size = core::mem::size_of::<Self>();
61
62 let data = unsafe {{ core::slice::from_raw_parts(self as *const Self as *const u8, size) }};
63
64 builder.field(&data);
65
66 builder.finish()
67 ));
68 }
69 }
70
71 let ident = &ast.ident;
72
73 let mut generics_cloned: Generics = ast.generics.clone();
74
75 let where_clause = generics_cloned.make_where_clause();
76
77 where_clause.predicates.extend(bound.iter().cloned());
78
79 let (impl_generics, ty_generics, where_clause) = generics_cloned.split_for_impl();
80
81 let debug_impl = quote! {
82 impl #impl_generics core::fmt::Debug for #ident #ty_generics #where_clause {
83 #[inline]
84 fn fmt(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result {
85 #builder_tokens
86 }
87 }
88 };
89
90 tokens.extend(debug_impl);
91 }
92}