educe/trait_handlers/hash/
hash_union.rs

1use quote::quote;
2use syn::{Data, DeriveInput, Meta};
3
4use super::models::{FieldAttributeBuilder, TypeAttributeBuilder};
5use crate::{supported_traits::Trait, trait_handlers::TraitHandler};
6
7pub(crate) struct HashUnionHandler;
8
9impl TraitHandler for HashUnionHandler {
10    #[inline]
11    fn trait_meta_handler(
12        ast: &DeriveInput,
13        token_stream: &mut proc_macro2::TokenStream,
14        traits: &[Trait],
15        meta: &Meta,
16    ) -> syn::Result<()> {
17        let type_attribute =
18            TypeAttributeBuilder {
19                enable_flag: true, enable_unsafe: true, enable_bound: false
20            }
21            .build_from_hash_meta(meta)?;
22
23        if !type_attribute.has_unsafe {
24            return Err(super::panic::union_without_unsafe(meta));
25        }
26
27        if let Data::Union(data) = &ast.data {
28            for field in data.fields.named.iter() {
29                let _ = FieldAttributeBuilder {
30                    enable_ignore: false, enable_method: false
31                }
32                .build_from_attributes(&field.attrs, traits)?;
33            }
34        }
35
36        let ident = &ast.ident;
37
38        let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl();
39
40        token_stream.extend(quote! {
41            impl #impl_generics ::core::hash::Hash for #ident #ty_generics #where_clause {
42                #[inline]
43                fn hash<H: ::core::hash::Hasher>(&self, state: &mut H) {
44                    let size = ::core::mem::size_of::<Self>();
45                    let data = unsafe { ::core::slice::from_raw_parts(self as *const Self as *const u8, size) };
46
47                    ::core::hash::Hash::hash(data, state)
48                }
49            }
50        });
51
52        Ok(())
53    }
54}