1//! [`Hash`](trait@std::hash::Hash) implementation.
2
3use proc_macro2::TokenStream;
4use quote::quote;
5
6use crate::{Data, DataType, DeriveTrait, Item, SimpleType, SplitGenerics, TraitImpl};
7
8/// Dummy-struct implement [`Trait`](crate::Trait) for
9/// [`Hash`](trait@std::hash::Hash).
10pub struct Hash;
11
12impl TraitImpl for Hash {
13 fn as_str(&self) -> &'static str {
14 "Hash"
15 }
16
17 fn default_derive_trait(&self) -> DeriveTrait {
18 DeriveTrait::Hash
19 }
20
21 fn build_signature(
22 &self,
23 _any_bound: bool,
24 _item: &Item,
25 _generics: &SplitGenerics<'_>,
26 _traits: &[DeriveTrait],
27 _trait_: &DeriveTrait,
28 body: &TokenStream,
29 ) -> TokenStream {
30 quote! {
31 fn hash<__H: ::core::hash::Hasher>(&self, __state: &mut __H) {
32 match self {
33 #body
34 }
35 }
36 }
37 }
38
39 fn build_body(
40 &self,
41 _any_bound: bool,
42 _traits: &[DeriveTrait],
43 trait_: &DeriveTrait,
44 data: &Data,
45 ) -> TokenStream {
46 let self_pattern = data.self_pattern();
47 let trait_path = trait_.path();
48
49 // Add hashing the variant if this is an enum.
50 let discriminant = if let DataType::Variant { .. } = data.type_ {
51 Some(quote! { #trait_path::hash(&::core::mem::discriminant(self), __state); })
52 } else {
53 None
54 };
55
56 match data.simple_type() {
57 SimpleType::Struct(_) | SimpleType::Tuple(_) => {
58 let self_ident = data.iter_self_ident(**trait_);
59
60 quote! {
61 #self_pattern => {
62 #discriminant
63 #(#trait_path::hash(#self_ident, __state);)*
64 }
65 }
66 }
67 SimpleType::Unit(_) => {
68 quote! {
69 #self_pattern => {
70 #discriminant
71 }
72 }
73 }
74 SimpleType::Union(_) => unreachable!("unexpected trait for union"),
75 }
76 }
77}
78