Use optimized append and len storage methods in SRML. (#3071)

* expose len from codec to storage.

* refactor runtime with len and append.

* Undo example.

* Remove imports.

* Bump codec.

* Optionify.

* Make decode_len counscious.

* Refactor.

* Update srml/support/src/storage/hashed/generator.rs

Co-Authored-By: Bastian Köcher <bkchr@users.noreply.github.com>

* Update srml/support/src/storage/hashed/generator.rs

Co-Authored-By: Bastian Köcher <bkchr@users.noreply.github.com>

* Update srml/support/src/storage/hashed/generator.rs

Co-Authored-By: Bastian Köcher <bkchr@users.noreply.github.com>

* Update srml/support/src/storage/hashed/generator.rs

Co-Authored-By: Bastian Köcher <bkchr@users.noreply.github.com>

* Fix merge.

* fix some docs.

* Add NoDefault trait.

* Bump.

* Final nits.

* Update srml/support/src/traits.rs

* new approach toward len.

* re-create lock file.

* Fix build errors and Option handling.

* More test fix

* Use default for append as well.

* Fix runtime.

* Add support for linked_map

* More tweaks from review.

* Fix style

* Change api for none-values

* Bump.
This commit is contained in:
Kian Paimani
2019-08-27 19:39:05 +02:00
committed by Bastian Köcher
parent 99a7492dbf
commit 095c7de7ff
13 changed files with 573 additions and 179 deletions
+125 -9
View File
@@ -17,10 +17,11 @@
//! Stuff to do with the runtime's storage.
use crate::rstd::prelude::*;
use crate::rstd::borrow::Borrow;
use crate::rstd::{borrow::Borrow, iter::FromIterator};
use codec::{Codec, Encode, Decode, KeyedVec, EncodeAppend};
use hashed::generator::{HashedStorage, StorageHasher};
use unhashed::generator::UnhashedStorage;
use crate::traits::{StorageDefault, Len};
#[macro_use]
pub mod storage_items;
@@ -107,6 +108,8 @@ impl UnhashedStorage for RuntimeStorage {
pub trait StorageValue<T: Codec> {
/// The type that get/take return.
type Query;
/// Something that can provide the default value of this storage type.
type Default: StorageDefault<T>;
/// Get the storage key.
fn key() -> &'static [u8];
@@ -136,12 +139,39 @@ pub trait StorageValue<T: Codec> {
/// Append the given item to the value in the storage.
///
/// `T` is required to implement `codec::EncodeAppend`.
fn append<I: Encode>(items: &[I]) -> Result<(), &'static str>
where T: EncodeAppend<Item=I>;
fn append<'a, I, R>(items: R) -> Result<(), &'static str> where
I: 'a + Encode,
T: EncodeAppend<Item=I>,
R: IntoIterator<Item=&'a I>,
R::IntoIter: ExactSizeIterator;
/// Append the given items to the value in the storage.
///
/// `T` is required to implement `Codec::EncodeAppend`.
///
/// Upon any failure, it replaces `items` as the new value (assuming that the previous stored
/// data is simply corrupt and no longer usable).
///
/// ### WARNING
///
/// use with care; if your use-case is not _exactly_ as what this function is doing,
/// you should use append and sensibly handle failure within the runtime code if it happens.
fn append_or_put<'a, I, R>(items: R) where
I: 'a + Encode + Clone,
T: EncodeAppend<Item=I> + FromIterator<I>,
R: IntoIterator<Item=&'a I> + Clone,
R::IntoIter: ExactSizeIterator;
/// Read the length of the value in a fast way, without decoding the entire value.
///
/// `T` is required to implement `Codec::DecodeLength`.
fn decode_len() -> Result<usize, &'static str>
where T: codec::DecodeLength, T: Len;
}
impl<T: Codec, U> StorageValue<T> for U where U: hashed::generator::StorageValue<T> {
type Query = U::Query;
type Default = U::Default;
fn key() -> &'static [u8] {
<U as hashed::generator::StorageValue<T>>::key()
@@ -167,17 +197,35 @@ impl<T: Codec, U> StorageValue<T> for U where U: hashed::generator::StorageValue
fn take() -> Self::Query {
U::take(&mut RuntimeStorage)
}
fn append<I: Encode>(items: &[I]) -> Result<(), &'static str>
where T: EncodeAppend<Item=I>
fn append<'a, I, R>(items: R) -> Result<(), &'static str> where
I: 'a + Encode,
T: EncodeAppend<Item=I>,
R: IntoIterator<Item=&'a I>,
R::IntoIter: ExactSizeIterator,
{
U::append(items, &mut RuntimeStorage)
}
fn append_or_put<'a, I, R>(items: R) where
I: 'a + Encode + Clone,
T: EncodeAppend<Item=I> + FromIterator<I>,
R: IntoIterator<Item=&'a I> + Clone,
R::IntoIter: ExactSizeIterator,
{
U::append_or_put(items, &mut RuntimeStorage)
}
fn decode_len() -> Result<usize, &'static str>
where T: codec::DecodeLength, T: Len
{
U::decode_len(&mut RuntimeStorage)
}
}
/// A strongly-typed map in storage.
pub trait StorageMap<K: Codec, V: Codec> {
/// The type that get/take return.
type Query;
/// Something that can provide the default value of this storage type.
type Default: StorageDefault<V>;
/// Get the prefix key in storage.
fn prefix() -> &'static [u8];
@@ -213,6 +261,7 @@ pub trait StorageMap<K: Codec, V: Codec> {
impl<K: Codec, V: Codec, U> StorageMap<K, V> for U where U: hashed::generator::StorageMap<K, V> {
type Query = U::Query;
type Default = U::Default;
fn prefix() -> &'static [u8] {
<U as hashed::generator::StorageMap<K, V>>::prefix()
@@ -260,18 +309,85 @@ pub trait AppendableStorageMap<K: Codec, V: Codec>: StorageMap<K, V> {
/// Append the given item to the value in the storage.
///
/// `T` is required to implement `codec::EncodeAppend`.
fn append<KeyArg: Borrow<K>, I: Encode>(key: KeyArg, items: &[I]) -> Result<(), &'static str>
where V: EncodeAppend<Item=I>;
fn append<'a, KeyArg, I, R>(
key: KeyArg,
items: R,
) -> Result<(), &'static str> where
KeyArg: Borrow<K>,
I: 'a + codec::Encode,
V: EncodeAppend<Item=I>,
R: IntoIterator<Item=&'a I> + Clone,
R::IntoIter: ExactSizeIterator;
/// Append the given items to the value in the storage.
///
/// `T` is required to implement `codec::EncodeAppend`.
///
/// Upon any failure, it replaces `items` as the new value (assuming that the previous stored
/// data is simply corrupt and no longer usable).
///
/// WARNING: use with care; if your use-case is not _exactly_ as what this function is doing,
/// you should use append and sensibly handle failure within the runtime code if it happens.
fn append_or_insert<'a, KeyArg, I, R>(
key: KeyArg,
items: R,
) where
KeyArg: Borrow<K>,
I: 'a + codec::Encode + Clone,
V: codec::EncodeAppend<Item=I> + FromIterator<I>,
R: IntoIterator<Item=&'a I> + Clone,
R::IntoIter: ExactSizeIterator;
}
impl<K: Codec, V: Codec, U> AppendableStorageMap<K, V> for U
where U: hashed::generator::AppendableStorageMap<K, V>
{
fn append<KeyArg: Borrow<K>, I: Encode>(key: KeyArg, items: &[I]) -> Result<(), &'static str>
where V: EncodeAppend<Item=I>
fn append<'a, KeyArg, I, R>(
key: KeyArg,
items: R,
) -> Result<(), &'static str> where
KeyArg: Borrow<K>,
I: 'a + codec::Encode,
V: EncodeAppend<Item=I>,
R: IntoIterator<Item=&'a I> + Clone,
R::IntoIter: ExactSizeIterator,
{
U::append(key.borrow(), items, &mut RuntimeStorage)
}
fn append_or_insert<'a, KeyArg, I, R>(
key: KeyArg,
items: R,
) where
KeyArg: Borrow<K>,
I: 'a + codec::Encode + Clone,
V: codec::EncodeAppend<Item=I> + FromIterator<I>,
R: IntoIterator<Item=&'a I> + Clone,
R::IntoIter: ExactSizeIterator,
{
U::append_or_insert(key.borrow(), items, &mut RuntimeStorage)
}
}
/// A storage map with a decodable length.
pub trait DecodeLengthStorageMap<K: Codec, V: Codec>: StorageMap<K, V> {
/// Read the length of the value in a fast way, without decoding the entire value.
///
/// `T` is required to implement `Codec::DecodeLength`.
///
/// Has the same logic as [`StorageValue`](trait.StorageValue.html).
fn decode_len<KeyArg: Borrow<K>>(key: KeyArg) -> Result<usize, &'static str>
where V: codec::DecodeLength, V: Len;
}
impl <K: Codec, V: Codec, U> DecodeLengthStorageMap<K, V> for U
where U: hashed::generator::DecodeLengthStorageMap<K, V>
{
fn decode_len<KeyArg: Borrow<K>>(key: KeyArg) -> Result<usize, &'static str>
where V: codec::DecodeLength, V: Len
{
U::decode_len(key.borrow(), &mut RuntimeStorage)
}
}
/// A storage map that can be enumerated.