Use EncodeLike for storages traits (#3676)

* impl

* patch

* lock

* some refactor

* some avoided copy

* new api without ref for doublemap

* fix

* version bump

* fix

* point to incoming release

* use codec latest

* bumpd impl version

* fix unused

* fix

* Update srml/support/src/storage/mod.rs

Co-Authored-By: Bastian Köcher <bkchr@users.noreply.github.com>
This commit is contained in:
thiolliere
2019-10-01 19:45:24 +02:00
committed by Bastian Köcher
parent 83d4764d46
commit 53e0ddee4e
36 changed files with 489 additions and 465 deletions
@@ -16,7 +16,7 @@
use rstd::prelude::*;
use rstd::borrow::Borrow;
use codec::{Codec, Encode, EncodeAppend};
use codec::{Ref, FullCodec, FullEncode, Encode, EncodeLike, EncodeAppend};
use crate::{storage::{self, unhashed}, hash::StorageHasher};
/// Generator for `StorageDoubleMap` used by `decl_storage`.
@@ -39,7 +39,7 @@ use crate::{storage::{self, unhashed}, hash::StorageHasher};
/// If the key2s are not trusted (e.g. can be set by a user), a cryptographic `hasher` such as
/// `blake2_256` must be used for Hasher2. Otherwise, other items in storage with the same first
/// key can be compromised.
pub trait StorageDoubleMap<K1: Encode, K2: Encode, V: Codec> {
pub trait StorageDoubleMap<K1: FullEncode, K2: FullEncode, V: FullCodec> {
/// The type that get/take returns.
type Query;
@@ -59,10 +59,9 @@ pub trait StorageDoubleMap<K1: Encode, K2: Encode, V: Codec> {
fn from_query_to_optional_value(v: Self::Query) -> Option<V>;
/// Generate the first part of the key used in top storage.
fn storage_double_map_final_key1<KArg1>(k1: &KArg1) -> <Self::Hasher1 as StorageHasher>::Output
fn storage_double_map_final_key1<KArg1>(k1: KArg1) -> <Self::Hasher1 as StorageHasher>::Output
where
KArg1: ?Sized + Encode,
K1: Borrow<KArg1>,
KArg1: EncodeLike<K1>,
{
let mut final_key1 = Self::key1_prefix().to_vec();
k1.encode_to(&mut final_key1);
@@ -70,12 +69,10 @@ pub trait StorageDoubleMap<K1: Encode, K2: Encode, V: Codec> {
}
/// Generate the full key used in top storage.
fn storage_double_map_final_key<KArg1, KArg2>(k1: &KArg1, k2: &KArg2) -> Vec<u8>
fn storage_double_map_final_key<KArg1, KArg2>(k1: KArg1, k2: KArg2) -> Vec<u8>
where
KArg1: ?Sized + Encode,
KArg2: ?Sized + Encode,
K1: Borrow<KArg1>,
K2: Borrow<KArg2>,
KArg1: EncodeLike<K1>,
KArg2: EncodeLike<K2>,
{
let mut final_key = Self::storage_double_map_final_key1(k1).as_ref().to_vec();
final_key.extend_from_slice(k2.using_encoded(Self::Hasher2::hash).as_ref());
@@ -85,39 +82,33 @@ pub trait StorageDoubleMap<K1: Encode, K2: Encode, V: Codec> {
impl<K1, K2, V, G> storage::StorageDoubleMap<K1, K2, V> for G
where
K1: Encode,
K2: Encode,
V: Codec,
K1: FullEncode,
K2: FullEncode,
V: FullCodec,
G: StorageDoubleMap<K1, K2, V>,
{
type Query = G::Query;
fn exists<KArg1, KArg2>(k1: &KArg1, k2: &KArg2) -> bool
fn exists<KArg1, KArg2>(k1: KArg1, k2: KArg2) -> bool
where
K1: Borrow<KArg1>,
K2: Borrow<KArg2>,
KArg1: ?Sized + Encode,
KArg2: ?Sized + Encode,
KArg1: EncodeLike<K1>,
KArg2: EncodeLike<K2>,
{
unhashed::exists(&Self::storage_double_map_final_key(k1, k2))
}
fn get<KArg1, KArg2>(k1: &KArg1, k2: &KArg2) -> Self::Query
fn get<KArg1, KArg2>(k1: KArg1, k2: KArg2) -> Self::Query
where
K1: Borrow<KArg1>,
K2: Borrow<KArg2>,
KArg1: ?Sized + Encode,
KArg2: ?Sized + Encode,
KArg1: EncodeLike<K1>,
KArg2: EncodeLike<K2>,
{
G::from_optional_value_to_query(unhashed::get(&Self::storage_double_map_final_key(k1, k2)))
}
fn take<KArg1, KArg2>(k1: &KArg1, k2: &KArg2) -> Self::Query
fn take<KArg1, KArg2>(k1: KArg1, k2: KArg2) -> Self::Query
where
K1: Borrow<KArg1>,
K2: Borrow<KArg2>,
KArg1: ?Sized + Encode,
KArg2: ?Sized + Encode,
KArg1: EncodeLike<K1>,
KArg2: EncodeLike<K2>,
{
let final_key = Self::storage_double_map_final_key(k1, k2);
@@ -125,62 +116,57 @@ where
G::from_optional_value_to_query(value)
}
fn insert<KArg1, KArg2, VArg>(k1: &KArg1, k2: &KArg2, val: &VArg)
fn insert<KArg1, KArg2, VArg>(k1: KArg1, k2: KArg2, val: VArg)
where
K1: Borrow<KArg1>,
K2: Borrow<KArg2>,
V: Borrow<VArg>,
KArg1: ?Sized + Encode,
KArg2: ?Sized + Encode,
VArg: ?Sized + Encode,
KArg1: EncodeLike<K1>,
KArg2: EncodeLike<K2>,
VArg: EncodeLike<V>,
{
unhashed::put(&Self::storage_double_map_final_key(k1, k2), &val.borrow())
}
fn remove<KArg1, KArg2>(k1: &KArg1, k2: &KArg2)
fn remove<KArg1, KArg2>(k1: KArg1, k2: KArg2)
where
K1: Borrow<KArg1>,
K2: Borrow<KArg2>,
KArg1: ?Sized + Encode,
KArg2: ?Sized + Encode,
KArg1: EncodeLike<K1>,
KArg2: EncodeLike<K2>,
{
unhashed::kill(&Self::storage_double_map_final_key(k1, k2))
}
fn remove_prefix<KArg1>(k1: &KArg1) where KArg1: ?Sized + Encode, K1: Borrow<KArg1> {
fn remove_prefix<KArg1>(k1: KArg1) where KArg1: EncodeLike<K1> {
unhashed::kill_prefix(Self::storage_double_map_final_key1(k1).as_ref())
}
fn mutate<KArg1, KArg2, R, F>(k1: &KArg1, k2: &KArg2, f: F) -> R
fn mutate<KArg1, KArg2, R, F>(k1: KArg1, k2: KArg2, f: F) -> R
where
K1: Borrow<KArg1>,
K2: Borrow<KArg2>,
KArg1: ?Sized + Encode,
KArg2: ?Sized + Encode,
KArg1: EncodeLike<K1>,
KArg2: EncodeLike<K2>,
F: FnOnce(&mut Self::Query) -> R,
{
let mut val = G::get(k1, k2);
let final_key = Self::storage_double_map_final_key(k1, k2);
let mut val = G::from_optional_value_to_query(unhashed::get(final_key.as_ref()));
let ret = f(&mut val);
match G::from_query_to_optional_value(val) {
Some(ref val) => G::insert(k1, k2, val),
None => G::remove(k1, k2),
Some(ref val) => unhashed::put(final_key.as_ref(), val),
None => unhashed::kill(final_key.as_ref()),
}
ret
}
fn append<KArg1, KArg2, I>(
k1: &KArg1,
k2: &KArg2,
items: &[I],
fn append<Items, Item, EncodeLikeItem, KArg1, KArg2>(
k1: KArg1,
k2: KArg2,
items: Items,
) -> Result<(), &'static str>
where
K1: Borrow<KArg1>,
K2: Borrow<KArg2>,
KArg1: ?Sized + Encode,
KArg2: ?Sized + Encode,
I: codec::Encode,
V: EncodeAppend<Item=I>,
KArg1: EncodeLike<K1>,
KArg2: EncodeLike<K2>,
Item: Encode,
EncodeLikeItem: EncodeLike<Item>,
V: EncodeAppend<Item=Item>,
Items: IntoIterator<Item=EncodeLikeItem>,
Items::IntoIter: ExactSizeIterator
{
let final_key = Self::storage_double_map_final_key(k1, k2);
@@ -192,7 +178,7 @@ where
}
});
let new_val = V::append(
let new_val = V::append_or_new(
encoded_value,
items,
).map_err(|_| "Could not append given item")?;
@@ -200,4 +186,22 @@ where
Ok(())
}
fn append_or_insert<Items, Item, EncodeLikeItem, KArg1, KArg2>(
k1: KArg1,
k2: KArg2,
items: Items,
)
where
KArg1: EncodeLike<K1>,
KArg2: EncodeLike<K2>,
Item: Encode,
EncodeLikeItem: EncodeLike<Item>,
V: EncodeAppend<Item=Item>,
Items: IntoIterator<Item=EncodeLikeItem> + Clone + EncodeLike<V>,
Items::IntoIter: ExactSizeIterator
{
Self::append(Ref::from(&k1), Ref::from(&k2), items.clone())
.unwrap_or_else(|_| Self::insert(k1, k2, items));
}
}
@@ -14,12 +14,9 @@
// You should have received a copy of the GNU General Public License
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
use codec::{Codec, Encode, Decode};
use codec::{FullCodec, Encode, Decode, EncodeLike, Ref};
use crate::{storage::{self, unhashed}, hash::StorageHasher, traits::Len};
use rstd::{
borrow::Borrow,
marker::PhantomData,
};
use rstd::marker::PhantomData;
/// Generator for `StorageLinkedMap` used by `decl_storage`.
///
@@ -43,7 +40,7 @@ use rstd::{
///
/// If the keys are not trusted (e.g. can be set by a user), a cryptographic `hasher` such as
/// `blake2_256` must be used. Otherwise, other values in storage can be compromised.
pub trait StorageLinkedMap<K: Codec, V: Codec> {
pub trait StorageLinkedMap<K: FullCodec, V: FullCodec> {
/// The type that get/take returns.
type Query;
@@ -65,10 +62,10 @@ pub trait StorageLinkedMap<K: Codec, V: Codec> {
/// Generate the full key used in top storage.
fn storage_linked_map_final_key<KeyArg>(key: KeyArg) -> <Self::Hasher as StorageHasher>::Output
where
KeyArg: Borrow<K>,
KeyArg: EncodeLike<K>,
{
let mut final_key = Self::prefix().to_vec();
key.borrow().encode_to(&mut final_key);
key.encode_to(&mut final_key);
Self::Hasher::hash(&final_key)
}
@@ -96,13 +93,29 @@ impl<Key> Default for Linkage<Key> {
}
}
// Encode like a linkage.
#[derive(Encode)]
struct EncodeLikeLinkage<PKey: EncodeLike<Key>, NKey: EncodeLike<Key>, Key: Encode> {
// Previous element key in storage (None for the first element)
previous: Option<PKey>,
// Next element key in storage (None for the last element)
next: Option<NKey>,
// The key of the linkage this type encode to
phantom: core::marker::PhantomData<Key>,
}
/// A key-value pair iterator for enumerable map.
pub struct Enumerator<K: Codec, V: Codec, G: StorageLinkedMap<K, V>> {
pub struct Enumerator<K: FullCodec, V: FullCodec, G: StorageLinkedMap<K, V>> {
next: Option<K>,
_phantom: PhantomData<(G, V)>,
}
impl<K: Codec, V: Codec, G: StorageLinkedMap<K, V>> Iterator for Enumerator<K, V, G> {
impl<K, V, G> Iterator for Enumerator<K, V, G>
where
K: FullCodec,
V: FullCodec,
G: StorageLinkedMap<K, V>,
{
type Item = (K, V);
fn next(&mut self) -> Option<Self::Item> {
@@ -123,7 +136,12 @@ impl<K: Codec, V: Codec, G: StorageLinkedMap<K, V>> Iterator for Enumerator<K, V
///
/// Takes care of updating previous and next elements points
/// as well as updates head if the element is first or last.
fn remove_linkage<K: Codec, V: Codec, G: StorageLinkedMap<K, V>>(linkage: Linkage<K>) {
fn remove_linkage<K, V, G>(linkage: Linkage<K>)
where
K: FullCodec,
V: FullCodec,
G: StorageLinkedMap<K, V>,
{
let next_key = linkage.next.as_ref()
.map(G::storage_linked_map_final_key)
.map(|x| x.as_ref().to_vec());
@@ -140,7 +158,7 @@ fn remove_linkage<K: Codec, V: Codec, G: StorageLinkedMap<K, V>>(linkage: Linkag
unhashed::put(prev_key.as_ref(), &res);
} else {
// we were first so let's update the head
write_head::<_, _, G>(linkage.next.as_ref());
write_head::<_, _, _, G>(linkage.next.as_ref());
}
if let Some(next_key) = next_key {
// Update previous of next element
@@ -155,9 +173,9 @@ fn remove_linkage<K: Codec, V: Codec, G: StorageLinkedMap<K, V>>(linkage: Linkag
/// Read the contained data and it's linkage.
fn read_with_linkage<K, V, G>(key: &[u8]) -> Option<(V, Linkage<K>)>
where
K: Codec,
V: Codec,
G: StorageLinkedMap<K, V>
K: FullCodec,
V: FullCodec,
G: StorageLinkedMap<K, V>,
{
unhashed::get(key)
}
@@ -165,11 +183,12 @@ where
/// Generate linkage for newly inserted element.
///
/// Takes care of updating head and previous head's pointer.
fn new_head_linkage<K, V, G>(key: &K) -> Linkage<K>
fn new_head_linkage<KeyArg, K, V, G>(key: KeyArg) -> Linkage<K>
where
K: Codec,
V: Codec,
G: StorageLinkedMap<K, V>
KeyArg: EncodeLike<K>,
K: FullCodec,
V: FullCodec,
G: StorageLinkedMap<K, V>,
{
if let Some(head) = read_head::<_, _, G>() {
// update previous head predecessor
@@ -179,20 +198,22 @@ where
.expect("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");
unhashed::put(head_key.as_ref(), &(data, Linkage {
let new_linkage = EncodeLikeLinkage::<_, _, K> {
previous: Some(Ref::from(&key)),
next: linkage.next.as_ref(),
previous: Some(key),
}));
phantom: Default::default(),
};
unhashed::put(head_key.as_ref(), &(data, new_linkage));
}
// update to current head
write_head::<_, _, G>(Some(key));
write_head::<_, _, _, G>(Some(key));
// return linkage with pointer to previous head
let mut linkage = Linkage::default();
linkage.next = Some(head);
linkage
} else {
// we are first - update the head and produce empty linkage
write_head::<_, _, G>(Some(key));
write_head::<_, _, _, G>(Some(key));
Linkage::default()
}
}
@@ -200,9 +221,9 @@ where
/// Read current head pointer.
fn read_head<K, V, G>() -> Option<K>
where
K: Codec,
V: Codec,
G: StorageLinkedMap<K, V>
K: FullCodec,
V: FullCodec,
G: StorageLinkedMap<K, V>,
{
unhashed::get(G::storage_linked_map_final_head_key().as_ref())
}
@@ -210,35 +231,41 @@ where
/// Overwrite current head pointer.
///
/// If `None` is given head is removed from storage.
fn write_head<K, V, G>(head: Option<&K>)
fn write_head<KeyArg, K, V, G>(head: Option<KeyArg>)
where
K: Codec,
V: Codec,
G: StorageLinkedMap<K, V>
KeyArg: EncodeLike<K>,
K: FullCodec,
V: FullCodec,
G: StorageLinkedMap<K, V>,
{
match head {
match head.as_ref() {
Some(head) => unhashed::put(G::storage_linked_map_final_head_key().as_ref(), head),
None => unhashed::kill(G::storage_linked_map_final_head_key().as_ref()),
}
}
impl<K: Codec, V: Codec, G: StorageLinkedMap<K, V>> storage::StorageLinkedMap<K, V> for G {
impl<K, V, G> storage::StorageLinkedMap<K, V> for G
where
K: FullCodec,
V: FullCodec,
G: StorageLinkedMap<K, V>,
{
type Query = G::Query;
type Enumerator = Enumerator<K, V, Self>;
fn exists<KeyArg: Borrow<K>>(key: KeyArg) -> bool {
fn exists<KeyArg: EncodeLike<K>>(key: KeyArg) -> bool {
unhashed::exists(Self::storage_linked_map_final_key(key).as_ref())
}
fn get<KeyArg: Borrow<K>>(key: KeyArg) -> Self::Query {
fn get<KeyArg: EncodeLike<K>>(key: KeyArg) -> Self::Query {
let val = unhashed::get(Self::storage_linked_map_final_key(key).as_ref());
G::from_optional_value_to_query(val)
}
fn swap<KeyArg1: Borrow<K>, KeyArg2: Borrow<K>>(key1: KeyArg1, key2: KeyArg2) {
let final_key1 = Self::storage_linked_map_final_key(key1.borrow());
let final_key2 = Self::storage_linked_map_final_key(key2.borrow());
fn swap<KeyArg1: EncodeLike<K>, KeyArg2: EncodeLike<K>>(key1: KeyArg1, key2: KeyArg2) {
let final_key1 = Self::storage_linked_map_final_key(Ref::from(&key1));
let final_key2 = Self::storage_linked_map_final_key(Ref::from(&key2));
let full_value_1 = read_with_linkage::<_, _, G>(final_key1.as_ref());
let full_value_2 = read_with_linkage::<_, _, G>(final_key2.as_ref());
@@ -251,13 +278,13 @@ impl<K: Codec, V: Codec, G: StorageLinkedMap<K, V>> storage::StorageLinkedMap<K,
// Remove key and insert the new one.
(Some((value, _linkage)), None) => {
Self::remove(key1);
let linkage = new_head_linkage::<_, _, G>(key2.borrow());
let linkage = new_head_linkage::<_, _, _, G>(key2);
unhashed::put(final_key2.as_ref(), &(value, linkage));
}
// Remove key and insert the new one.
(None, Some((value, _linkage))) => {
Self::remove(key2);
let linkage = new_head_linkage::<_, _, G>(key1.borrow());
let linkage = new_head_linkage::<_, _, _, G>(key1);
unhashed::put(final_key1.as_ref(), &(value, linkage));
}
// No-op.
@@ -265,37 +292,23 @@ impl<K: Codec, V: Codec, G: StorageLinkedMap<K, V>> storage::StorageLinkedMap<K,
}
}
fn insert<KeyArg: Borrow<K>, ValArg: Borrow<V>>(key: KeyArg, val: ValArg) {
let final_key = Self::storage_linked_map_final_key(key.borrow());
fn insert<KeyArg: EncodeLike<K>, ValArg: EncodeLike<V>>(key: KeyArg, val: ValArg) {
let final_key = Self::storage_linked_map_final_key(Ref::from(&key));
let linkage = match read_with_linkage::<_, _, G>(final_key.as_ref()) {
// overwrite but reuse existing linkage
Some((_data, linkage)) => linkage,
// create new linkage
None => new_head_linkage::<_, _, G>(key.borrow()),
None => new_head_linkage::<_, _, _, G>(key),
};
unhashed::put(final_key.as_ref(), &(val.borrow(), linkage))
unhashed::put(final_key.as_ref(), &(val, linkage))
}
fn insert_ref<KeyArg: Borrow<K>, ValArg: ?Sized + Encode>(key: KeyArg, val: &ValArg)
where
V: AsRef<ValArg>
{
let final_key = Self::storage_linked_map_final_key(key.borrow());
let linkage = match read_with_linkage::<_, _, G>(final_key.as_ref()) {
// overwrite but reuse existing linkage
Some((_data, linkage)) => linkage,
// create new linkage
None => new_head_linkage::<_, _, G>(key.borrow()),
};
unhashed::put(final_key.as_ref(), &(&val, &linkage))
}
fn remove<KeyArg: Borrow<K>>(key: KeyArg) {
fn remove<KeyArg: EncodeLike<K>>(key: KeyArg) {
G::take(key);
}
fn mutate<KeyArg: Borrow<K>, R, F: FnOnce(&mut Self::Query) -> R>(key: KeyArg, f: F) -> R {
let final_key = Self::storage_linked_map_final_key(key.borrow());
fn mutate<KeyArg: EncodeLike<K>, R, F: FnOnce(&mut Self::Query) -> R>(key: KeyArg, f: F) -> R {
let final_key = Self::storage_linked_map_final_key(Ref::from(&key));
let (mut val, _linkage) = read_with_linkage::<_, _, G>(final_key.as_ref())
.map(|(data, linkage)| (G::from_optional_value_to_query(Some(data)), Some(linkage)))
@@ -303,13 +316,13 @@ impl<K: Codec, V: Codec, G: StorageLinkedMap<K, V>> storage::StorageLinkedMap<K,
let ret = f(&mut val);
match G::from_query_to_optional_value(val) {
Some(ref val) => G::insert(key.borrow(), val),
None => G::remove(key.borrow()),
Some(ref val) => G::insert(key, val),
None => G::remove(key),
}
ret
}
fn take<KeyArg: Borrow<K>>(key: KeyArg) -> Self::Query {
fn take<KeyArg: EncodeLike<K>>(key: KeyArg) -> Self::Query {
let final_key = Self::storage_linked_map_final_key(key);
let full_value: Option<(V, Linkage<K>)> = unhashed::take(final_key.as_ref());
@@ -333,7 +346,7 @@ impl<K: Codec, V: Codec, G: StorageLinkedMap<K, V>> storage::StorageLinkedMap<K,
read_head::<_, _, G>()
}
fn decode_len<KeyArg: Borrow<K>>(key: KeyArg) -> Result<usize, &'static str>
fn decode_len<KeyArg: EncodeLike<K>>(key: KeyArg) -> Result<usize, &'static str>
where V: codec::DecodeLength + Len
{
let key = Self::storage_linked_map_final_key(key);
@@ -17,7 +17,7 @@
#[cfg(not(feature = "std"))]
use rstd::prelude::*;
use rstd::borrow::Borrow;
use codec::{Codec, Encode};
use codec::{FullCodec, FullEncode, Encode, EncodeLike, Ref, EncodeAppend};
use crate::{storage::{self, unhashed}, hash::StorageHasher, traits::Len};
/// Generator for `StorageMap` used by `decl_storage`.
@@ -31,7 +31,7 @@ use crate::{storage::{self, unhashed}, hash::StorageHasher, traits::Len};
///
/// If the keys are not trusted (e.g. can be set by a user), a cryptographic `hasher` such as
/// `blake2_256` must be used. Otherwise, other values in storage can be compromised.
pub trait StorageMap<K: Codec, V: Codec> {
pub trait StorageMap<K: FullEncode, V: FullCodec> {
/// The type that get/take returns.
type Query;
@@ -50,7 +50,7 @@ pub trait StorageMap<K: Codec, V: Codec> {
/// Generate the full key used in top storage.
fn storage_map_final_key<KeyArg>(key: KeyArg) -> <Self::Hasher as StorageHasher>::Output
where
KeyArg: Borrow<K>,
KeyArg: EncodeLike<K>,
{
let mut final_key = Self::prefix().to_vec();
key.borrow().encode_to(&mut final_key);
@@ -58,14 +58,14 @@ pub trait StorageMap<K: Codec, V: Codec> {
}
}
impl<K: Codec, V: Codec, G: StorageMap<K, V>> storage::StorageMap<K, V> for G {
impl<K: FullEncode, V: FullCodec, G: StorageMap<K, V>> storage::StorageMap<K, V> for G {
type Query = G::Query;
fn hashed_key_for<KeyArg: Borrow<K>>(key: KeyArg) -> Vec<u8> {
fn hashed_key_for<KeyArg: EncodeLike<K>>(key: KeyArg) -> Vec<u8> {
Self::storage_map_final_key(key).as_ref().to_vec()
}
fn swap<KeyArg1: Borrow<K>, KeyArg2: Borrow<K>>(key1: KeyArg1, key2: KeyArg2) {
fn swap<KeyArg1: EncodeLike<K>, KeyArg2: EncodeLike<K>>(key1: KeyArg1, key2: KeyArg2) {
let k1 = Self::storage_map_final_key(key1);
let k2 = Self::storage_map_final_key(key2);
@@ -82,52 +82,48 @@ impl<K: Codec, V: Codec, G: StorageMap<K, V>> storage::StorageMap<K, V> for G {
}
}
fn exists<KeyArg: Borrow<K>>(key: KeyArg) -> bool {
fn exists<KeyArg: EncodeLike<K>>(key: KeyArg) -> bool {
unhashed::exists(Self::storage_map_final_key(key).as_ref())
}
fn get<KeyArg: Borrow<K>>(key: KeyArg) -> Self::Query {
fn get<KeyArg: EncodeLike<K>>(key: KeyArg) -> Self::Query {
G::from_optional_value_to_query(unhashed::get(Self::storage_map_final_key(key).as_ref()))
}
fn insert<KeyArg: Borrow<K>, ValArg: Borrow<V>>(key: KeyArg, val: ValArg) {
fn insert<KeyArg: EncodeLike<K>, ValArg: EncodeLike<V>>(key: KeyArg, val: ValArg) {
unhashed::put(Self::storage_map_final_key(key).as_ref(), &val.borrow())
}
fn insert_ref<KeyArg: Borrow<K>, ValArg: ?Sized + Encode>(key: KeyArg, val: &ValArg)
where V: AsRef<ValArg>
{
val.using_encoded(|b| unhashed::put_raw(Self::storage_map_final_key(key).as_ref(), b))
}
fn remove<KeyArg: Borrow<K>>(key: KeyArg) {
fn remove<KeyArg: EncodeLike<K>>(key: KeyArg) {
unhashed::kill(Self::storage_map_final_key(key).as_ref())
}
fn mutate<KeyArg: Borrow<K>, R, F: FnOnce(&mut Self::Query) -> R>(key: KeyArg, f: F) -> R {
let mut val = G::get(key.borrow());
fn mutate<KeyArg: EncodeLike<K>, R, F: FnOnce(&mut Self::Query) -> R>(key: KeyArg, f: F) -> R {
let final_key = Self::storage_map_final_key(key);
let mut val = G::from_optional_value_to_query(unhashed::get(final_key.as_ref()));
let ret = f(&mut val);
match G::from_query_to_optional_value(val) {
Some(ref val) => G::insert(key, val),
None => G::remove(key),
Some(ref val) => unhashed::put(final_key.as_ref(), &val.borrow()),
None => unhashed::kill(final_key.as_ref()),
}
ret
}
fn take<KeyArg: Borrow<K>>(key: KeyArg) -> Self::Query {
fn take<KeyArg: EncodeLike<K>>(key: KeyArg) -> Self::Query {
let key = Self::storage_map_final_key(key);
let value = unhashed::take(key.as_ref());
G::from_optional_value_to_query(value)
}
fn append<'a, I, R, KeyArg>(key: KeyArg, items: R) -> Result<(), &'static str>
fn append<Items, Item, EncodeLikeItem, KeyArg>(key: KeyArg, items: Items) -> Result<(), &'static str>
where
KeyArg: Borrow<K>,
I: 'a + codec::Encode,
V: codec::EncodeAppend<Item=I>,
R: IntoIterator<Item=&'a I>,
R::IntoIter: ExactSizeIterator,
KeyArg: EncodeLike<K>,
Item: Encode,
EncodeLikeItem: EncodeLike<Item>,
V: EncodeAppend<Item=Item>,
Items: IntoIterator<Item=EncodeLikeItem>,
Items::IntoIter: ExactSizeIterator,
{
let key = Self::storage_map_final_key(key);
let encoded_value = unhashed::get_raw(key.as_ref())
@@ -138,7 +134,7 @@ impl<K: Codec, V: Codec, G: StorageMap<K, V>> storage::StorageMap<K, V> for G {
}
});
let new_val = V::append(
let new_val = V::append_or_new(
encoded_value,
items,
).map_err(|_| "Could not append given item")?;
@@ -146,19 +142,20 @@ impl<K: Codec, V: Codec, G: StorageMap<K, V>> storage::StorageMap<K, V> for G {
Ok(())
}
fn append_or_insert<'a, I, R, KeyArg>(key: KeyArg, items: R)
fn append_or_insert<Items, Item, EncodeLikeItem, KeyArg>(key: KeyArg, items: Items)
where
KeyArg: Borrow<K>,
I: 'a + codec::Encode + Clone,
V: codec::EncodeAppend<Item=I> + crate::rstd::iter::FromIterator<I>,
R: IntoIterator<Item=&'a I> + Clone,
R::IntoIter: ExactSizeIterator,
KeyArg: EncodeLike<K>,
Item: Encode,
EncodeLikeItem: EncodeLike<Item>,
V: EncodeAppend<Item=Item>,
Items: IntoIterator<Item=EncodeLikeItem> + Clone + EncodeLike<V>,
Items::IntoIter: ExactSizeIterator,
{
Self::append(key.borrow(), items.clone())
.unwrap_or_else(|_| Self::insert(key, &items.into_iter().cloned().collect()));
Self::append(Ref::from(&key), items.clone())
.unwrap_or_else(|_| Self::insert(key, items));
}
fn decode_len<KeyArg: Borrow<K>>(key: KeyArg) -> Result<usize, &'static str>
fn decode_len<KeyArg: EncodeLike<K>>(key: KeyArg) -> Result<usize, &'static str>
where V: codec::DecodeLength + Len
{
let key = Self::storage_map_final_key(key);
@@ -16,8 +16,7 @@
#[cfg(not(feature = "std"))]
use rstd::prelude::*;
use rstd::{borrow::Borrow, iter::FromIterator};
use codec::{Codec, Encode};
use codec::{FullCodec, Encode, EncodeAppend, EncodeLike};
use crate::{storage::{self, unhashed}, hash::{Twox128, StorageHasher}, traits::Len};
/// Generator for `StorageValue` used by `decl_storage`.
@@ -26,7 +25,7 @@ use crate::{storage::{self, unhashed}, hash::{Twox128, StorageHasher}, traits::L
/// ```nocompile
/// Twox128(unhashed_key)
/// ```
pub trait StorageValue<T: Codec> {
pub trait StorageValue<T: FullCodec> {
/// The type that get/take returns.
type Query;
@@ -45,7 +44,7 @@ pub trait StorageValue<T: Codec> {
}
}
impl<T: Codec, G: StorageValue<T>> storage::StorageValue<T> for G {
impl<T: FullCodec, G: StorageValue<T>> storage::StorageValue<T> for G {
type Query = G::Query;
fn hashed_key() -> [u8; 16] {
@@ -61,12 +60,8 @@ impl<T: Codec, G: StorageValue<T>> storage::StorageValue<T> for G {
G::from_optional_value_to_query(value)
}
fn put<Arg: Borrow<T>>(val: Arg) {
unhashed::put(&Self::storage_value_final_key(), val.borrow())
}
fn put_ref<Arg: ?Sized + Encode>(val: &Arg) where T: AsRef<Arg> {
val.using_encoded(|b| unhashed::put_raw(&Self::storage_value_final_key(), b))
fn put<Arg: EncodeLike<T>>(val: Arg) {
unhashed::put(&Self::storage_value_final_key(), &val)
}
fn kill() {
@@ -96,12 +91,13 @@ impl<T: Codec, G: StorageValue<T>> storage::StorageValue<T> for G {
/// Append the given items to the value in the storage.
///
/// `T` is required to implement `codec::EncodeAppend`.
fn append<'a, I, R>(items: R) -> Result<(), &'static str>
fn append<Items, Item, EncodeLikeItem>(items: Items) -> Result<(), &'static str>
where
I: 'a + codec::Encode,
T: codec::EncodeAppend<Item=I>,
R: IntoIterator<Item=&'a I>,
R::IntoIter: ExactSizeIterator,
Item: Encode,
EncodeLikeItem: EncodeLike<Item>,
T: EncodeAppend<Item=Item>,
Items: IntoIterator<Item=EncodeLikeItem>,
Items::IntoIter: ExactSizeIterator,
{
let key = Self::storage_value_final_key();
let encoded_value = unhashed::get_raw(&key)
@@ -112,7 +108,7 @@ impl<T: Codec, G: StorageValue<T>> storage::StorageValue<T> for G {
}
});
let new_val = T::append(
let new_val = T::append_or_new(
encoded_value,
items,
).map_err(|_| "Could not append given item")?;
@@ -124,15 +120,14 @@ impl<T: Codec, G: StorageValue<T>> storage::StorageValue<T> for G {
/// old (presumably corrupt) value is replaced with the given `items`.
///
/// `T` is required to implement `codec::EncodeAppend`.
fn append_or_put<'a, I, R>(items: R)
where
I: 'a + codec::Encode + Clone,
T: codec::EncodeAppend<Item=I> + FromIterator<I>,
R: IntoIterator<Item=&'a I> + Clone,
R::IntoIter: ExactSizeIterator,
fn append_or_put<Items, Item, EncodeLikeItem>(items: Items) where
Item: Encode,
EncodeLikeItem: EncodeLike<Item>,
T: EncodeAppend<Item=Item>,
Items: IntoIterator<Item=EncodeLikeItem> + Clone + EncodeLike<T>,
Items::IntoIter: ExactSizeIterator
{
Self::append(items.clone())
.unwrap_or_else(|_| Self::put(&items.into_iter().cloned().collect()));
Self::append(items.clone()).unwrap_or_else(|_| Self::put(items));
}
/// Read the length of the value in a fast way, without decoding the entire value.