ink_macro/storage/
storable_hint.rs1use ink_ir::utils::find_storage_key_salt;
16use proc_macro2::TokenStream as TokenStream2;
17use quote::{
18 format_ident,
19 quote,
20 ToTokens,
21};
22use syn::{
23 parse2,
24 GenericParam,
25};
26
27fn storable_hint_inner(s: synstructure::Structure) -> TokenStream2 {
28 let ident = s.ast().ident.clone();
29 let salt_ident = format_ident!("__ink_generic_salt");
30
31 let mut generics = s.ast().generics.clone();
32 generics.params.push(
33 parse2(quote! { #salt_ident : ::ink::storage::traits::StorageKey }).unwrap(),
34 );
35
36 let (impl_generics, _, where_clause) = generics.split_for_impl();
37 let (_, ty_generics_original, _) = s.ast().generics.split_for_impl();
38
39 if let Some(inner_salt_ident) = find_storage_key_salt(s.ast()) {
40 let inner_salt_ident = inner_salt_ident.ident.to_token_stream();
41 let ty_generics: Vec<_> = s
42 .ast()
43 .generics
44 .params
45 .clone()
46 .into_iter()
47 .map(|param| {
48 let ident = match param {
49 GenericParam::Type(t) => t.ident.to_token_stream(),
50 GenericParam::Lifetime(l) => l.lifetime.to_token_stream(),
51 GenericParam::Const(c) => c.ident.to_token_stream(),
52 };
53 if inner_salt_ident.to_string() == ident.to_string() {
54 Some(quote! {
55 #salt_ident
56 })
57 } else {
58 Some(ident)
59 }
60 })
61 .collect();
62
63 quote! {
64 impl #impl_generics ::ink::storage::traits::StorableHint<#salt_ident> for #ident #ty_generics_original #where_clause {
65 type Type = #ident <#(#ty_generics),*>;
66 type PreferredKey = #inner_salt_ident;
67 }
68 }
69 } else {
70 quote! {
71 impl #impl_generics ::ink::storage::traits::StorableHint<#salt_ident> for #ident #ty_generics_original #where_clause {
72 type Type = #ident #ty_generics_original;
73 type PreferredKey = ::ink::storage::traits::AutoKey;
74 }
75 }
76 }
77}
78
79pub fn storable_hint_derive(s: synstructure::Structure) -> TokenStream2 {
80 let derive = storable_hint_inner(s);
81
82 quote! {
83 const _ : () = {
84 #derive
85 };
86 }
87}