ink_codegen/generator/
storage.rs1use crate::GenerateCode;
16use derive_more::From;
17use proc_macro2::TokenStream as TokenStream2;
18use quote::{
19 quote,
20 quote_spanned,
21};
22use syn::spanned::Spanned as _;
23
24#[derive(From)]
26pub struct Storage<'a> {
27 contract: &'a ir::Contract,
28}
29impl_as_ref_for_generator!(Storage);
30
31impl GenerateCode for Storage<'_> {
32 fn generate_code(&self) -> TokenStream2 {
33 let storage_span = self.contract.module().storage().span();
34 let access_env_impls = self.generate_access_env_trait_impls();
35 let storage_struct = self.generate_storage_struct();
36 quote_spanned!(storage_span =>
37 #storage_struct
38 #access_env_impls
39
40 const _: () = {
41 #[allow(unused_imports)]
43 use ::ink::codegen::{
44 Env as _,
45 StaticEnv as _,
46 };
47 };
48 )
49 }
50}
51
52impl Storage<'_> {
53 fn generate_access_env_trait_impls(&self) -> TokenStream2 {
54 let storage_ident = &self.contract.module().storage().ident();
55 quote! {
56 const _: () = {
57 impl<'a> ::ink::codegen::Env for &'a #storage_ident {
58 type EnvAccess = ::ink::EnvAccess<
59 'a, <#storage_ident as ::ink::env::ContractEnv>::Env>;
60
61 fn env(self) -> Self::EnvAccess {
62 <<Self as ::ink::codegen::Env>::EnvAccess
63 as ::core::default::Default>::default()
64 }
65 }
66
67 impl<'a> ::ink::codegen::StaticEnv for #storage_ident {
68 type EnvAccess = ::ink::EnvAccess<
69 'static, <#storage_ident as ::ink::env::ContractEnv>::Env>;
70
71 fn env() -> Self::EnvAccess {
72 <<Self as ::ink::codegen::StaticEnv>::EnvAccess
73 as ::core::default::Default>::default()
74 }
75 }
76 };
77 }
78 }
79
80 fn generate_storage_struct(&self) -> TokenStream2 {
95 let storage = self.contract.module().storage();
96 let span = storage.span();
97 let ident = storage.ident();
98 let generics = storage.generics();
99 let attrs = storage.attrs();
100 let fields = storage.fields();
101 quote_spanned!( span =>
102 #(#attrs)*
103 #[::ink::storage_item]
104 #[cfg_attr(test, derive(::core::fmt::Debug))]
105 pub struct #ident #generics {
106 #( #fields ),*
107 }
108
109 const _: () = {
110 impl ::ink::reflect::ContractName for #ident {
111 const NAME: &'static str = ::core::stringify!(#ident);
112 }
113
114 #[allow(non_camel_case_types)]
115 trait __ink_StorageMarker {}
116 impl __ink_StorageMarker for #ident {}
117 };
118 )
119 }
120}