mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-13 08:11:04 +00:00
Fix linked map for trait types and Option (#1809)
* Fix linked map for traits. * Fix Option<_> variant. * Improve naming a tad * Rebuild runtime * Encapsulate private data in the inner module. * Bump impl version. * Fix deriving codec in srml-example. * Fix derivation without importing parity-codec-derive. * Fix config() for map.
This commit is contained in:
+11
-1
@@ -151,6 +151,15 @@ name = "crossbeam"
|
||||
version = "0.2.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-channel"
|
||||
version = "0.3.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"crossbeam-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-deque"
|
||||
version = "0.6.2"
|
||||
@@ -1309,12 +1318,12 @@ dependencies = [
|
||||
name = "substrate-consensus-common"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"crossbeam-channel 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parity-codec 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parity-codec-derive 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"sr-primitives 0.1.0",
|
||||
"sr-version 0.1.0",
|
||||
"substrate-inherents 0.1.0",
|
||||
@@ -1872,6 +1881,7 @@ dependencies = [
|
||||
"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
|
||||
"checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e"
|
||||
"checksum crossbeam 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)" = "bd66663db5a988098a89599d4857919b3acf7f61402e61365acfd3919857b9be"
|
||||
"checksum crossbeam-channel 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8d4f5844607ce8da3fff431e7dba56cda8bfcc570aa50bee36adba8a32b8cad7"
|
||||
"checksum crossbeam-deque 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4fe1b6f945f824c7a25afe44f62e25d714c0cc523f8e99d8db5cd1026e1269d3"
|
||||
"checksum crossbeam-epoch 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2449aaa4ec7ef96e5fb24db16024b935df718e9ae1cec0a1e68feeca2efca7b8"
|
||||
"checksum crossbeam-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e07fc155212827475223f0bcfae57e945e694fc90950ddf3f6695bbfd5555c72"
|
||||
|
||||
BIN
Binary file not shown.
+1
-1
@@ -1563,12 +1563,12 @@ dependencies = [
|
||||
name = "substrate-consensus-common"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"crossbeam-channel 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parity-codec 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parity-codec-derive 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"sr-primitives 0.1.0",
|
||||
"sr-version 0.1.0",
|
||||
"substrate-inherents 0.1.0",
|
||||
|
||||
@@ -61,7 +61,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
|
||||
impl_name: create_runtime_str!("substrate-node"),
|
||||
authoring_version: 10,
|
||||
spec_version: 29,
|
||||
impl_version: 29,
|
||||
impl_version: 30,
|
||||
apis: RUNTIME_API_VERSIONS,
|
||||
};
|
||||
|
||||
|
||||
Generated
+11
-1
@@ -151,6 +151,15 @@ name = "crossbeam"
|
||||
version = "0.2.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-channel"
|
||||
version = "0.3.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"crossbeam-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-deque"
|
||||
version = "0.6.2"
|
||||
@@ -1679,12 +1688,12 @@ dependencies = [
|
||||
name = "substrate-consensus-common"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"crossbeam-channel 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parity-codec 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parity-codec-derive 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"sr-primitives 0.1.0",
|
||||
"sr-version 0.1.0",
|
||||
"substrate-inherents 0.1.0",
|
||||
@@ -2224,6 +2233,7 @@ dependencies = [
|
||||
"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
|
||||
"checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e"
|
||||
"checksum crossbeam 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)" = "bd66663db5a988098a89599d4857919b3acf7f61402e61365acfd3919857b9be"
|
||||
"checksum crossbeam-channel 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8d4f5844607ce8da3fff431e7dba56cda8bfcc570aa50bee36adba8a32b8cad7"
|
||||
"checksum crossbeam-deque 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4fe1b6f945f824c7a25afe44f62e25d714c0cc523f8e99d8db5cd1026e1269d3"
|
||||
"checksum crossbeam-epoch 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2449aaa4ec7ef96e5fb24db16024b935df718e9ae1cec0a1e68feeca2efca7b8"
|
||||
"checksum crossbeam-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e07fc155212827475223f0bcfae57e945e694fc90950ddf3f6695bbfd5555c72"
|
||||
|
||||
BIN
Binary file not shown.
@@ -63,6 +63,10 @@ decl_storage! {
|
||||
// `fn getter_name(key: KeyType) -> ValueType` for map items.
|
||||
Dummy get(dummy) config(): Option<T::Balance>;
|
||||
|
||||
// A map that has enumerable entries.
|
||||
Bar get(bar) config(): linked_map T::AccountId => T::Balance;
|
||||
|
||||
|
||||
// this one uses the default, we'll demonstrate the usage of 'mutate' API.
|
||||
Foo get(foo) config(): T::Balance;
|
||||
}
|
||||
@@ -292,6 +296,8 @@ mod tests {
|
||||
t.extend(balances::GenesisConfig::<Test>::default().build_storage().unwrap().0);
|
||||
t.extend(GenesisConfig::<Test>{
|
||||
dummy: 42,
|
||||
// we configure the map with (key, value) pairs.
|
||||
bar: vec![(1, 2), (2, 3)],
|
||||
foo: 24,
|
||||
}.build_storage().unwrap().0);
|
||||
t.into()
|
||||
|
||||
@@ -193,15 +193,14 @@ impl<'a> Impls<'a> {
|
||||
let head_key = format!("head of {}", prefix);
|
||||
let prefix = format!("{}", prefix);
|
||||
let name_lowercase = name.to_string().to_lowercase();
|
||||
let key_for = syn::Ident::new(&format!("key_for_{}", name_lowercase), name.span());
|
||||
let internal_module = syn::Ident::new(&format!("__internal_do_not_use_{}", name_lowercase), name.span());
|
||||
let linkage = syn::Ident::new(&format!("Linkage{}", name), name.span());
|
||||
let borrowing_linkage = syn::Ident::new(&format!("Borrowing{}", linkage), name.span());
|
||||
let enumerator = syn::Ident::new(&format!("Enumerator{}", name), name.span());
|
||||
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::storage::generator::PhantomData };
|
||||
let as_map = quote!{ <Self as #scrate::storage::generator::StorageMap<#kty, #typ>> };
|
||||
let put_or_insert = quote! {
|
||||
match linkage {
|
||||
Some(linkage) => storage.put(key_for, &(val, linkage)),
|
||||
None => <Self as #scrate::storage::generator::StorageMap<#kty, #typ>>::insert(key, &val, storage),
|
||||
None => #as_map::insert(key, &val, storage),
|
||||
}
|
||||
};
|
||||
let mutate_impl = if !type_infos.is_option {
|
||||
@@ -210,146 +209,185 @@ impl<'a> Impls<'a> {
|
||||
quote! {
|
||||
match val {
|
||||
Some(ref val) => #put_or_insert,
|
||||
None => <Self as #scrate::storage::generator::StorageMap<#kty, #typ>>::remove(key, storage),
|
||||
None => #as_map::remove(key, storage),
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// generator for linked map
|
||||
quote! {
|
||||
let helpers = quote! {
|
||||
/// Linkage data of an element (it's successor and predecessor)
|
||||
#[derive(#scrate::parity_codec_derive::Encode, #scrate::parity_codec_derive::Decode)]
|
||||
pub(crate) struct #linkage<Key> {
|
||||
/// Previous element key in storage (None for the first element)
|
||||
pub previous: Option<Key>,
|
||||
/// Next element key in storage (None for the last element)
|
||||
pub next: Option<Key>,
|
||||
}
|
||||
|
||||
mod #internal_module {
|
||||
mod #inner_module {
|
||||
use super::*;
|
||||
|
||||
#[derive(Default, parity_codec_derive::Encode, parity_codec_derive::Decode)]
|
||||
pub struct #linkage {
|
||||
/// Previous element key in storage (None for the first element)
|
||||
previous: Option<#kty>,
|
||||
/// Next element key in storage (None for the last element)
|
||||
next: Option<#kty>,
|
||||
}
|
||||
/// Re-exported version of linkage to overcome proc-macro derivation issue.
|
||||
pub(crate) use super::#linkage as Linkage;
|
||||
|
||||
/// A helper struct to avoid unnecessary key cloning.
|
||||
///
|
||||
/// NOTE It has to have exact same parity-codec encoding as #linkage!
|
||||
#[derive(parity_codec_derive::Encode)]
|
||||
struct #borrowing_linkage<'a> {
|
||||
previous: Option<&'a #kty>,
|
||||
next: Option<&'a #kty>,
|
||||
}
|
||||
|
||||
impl #linkage {
|
||||
/// 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.
|
||||
pub fn remove<S: #scrate::GenericStorage>(
|
||||
self,
|
||||
storage: &S,
|
||||
) {
|
||||
let next_key = self.next.as_ref().map(|x| #key_for(x));
|
||||
let prev_key = self.previous.as_ref().map(|x| #key_for(x));
|
||||
|
||||
if let Some(prev_key) = prev_key {
|
||||
// Retrieve previous element and update `next`
|
||||
let mut res = Self::read(storage, &*prev_key)
|
||||
.expect("Linkage is updated in case entry is removed; it always points to existing keys; qed");
|
||||
res.1.next = self.next;
|
||||
storage.put(&*prev_key, &res);
|
||||
} else {
|
||||
// we were first so let's update the head
|
||||
Self::write_head(storage, self.next.as_ref());
|
||||
}
|
||||
|
||||
if let Some(next_key) = next_key {
|
||||
// Update previous of next element
|
||||
let mut res = Self::read(storage, &*next_key)
|
||||
.expect("Linkage is updated in case entry is removed; it always points to existing keys; qed");
|
||||
res.1.previous = self.previous;
|
||||
storage.put(&*next_key, &res);
|
||||
}
|
||||
}
|
||||
|
||||
/// Read the contained data and it's linkage.
|
||||
pub fn read<S: #scrate::GenericStorage>(storage: &S, key: &[u8]) -> Option<(#value_type, #linkage)> {
|
||||
storage.get(key)
|
||||
}
|
||||
|
||||
/// Generate linkage for newly inserted element.
|
||||
///
|
||||
/// Takes care of updating head and previous head's pointer.
|
||||
pub fn insert_new_head<S: #scrate::GenericStorage>(
|
||||
storage: &S,
|
||||
key: &#kty,
|
||||
) -> Self {
|
||||
if let Some(head) = Self::read_head(storage) {
|
||||
// update previous head predecessor
|
||||
{
|
||||
let head_key = #key_for(&head);
|
||||
let (data, linkage) = Self::read(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, #borrowing_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::default();
|
||||
linkage.next = Some(head);
|
||||
linkage
|
||||
} else {
|
||||
// we are first - update the head and produce empty linkage
|
||||
Self::write_head(storage, Some(key));
|
||||
Self::default()
|
||||
}
|
||||
}
|
||||
|
||||
/// Read current head pointer.
|
||||
pub fn read_head<S: #scrate::GenericStorage>(storage: &S) -> Option<#kty> {
|
||||
storage.get(#head_key.as_bytes())
|
||||
}
|
||||
|
||||
/// Overwrite current head pointer.
|
||||
///
|
||||
/// If `None` is given head is removed from storage.
|
||||
fn write_head<S: #scrate::GenericStorage>(storage: &S, head: Option<&#kty>) {
|
||||
match head {
|
||||
Some(head) => storage.put(#head_key.as_bytes(), head),
|
||||
None => storage.kill(#head_key.as_bytes()),
|
||||
impl<Key> Default for Linkage<Key> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
previous: None,
|
||||
next: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct #enumerator<'a, S> {
|
||||
/// A key-value pair iterator for enumerable map.
|
||||
pub(crate) struct Enumerator<'a, S, K, V> {
|
||||
pub storage: &'a S,
|
||||
pub next: Option<#kty>,
|
||||
pub next: Option<K>,
|
||||
pub _data: #phantom_data<V>,
|
||||
}
|
||||
|
||||
impl<'a, S: #scrate::GenericStorage> Iterator for #enumerator<'a, S> {
|
||||
type Item = (#kty, #typ);
|
||||
impl<'a, S: #scrate::GenericStorage, K, V> Iterator for Enumerator<'a, S, K, V> where
|
||||
K: 'a + #scrate::codec::Codec,
|
||||
V: 'a + #scrate::codec::Decode,
|
||||
{
|
||||
type Item = (K, V);
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let next = self.next.take()?;
|
||||
let key_for = #key_for(&next);
|
||||
let (val, linkage) = #linkage::read(self.storage, &*key_for)
|
||||
let key_for = key_for(&next);
|
||||
let (val, linkage): (V, Linkage<K>) = 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))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn #key_for(key: &#kty) -> #scrate::rstd::vec::Vec<u8> {
|
||||
let mut key_for = #prefix.as_bytes().to_vec();
|
||||
#scrate::codec::Encode::encode_to(&key, &mut key_for);
|
||||
key_for
|
||||
}
|
||||
/// Generate a storage key for given item.
|
||||
pub(crate) fn key_for<Key: #scrate::codec::Encode>(key: &Key) -> #scrate::rstd::vec::Vec<u8> {
|
||||
let mut key_for = #prefix.as_bytes().to_vec();
|
||||
#scrate::codec::Encode::encode_to(&key, &mut key_for);
|
||||
key_for
|
||||
}
|
||||
|
||||
#visibility struct #name<#traitinstance: #traittype>(#scrate::storage::generator::PhantomData<#traitinstance>);
|
||||
pub(crate) trait Utils<#traitinstance: #traittype> {
|
||||
/// 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<S: #scrate::GenericStorage>(linkage: Linkage<#kty>, storage: &S);
|
||||
|
||||
/// Read the contained data and it's linkage.
|
||||
fn read_with_linkage<S: #scrate::GenericStorage>(storage: &S, key: &[u8]) -> Option<(#value_type, Linkage<#kty>)>;
|
||||
|
||||
/// Generate linkage for newly inserted element.
|
||||
///
|
||||
/// Takes care of updating head and previous head's pointer.
|
||||
fn new_head_linkage<S: #scrate::GenericStorage>(
|
||||
storage: &S,
|
||||
key: &#kty,
|
||||
) -> Linkage<#kty>;
|
||||
|
||||
/// Read current head pointer.
|
||||
fn read_head<S: #scrate::GenericStorage>(storage: &S) -> Option<#kty>;
|
||||
|
||||
/// Overwrite current head pointer.
|
||||
///
|
||||
/// If `None` is given head is removed from storage.
|
||||
fn write_head<S: #scrate::GenericStorage>(storage: &S, head: Option<&#kty>);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let structure = quote! {
|
||||
#visibility struct #name<#traitinstance: #traittype>(#phantom_data<#traitinstance>);
|
||||
|
||||
impl<#traitinstance: #traittype> self::#inner_module::Utils<#traitinstance> for #name<#traitinstance> {
|
||||
fn remove_linkage<S: #scrate::GenericStorage>(
|
||||
linkage: self::#inner_module::Linkage<#kty>,
|
||||
storage: &S,
|
||||
) {
|
||||
use self::#inner_module::{key_for, Utils};
|
||||
|
||||
let next_key = linkage.next.as_ref().map(|x| key_for(x));
|
||||
let prev_key = linkage.previous.as_ref().map(|x| 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<S: #scrate::GenericStorage>(
|
||||
storage: &S,
|
||||
key: &[u8],
|
||||
) -> Option<(#value_type, self::#inner_module::Linkage<#kty>)> {
|
||||
storage.get(key)
|
||||
}
|
||||
|
||||
fn new_head_linkage<S: #scrate::GenericStorage>(
|
||||
storage: &S,
|
||||
key: &#kty,
|
||||
) -> self::#inner_module::Linkage<#kty> {
|
||||
use self::#inner_module::{key_for, Utils};
|
||||
|
||||
if let Some(head) = Self::read_head(storage) {
|
||||
// update previous head predecessor
|
||||
{
|
||||
let head_key = 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<S: #scrate::GenericStorage>(storage: &S) -> Option<#kty> {
|
||||
storage.get(#head_key.as_bytes())
|
||||
}
|
||||
|
||||
fn write_head<S: #scrate::GenericStorage>(storage: &S, head: Option<&#kty>) {
|
||||
match head {
|
||||
Some(head) => storage.put(#head_key.as_bytes(), head),
|
||||
None => storage.kill(#head_key.as_bytes()),
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
quote! {
|
||||
#helpers
|
||||
|
||||
#structure
|
||||
|
||||
impl<#traitinstance: #traittype> #scrate::storage::generator::StorageMap<#kty, #typ> for #name<#traitinstance> {
|
||||
type Query = #value_type;
|
||||
@@ -361,49 +399,55 @@ impl<'a> Impls<'a> {
|
||||
|
||||
/// Get the storage key used to fetch a value corresponding to a specific key.
|
||||
fn key_for(x: &#kty) -> #scrate::rstd::vec::Vec<u8> {
|
||||
#key_for(x)
|
||||
self::#inner_module::key_for(x)
|
||||
}
|
||||
|
||||
/// Load the value associated with the given key from the map.
|
||||
fn get<S: #scrate::GenericStorage>(key: &#kty, storage: &S) -> Self::Query {
|
||||
storage.get(&*#key_for(key)).#option_simple_1(|| #fielddefault)
|
||||
storage.get(&*#as_map::key_for(key)).#option_simple_1(|| #fielddefault)
|
||||
}
|
||||
|
||||
/// Take the value, reading and removing it.
|
||||
fn take<S: #scrate::GenericStorage>(key: &#kty, storage: &S) -> Self::Query {
|
||||
let res: Option<(#value_type, self::#internal_module::#linkage)> = storage.take(&*#key_for(key));
|
||||
use self::#inner_module::{Utils, key_for};
|
||||
|
||||
let res: Option<(#value_type, self::#inner_module::Linkage<#kty>)> = storage.take(&*key_for(key));
|
||||
match res {
|
||||
Some((data, linkage)) => {
|
||||
linkage.remove(storage);
|
||||
Self::remove_linkage(linkage, storage);
|
||||
data
|
||||
},
|
||||
None => #fielddefault
|
||||
None => #fielddefault,
|
||||
}
|
||||
}
|
||||
|
||||
/// Remove the value under a key.
|
||||
fn remove<S: #scrate::GenericStorage>(key: &#kty, storage: &S) {
|
||||
<Self as #scrate::storage::generator::StorageMap<#kty, #typ>>::take(key, storage);
|
||||
#as_map::take(key, storage);
|
||||
}
|
||||
|
||||
/// Store a value to be associated with the given key from the map.
|
||||
fn insert<S: #scrate::GenericStorage>(key: &#kty, val: &#typ, storage: &S) {
|
||||
let key_for = &*#key_for(key);
|
||||
let linkage = match self::#internal_module::#linkage::read(storage, key_for) {
|
||||
use self::#inner_module::{Utils, key_for};
|
||||
|
||||
let key_for = &*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::#internal_module::#linkage::insert_new_head(storage, key),
|
||||
None => Self::new_head_linkage(storage, key),
|
||||
};
|
||||
storage.put(key_for, &(*val, linkage))
|
||||
storage.put(key_for, &(val, linkage))
|
||||
}
|
||||
|
||||
/// Mutate the value under a key
|
||||
fn mutate<R, F: FnOnce(&mut Self::Query) -> R, S: #scrate::GenericStorage>(key: &#kty, f: F, storage: &S) -> R {
|
||||
let key_for = &*#key_for(key);
|
||||
let (mut val, linkage) = self::#internal_module::#linkage::read(storage, key_for)
|
||||
use self::#inner_module::{Utils, key_for};
|
||||
|
||||
let key_for = &*key_for(key);
|
||||
let (mut val, linkage) = Self::read_with_linkage(storage, key_for)
|
||||
.map(|(data, linkage)| (data, Some(linkage)))
|
||||
.#option_simple_1(|| (#fielddefault, None));
|
||||
.unwrap_or_else(|| (#fielddefault, None));
|
||||
|
||||
let ret = f(&mut val);
|
||||
#mutate_impl ;
|
||||
@@ -413,13 +457,21 @@ impl<'a> Impls<'a> {
|
||||
|
||||
impl<#traitinstance: #traittype> #scrate::storage::generator::EnumerableStorageMap<#kty, #typ> for #name<#traitinstance> {
|
||||
fn head<S: #scrate::GenericStorage>(storage: &S) -> Option<#kty> {
|
||||
self::#internal_module::#linkage::read_head(storage)
|
||||
use self::#inner_module::Utils;
|
||||
|
||||
Self::read_head(storage)
|
||||
}
|
||||
|
||||
fn enumerate<'a, S: #scrate::GenericStorage>(storage: &'a S) -> #scrate::storage::generator::Box<dyn Iterator<Item = (#kty, #typ)> + 'a> {
|
||||
#scrate::storage::generator::Box::new(self::#internal_module::#enumerator {
|
||||
next: self::#internal_module::#linkage::read_head(storage),
|
||||
fn enumerate<'a, S: #scrate::GenericStorage>(storage: &'a S) -> #scrate::storage::generator::Box<dyn Iterator<Item = (#kty, #typ)> + 'a> where
|
||||
#kty: 'a,
|
||||
#typ: 'a,
|
||||
{
|
||||
use self::#inner_module::{Utils, Enumerator};
|
||||
|
||||
#scrate::storage::generator::Box::new(Enumerator {
|
||||
next: Self::read_head(storage),
|
||||
storage,
|
||||
_data: #phantom_data::<#typ>::default(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -192,24 +192,33 @@ fn decl_store_extra_genesis(
|
||||
is_trait_needed = true;
|
||||
has_trait_field = true;
|
||||
}
|
||||
for t in ext::get_non_bound_serde_derive_types(type_infos.value_type, &traitinstance).into_iter() {
|
||||
for t in ext::get_non_bound_serde_derive_types(type_infos.value_type, &traitinstance) {
|
||||
serde_complete_bound.insert(t);
|
||||
}
|
||||
if let DeclStorageTypeInfosKind::Map { key_type, .. } = type_infos.kind {
|
||||
for t in ext::get_non_bound_serde_derive_types(key_type, &traitinstance).into_iter() {
|
||||
for t in ext::get_non_bound_serde_derive_types(key_type, &traitinstance) {
|
||||
serde_complete_bound.insert(t);
|
||||
}
|
||||
}
|
||||
let storage_type = type_infos.typ.clone();
|
||||
config_field.extend(quote!( pub #ident: #storage_type, ));
|
||||
config_field.extend(match type_infos.kind {
|
||||
DeclStorageTypeInfosKind::Simple => {
|
||||
quote!( pub #ident: #storage_type, )
|
||||
},
|
||||
DeclStorageTypeInfosKind::Map {key_type, .. } => {
|
||||
quote!( pub #ident: Vec<(#key_type, #storage_type)>, )
|
||||
},
|
||||
});
|
||||
opt_build = Some(build.as_ref().map(|b| &b.expr.content).map(|b|quote!( #b ))
|
||||
.unwrap_or_else(|| quote!( (|config: &GenesisConfig<#traitinstance>| config.#ident.clone()) )));
|
||||
|
||||
let fielddefault = default_value.inner.as_ref().map(|d| &d.expr).map(|d|
|
||||
if type_infos.is_option {
|
||||
quote!( #d.unwrap_or_default() )
|
||||
} else {
|
||||
quote!( #d )
|
||||
}).unwrap_or_else(|| quote!( Default::default() ));
|
||||
|
||||
config_field_default.extend(quote!( #ident: #fielddefault, ));
|
||||
} else {
|
||||
opt_build = build.as_ref().map(|b| &b.expr.content).map(|b| quote!( #b ));
|
||||
|
||||
@@ -136,11 +136,12 @@ macro_rules! for_each_tuple {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use parity_codec::Codec;
|
||||
use runtime_io::{with_externalities, Blake2Hasher};
|
||||
use runtime_primitives::BuildStorage;
|
||||
|
||||
pub trait Trait {
|
||||
type BlockNumber;
|
||||
type BlockNumber: Codec + Default;
|
||||
type Origin;
|
||||
}
|
||||
|
||||
@@ -160,6 +161,8 @@ mod tests {
|
||||
decl_storage! {
|
||||
trait Store for Module<T: Trait> as Example {
|
||||
pub Data get(data) build(|_| vec![(15u32, 42u64)]): linked_map u32 => u64;
|
||||
pub GenericData get(generic_data): linked_map T::BlockNumber => T::BlockNumber;
|
||||
pub GenericData2 get(generic_data2): linked_map T::BlockNumber => Option<T::BlockNumber>;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -223,7 +223,7 @@ pub trait EnumerableStorageMap<K: codec::Codec, V: codec::Codec>: StorageMap<K,
|
||||
fn head<S: Storage>(storage: &S) -> Option<K>;
|
||||
|
||||
/// Enumerate all elements in the map.
|
||||
fn enumerate<'a, S: Storage>(storage: &'a S) -> Box<dyn Iterator<Item = (K, V)> + 'a>;
|
||||
fn enumerate<'a, S: Storage>(storage: &'a S) -> Box<dyn Iterator<Item = (K, V)> + 'a> where K: 'a, V: 'a;
|
||||
}
|
||||
|
||||
// FIXME #1466 Remove this in favour of `decl_storage` macro.
|
||||
|
||||
@@ -345,7 +345,7 @@ pub trait EnumerableStorageMap<K: Codec, V: Codec>: StorageMap<K, V> {
|
||||
fn head() -> Option<K>;
|
||||
|
||||
/// Enumerate all elements in the map.
|
||||
fn enumerate() -> Box<dyn Iterator<Item = (K, V)>>;
|
||||
fn enumerate() -> Box<dyn Iterator<Item = (K, V)>> where K: 'static, V: 'static;
|
||||
}
|
||||
|
||||
impl<K: Codec, V: Codec, U> EnumerableStorageMap<K, V> for U where U: generator::EnumerableStorageMap<K, V> {
|
||||
@@ -353,7 +353,7 @@ impl<K: Codec, V: Codec, U> EnumerableStorageMap<K, V> for U where U: generator:
|
||||
<U as generator::EnumerableStorageMap<K, V>>::head(&RuntimeStorage)
|
||||
}
|
||||
|
||||
fn enumerate() -> Box<dyn Iterator<Item = (K, V)>> {
|
||||
fn enumerate() -> Box<dyn Iterator<Item = (K, V)>> where K: 'static, V: 'static {
|
||||
<U as generator::EnumerableStorageMap<K, V>>::enumerate(&RuntimeStorage)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user