// Copyright 2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // Substrate is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . use crate::storage::transformation::{DeclStorageTypeInfos, InstanceOpts}; use srml_support_procedural_tools::syn_ext as ext; use proc_macro2::TokenStream as TokenStream2; use syn::Ident; use quote::quote; pub fn option_unwrap(is_option: bool) -> TokenStream2 { if !is_option { // raw type case quote!( unwrap_or_else ) } else { // Option<> type case quote!( or_else ) } } // prefix for consts in trait Instance pub(crate) const PREFIX_FOR: &str = "PREFIX_FOR_"; pub(crate) const HEAD_KEY_FOR: &str = "HEAD_KEY_FOR_"; pub(crate) struct Impls<'a, I: Iterator> { pub scrate: &'a TokenStream2, pub visibility: &'a syn::Visibility, pub traitinstance: &'a syn::Ident, pub traittype: &'a syn::TypeParamBound, pub instance_opts: &'a InstanceOpts, pub type_infos: DeclStorageTypeInfos<'a>, pub fielddefault: TokenStream2, pub prefix: String, pub cratename: &'a syn::Ident, pub name: &'a syn::Ident, pub attrs: I, } impl<'a, I: Iterator> Impls<'a, I> { pub fn simple_value(self) -> TokenStream2 { let Self { scrate, visibility, traitinstance, traittype, instance_opts, type_infos, fielddefault, prefix, name, attrs, .. } = self; let DeclStorageTypeInfos { typ, value_type, is_option, .. } = type_infos; let option_simple_1 = option_unwrap(is_option); let mutate_impl = if !is_option { quote!{ >::put(&val, storage) } } else { quote!{ match val { Some(ref val) => >::put(&val, storage), None => >::kill(storage), } } }; let InstanceOpts { equal_default_instance, bound_instantiable, instance, .. } = instance_opts; let final_prefix = if let Some(instance) = instance { let const_name = Ident::new(&format!("{}{}", PREFIX_FOR, name.to_string()), proc_macro2::Span::call_site()); quote!{ #instance::#const_name.as_bytes() } } else { quote!{ #prefix.as_bytes() } }; let (struct_trait, impl_trait, trait_and_instance) = if ext::type_contains_ident( value_type, traitinstance ) { ( quote!(#traitinstance: #traittype, #instance #bound_instantiable #equal_default_instance), quote!(#traitinstance: #traittype, #instance #bound_instantiable), quote!(#traitinstance, #instance), ) } else { ( quote!(#instance #bound_instantiable #equal_default_instance), quote!(#instance #bound_instantiable), quote!(#instance) ) }; // generator for value quote! { #( #[ #attrs ] )* #visibility struct #name<#struct_trait>( #scrate::rstd::marker::PhantomData<(#trait_and_instance)> ); impl<#impl_trait> #scrate::storage::hashed::generator::StorageValue<#typ> for #name<#trait_and_instance> { type Query = #value_type; /// Get the storage key. fn key() -> &'static [u8] { #final_prefix } /// Load the value from the provided storage instance. fn get>(storage: &S) -> Self::Query { storage.get(>::key()) .#option_simple_1(|| #fielddefault) } /// Take a value from storage, removing it afterwards. fn take>(storage: &mut S) -> Self::Query { storage.take(>::key()) .#option_simple_1(|| #fielddefault) } /// Mutate the value under a key. fn mutate(f: F, storage: &mut S) -> R where F: FnOnce(&mut Self::Query) -> R, S: #scrate::HashedStorage<#scrate::Twox128>, { let mut val = >::get(storage); let ret = f(&mut val); #mutate_impl ; ret } } } } pub fn map(self, hasher: TokenStream2, kty: &syn::Type) -> TokenStream2 { let Self { scrate, visibility, traitinstance, traittype, instance_opts, type_infos, fielddefault, prefix, name, attrs, .. } = self; let DeclStorageTypeInfos { typ, value_type, is_option, .. } = type_infos; let option_simple_1 = option_unwrap(is_option); let as_map = quote!{ > }; let mutate_impl = if !is_option { quote!{ #as_map::insert(key, &val, storage) } } else { quote!{ match val { Some(ref val) => #as_map::insert(key, &val, storage), None => #as_map::remove(key, storage), } } }; let InstanceOpts { equal_default_instance, bound_instantiable, instance, .. } = instance_opts; let final_prefix = if let Some(instance) = instance { let const_name = syn::Ident::new(&format!("{}{}", PREFIX_FOR, name.to_string()), proc_macro2::Span::call_site()); quote!{ #instance::#const_name.as_bytes() } } else { quote!{ #prefix.as_bytes() } }; let (struct_trait, impl_trait, trait_and_instance) = if ext::type_contains_ident(value_type, traitinstance) || ext::type_contains_ident(kty, traitinstance) { ( quote!(#traitinstance: #traittype, #instance #bound_instantiable #equal_default_instance), quote!(#traitinstance: #traittype, #instance #bound_instantiable), quote!(#traitinstance, #instance), ) } else { ( quote!(#instance #bound_instantiable #equal_default_instance), quote!(#instance #bound_instantiable), quote!(#instance) ) }; // generator for map quote!{ #( #[ #attrs ] )* #visibility struct #name<#struct_trait>( #scrate::rstd::marker::PhantomData<(#trait_and_instance)> ); impl<#impl_trait> #scrate::storage::hashed::generator::StorageMap<#kty, #typ> for #name<#trait_and_instance> { type Query = #value_type; type Hasher = #scrate::#hasher; /// Get the prefix key in storage. fn prefix() -> &'static [u8] { #final_prefix } /// Get the storage key used to fetch a value corresponding to a specific key. fn key_for(x: &#kty) -> #scrate::rstd::vec::Vec { let mut key = #as_map::prefix().to_vec(); #scrate::codec::Encode::encode_to(x, &mut key); key } /// Load the value associated with the given key from the map. fn get>(key: &#kty, storage: &S) -> Self::Query { let key = #as_map::key_for(key); storage.get(&key[..]).#option_simple_1(|| #fielddefault) } /// Take the value, reading and removing it. fn take>(key: &#kty, storage: &mut S) -> Self::Query { let key = #as_map::key_for(key); storage.take(&key[..]).#option_simple_1(|| #fielddefault) } /// Mutate the value under a key fn mutate(key: &#kty, f: F, storage: &mut S) -> R where F: FnOnce(&mut Self::Query) -> R, S: #scrate::HashedStorage<#scrate::#hasher>, { let mut val = #as_map::get(key, storage); let ret = f(&mut val); #mutate_impl ; ret } } impl<#impl_trait> #scrate::storage::hashed::generator::AppendableStorageMap<#kty, #typ> for #name<#trait_and_instance> {} } } pub fn linked_map(self, hasher: TokenStream2, kty: &syn::Type) -> TokenStream2 { let Self { scrate, visibility, traitinstance, traittype, instance_opts, type_infos, fielddefault, prefix, name, attrs, .. } = self; let InstanceOpts { equal_default_instance, bound_instantiable, instance, .. } = instance_opts; let final_prefix = if let Some(instance) = instance { let const_name = syn::Ident::new(&format!("{}{}", PREFIX_FOR, name.to_string()), proc_macro2::Span::call_site()); quote!{ #instance::#const_name.as_bytes() } } else { quote!{ #prefix.as_bytes() } }; // make sure to use different prefix for head and elements. let final_head_key = if let Some(instance) = instance { let const_name = syn::Ident::new(&format!("{}{}", HEAD_KEY_FOR, name.to_string()), proc_macro2::Span::call_site()); quote!{ #instance::#const_name.as_bytes() } } else { let final_head_key = format!("head of {}", prefix); quote!{ #final_head_key.as_bytes() } }; let DeclStorageTypeInfos { typ, value_type, is_option, .. } = type_infos; let option_simple_1 = option_unwrap(is_option); let name_lowercase = name.to_string().to_lowercase(); let inner_module = syn::Ident::new(&format!("__linked_map_details_for_{}_do_not_use", name_lowercase), name.span()); let linkage = syn::Ident::new(&format!("__LinkageFor{}DoNotUse", name), name.span()); let phantom_data = quote! { #scrate::rstd::marker::PhantomData }; let as_map = quote!{ > }; let put_or_insert = quote! { match linkage { Some(linkage) => storage.put(key_for, &(val, linkage)), None => #as_map::insert(key, &val, storage), } }; let mutate_impl = if !type_infos.is_option { put_or_insert } else { quote! { match val { Some(ref val) => #put_or_insert, None => #as_map::remove(key, storage), } } }; let (struct_trait, impl_trait, trait_and_instance, trait_lifetime) = if ext::type_contains_ident( value_type, traitinstance ) || ext::type_contains_ident(kty, traitinstance) { ( quote!(#traitinstance: #traittype, #instance #bound_instantiable #equal_default_instance), quote!(#traitinstance: #traittype, #instance #bound_instantiable), quote!(#traitinstance, #instance), quote!(#traitinstance: 'static), ) } else { ( quote!(#instance #bound_instantiable #equal_default_instance), quote!(#instance #bound_instantiable), quote!(#instance), quote!() ) }; // generator for linked map let helpers = quote! { /// Linkage data of an element (it's successor and predecessor) #[derive(#scrate::codec::Encode, #scrate::codec::Decode)] pub(crate) struct #linkage { /// Previous element key in storage (None for the first element) pub previous: Option, /// Next element key in storage (None for the last element) pub next: Option, } mod #inner_module { use super::*; /// Re-exported version of linkage to overcome proc-macro derivation issue. pub(crate) use super::#linkage as Linkage; impl Default for Linkage { fn default() -> Self { Self { previous: None, next: None, } } } /// A key-value pair iterator for enumerable map. pub(crate) struct Enumerator<'a, S, K, V> { pub storage: &'a S, pub next: Option, pub _data: #phantom_data, } impl<'a, S: #scrate::HashedStorage<#scrate::#hasher>, #impl_trait> Iterator for Enumerator<'a, S, #kty, (#typ, #trait_and_instance)> { type Item = (#kty, #typ); fn next(&mut self) -> Option { let next = self.next.take()?; let key_for = as #scrate::storage::hashed::generator::StorageMap<#kty, #typ>>::key_for(&next); let (val, linkage): (#typ, Linkage<#kty>) = self.storage.get(&*key_for) .expect("previous/next only contain existing entires; we enumerate using next; entry exists; qed"); self.next = linkage.next; Some((next, val)) } } pub(crate) trait Utils<#struct_trait> { /// Update linkage when this element is removed. /// /// Takes care of updating previous and next elements points /// as well as updates head if the element is first or last. fn remove_linkage>(linkage: Linkage<#kty>, storage: &mut S); /// Read the contained data and it's linkage. fn read_with_linkage(storage: &S, key: &[u8]) -> Option<(#value_type, Linkage<#kty>)> where S: #scrate::HashedStorage<#scrate::#hasher>; /// Generate linkage for newly inserted element. /// /// Takes care of updating head and previous head's pointer. fn new_head_linkage>( storage: &mut S, key: &#kty, ) -> Linkage<#kty>; /// Read current head pointer. fn read_head>(storage: &S) -> Option<#kty>; /// Overwrite current head pointer. /// /// If `None` is given head is removed from storage. fn write_head>(storage: &mut S, head: Option<&#kty>); } } }; let structure = quote! { #( #[ #attrs ] )* #visibility struct #name<#struct_trait>(#phantom_data<(#trait_and_instance)>); impl<#impl_trait> self::#inner_module::Utils<#trait_and_instance> for #name<#trait_and_instance> { fn remove_linkage>( linkage: self::#inner_module::Linkage<#kty>, storage: &mut S, ) { use self::#inner_module::Utils; let next_key = linkage.next.as_ref().map(|x| #as_map::key_for(x)); let prev_key = linkage.previous.as_ref().map(|x| #as_map::key_for(x)); if let Some(prev_key) = prev_key { // Retrieve previous element and update `next` let mut res = Self::read_with_linkage(storage, &*prev_key) .expect("Linkage is updated in case entry is removed; it always points to existing keys; qed"); res.1.next = linkage.next; storage.put(&*prev_key, &res); } else { // we were first so let's update the head Self::write_head(storage, linkage.next.as_ref()); } if let Some(next_key) = next_key { // Update previous of next element let mut res = Self::read_with_linkage(storage, &*next_key) .expect("Linkage is updated in case entry is removed; it always points to existing keys; qed"); res.1.previous = linkage.previous; storage.put(&*next_key, &res); } } fn read_with_linkage>( storage: &S, key: &[u8], ) -> Option<(#value_type, self::#inner_module::Linkage<#kty>)> { storage.get(key) } fn new_head_linkage>( storage: &mut S, key: &#kty, ) -> self::#inner_module::Linkage<#kty> { use self::#inner_module::Utils; if let Some(head) = Self::read_head(storage) { // update previous head predecessor { let head_key = #as_map::key_for(&head); let (data, linkage) = Self::read_with_linkage(storage, &*head_key).expect(r#" head is set when first element is inserted and unset when last element is removed; if head is Some then it points to existing key; qed "#); storage.put(&*head_key, &(data, self::#inner_module::Linkage { next: linkage.next.as_ref(), previous: Some(key), })); } // update to current head Self::write_head(storage, Some(key)); // return linkage with pointer to previous head let mut linkage = self::#inner_module::Linkage::default(); linkage.next = Some(head); linkage } else { // we are first - update the head and produce empty linkage Self::write_head(storage, Some(key)); self::#inner_module::Linkage::default() } } fn read_head>(storage: &S) -> Option<#kty> { storage.get(#final_head_key) } fn write_head>(storage: &mut S, head: Option<&#kty>) { match head { Some(head) => storage.put(#final_head_key, head), None => storage.kill(#final_head_key), } } } }; quote! { #helpers #structure impl<#impl_trait> #scrate::storage::hashed::generator::StorageMap<#kty, #typ> for #name<#trait_and_instance> { type Query = #value_type; type Hasher = #scrate::#hasher; /// Get the prefix key in storage. fn prefix() -> &'static [u8] { #final_prefix } /// Get the storage key used to fetch a value corresponding to a specific key. fn key_for(key: &#kty) -> #scrate::rstd::vec::Vec { let mut key_for = #as_map::prefix().to_vec(); #scrate::codec::Encode::encode_to(&key, &mut key_for); key_for } /// Load the value associated with the given key from the map. fn get>(key: &#kty, storage: &S) -> Self::Query { storage.get(&*#as_map::key_for(key)).#option_simple_1(|| #fielddefault) } /// Take the value, reading and removing it. fn take>(key: &#kty, storage: &mut S) -> Self::Query { use self::#inner_module::Utils; let res: Option<(#value_type, self::#inner_module::Linkage<#kty>)> = storage.take(&*#as_map::key_for(key)); match res { Some((data, linkage)) => { Self::remove_linkage(linkage, storage); data }, None => #fielddefault, } } /// Remove the value under a key. fn remove>(key: &#kty, storage: &mut S) { #as_map::take(key, storage); } /// Store a value to be associated with the given key from the map. fn insert>(key: &#kty, val: &#typ, storage: &mut S) { use self::#inner_module::Utils; let key_for = &*#as_map::key_for(key); let linkage = match Self::read_with_linkage(storage, key_for) { // overwrite but reuse existing linkage Some((_data, linkage)) => linkage, // create new linkage None => Self::new_head_linkage(storage, key), }; storage.put(key_for, &(val, linkage)) } /// Mutate the value under a key fn mutate(key: &#kty, f: F, storage: &mut S) -> R where F: FnOnce(&mut Self::Query) -> R, S: #scrate::HashedStorage<#scrate::#hasher>, { use self::#inner_module::Utils; let key_for = &*#as_map::key_for(key); let (mut val, linkage) = Self::read_with_linkage(storage, key_for) .map(|(data, linkage)| (data, Some(linkage))) .unwrap_or_else(|| (#fielddefault, None)); let ret = f(&mut val); #mutate_impl ; ret } } impl<#impl_trait> #scrate::storage::hashed::generator::EnumerableStorageMap<#kty, #typ> for #name<#trait_and_instance> where #trait_lifetime { fn head>(storage: &S) -> Option<#kty> { use self::#inner_module::Utils; Self::read_head(storage) } fn enumerate<'a, S>( storage: &'a S ) -> #scrate::rstd::boxed::Box + 'a> where S: #scrate::HashedStorage<#scrate::#hasher>, #kty: 'a, #typ: 'a, { use self::#inner_module::{Utils, Enumerator}; #scrate::rstd::boxed::Box::new(Enumerator { next: Self::read_head(storage), storage, _data: #phantom_data::<(#typ, #trait_and_instance)>::default(), }) } } } } pub fn double_map( self, hasher: TokenStream2, k1ty: &syn::Type, k2ty: &syn::Type, k2_hasher: TokenStream2, ) -> TokenStream2 { let Self { scrate, visibility, traitinstance, traittype, type_infos, fielddefault, prefix, name, attrs, instance_opts, .. } = self; let DeclStorageTypeInfos { typ, value_type, is_option, .. } = type_infos; let option_simple_1 = option_unwrap(is_option); let as_double_map = quote!{ > }; let mutate_impl = if !is_option { quote!{ #as_double_map::insert(key1, key2, &val, storage) } } else { quote!{ match val { Some(ref val) => #as_double_map::insert(key1, key2, &val, storage), None => #as_double_map::remove(key1, key2, storage), } } }; let InstanceOpts { equal_default_instance, bound_instantiable, instance, .. } = instance_opts; let final_prefix = if let Some(instance) = instance { let const_name = syn::Ident::new(&format!("{}{}", PREFIX_FOR, name.to_string()), proc_macro2::Span::call_site()); quote!{ #instance::#const_name.as_bytes() } } else { quote!{ #prefix.as_bytes() } }; let (struct_trait, impl_trait, trait_and_instance) = if ext::type_contains_ident(value_type, traitinstance) || ext::type_contains_ident(k1ty, traitinstance) || ext::type_contains_ident(k2ty, traitinstance) { ( quote!(#traitinstance: #traittype, #instance #bound_instantiable #equal_default_instance), quote!(#traitinstance: #traittype, #instance #bound_instantiable), quote!(#traitinstance, #instance), ) } else { ( quote!(#instance #bound_instantiable #equal_default_instance), quote!(#instance #bound_instantiable), quote!(#instance) ) }; // generator for double map quote!{ #( #[ #attrs ] )* #visibility struct #name<#struct_trait> (#scrate::rstd::marker::PhantomData<(#trait_and_instance)>); impl<#impl_trait> #scrate::storage::unhashed::generator::StorageDoubleMap<#k1ty, #k2ty, #typ> for #name<#trait_and_instance> { type Query = #value_type; fn prefix_for(k1: &#k1ty) -> Vec { use #scrate::storage::hashed::generator::StorageHasher; let mut key = #as_double_map::prefix().to_vec(); #scrate::codec::Encode::encode_to(k1, &mut key); #scrate::#hasher::hash(&key[..]).to_vec() } fn prefix() -> &'static [u8] { #final_prefix } fn key_for(k1: &#k1ty, k2: &#k2ty) -> Vec { use #scrate::storage::hashed::generator::StorageHasher; let mut key = #as_double_map::prefix_for(k1); #scrate::codec::Encode::using_encoded(k2, |e| key.extend(&#scrate::#k2_hasher::hash(e))); key } fn get(key1: &#k1ty, key2: &#k2ty, storage: &S) -> Self::Query { let key = #as_double_map::key_for(key1, key2); storage.get(&key).#option_simple_1(|| #fielddefault) } fn take(key1: &#k1ty, key2: &#k2ty, storage: &mut S) -> Self::Query { let key = #as_double_map::key_for(key1, key2); storage.take(&key).#option_simple_1(|| #fielddefault) } fn mutate(key1: &#k1ty, key2: &#k2ty, f: F, storage: &mut S) -> R where F: FnOnce(&mut Self::Query) -> R, S: #scrate::UnhashedStorage, { let mut val = #as_double_map::get(key1, key2, storage); let ret = f(&mut val); #mutate_impl ; ret } } } } }