mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-27 08:07:58 +00:00
Run cargo fmt on the whole code base (#9394)
* Run cargo fmt on the whole code base * Second run * Add CI check * Fix compilation * More unnecessary braces * Handle weights * Use --all * Use correct attributes... * Fix UI tests * AHHHHHHHHH * 🤦 * Docs * Fix compilation * 🤷 * Please stop * 🤦 x 2 * More * make rustfmt.toml consistent with polkadot Co-authored-by: André Silva <andrerfosilva@gmail.com>
This commit is contained in:
@@ -17,15 +17,12 @@
|
||||
|
||||
//! Traits, types and structs to support a bounded BTreeMap.
|
||||
|
||||
use crate::{storage::StorageDecodeLength, traits::Get};
|
||||
use codec::{Decode, Encode, MaxEncodedLen};
|
||||
use sp_std::{
|
||||
borrow::Borrow, collections::btree_map::BTreeMap, convert::TryFrom, fmt, marker::PhantomData,
|
||||
ops::Deref,
|
||||
};
|
||||
use crate::{
|
||||
storage::StorageDecodeLength,
|
||||
traits::Get,
|
||||
};
|
||||
use codec::{Encode, Decode, MaxEncodedLen};
|
||||
|
||||
/// A bounded map based on a B-Tree.
|
||||
///
|
||||
@@ -46,7 +43,7 @@ where
|
||||
fn decode<I: codec::Input>(input: &mut I) -> Result<Self, codec::Error> {
|
||||
let inner = BTreeMap::<K, V>::decode(input)?;
|
||||
if inner.len() > S::get() as usize {
|
||||
return Err("BoundedBTreeMap exceeds its limit".into());
|
||||
return Err("BoundedBTreeMap exceeds its limit".into())
|
||||
}
|
||||
Ok(Self(inner, PhantomData))
|
||||
}
|
||||
@@ -280,7 +277,9 @@ where
|
||||
type Error = ();
|
||||
|
||||
fn try_from(value: BTreeMap<K, V>) -> Result<Self, Self::Error> {
|
||||
(value.len() <= Self::bound()).then(move || BoundedBTreeMap(value, PhantomData)).ok_or(())
|
||||
(value.len() <= Self::bound())
|
||||
.then(move || BoundedBTreeMap(value, PhantomData))
|
||||
.ok_or(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -303,9 +302,9 @@ impl<K, V, S> codec::EncodeLike<BTreeMap<K, V>> for BoundedBTreeMap<K, V, S> whe
|
||||
#[cfg(test)]
|
||||
pub mod test {
|
||||
use super::*;
|
||||
use crate::Twox128;
|
||||
use sp_io::TestExternalities;
|
||||
use sp_std::convert::TryInto;
|
||||
use crate::Twox128;
|
||||
|
||||
crate::parameter_types! {
|
||||
pub const Seven: u32 = 7;
|
||||
|
||||
@@ -17,15 +17,12 @@
|
||||
|
||||
//! Traits, types and structs to support a bounded `BTreeSet`.
|
||||
|
||||
use crate::{storage::StorageDecodeLength, traits::Get};
|
||||
use codec::{Decode, Encode, MaxEncodedLen};
|
||||
use sp_std::{
|
||||
borrow::Borrow, collections::btree_set::BTreeSet, convert::TryFrom, fmt, marker::PhantomData,
|
||||
ops::Deref,
|
||||
};
|
||||
use crate::{
|
||||
storage::StorageDecodeLength,
|
||||
traits::Get,
|
||||
};
|
||||
use codec::{Encode, Decode, MaxEncodedLen};
|
||||
|
||||
/// A bounded set based on a B-Tree.
|
||||
///
|
||||
@@ -45,7 +42,7 @@ where
|
||||
fn decode<I: codec::Input>(input: &mut I) -> Result<Self, codec::Error> {
|
||||
let inner = BTreeSet::<T>::decode(input)?;
|
||||
if inner.len() > S::get() as usize {
|
||||
return Err("BoundedBTreeSet exceeds its limit".into());
|
||||
return Err("BoundedBTreeSet exceeds its limit".into())
|
||||
}
|
||||
Ok(Self(inner, PhantomData))
|
||||
}
|
||||
@@ -266,7 +263,9 @@ where
|
||||
type Error = ();
|
||||
|
||||
fn try_from(value: BTreeSet<T>) -> Result<Self, Self::Error> {
|
||||
(value.len() <= Self::bound()).then(move || BoundedBTreeSet(value, PhantomData)).ok_or(())
|
||||
(value.len() <= Self::bound())
|
||||
.then(move || BoundedBTreeSet(value, PhantomData))
|
||||
.ok_or(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -281,16 +280,14 @@ impl<T, S> codec::DecodeLength for BoundedBTreeSet<T, S> {
|
||||
|
||||
impl<T, S> StorageDecodeLength for BoundedBTreeSet<T, S> {}
|
||||
|
||||
impl<T, S> codec::EncodeLike<BTreeSet<T>> for BoundedBTreeSet<T, S> where
|
||||
BTreeSet<T>: Encode
|
||||
{}
|
||||
impl<T, S> codec::EncodeLike<BTreeSet<T>> for BoundedBTreeSet<T, S> where BTreeSet<T>: Encode {}
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod test {
|
||||
use super::*;
|
||||
use crate::Twox128;
|
||||
use sp_io::TestExternalities;
|
||||
use sp_std::convert::TryInto;
|
||||
use crate::Twox128;
|
||||
|
||||
crate::parameter_types! {
|
||||
pub const Seven: u32 = 7;
|
||||
|
||||
@@ -18,17 +18,16 @@
|
||||
//! Traits, types and structs to support putting a bounded vector into storage, as a raw value, map
|
||||
//! or a double map.
|
||||
|
||||
use sp_std::prelude::*;
|
||||
use sp_std::{convert::TryFrom, fmt, marker::PhantomData};
|
||||
use codec::{Encode, Decode, EncodeLike, MaxEncodedLen};
|
||||
use crate::{
|
||||
storage::{StorageDecodeLength, StorageTryAppend},
|
||||
traits::Get,
|
||||
};
|
||||
use codec::{Decode, Encode, EncodeLike, MaxEncodedLen};
|
||||
use core::{
|
||||
ops::{Deref, Index, IndexMut},
|
||||
slice::SliceIndex,
|
||||
};
|
||||
use crate::{
|
||||
traits::Get,
|
||||
storage::{StorageDecodeLength, StorageTryAppend},
|
||||
};
|
||||
use sp_std::{convert::TryFrom, fmt, marker::PhantomData, prelude::*};
|
||||
|
||||
/// A bounded vector.
|
||||
///
|
||||
@@ -71,7 +70,7 @@ impl<T: Decode, S: Get<u32>> Decode for BoundedVec<T, S> {
|
||||
fn decode<I: codec::Input>(input: &mut I) -> Result<Self, codec::Error> {
|
||||
let inner = Vec::<T>::decode(input)?;
|
||||
if inner.len() > S::get() as usize {
|
||||
return Err("BoundedVec exceeds its limit".into());
|
||||
return Err("BoundedVec exceeds its limit".into())
|
||||
}
|
||||
Ok(Self(inner, PhantomData))
|
||||
}
|
||||
@@ -341,9 +340,9 @@ where
|
||||
#[cfg(test)]
|
||||
pub mod test {
|
||||
use super::*;
|
||||
use crate::Twox128;
|
||||
use sp_io::TestExternalities;
|
||||
use sp_std::convert::TryInto;
|
||||
use crate::Twox128;
|
||||
|
||||
crate::parameter_types! {
|
||||
pub const Seven: u32 = 7;
|
||||
|
||||
@@ -21,23 +21,17 @@
|
||||
// NOTE: could replace unhashed by having only one kind of storage (top trie being the child info
|
||||
// of null length parent storage key).
|
||||
|
||||
use crate::sp_std::prelude::*;
|
||||
use codec::{Codec, Encode, Decode};
|
||||
pub use sp_core::storage::{ChildInfo, ChildType};
|
||||
pub use crate::sp_io::KillStorageResult;
|
||||
use crate::sp_std::prelude::*;
|
||||
use codec::{Codec, Decode, Encode};
|
||||
pub use sp_core::storage::{ChildInfo, ChildType};
|
||||
|
||||
/// Return the value of the item in storage under `key`, or `None` if there is no explicit entry.
|
||||
pub fn get<T: Decode + Sized>(
|
||||
child_info: &ChildInfo,
|
||||
key: &[u8],
|
||||
) -> Option<T> {
|
||||
pub fn get<T: Decode + Sized>(child_info: &ChildInfo, key: &[u8]) -> Option<T> {
|
||||
match child_info.child_type() {
|
||||
ChildType::ParentKeyId => {
|
||||
let storage_key = child_info.storage_key();
|
||||
sp_io::default_child_storage::get(
|
||||
storage_key,
|
||||
key,
|
||||
).and_then(|v| {
|
||||
sp_io::default_child_storage::get(storage_key, key).and_then(|v| {
|
||||
Decode::decode(&mut &v[..]).map(Some).unwrap_or_else(|_| {
|
||||
// TODO #3700: error should be handleable.
|
||||
crate::runtime_print!(
|
||||
@@ -54,20 +48,13 @@ pub fn get<T: Decode + Sized>(
|
||||
|
||||
/// Return the value of the item in storage under `key`, or the type's default if there is no
|
||||
/// explicit entry.
|
||||
pub fn get_or_default<T: Decode + Sized + Default>(
|
||||
child_info: &ChildInfo,
|
||||
key: &[u8],
|
||||
) -> T {
|
||||
pub fn get_or_default<T: Decode + Sized + Default>(child_info: &ChildInfo, key: &[u8]) -> T {
|
||||
get(child_info, key).unwrap_or_else(Default::default)
|
||||
}
|
||||
|
||||
/// Return the value of the item in storage under `key`, or `default_value` if there is no
|
||||
/// explicit entry.
|
||||
pub fn get_or<T: Decode + Sized>(
|
||||
child_info: &ChildInfo,
|
||||
key: &[u8],
|
||||
default_value: T,
|
||||
) -> T {
|
||||
pub fn get_or<T: Decode + Sized>(child_info: &ChildInfo, key: &[u8], default_value: T) -> T {
|
||||
get(child_info, key).unwrap_or(default_value)
|
||||
}
|
||||
|
||||
@@ -82,27 +69,16 @@ pub fn get_or_else<T: Decode + Sized, F: FnOnce() -> T>(
|
||||
}
|
||||
|
||||
/// Put `value` in storage under `key`.
|
||||
pub fn put<T: Encode>(
|
||||
child_info: &ChildInfo,
|
||||
key: &[u8],
|
||||
value: &T,
|
||||
) {
|
||||
pub fn put<T: Encode>(child_info: &ChildInfo, key: &[u8], value: &T) {
|
||||
match child_info.child_type() {
|
||||
ChildType::ParentKeyId => value.using_encoded(|slice|
|
||||
sp_io::default_child_storage::set(
|
||||
child_info.storage_key(),
|
||||
key,
|
||||
slice,
|
||||
)
|
||||
),
|
||||
ChildType::ParentKeyId => value.using_encoded(|slice| {
|
||||
sp_io::default_child_storage::set(child_info.storage_key(), key, slice)
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
/// Remove `key` from storage, returning its value if it had an explicit entry or `None` otherwise.
|
||||
pub fn take<T: Decode + Sized>(
|
||||
child_info: &ChildInfo,
|
||||
key: &[u8],
|
||||
) -> Option<T> {
|
||||
pub fn take<T: Decode + Sized>(child_info: &ChildInfo, key: &[u8]) -> Option<T> {
|
||||
let r = get(child_info, key);
|
||||
if r.is_some() {
|
||||
kill(child_info, key);
|
||||
@@ -112,20 +88,13 @@ pub fn take<T: Decode + Sized>(
|
||||
|
||||
/// Remove `key` from storage, returning its value, or, if there was no explicit entry in storage,
|
||||
/// the default for its type.
|
||||
pub fn take_or_default<T: Codec + Sized + Default>(
|
||||
child_info: &ChildInfo,
|
||||
key: &[u8],
|
||||
) -> T {
|
||||
pub fn take_or_default<T: Codec + Sized + Default>(child_info: &ChildInfo, key: &[u8]) -> T {
|
||||
take(child_info, key).unwrap_or_else(Default::default)
|
||||
}
|
||||
|
||||
/// Return the value of the item in storage under `key`, or `default_value` if there is no
|
||||
/// explicit entry. Ensure there is no explicit entry on return.
|
||||
pub fn take_or<T: Codec + Sized>(
|
||||
child_info: &ChildInfo,
|
||||
key: &[u8],
|
||||
default_value: T,
|
||||
) -> T {
|
||||
pub fn take_or<T: Codec + Sized>(child_info: &ChildInfo, key: &[u8], default_value: T) -> T {
|
||||
take(child_info, key).unwrap_or(default_value)
|
||||
}
|
||||
|
||||
@@ -140,15 +109,11 @@ pub fn take_or_else<T: Codec + Sized, F: FnOnce() -> T>(
|
||||
}
|
||||
|
||||
/// Check to see if `key` has an explicit entry in storage.
|
||||
pub fn exists(
|
||||
child_info: &ChildInfo,
|
||||
key: &[u8],
|
||||
) -> bool {
|
||||
pub fn exists(child_info: &ChildInfo, key: &[u8]) -> bool {
|
||||
match child_info.child_type() {
|
||||
ChildType::ParentKeyId => sp_io::default_child_storage::read(
|
||||
child_info.storage_key(),
|
||||
key, &mut [0;0][..], 0,
|
||||
).is_some(),
|
||||
ChildType::ParentKeyId =>
|
||||
sp_io::default_child_storage::read(child_info.storage_key(), key, &mut [0; 0][..], 0)
|
||||
.is_some(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -171,86 +136,50 @@ pub fn exists(
|
||||
/// not make much sense because it is not cumulative when called inside the same block.
|
||||
/// Use this function to distribute the deletion of a single child trie across multiple
|
||||
/// blocks.
|
||||
pub fn kill_storage(
|
||||
child_info: &ChildInfo,
|
||||
limit: Option<u32>,
|
||||
) -> KillStorageResult {
|
||||
pub fn kill_storage(child_info: &ChildInfo, limit: Option<u32>) -> KillStorageResult {
|
||||
match child_info.child_type() {
|
||||
ChildType::ParentKeyId => sp_io::default_child_storage::storage_kill(
|
||||
child_info.storage_key(),
|
||||
limit
|
||||
),
|
||||
ChildType::ParentKeyId =>
|
||||
sp_io::default_child_storage::storage_kill(child_info.storage_key(), limit),
|
||||
}
|
||||
}
|
||||
|
||||
/// Ensure `key` has no explicit entry in storage.
|
||||
pub fn kill(
|
||||
child_info: &ChildInfo,
|
||||
key: &[u8],
|
||||
) {
|
||||
pub fn kill(child_info: &ChildInfo, key: &[u8]) {
|
||||
match child_info.child_type() {
|
||||
ChildType::ParentKeyId => {
|
||||
sp_io::default_child_storage::clear(
|
||||
child_info.storage_key(),
|
||||
key,
|
||||
);
|
||||
sp_io::default_child_storage::clear(child_info.storage_key(), key);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// Get a Vec of bytes from storage.
|
||||
pub fn get_raw(
|
||||
child_info: &ChildInfo,
|
||||
key: &[u8],
|
||||
) -> Option<Vec<u8>> {
|
||||
pub fn get_raw(child_info: &ChildInfo, key: &[u8]) -> Option<Vec<u8>> {
|
||||
match child_info.child_type() {
|
||||
ChildType::ParentKeyId => sp_io::default_child_storage::get(
|
||||
child_info.storage_key(),
|
||||
key,
|
||||
),
|
||||
ChildType::ParentKeyId => sp_io::default_child_storage::get(child_info.storage_key(), key),
|
||||
}
|
||||
}
|
||||
|
||||
/// Put a raw byte slice into storage.
|
||||
pub fn put_raw(
|
||||
child_info: &ChildInfo,
|
||||
key: &[u8],
|
||||
value: &[u8],
|
||||
) {
|
||||
pub fn put_raw(child_info: &ChildInfo, key: &[u8], value: &[u8]) {
|
||||
match child_info.child_type() {
|
||||
ChildType::ParentKeyId => sp_io::default_child_storage::set(
|
||||
child_info.storage_key(),
|
||||
key,
|
||||
value,
|
||||
),
|
||||
ChildType::ParentKeyId =>
|
||||
sp_io::default_child_storage::set(child_info.storage_key(), key, value),
|
||||
}
|
||||
}
|
||||
|
||||
/// Calculate current child root value.
|
||||
pub fn root(
|
||||
child_info: &ChildInfo,
|
||||
) -> Vec<u8> {
|
||||
pub fn root(child_info: &ChildInfo) -> Vec<u8> {
|
||||
match child_info.child_type() {
|
||||
ChildType::ParentKeyId => sp_io::default_child_storage::root(
|
||||
child_info.storage_key(),
|
||||
),
|
||||
ChildType::ParentKeyId => sp_io::default_child_storage::root(child_info.storage_key()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the length in bytes of the value without reading it. `None` if it does not exist.
|
||||
pub fn len(
|
||||
child_info: &ChildInfo,
|
||||
key: &[u8],
|
||||
) -> Option<u32> {
|
||||
pub fn len(child_info: &ChildInfo, key: &[u8]) -> Option<u32> {
|
||||
match child_info.child_type() {
|
||||
ChildType::ParentKeyId => {
|
||||
let mut buffer = [0; 0];
|
||||
sp_io::default_child_storage::read(
|
||||
child_info.storage_key(),
|
||||
key,
|
||||
&mut buffer,
|
||||
0,
|
||||
)
|
||||
}
|
||||
sp_io::default_child_storage::read(child_info.storage_key(), key, &mut buffer, 0)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,11 +15,13 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use sp_std::prelude::*;
|
||||
use sp_std::borrow::Borrow;
|
||||
use codec::{FullCodec, FullEncode, Decode, Encode, EncodeLike};
|
||||
use crate::{storage::{self, unhashed, KeyPrefixIterator, StorageAppend, PrefixIterator}, Never};
|
||||
use crate::hash::{StorageHasher, Twox128, ReversibleStorageHasher};
|
||||
use crate::{
|
||||
hash::{ReversibleStorageHasher, StorageHasher, Twox128},
|
||||
storage::{self, unhashed, KeyPrefixIterator, PrefixIterator, StorageAppend},
|
||||
Never,
|
||||
};
|
||||
use codec::{Decode, Encode, EncodeLike, FullCodec, FullEncode};
|
||||
use sp_std::{borrow::Borrow, prelude::*};
|
||||
|
||||
/// Generator for `StorageDoubleMap` used by `decl_storage`.
|
||||
///
|
||||
@@ -63,9 +65,8 @@ pub trait StorageDoubleMap<K1: FullEncode, K2: FullEncode, V: FullCodec> {
|
||||
let module_prefix_hashed = Twox128::hash(Self::module_prefix());
|
||||
let storage_prefix_hashed = Twox128::hash(Self::storage_prefix());
|
||||
|
||||
let mut result = Vec::with_capacity(
|
||||
module_prefix_hashed.len() + storage_prefix_hashed.len()
|
||||
);
|
||||
let mut result =
|
||||
Vec::with_capacity(module_prefix_hashed.len() + storage_prefix_hashed.len());
|
||||
|
||||
result.extend_from_slice(&module_prefix_hashed[..]);
|
||||
result.extend_from_slice(&storage_prefix_hashed[..]);
|
||||
@@ -80,7 +81,8 @@ pub trait StorageDoubleMap<K1: FullEncode, K2: FullEncode, V: FullCodec> {
|
||||
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) -> Vec<u8> where
|
||||
fn storage_double_map_final_key1<KArg1>(k1: KArg1) -> Vec<u8>
|
||||
where
|
||||
KArg1: EncodeLike<K1>,
|
||||
{
|
||||
let module_prefix_hashed = Twox128::hash(Self::module_prefix());
|
||||
@@ -88,7 +90,7 @@ pub trait StorageDoubleMap<K1: FullEncode, K2: FullEncode, V: FullCodec> {
|
||||
let key_hashed = k1.borrow().using_encoded(Self::Hasher1::hash);
|
||||
|
||||
let mut final_key = Vec::with_capacity(
|
||||
module_prefix_hashed.len() + storage_prefix_hashed.len() + key_hashed.as_ref().len()
|
||||
module_prefix_hashed.len() + storage_prefix_hashed.len() + key_hashed.as_ref().len(),
|
||||
);
|
||||
|
||||
final_key.extend_from_slice(&module_prefix_hashed[..]);
|
||||
@@ -99,7 +101,8 @@ pub trait StorageDoubleMap<K1: FullEncode, K2: FullEncode, V: FullCodec> {
|
||||
}
|
||||
|
||||
/// Generate the full key used in top storage.
|
||||
fn storage_double_map_final_key<KArg1, KArg2>(k1: KArg1, k2: KArg2) -> Vec<u8> where
|
||||
fn storage_double_map_final_key<KArg1, KArg2>(k1: KArg1, k2: KArg2) -> Vec<u8>
|
||||
where
|
||||
KArg1: EncodeLike<K1>,
|
||||
KArg2: EncodeLike<K2>,
|
||||
{
|
||||
@@ -109,10 +112,10 @@ pub trait StorageDoubleMap<K1: FullEncode, K2: FullEncode, V: FullCodec> {
|
||||
let key2_hashed = k2.borrow().using_encoded(Self::Hasher2::hash);
|
||||
|
||||
let mut final_key = Vec::with_capacity(
|
||||
module_prefix_hashed.len()
|
||||
+ storage_prefix_hashed.len()
|
||||
+ key1_hashed.as_ref().len()
|
||||
+ key2_hashed.as_ref().len()
|
||||
module_prefix_hashed.len() +
|
||||
storage_prefix_hashed.len() +
|
||||
key1_hashed.as_ref().len() +
|
||||
key2_hashed.as_ref().len(),
|
||||
);
|
||||
|
||||
final_key.extend_from_slice(&module_prefix_hashed[..]);
|
||||
@@ -124,7 +127,8 @@ pub trait StorageDoubleMap<K1: FullEncode, K2: FullEncode, V: FullCodec> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<K1, K2, V, G> storage::StorageDoubleMap<K1, K2, V> for G where
|
||||
impl<K1, K2, V, G> storage::StorageDoubleMap<K1, K2, V> for G
|
||||
where
|
||||
K1: FullEncode,
|
||||
K2: FullEncode,
|
||||
V: FullCodec,
|
||||
@@ -132,21 +136,24 @@ impl<K1, K2, V, G> storage::StorageDoubleMap<K1, K2, V> for G where
|
||||
{
|
||||
type Query = G::Query;
|
||||
|
||||
fn hashed_key_for<KArg1, KArg2>(k1: KArg1, k2: KArg2) -> Vec<u8> where
|
||||
fn hashed_key_for<KArg1, KArg2>(k1: KArg1, k2: KArg2) -> Vec<u8>
|
||||
where
|
||||
KArg1: EncodeLike<K1>,
|
||||
KArg2: EncodeLike<K2>,
|
||||
{
|
||||
Self::storage_double_map_final_key(k1, k2)
|
||||
}
|
||||
|
||||
fn contains_key<KArg1, KArg2>(k1: KArg1, k2: KArg2) -> bool where
|
||||
fn contains_key<KArg1, KArg2>(k1: KArg1, k2: KArg2) -> bool
|
||||
where
|
||||
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 where
|
||||
fn get<KArg1, KArg2>(k1: KArg1, k2: KArg2) -> Self::Query
|
||||
where
|
||||
KArg1: EncodeLike<K1>,
|
||||
KArg2: EncodeLike<K2>,
|
||||
{
|
||||
@@ -156,11 +163,13 @@ impl<K1, K2, V, G> storage::StorageDoubleMap<K1, K2, V> for G where
|
||||
fn try_get<KArg1, KArg2>(k1: KArg1, k2: KArg2) -> Result<V, ()>
|
||||
where
|
||||
KArg1: EncodeLike<K1>,
|
||||
KArg2: EncodeLike<K2> {
|
||||
KArg2: EncodeLike<K2>,
|
||||
{
|
||||
unhashed::get(&Self::storage_double_map_final_key(k1, k2)).ok_or(())
|
||||
}
|
||||
|
||||
fn take<KArg1, KArg2>(k1: KArg1, k2: KArg2) -> Self::Query where
|
||||
fn take<KArg1, KArg2>(k1: KArg1, k2: KArg2) -> Self::Query
|
||||
where
|
||||
KArg1: EncodeLike<K1>,
|
||||
KArg2: EncodeLike<K2>,
|
||||
{
|
||||
@@ -170,16 +179,12 @@ impl<K1, K2, V, G> storage::StorageDoubleMap<K1, K2, V> for G where
|
||||
G::from_optional_value_to_query(value)
|
||||
}
|
||||
|
||||
fn swap<XKArg1, XKArg2, YKArg1, YKArg2>(
|
||||
x_k1: XKArg1,
|
||||
x_k2: XKArg2,
|
||||
y_k1: YKArg1,
|
||||
y_k2: YKArg2
|
||||
) where
|
||||
fn swap<XKArg1, XKArg2, YKArg1, YKArg2>(x_k1: XKArg1, x_k2: XKArg2, y_k1: YKArg1, y_k2: YKArg2)
|
||||
where
|
||||
XKArg1: EncodeLike<K1>,
|
||||
XKArg2: EncodeLike<K2>,
|
||||
YKArg1: EncodeLike<K1>,
|
||||
YKArg2: EncodeLike<K2>
|
||||
YKArg2: EncodeLike<K2>,
|
||||
{
|
||||
let final_x_key = Self::storage_double_map_final_key(x_k1, x_k2);
|
||||
let final_y_key = Self::storage_double_map_final_key(y_k1, y_k2);
|
||||
@@ -197,7 +202,8 @@ impl<K1, K2, V, G> storage::StorageDoubleMap<K1, K2, V> for G where
|
||||
}
|
||||
}
|
||||
|
||||
fn insert<KArg1, KArg2, VArg>(k1: KArg1, k2: KArg2, val: VArg) where
|
||||
fn insert<KArg1, KArg2, VArg>(k1: KArg1, k2: KArg2, val: VArg)
|
||||
where
|
||||
KArg1: EncodeLike<K1>,
|
||||
KArg2: EncodeLike<K2>,
|
||||
VArg: EncodeLike<V>,
|
||||
@@ -205,7 +211,8 @@ impl<K1, K2, V, G> storage::StorageDoubleMap<K1, K2, V> for G where
|
||||
unhashed::put(&Self::storage_double_map_final_key(k1, k2), &val.borrow())
|
||||
}
|
||||
|
||||
fn remove<KArg1, KArg2>(k1: KArg1, k2: KArg2) where
|
||||
fn remove<KArg1, KArg2>(k1: KArg1, k2: KArg2)
|
||||
where
|
||||
KArg1: EncodeLike<K1>,
|
||||
KArg2: EncodeLike<K2>,
|
||||
{
|
||||
@@ -213,12 +220,15 @@ impl<K1, K2, V, G> storage::StorageDoubleMap<K1, K2, V> for G where
|
||||
}
|
||||
|
||||
fn remove_prefix<KArg1>(k1: KArg1, limit: Option<u32>) -> sp_io::KillStorageResult
|
||||
where KArg1: EncodeLike<K1> {
|
||||
where
|
||||
KArg1: EncodeLike<K1>,
|
||||
{
|
||||
unhashed::kill_prefix(Self::storage_double_map_final_key1(k1).as_ref(), limit)
|
||||
}
|
||||
|
||||
fn iter_prefix_values<KArg1>(k1: KArg1) -> storage::PrefixIterator<V> where
|
||||
KArg1: ?Sized + EncodeLike<K1>
|
||||
fn iter_prefix_values<KArg1>(k1: KArg1) -> storage::PrefixIterator<V>
|
||||
where
|
||||
KArg1: ?Sized + EncodeLike<K1>,
|
||||
{
|
||||
let prefix = Self::storage_double_map_final_key1(k1);
|
||||
storage::PrefixIterator {
|
||||
@@ -229,12 +239,14 @@ impl<K1, K2, V, G> storage::StorageDoubleMap<K1, K2, V> for G where
|
||||
}
|
||||
}
|
||||
|
||||
fn mutate<KArg1, KArg2, R, F>(k1: KArg1, k2: KArg2, f: F) -> R where
|
||||
fn mutate<KArg1, KArg2, R, F>(k1: KArg1, k2: KArg2, f: F) -> R
|
||||
where
|
||||
KArg1: EncodeLike<K1>,
|
||||
KArg2: EncodeLike<K2>,
|
||||
F: FnOnce(&mut Self::Query) -> R,
|
||||
{
|
||||
Self::try_mutate(k1, k2, |v| Ok::<R, Never>(f(v))).expect("`Never` can not be constructed; qed")
|
||||
Self::try_mutate(k1, k2, |v| Ok::<R, Never>(f(v)))
|
||||
.expect("`Never` can not be constructed; qed")
|
||||
}
|
||||
|
||||
fn mutate_exists<KArg1, KArg2, R, F>(k1: KArg1, k2: KArg2, f: F) -> R
|
||||
@@ -243,10 +255,12 @@ impl<K1, K2, V, G> storage::StorageDoubleMap<K1, K2, V> for G where
|
||||
KArg2: EncodeLike<K2>,
|
||||
F: FnOnce(&mut Option<V>) -> R,
|
||||
{
|
||||
Self::try_mutate_exists(k1, k2, |v| Ok::<R, Never>(f(v))).expect("`Never` can not be constructed; qed")
|
||||
Self::try_mutate_exists(k1, k2, |v| Ok::<R, Never>(f(v)))
|
||||
.expect("`Never` can not be constructed; qed")
|
||||
}
|
||||
|
||||
fn try_mutate<KArg1, KArg2, R, E, F>(k1: KArg1, k2: KArg2, f: F) -> Result<R, E> where
|
||||
fn try_mutate<KArg1, KArg2, R, E, F>(k1: KArg1, k2: KArg2, f: F) -> Result<R, E>
|
||||
where
|
||||
KArg1: EncodeLike<K1>,
|
||||
KArg2: EncodeLike<K2>,
|
||||
F: FnOnce(&mut Self::Query) -> Result<R, E>,
|
||||
@@ -283,11 +297,8 @@ impl<K1, K2, V, G> storage::StorageDoubleMap<K1, K2, V> for G where
|
||||
ret
|
||||
}
|
||||
|
||||
fn append<Item, EncodeLikeItem, KArg1, KArg2>(
|
||||
k1: KArg1,
|
||||
k2: KArg2,
|
||||
item: EncodeLikeItem,
|
||||
) where
|
||||
fn append<Item, EncodeLikeItem, KArg1, KArg2>(k1: KArg1, k2: KArg2, item: EncodeLikeItem)
|
||||
where
|
||||
KArg1: EncodeLike<K1>,
|
||||
KArg2: EncodeLike<K2>,
|
||||
Item: Encode,
|
||||
@@ -303,7 +314,10 @@ impl<K1, K2, V, G> storage::StorageDoubleMap<K1, K2, V> for G where
|
||||
OldHasher2: StorageHasher,
|
||||
KeyArg1: EncodeLike<K1>,
|
||||
KeyArg2: EncodeLike<K2>,
|
||||
>(key1: KeyArg1, key2: KeyArg2) -> Option<V> {
|
||||
>(
|
||||
key1: KeyArg1,
|
||||
key2: KeyArg2,
|
||||
) -> Option<V> {
|
||||
let old_key = {
|
||||
let module_prefix_hashed = Twox128::hash(Self::module_prefix());
|
||||
let storage_prefix_hashed = Twox128::hash(Self::storage_prefix());
|
||||
@@ -311,10 +325,10 @@ impl<K1, K2, V, G> storage::StorageDoubleMap<K1, K2, V> for G where
|
||||
let key2_hashed = key2.borrow().using_encoded(OldHasher2::hash);
|
||||
|
||||
let mut final_key = Vec::with_capacity(
|
||||
module_prefix_hashed.len()
|
||||
+ storage_prefix_hashed.len()
|
||||
+ key1_hashed.as_ref().len()
|
||||
+ key2_hashed.as_ref().len()
|
||||
module_prefix_hashed.len() +
|
||||
storage_prefix_hashed.len() +
|
||||
key1_hashed.as_ref().len() +
|
||||
key2_hashed.as_ref().len(),
|
||||
);
|
||||
|
||||
final_key.extend_from_slice(&module_prefix_hashed[..]);
|
||||
@@ -331,14 +345,11 @@ impl<K1, K2, V, G> storage::StorageDoubleMap<K1, K2, V> for G where
|
||||
}
|
||||
}
|
||||
|
||||
impl<
|
||||
K1: FullCodec,
|
||||
K2: FullCodec,
|
||||
V: FullCodec,
|
||||
G: StorageDoubleMap<K1, K2, V>,
|
||||
> storage::IterableStorageDoubleMap<K1, K2, V> for G where
|
||||
impl<K1: FullCodec, K2: FullCodec, V: FullCodec, G: StorageDoubleMap<K1, K2, V>>
|
||||
storage::IterableStorageDoubleMap<K1, K2, V> for G
|
||||
where
|
||||
G::Hasher1: ReversibleStorageHasher,
|
||||
G::Hasher2: ReversibleStorageHasher
|
||||
G::Hasher2: ReversibleStorageHasher,
|
||||
{
|
||||
type PartialKeyIterator = KeyPrefixIterator<K2>;
|
||||
type PrefixIterator = PrefixIterator<(K2, V)>;
|
||||
@@ -367,7 +378,7 @@ impl<
|
||||
closure: |raw_key_without_prefix| {
|
||||
let mut key_material = G::Hasher2::reverse(raw_key_without_prefix);
|
||||
K2::decode(&mut key_material)
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -405,7 +416,7 @@ impl<
|
||||
let mut k2_material = G::Hasher2::reverse(k1_k2_material);
|
||||
let k2 = K2::decode(&mut k2_material)?;
|
||||
Ok((k1, k2))
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -418,8 +429,8 @@ impl<
|
||||
fn translate<O: Decode, F: FnMut(K1, K2, O) -> Option<V>>(mut f: F) {
|
||||
let prefix = G::prefix_hash();
|
||||
let mut previous_key = prefix.clone();
|
||||
while let Some(next) = sp_io::storage::next_key(&previous_key)
|
||||
.filter(|n| n.starts_with(&prefix))
|
||||
while let Some(next) =
|
||||
sp_io::storage::next_key(&previous_key).filter(|n| n.starts_with(&prefix))
|
||||
{
|
||||
previous_key = next;
|
||||
let value = match unhashed::get::<O>(&previous_key) {
|
||||
@@ -458,11 +469,11 @@ impl<
|
||||
/// Test iterators for StorageDoubleMap
|
||||
#[cfg(test)]
|
||||
mod test_iterators {
|
||||
use codec::{Encode, Decode};
|
||||
use crate::{
|
||||
hash::StorageHasher,
|
||||
storage::{generator::StorageDoubleMap, IterableStorageDoubleMap, unhashed},
|
||||
storage::{generator::StorageDoubleMap, unhashed, IterableStorageDoubleMap},
|
||||
};
|
||||
use codec::{Decode, Encode};
|
||||
|
||||
pub trait Config: 'static {
|
||||
type Origin;
|
||||
@@ -521,10 +532,7 @@ mod test_iterators {
|
||||
vec![(3, 3), (0, 0), (2, 2), (1, 1)],
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
DoubleMap::iter_values().collect::<Vec<_>>(),
|
||||
vec![3, 0, 2, 1],
|
||||
);
|
||||
assert_eq!(DoubleMap::iter_values().collect::<Vec<_>>(), vec![3, 0, 2, 1],);
|
||||
|
||||
assert_eq!(
|
||||
DoubleMap::drain().collect::<Vec<_>>(),
|
||||
@@ -551,15 +559,9 @@ mod test_iterators {
|
||||
vec![(1, 1), (2, 2), (0, 0), (3, 3)],
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
DoubleMap::iter_key_prefix(k1).collect::<Vec<_>>(),
|
||||
vec![1, 2, 0, 3],
|
||||
);
|
||||
assert_eq!(DoubleMap::iter_key_prefix(k1).collect::<Vec<_>>(), vec![1, 2, 0, 3],);
|
||||
|
||||
assert_eq!(
|
||||
DoubleMap::iter_prefix_values(k1).collect::<Vec<_>>(),
|
||||
vec![1, 2, 0, 3],
|
||||
);
|
||||
assert_eq!(DoubleMap::iter_prefix_values(k1).collect::<Vec<_>>(), vec![1, 2, 0, 3],);
|
||||
|
||||
assert_eq!(
|
||||
DoubleMap::drain_prefix(k1).collect::<Vec<_>>(),
|
||||
@@ -580,15 +582,12 @@ mod test_iterators {
|
||||
}
|
||||
|
||||
// Wrong key1
|
||||
unhashed::put(
|
||||
&[prefix.clone(), vec![1, 2, 3]].concat(),
|
||||
&3u64.encode()
|
||||
);
|
||||
unhashed::put(&[prefix.clone(), vec![1, 2, 3]].concat(), &3u64.encode());
|
||||
|
||||
// Wrong key2
|
||||
unhashed::put(
|
||||
&[prefix.clone(), crate::Blake2_128Concat::hash(&1u16.encode())].concat(),
|
||||
&3u64.encode()
|
||||
&3u64.encode(),
|
||||
);
|
||||
|
||||
// Wrong value
|
||||
@@ -597,11 +596,12 @@ mod test_iterators {
|
||||
prefix.clone(),
|
||||
crate::Blake2_128Concat::hash(&1u16.encode()),
|
||||
crate::Twox64Concat::hash(&2u32.encode()),
|
||||
].concat(),
|
||||
]
|
||||
.concat(),
|
||||
&vec![1],
|
||||
);
|
||||
|
||||
DoubleMap::translate(|_k1, _k2, v: u64| Some(v*2));
|
||||
DoubleMap::translate(|_k1, _k2, v: u64| Some(v * 2));
|
||||
assert_eq!(
|
||||
DoubleMap::iter().collect::<Vec<_>>(),
|
||||
vec![(3, 3, 6), (0, 0, 0), (2, 2, 4), (1, 1, 2)],
|
||||
|
||||
@@ -15,14 +15,15 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use crate::{
|
||||
hash::{ReversibleStorageHasher, StorageHasher, Twox128},
|
||||
storage::{self, unhashed, KeyPrefixIterator, PrefixIterator, StorageAppend},
|
||||
Never,
|
||||
};
|
||||
use codec::{Decode, Encode, EncodeLike, FullCodec, FullEncode};
|
||||
use sp_std::borrow::Borrow;
|
||||
#[cfg(not(feature = "std"))]
|
||||
use sp_std::prelude::*;
|
||||
use sp_std::borrow::Borrow;
|
||||
use codec::{FullCodec, FullEncode, Decode, Encode, EncodeLike};
|
||||
use crate::{
|
||||
storage::{self, unhashed, KeyPrefixIterator, StorageAppend, PrefixIterator},
|
||||
Never, hash::{StorageHasher, Twox128, ReversibleStorageHasher},
|
||||
};
|
||||
|
||||
/// Generator for `StorageMap` used by `decl_storage`.
|
||||
///
|
||||
@@ -54,9 +55,8 @@ pub trait StorageMap<K: FullEncode, V: FullCodec> {
|
||||
let module_prefix_hashed = Twox128::hash(Self::module_prefix());
|
||||
let storage_prefix_hashed = Twox128::hash(Self::storage_prefix());
|
||||
|
||||
let mut result = Vec::with_capacity(
|
||||
module_prefix_hashed.len() + storage_prefix_hashed.len()
|
||||
);
|
||||
let mut result =
|
||||
Vec::with_capacity(module_prefix_hashed.len() + storage_prefix_hashed.len());
|
||||
|
||||
result.extend_from_slice(&module_prefix_hashed[..]);
|
||||
result.extend_from_slice(&storage_prefix_hashed[..]);
|
||||
@@ -71,7 +71,8 @@ pub trait StorageMap<K: FullEncode, V: FullCodec> {
|
||||
fn from_query_to_optional_value(v: Self::Query) -> Option<V>;
|
||||
|
||||
/// Generate the full key used in top storage.
|
||||
fn storage_map_final_key<KeyArg>(key: KeyArg) -> Vec<u8> where
|
||||
fn storage_map_final_key<KeyArg>(key: KeyArg) -> Vec<u8>
|
||||
where
|
||||
KeyArg: EncodeLike<K>,
|
||||
{
|
||||
let module_prefix_hashed = Twox128::hash(Self::module_prefix());
|
||||
@@ -79,7 +80,7 @@ pub trait StorageMap<K: FullEncode, V: FullCodec> {
|
||||
let key_hashed = key.borrow().using_encoded(Self::Hasher::hash);
|
||||
|
||||
let mut final_key = Vec::with_capacity(
|
||||
module_prefix_hashed.len() + storage_prefix_hashed.len() + key_hashed.as_ref().len()
|
||||
module_prefix_hashed.len() + storage_prefix_hashed.len() + key_hashed.as_ref().len(),
|
||||
);
|
||||
|
||||
final_key.extend_from_slice(&module_prefix_hashed[..]);
|
||||
@@ -98,11 +99,9 @@ pub struct StorageMapIterator<K, V, Hasher> {
|
||||
_phantom: ::sp_std::marker::PhantomData<(K, V, Hasher)>,
|
||||
}
|
||||
|
||||
impl<
|
||||
K: Decode + Sized,
|
||||
V: Decode + Sized,
|
||||
Hasher: ReversibleStorageHasher
|
||||
> Iterator for StorageMapIterator<K, V, Hasher> {
|
||||
impl<K: Decode + Sized, V: Decode + Sized, Hasher: ReversibleStorageHasher> Iterator
|
||||
for StorageMapIterator<K, V, Hasher>
|
||||
{
|
||||
type Item = (K, V);
|
||||
|
||||
fn next(&mut self) -> Option<(K, V)> {
|
||||
@@ -117,27 +116,25 @@ impl<
|
||||
if self.drain {
|
||||
unhashed::kill(&self.previous_key)
|
||||
}
|
||||
let mut key_material = Hasher::reverse(&self.previous_key[self.prefix.len()..]);
|
||||
let mut key_material =
|
||||
Hasher::reverse(&self.previous_key[self.prefix.len()..]);
|
||||
match K::decode(&mut key_material) {
|
||||
Ok(key) => Some((key, value)),
|
||||
Err(_) => continue,
|
||||
}
|
||||
}
|
||||
},
|
||||
None => continue,
|
||||
}
|
||||
}
|
||||
},
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<
|
||||
K: FullCodec,
|
||||
V: FullCodec,
|
||||
G: StorageMap<K, V>,
|
||||
> storage::IterableStorageMap<K, V> for G where
|
||||
G::Hasher: ReversibleStorageHasher
|
||||
impl<K: FullCodec, V: FullCodec, G: StorageMap<K, V>> storage::IterableStorageMap<K, V> for G
|
||||
where
|
||||
G::Hasher: ReversibleStorageHasher,
|
||||
{
|
||||
type Iterator = PrefixIterator<(K, V)>;
|
||||
type KeyIterator = KeyPrefixIterator<K>;
|
||||
@@ -166,7 +163,7 @@ impl<
|
||||
closure: |raw_key_without_prefix| {
|
||||
let mut key_material = G::Hasher::reverse(raw_key_without_prefix);
|
||||
K::decode(&mut key_material)
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -180,8 +177,8 @@ impl<
|
||||
fn translate<O: Decode, F: FnMut(K, O) -> Option<V>>(mut f: F) {
|
||||
let prefix = G::prefix_hash();
|
||||
let mut previous_key = prefix.clone();
|
||||
while let Some(next) = sp_io::storage::next_key(&previous_key)
|
||||
.filter(|n| n.starts_with(&prefix))
|
||||
while let Some(next) =
|
||||
sp_io::storage::next_key(&previous_key).filter(|n| n.starts_with(&prefix))
|
||||
{
|
||||
previous_key = next;
|
||||
let value = match unhashed::get::<O>(&previous_key) {
|
||||
@@ -254,16 +251,21 @@ impl<K: FullEncode, V: FullCodec, G: StorageMap<K, V>> storage::StorageMap<K, V>
|
||||
}
|
||||
|
||||
fn mutate<KeyArg: EncodeLike<K>, R, F: FnOnce(&mut Self::Query) -> R>(key: KeyArg, f: F) -> R {
|
||||
Self::try_mutate(key, |v| Ok::<R, Never>(f(v))).expect("`Never` can not be constructed; qed")
|
||||
Self::try_mutate(key, |v| Ok::<R, Never>(f(v)))
|
||||
.expect("`Never` can not be constructed; qed")
|
||||
}
|
||||
|
||||
fn mutate_exists<KeyArg: EncodeLike<K>, R, F: FnOnce(&mut Option<V>) -> R>(key: KeyArg, f: F) -> R {
|
||||
Self::try_mutate_exists(key, |v| Ok::<R, Never>(f(v))).expect("`Never` can not be constructed; qed")
|
||||
fn mutate_exists<KeyArg: EncodeLike<K>, R, F: FnOnce(&mut Option<V>) -> R>(
|
||||
key: KeyArg,
|
||||
f: F,
|
||||
) -> R {
|
||||
Self::try_mutate_exists(key, |v| Ok::<R, Never>(f(v)))
|
||||
.expect("`Never` can not be constructed; qed")
|
||||
}
|
||||
|
||||
fn try_mutate<KeyArg: EncodeLike<K>, R, E, F: FnOnce(&mut Self::Query) -> Result<R, E>>(
|
||||
key: KeyArg,
|
||||
f: F
|
||||
f: F,
|
||||
) -> Result<R, E> {
|
||||
let final_key = Self::storage_map_final_key(key);
|
||||
let mut val = G::from_optional_value_to_query(unhashed::get(final_key.as_ref()));
|
||||
@@ -280,7 +282,7 @@ impl<K: FullEncode, V: FullCodec, G: StorageMap<K, V>> storage::StorageMap<K, V>
|
||||
|
||||
fn try_mutate_exists<KeyArg: EncodeLike<K>, R, E, F: FnOnce(&mut Option<V>) -> Result<R, E>>(
|
||||
key: KeyArg,
|
||||
f: F
|
||||
f: F,
|
||||
) -> Result<R, E> {
|
||||
let final_key = Self::storage_map_final_key(key);
|
||||
let mut val = unhashed::get(final_key.as_ref());
|
||||
@@ -319,7 +321,9 @@ impl<K: FullEncode, V: FullCodec, G: StorageMap<K, V>> storage::StorageMap<K, V>
|
||||
let key_hashed = key.borrow().using_encoded(OldHasher::hash);
|
||||
|
||||
let mut final_key = Vec::with_capacity(
|
||||
module_prefix_hashed.len() + storage_prefix_hashed.len() + key_hashed.as_ref().len()
|
||||
module_prefix_hashed.len() +
|
||||
storage_prefix_hashed.len() +
|
||||
key_hashed.as_ref().len(),
|
||||
);
|
||||
|
||||
final_key.extend_from_slice(&module_prefix_hashed[..]);
|
||||
@@ -338,11 +342,11 @@ impl<K: FullEncode, V: FullCodec, G: StorageMap<K, V>> storage::StorageMap<K, V>
|
||||
/// Test iterators for StorageMap
|
||||
#[cfg(test)]
|
||||
mod test_iterators {
|
||||
use codec::{Encode, Decode};
|
||||
use crate::{
|
||||
hash::StorageHasher,
|
||||
storage::{generator::StorageMap, IterableStorageMap, unhashed},
|
||||
storage::{generator::StorageMap, unhashed, IterableStorageMap},
|
||||
};
|
||||
use codec::{Decode, Encode};
|
||||
|
||||
pub trait Config: 'static {
|
||||
type Origin;
|
||||
@@ -421,7 +425,7 @@ mod test_iterators {
|
||||
&vec![1],
|
||||
);
|
||||
|
||||
Map::translate(|_k1, v: u64| Some(v*2));
|
||||
Map::translate(|_k1, v: u64| Some(v * 2));
|
||||
assert_eq!(Map::iter().collect::<Vec<_>>(), vec![(3, 6), (0, 0), (2, 4), (1, 2)]);
|
||||
})
|
||||
}
|
||||
|
||||
@@ -24,23 +24,25 @@
|
||||
//!
|
||||
//! This is internal api and is subject to change.
|
||||
|
||||
mod double_map;
|
||||
mod map;
|
||||
mod nmap;
|
||||
mod double_map;
|
||||
mod value;
|
||||
|
||||
pub use double_map::StorageDoubleMap;
|
||||
pub use map::StorageMap;
|
||||
pub use nmap::StorageNMap;
|
||||
pub use double_map::StorageDoubleMap;
|
||||
pub use value::StorageValue;
|
||||
|
||||
#[cfg(test)]
|
||||
#[allow(dead_code)]
|
||||
mod tests {
|
||||
use sp_io::TestExternalities;
|
||||
use crate::{
|
||||
assert_noop, assert_ok,
|
||||
storage::{generator::StorageValue, unhashed, IterableStorageMap},
|
||||
};
|
||||
use codec::Encode;
|
||||
use crate::storage::{unhashed, generator::StorageValue, IterableStorageMap};
|
||||
use crate::{assert_noop, assert_ok};
|
||||
use sp_io::TestExternalities;
|
||||
|
||||
struct Runtime;
|
||||
|
||||
@@ -80,7 +82,7 @@ mod tests {
|
||||
|
||||
// translate
|
||||
let translate_fn = |old: Option<u32>| -> Option<(u64, u64)> {
|
||||
old.map(|o| (o.into(), (o*2).into()))
|
||||
old.map(|o| (o.into(), (o * 2).into()))
|
||||
};
|
||||
let res = Value::translate(translate_fn);
|
||||
debug_assert!(res.is_ok());
|
||||
@@ -105,11 +107,16 @@ mod tests {
|
||||
);
|
||||
|
||||
// do translation.
|
||||
NumberMap::translate(|k: u32, v: u64| if k % 2 == 0 { Some((k as u64) << 32 | v) } else { None });
|
||||
NumberMap::translate(
|
||||
|k: u32, v: u64| if k % 2 == 0 { Some((k as u64) << 32 | v) } else { None },
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
NumberMap::iter().collect::<Vec<_>>(),
|
||||
(0..50u32).map(|x| x * 2).map(|x| (x, (x as u64) << 32 | x as u64)).collect::<Vec<_>>(),
|
||||
(0..50u32)
|
||||
.map(|x| x * 2)
|
||||
.map(|x| (x, (x as u64) << 32 | x as u64))
|
||||
.collect::<Vec<_>>(),
|
||||
);
|
||||
})
|
||||
}
|
||||
@@ -123,20 +130,29 @@ mod tests {
|
||||
assert_eq!(DoubleMap::get(0, 0), 0);
|
||||
|
||||
// `assert_noop` ensures that the state does not change
|
||||
assert_noop!(Value::try_mutate(|value| -> Result<(), &'static str> {
|
||||
*value = (2, 2);
|
||||
Err("don't change value")
|
||||
}), "don't change value");
|
||||
assert_noop!(
|
||||
Value::try_mutate(|value| -> Result<(), &'static str> {
|
||||
*value = (2, 2);
|
||||
Err("don't change value")
|
||||
}),
|
||||
"don't change value"
|
||||
);
|
||||
|
||||
assert_noop!(NumberMap::try_mutate(0, |value| -> Result<(), &'static str> {
|
||||
*value = 4;
|
||||
Err("don't change value")
|
||||
}), "don't change value");
|
||||
assert_noop!(
|
||||
NumberMap::try_mutate(0, |value| -> Result<(), &'static str> {
|
||||
*value = 4;
|
||||
Err("don't change value")
|
||||
}),
|
||||
"don't change value"
|
||||
);
|
||||
|
||||
assert_noop!(DoubleMap::try_mutate(0, 0, |value| -> Result<(), &'static str> {
|
||||
*value = 6;
|
||||
Err("don't change value")
|
||||
}), "don't change value");
|
||||
assert_noop!(
|
||||
DoubleMap::try_mutate(0, 0, |value| -> Result<(), &'static str> {
|
||||
*value = 6;
|
||||
Err("don't change value")
|
||||
}),
|
||||
"don't change value"
|
||||
);
|
||||
|
||||
// Showing this explicitly for clarity
|
||||
assert_eq!(Value::get(), (0, 0));
|
||||
|
||||
@@ -228,7 +228,7 @@ where
|
||||
fn try_mutate<KArg, R, E, F>(key: KArg, f: F) -> Result<R, E>
|
||||
where
|
||||
KArg: EncodeLikeTuple<K::KArg> + TupleToEncodedIter,
|
||||
F: FnOnce(&mut Self::Query) -> Result<R, E>
|
||||
F: FnOnce(&mut Self::Query) -> Result<R, E>,
|
||||
{
|
||||
let final_key = Self::storage_n_map_final_key::<K, _>(key);
|
||||
let mut val = G::from_optional_value_to_query(unhashed::get(final_key.as_ref()));
|
||||
@@ -373,7 +373,7 @@ impl<K: ReversibleKeyGenerator, V: FullCodec, G: StorageNMap<K, V>>
|
||||
closure: |raw_key_without_prefix| {
|
||||
let (final_key, _) = K::decode_final_key(raw_key_without_prefix)?;
|
||||
Ok(final_key)
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -394,16 +394,16 @@ impl<K: ReversibleKeyGenerator, V: FullCodec, G: StorageNMap<K, V>>
|
||||
Some(value) => value,
|
||||
None => {
|
||||
log::error!("Invalid translate: fail to decode old value");
|
||||
continue;
|
||||
}
|
||||
continue
|
||||
},
|
||||
};
|
||||
|
||||
let final_key = match K::decode_final_key(&previous_key[prefix.len()..]) {
|
||||
Ok((final_key, _)) => final_key,
|
||||
Err(_) => {
|
||||
log::error!("Invalid translate: fail to decode key");
|
||||
continue;
|
||||
}
|
||||
continue
|
||||
},
|
||||
};
|
||||
|
||||
match f(final_key, value) {
|
||||
@@ -452,10 +452,7 @@ mod test_iterators {
|
||||
|
||||
fn key_after_prefix(mut prefix: Vec<u8>) -> Vec<u8> {
|
||||
let last = prefix.iter_mut().last().unwrap();
|
||||
assert!(
|
||||
*last != 255,
|
||||
"mock function not implemented for this prefix"
|
||||
);
|
||||
assert!(*last != 255, "mock function not implemented for this prefix");
|
||||
*last += 1;
|
||||
prefix
|
||||
}
|
||||
@@ -498,10 +495,7 @@ mod test_iterators {
|
||||
vec![((3, 3), 3), ((0, 0), 0), ((2, 2), 2), ((1, 1), 1)],
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
NMap::iter_keys().collect::<Vec<_>>(),
|
||||
vec![(3, 3), (0, 0), (2, 2), (1, 1)],
|
||||
);
|
||||
assert_eq!(NMap::iter_keys().collect::<Vec<_>>(), vec![(3, 3), (0, 0), (2, 2), (1, 1)],);
|
||||
|
||||
assert_eq!(NMap::iter_values().collect::<Vec<_>>(), vec![3, 0, 2, 1],);
|
||||
|
||||
@@ -511,10 +505,7 @@ mod test_iterators {
|
||||
);
|
||||
|
||||
assert_eq!(NMap::iter().collect::<Vec<_>>(), vec![]);
|
||||
assert_eq!(
|
||||
unhashed::get(&key_before_prefix(prefix.clone())),
|
||||
Some(1u64)
|
||||
);
|
||||
assert_eq!(unhashed::get(&key_before_prefix(prefix.clone())), Some(1u64));
|
||||
assert_eq!(unhashed::get(&key_after_prefix(prefix.clone())), Some(1u64));
|
||||
|
||||
// Prefix iterator
|
||||
@@ -533,15 +524,9 @@ mod test_iterators {
|
||||
vec![(1, 1), (2, 2), (0, 0), (3, 3)],
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
NMap::iter_key_prefix((k1,)).collect::<Vec<_>>(),
|
||||
vec![1, 2, 0, 3],
|
||||
);
|
||||
assert_eq!(NMap::iter_key_prefix((k1,)).collect::<Vec<_>>(), vec![1, 2, 0, 3],);
|
||||
|
||||
assert_eq!(
|
||||
NMap::iter_prefix_values((k1,)).collect::<Vec<_>>(),
|
||||
vec![1, 2, 0, 3],
|
||||
);
|
||||
assert_eq!(NMap::iter_prefix_values((k1,)).collect::<Vec<_>>(), vec![1, 2, 0, 3],);
|
||||
|
||||
assert_eq!(
|
||||
NMap::drain_prefix((k1,)).collect::<Vec<_>>(),
|
||||
@@ -549,10 +534,7 @@ mod test_iterators {
|
||||
);
|
||||
|
||||
assert_eq!(NMap::iter_prefix((k1,)).collect::<Vec<_>>(), vec![]);
|
||||
assert_eq!(
|
||||
unhashed::get(&key_before_prefix(prefix.clone())),
|
||||
Some(1u64)
|
||||
);
|
||||
assert_eq!(unhashed::get(&key_before_prefix(prefix.clone())), Some(1u64));
|
||||
assert_eq!(unhashed::get(&key_after_prefix(prefix.clone())), Some(1u64));
|
||||
|
||||
// Translate
|
||||
@@ -569,11 +551,7 @@ mod test_iterators {
|
||||
|
||||
// Wrong key2
|
||||
unhashed::put(
|
||||
&[
|
||||
prefix.clone(),
|
||||
crate::Blake2_128Concat::hash(&1u16.encode()),
|
||||
]
|
||||
.concat(),
|
||||
&[prefix.clone(), crate::Blake2_128Concat::hash(&1u16.encode())].concat(),
|
||||
&3u64.encode(),
|
||||
);
|
||||
|
||||
|
||||
@@ -15,12 +15,12 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use codec::{FullCodec, Encode, EncodeLike, Decode};
|
||||
use crate::{
|
||||
Never,
|
||||
hash::{StorageHasher, Twox128},
|
||||
storage::{self, unhashed, StorageAppend},
|
||||
hash::{Twox128, StorageHasher},
|
||||
Never,
|
||||
};
|
||||
use codec::{Decode, Encode, EncodeLike, FullCodec};
|
||||
|
||||
/// Generator for `StorageValue` used by `decl_storage`.
|
||||
///
|
||||
@@ -78,7 +78,8 @@ impl<T: FullCodec, G: StorageValue<T>> storage::StorageValue<T> for G {
|
||||
|
||||
// attempt to get the length directly.
|
||||
let maybe_old = unhashed::get_raw(&key)
|
||||
.map(|old_data| O::decode(&mut &old_data[..]).map_err(|_| ())).transpose()?;
|
||||
.map(|old_data| O::decode(&mut &old_data[..]).map_err(|_| ()))
|
||||
.transpose()?;
|
||||
let maybe_new = f(maybe_old);
|
||||
if let Some(new) = maybe_new.as_ref() {
|
||||
new.using_encoded(|d| unhashed::put_raw(&key, d));
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
//! Operation on runtime storage using hashed keys.
|
||||
|
||||
use super::unhashed;
|
||||
use codec::{Decode, Encode};
|
||||
use sp_std::prelude::*;
|
||||
use codec::{Encode, Decode};
|
||||
|
||||
/// Return the value of the item in storage under `key`, or `None` if there is no explicit entry.
|
||||
pub fn get<T, HashFn, R>(hash: &HashFn, key: &[u8]) -> Option<T>
|
||||
|
||||
@@ -17,10 +17,9 @@
|
||||
|
||||
//! Some utilities for helping access storage with arbitrary key types.
|
||||
|
||||
use crate::{hash::ReversibleStorageHasher, storage::unhashed, StorageHasher, Twox128};
|
||||
use codec::{Decode, Encode};
|
||||
use sp_std::prelude::*;
|
||||
use codec::{Encode, Decode};
|
||||
use crate::{StorageHasher, Twox128, storage::unhashed};
|
||||
use crate::hash::ReversibleStorageHasher;
|
||||
|
||||
use super::PrefixIterator;
|
||||
|
||||
@@ -34,14 +33,18 @@ pub struct StorageIterator<T> {
|
||||
|
||||
impl<T> StorageIterator<T> {
|
||||
/// Construct iterator to iterate over map items in `module` for the map called `item`.
|
||||
#[deprecated(note="Please use the storage_iter or storage_iter_with_suffix functions instead")]
|
||||
#[deprecated(
|
||||
note = "Please use the storage_iter or storage_iter_with_suffix functions instead"
|
||||
)]
|
||||
pub fn new(module: &[u8], item: &[u8]) -> Self {
|
||||
#[allow(deprecated)]
|
||||
Self::with_suffix(module, item, &[][..])
|
||||
}
|
||||
|
||||
/// Construct iterator to iterate over map items in `module` for the map called `item`.
|
||||
#[deprecated(note="Please use the storage_iter or storage_iter_with_suffix functions instead")]
|
||||
#[deprecated(
|
||||
note = "Please use the storage_iter or storage_iter_with_suffix functions instead"
|
||||
)]
|
||||
pub fn with_suffix(module: &[u8], item: &[u8], suffix: &[u8]) -> Self {
|
||||
let mut prefix = Vec::new();
|
||||
prefix.extend_from_slice(&Twox128::hash(module));
|
||||
@@ -75,10 +78,10 @@ impl<T: Decode + Sized> Iterator for StorageIterator<T> {
|
||||
frame_support::storage::unhashed::kill(&next);
|
||||
}
|
||||
Some((self.previous_key[self.prefix.len()..].to_vec(), value))
|
||||
}
|
||||
},
|
||||
None => continue,
|
||||
}
|
||||
}
|
||||
},
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
@@ -95,14 +98,18 @@ pub struct StorageKeyIterator<K, T, H: ReversibleStorageHasher> {
|
||||
|
||||
impl<K, T, H: ReversibleStorageHasher> StorageKeyIterator<K, T, H> {
|
||||
/// Construct iterator to iterate over map items in `module` for the map called `item`.
|
||||
#[deprecated(note="Please use the storage_key_iter or storage_key_iter_with_suffix functions instead")]
|
||||
#[deprecated(
|
||||
note = "Please use the storage_key_iter or storage_key_iter_with_suffix functions instead"
|
||||
)]
|
||||
pub fn new(module: &[u8], item: &[u8]) -> Self {
|
||||
#[allow(deprecated)]
|
||||
Self::with_suffix(module, item, &[][..])
|
||||
}
|
||||
|
||||
/// Construct iterator to iterate over map items in `module` for the map called `item`.
|
||||
#[deprecated(note="Please use the storage_key_iter or storage_key_iter_with_suffix functions instead")]
|
||||
#[deprecated(
|
||||
note = "Please use the storage_key_iter or storage_key_iter_with_suffix functions instead"
|
||||
)]
|
||||
pub fn with_suffix(module: &[u8], item: &[u8], suffix: &[u8]) -> Self {
|
||||
let mut prefix = Vec::new();
|
||||
prefix.extend_from_slice(&Twox128::hash(module));
|
||||
@@ -141,13 +148,13 @@ impl<K: Decode + Sized, T: Decode + Sized, H: ReversibleStorageHasher> Iterator
|
||||
frame_support::storage::unhashed::kill(&next);
|
||||
}
|
||||
Some((key, value))
|
||||
}
|
||||
},
|
||||
None => continue,
|
||||
}
|
||||
}
|
||||
},
|
||||
Err(_) => continue,
|
||||
}
|
||||
}
|
||||
},
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
@@ -187,7 +194,11 @@ pub fn storage_key_iter<K: Decode + Sized, T: Decode + Sized, H: ReversibleStora
|
||||
}
|
||||
|
||||
/// Construct iterator to iterate over map items in `module` for the map called `item`.
|
||||
pub fn storage_key_iter_with_suffix<K: Decode + Sized, T: Decode + Sized, H: ReversibleStorageHasher>(
|
||||
pub fn storage_key_iter_with_suffix<
|
||||
K: Decode + Sized,
|
||||
T: Decode + Sized,
|
||||
H: ReversibleStorageHasher,
|
||||
>(
|
||||
module: &[u8],
|
||||
item: &[u8],
|
||||
suffix: &[u8],
|
||||
@@ -279,7 +290,7 @@ pub fn take_storage_item<K: Encode + Sized, T: Decode + Sized, H: StorageHasher>
|
||||
pub fn move_storage_from_pallet(
|
||||
storage_name: &[u8],
|
||||
old_pallet_name: &[u8],
|
||||
new_pallet_name: &[u8]
|
||||
new_pallet_name: &[u8],
|
||||
) {
|
||||
let mut new_prefix = Vec::new();
|
||||
new_prefix.extend_from_slice(&Twox128::hash(new_pallet_name));
|
||||
@@ -347,18 +358,14 @@ pub fn move_prefix(from_prefix: &[u8], to_prefix: &[u8]) {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{
|
||||
move_pallet, move_prefix, move_storage_from_pallet, storage_iter, storage_key_iter,
|
||||
};
|
||||
use crate::{
|
||||
pallet_prelude::{StorageValue, StorageMap, Twox64Concat, Twox128},
|
||||
hash::StorageHasher,
|
||||
pallet_prelude::{StorageMap, StorageValue, Twox128, Twox64Concat},
|
||||
};
|
||||
use sp_io::TestExternalities;
|
||||
use super::{
|
||||
move_prefix,
|
||||
move_pallet,
|
||||
move_storage_from_pallet,
|
||||
storage_iter,
|
||||
storage_key_iter,
|
||||
};
|
||||
|
||||
struct OldPalletStorageValuePrefix;
|
||||
impl frame_support::traits::StorageInstance for OldPalletStorageValuePrefix {
|
||||
@@ -459,21 +466,22 @@ mod tests {
|
||||
OldStorageMap::insert(3, 4);
|
||||
|
||||
assert_eq!(
|
||||
storage_key_iter::<i32, i32, Twox64Concat>(b"my_old_pallet", b"foo_map").collect::<Vec<_>>(),
|
||||
storage_key_iter::<i32, i32, Twox64Concat>(b"my_old_pallet", b"foo_map")
|
||||
.collect::<Vec<_>>(),
|
||||
vec![(1, 2), (3, 4)],
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
storage_iter(b"my_old_pallet", b"foo_map").drain().map(|t| t.1).collect::<Vec<i32>>(),
|
||||
storage_iter(b"my_old_pallet", b"foo_map")
|
||||
.drain()
|
||||
.map(|t| t.1)
|
||||
.collect::<Vec<i32>>(),
|
||||
vec![2, 4],
|
||||
);
|
||||
assert_eq!(OldStorageMap::iter().collect::<Vec<_>>(), vec![]);
|
||||
|
||||
// Empty because storage iterator skips over the entry under the first key
|
||||
assert_eq!(
|
||||
storage_iter::<i32>(b"my_old_pallet", b"foo_value").drain().next(),
|
||||
None
|
||||
);
|
||||
assert_eq!(storage_iter::<i32>(b"my_old_pallet", b"foo_value").drain().next(), None);
|
||||
assert_eq!(OldStorageValue::get(), Some(3));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -17,31 +17,31 @@
|
||||
|
||||
//! Stuff to do with the runtime's storage.
|
||||
|
||||
use sp_core::storage::ChildInfo;
|
||||
use sp_std::prelude::*;
|
||||
use codec::{FullCodec, FullEncode, Encode, EncodeLike, Decode};
|
||||
use crate::{
|
||||
hash::{Twox128, StorageHasher, ReversibleStorageHasher},
|
||||
hash::{ReversibleStorageHasher, StorageHasher, Twox128},
|
||||
storage::types::{
|
||||
EncodeLikeTuple, HasKeyPrefix, HasReversibleKeyPrefix, KeyGenerator,
|
||||
ReversibleKeyGenerator, TupleToEncodedIter,
|
||||
},
|
||||
};
|
||||
use codec::{Decode, Encode, EncodeLike, FullCodec, FullEncode};
|
||||
use sp_core::storage::ChildInfo;
|
||||
use sp_runtime::generic::{Digest, DigestItem};
|
||||
pub use sp_runtime::TransactionOutcome;
|
||||
use sp_std::prelude::*;
|
||||
pub use types::Key;
|
||||
|
||||
pub mod unhashed;
|
||||
pub mod hashed;
|
||||
pub mod bounded_btree_map;
|
||||
pub mod bounded_btree_set;
|
||||
pub mod bounded_vec;
|
||||
pub mod weak_bounded_vec;
|
||||
pub mod child;
|
||||
#[doc(hidden)]
|
||||
pub mod generator;
|
||||
pub mod hashed;
|
||||
pub mod migration;
|
||||
pub mod types;
|
||||
pub mod unhashed;
|
||||
pub mod weak_bounded_vec;
|
||||
|
||||
#[cfg(all(feature = "std", any(test, debug_assertions)))]
|
||||
mod debug_helper {
|
||||
@@ -101,9 +101,7 @@ pub fn require_transaction() {
|
||||
///
|
||||
/// Transactions can be nested to any depth. Commits happen to the parent transaction.
|
||||
pub fn with_transaction<R>(f: impl FnOnce() -> TransactionOutcome<R>) -> R {
|
||||
use sp_io::storage::{
|
||||
start_transaction, commit_transaction, rollback_transaction,
|
||||
};
|
||||
use sp_io::storage::{commit_transaction, rollback_transaction, start_transaction};
|
||||
use TransactionOutcome::*;
|
||||
|
||||
start_transaction();
|
||||
@@ -112,8 +110,14 @@ pub fn with_transaction<R>(f: impl FnOnce() -> TransactionOutcome<R>) -> R {
|
||||
let _guard = debug_helper::inc_transaction_level();
|
||||
|
||||
match f() {
|
||||
Commit(res) => { commit_transaction(); res },
|
||||
Rollback(res) => { rollback_transaction(); res },
|
||||
Commit(res) => {
|
||||
commit_transaction();
|
||||
res
|
||||
},
|
||||
Rollback(res) => {
|
||||
rollback_transaction();
|
||||
res
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -205,7 +209,10 @@ pub trait StorageValue<T: FullCodec> {
|
||||
///
|
||||
/// `None` does not mean that `get()` does not return a value. The default value is completly
|
||||
/// ignored by this function.
|
||||
fn decode_len() -> Option<usize> where T: StorageDecodeLength {
|
||||
fn decode_len() -> Option<usize>
|
||||
where
|
||||
T: StorageDecodeLength,
|
||||
{
|
||||
T::decode_len(&Self::hashed_key())
|
||||
}
|
||||
}
|
||||
@@ -252,7 +259,10 @@ pub trait StorageMap<K: FullEncode, V: FullCodec> {
|
||||
/// Mutate the value under a key.
|
||||
///
|
||||
/// Deletes the item if mutated to a `None`.
|
||||
fn mutate_exists<KeyArg: EncodeLike<K>, R, F: FnOnce(&mut Option<V>) -> R>(key: KeyArg, f: F) -> R;
|
||||
fn mutate_exists<KeyArg: EncodeLike<K>, R, F: FnOnce(&mut Option<V>) -> R>(
|
||||
key: KeyArg,
|
||||
f: F,
|
||||
) -> R;
|
||||
|
||||
/// Mutate the item, only if an `Ok` value is returned. Deletes the item if mutated to a `None`.
|
||||
fn try_mutate_exists<KeyArg: EncodeLike<K>, R, E, F: FnOnce(&mut Option<V>) -> Result<R, E>>(
|
||||
@@ -292,7 +302,8 @@ pub trait StorageMap<K: FullEncode, V: FullCodec> {
|
||||
/// `None` does not mean that `get()` does not return a value. The default value is completly
|
||||
/// ignored by this function.
|
||||
fn decode_len<KeyArg: EncodeLike<K>>(key: KeyArg) -> Option<usize>
|
||||
where V: StorageDecodeLength,
|
||||
where
|
||||
V: StorageDecodeLength,
|
||||
{
|
||||
V::decode_len(&Self::hashed_key_for(key))
|
||||
}
|
||||
@@ -337,11 +348,9 @@ pub trait IterableStorageMap<K: FullEncode, V: FullCodec>: StorageMap<K, V> {
|
||||
}
|
||||
|
||||
/// A strongly-typed double map in storage whose secondary keys and values can be iterated over.
|
||||
pub trait IterableStorageDoubleMap<
|
||||
K1: FullCodec,
|
||||
K2: FullCodec,
|
||||
V: FullCodec
|
||||
>: StorageDoubleMap<K1, K2, V> {
|
||||
pub trait IterableStorageDoubleMap<K1: FullCodec, K2: FullCodec, V: FullCodec>:
|
||||
StorageDoubleMap<K1, K2, V>
|
||||
{
|
||||
/// The type that iterates over all `key2`.
|
||||
type PartialKeyIterator: Iterator<Item = K2>;
|
||||
|
||||
@@ -401,19 +410,22 @@ pub trait IterableStorageNMap<K: ReversibleKeyGenerator, V: FullCodec>: StorageN
|
||||
/// remove values whose prefix is `kp` to the map while doing this, you'll get undefined
|
||||
/// results.
|
||||
fn iter_prefix<KP>(kp: KP) -> PrefixIterator<(<K as HasKeyPrefix<KP>>::Suffix, V)>
|
||||
where K: HasReversibleKeyPrefix<KP>;
|
||||
where
|
||||
K: HasReversibleKeyPrefix<KP>;
|
||||
|
||||
/// Enumerate all suffix keys in the map with prefix key `kp` in no particular order. If you
|
||||
/// add or remove values whose prefix is `kp` to the map while doing this, you'll get undefined
|
||||
/// results.
|
||||
fn iter_key_prefix<KP>(kp: KP) -> KeyPrefixIterator<<K as HasKeyPrefix<KP>>::Suffix>
|
||||
where K: HasReversibleKeyPrefix<KP>;
|
||||
where
|
||||
K: HasReversibleKeyPrefix<KP>;
|
||||
|
||||
/// Remove all elements from the map with prefix key `kp` and iterate through them in no
|
||||
/// particular order. If you add elements with prefix key `kp` to the map while doing this,
|
||||
/// you'll get undefined results.
|
||||
fn drain_prefix<KP>(kp: KP) -> PrefixIterator<(<K as HasKeyPrefix<KP>>::Suffix, V)>
|
||||
where K: HasReversibleKeyPrefix<KP>;
|
||||
where
|
||||
K: HasReversibleKeyPrefix<KP>;
|
||||
|
||||
/// Enumerate all elements in the map in no particular order. If you add or remove values to
|
||||
/// the map while doing this, you'll get undefined results.
|
||||
@@ -499,11 +511,13 @@ pub trait StorageDoubleMap<K1: FullEncode, K2: FullEncode, V: FullCodec> {
|
||||
|
||||
/// Remove all values under the first key.
|
||||
fn remove_prefix<KArg1>(k1: KArg1, limit: Option<u32>) -> sp_io::KillStorageResult
|
||||
where KArg1: ?Sized + EncodeLike<K1>;
|
||||
where
|
||||
KArg1: ?Sized + EncodeLike<K1>;
|
||||
|
||||
/// Iterate over values that share the first key.
|
||||
fn iter_prefix_values<KArg1>(k1: KArg1) -> PrefixIterator<V>
|
||||
where KArg1: ?Sized + EncodeLike<K1>;
|
||||
where
|
||||
KArg1: ?Sized + EncodeLike<K1>;
|
||||
|
||||
/// Mutate the value under the given keys.
|
||||
fn mutate<KArg1, KArg2, R, F>(k1: KArg1, k2: KArg2, f: F) -> R
|
||||
@@ -542,11 +556,8 @@ pub trait StorageDoubleMap<K1: FullEncode, K2: FullEncode, V: FullCodec> {
|
||||
/// If the storage item is not encoded properly, the storage will be overwritten
|
||||
/// and set to `[item]`. Any default value set for the storage item will be ignored
|
||||
/// on overwrite.
|
||||
fn append<Item, EncodeLikeItem, KArg1, KArg2>(
|
||||
k1: KArg1,
|
||||
k2: KArg2,
|
||||
item: EncodeLikeItem,
|
||||
) where
|
||||
fn append<Item, EncodeLikeItem, KArg1, KArg2>(k1: KArg1, k2: KArg2, item: EncodeLikeItem)
|
||||
where
|
||||
KArg1: EncodeLike<K1>,
|
||||
KArg2: EncodeLike<K2>,
|
||||
Item: Encode,
|
||||
@@ -566,10 +577,10 @@ pub trait StorageDoubleMap<K1: FullEncode, K2: FullEncode, V: FullCodec> {
|
||||
/// `None` does not mean that `get()` does not return a value. The default value is completly
|
||||
/// ignored by this function.
|
||||
fn decode_len<KArg1, KArg2>(key1: KArg1, key2: KArg2) -> Option<usize>
|
||||
where
|
||||
KArg1: EncodeLike<K1>,
|
||||
KArg2: EncodeLike<K2>,
|
||||
V: StorageDecodeLength,
|
||||
where
|
||||
KArg1: EncodeLike<K1>,
|
||||
KArg2: EncodeLike<K2>,
|
||||
V: StorageDecodeLength,
|
||||
{
|
||||
V::decode_len(&Self::hashed_key_for(key1, key2))
|
||||
}
|
||||
@@ -583,7 +594,10 @@ pub trait StorageDoubleMap<K1: FullEncode, K2: FullEncode, V: FullCodec> {
|
||||
OldHasher2: StorageHasher,
|
||||
KeyArg1: EncodeLike<K1>,
|
||||
KeyArg2: EncodeLike<K2>,
|
||||
>(key1: KeyArg1, key2: KeyArg2) -> Option<V>;
|
||||
>(
|
||||
key1: KeyArg1,
|
||||
key2: KeyArg2,
|
||||
) -> Option<V>;
|
||||
}
|
||||
|
||||
/// An implementation of a map with an arbitrary number of keys.
|
||||
@@ -625,10 +639,13 @@ pub trait StorageNMap<K: KeyGenerator, V: FullCodec> {
|
||||
|
||||
/// Remove all values under the partial prefix key.
|
||||
fn remove_prefix<KP>(partial_key: KP, limit: Option<u32>) -> sp_io::KillStorageResult
|
||||
where K: HasKeyPrefix<KP>;
|
||||
where
|
||||
K: HasKeyPrefix<KP>;
|
||||
|
||||
/// Iterate over values that share the partial prefix key.
|
||||
fn iter_prefix_values<KP>(partial_key: KP) -> PrefixIterator<V> where K: HasKeyPrefix<KP>;
|
||||
fn iter_prefix_values<KP>(partial_key: KP) -> PrefixIterator<V>
|
||||
where
|
||||
K: HasKeyPrefix<KP>;
|
||||
|
||||
/// Mutate the value under a key.
|
||||
fn mutate<KArg, R, F>(key: KArg, f: F) -> R
|
||||
@@ -741,7 +758,7 @@ impl<T> Iterator for PrefixIterator<T> {
|
||||
self.previous_key,
|
||||
);
|
||||
continue
|
||||
}
|
||||
},
|
||||
};
|
||||
if self.drain {
|
||||
unhashed::kill(&self.previous_key)
|
||||
@@ -756,11 +773,11 @@ impl<T> Iterator for PrefixIterator<T> {
|
||||
e,
|
||||
);
|
||||
continue
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
Some(item)
|
||||
}
|
||||
},
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
@@ -807,12 +824,12 @@ impl<T> Iterator for KeyPrefixIterator<T> {
|
||||
Ok(item) => return Some(item),
|
||||
Err(e) => {
|
||||
log::error!("key failed to decode at {:?}: {:?}", self.previous_key, e);
|
||||
continue;
|
||||
}
|
||||
continue
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
return None;
|
||||
return None
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -871,7 +888,10 @@ impl<K: Decode + Sized, T: Decode + Sized> ChildTriePrefixIterator<(K, T)> {
|
||||
/// Construct iterator to iterate over child trie items in `child_info` with the prefix `prefix`.
|
||||
///
|
||||
/// NOTE: Iterator with [`Self::drain`] will remove any key or value who failed to decode
|
||||
pub fn with_prefix_over_key<H: ReversibleStorageHasher>(child_info: &ChildInfo, prefix: &[u8]) -> Self {
|
||||
pub fn with_prefix_over_key<H: ReversibleStorageHasher>(
|
||||
child_info: &ChildInfo,
|
||||
prefix: &[u8],
|
||||
) -> Self {
|
||||
let prefix = prefix.to_vec();
|
||||
let previous_key = prefix.clone();
|
||||
let closure = |raw_key_without_prefix: &[u8], raw_value: &[u8]| {
|
||||
@@ -888,7 +908,7 @@ impl<K: Decode + Sized, T: Decode + Sized> ChildTriePrefixIterator<(K, T)> {
|
||||
drain: false,
|
||||
fetch_previous_key: true,
|
||||
closure,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -905,7 +925,7 @@ impl<T> Iterator for ChildTriePrefixIterator<T> {
|
||||
&self.child_info.storage_key(),
|
||||
&self.previous_key,
|
||||
)
|
||||
.filter(|n| n.starts_with(&self.prefix))
|
||||
.filter(|n| n.starts_with(&self.prefix))
|
||||
};
|
||||
break match maybe_next {
|
||||
Some(next) => {
|
||||
@@ -918,7 +938,7 @@ impl<T> Iterator for ChildTriePrefixIterator<T> {
|
||||
self.previous_key,
|
||||
);
|
||||
continue
|
||||
}
|
||||
},
|
||||
};
|
||||
if self.drain {
|
||||
child::kill(&self.child_info, &self.previous_key)
|
||||
@@ -933,11 +953,11 @@ impl<T> Iterator for ChildTriePrefixIterator<T> {
|
||||
e,
|
||||
);
|
||||
continue
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
Some(item)
|
||||
}
|
||||
},
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
@@ -999,8 +1019,8 @@ pub trait StoragePrefixedMap<Value: FullCodec> {
|
||||
fn translate_values<OldValue: Decode, F: FnMut(OldValue) -> Option<Value>>(mut f: F) {
|
||||
let prefix = Self::final_prefix();
|
||||
let mut previous_key = prefix.clone().to_vec();
|
||||
while let Some(next) = sp_io::storage::next_key(&previous_key)
|
||||
.filter(|n| n.starts_with(&prefix))
|
||||
while let Some(next) =
|
||||
sp_io::storage::next_key(&previous_key).filter(|n| n.starts_with(&prefix))
|
||||
{
|
||||
previous_key = next;
|
||||
let maybe_value = unhashed::get::<OldValue>(&previous_key);
|
||||
@@ -1010,10 +1030,7 @@ pub trait StoragePrefixedMap<Value: FullCodec> {
|
||||
None => unhashed::kill(&previous_key),
|
||||
},
|
||||
None => {
|
||||
log::error!(
|
||||
"old key failed to decode at {:?}",
|
||||
previous_key,
|
||||
);
|
||||
log::error!("old key failed to decode at {:?}", previous_key,);
|
||||
continue
|
||||
},
|
||||
}
|
||||
@@ -1218,13 +1235,13 @@ where
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use sp_core::hashing::twox_128;
|
||||
use crate::{hash::Identity, assert_ok};
|
||||
use sp_io::TestExternalities;
|
||||
use generator::StorageValue as _;
|
||||
use crate::{assert_ok, hash::Identity};
|
||||
use bounded_vec::BoundedVec;
|
||||
use weak_bounded_vec::WeakBoundedVec;
|
||||
use core::convert::{TryFrom, TryInto};
|
||||
use generator::StorageValue as _;
|
||||
use sp_core::hashing::twox_128;
|
||||
use sp_io::TestExternalities;
|
||||
use weak_bounded_vec::WeakBoundedVec;
|
||||
|
||||
#[test]
|
||||
fn prefixed_map_works() {
|
||||
@@ -1363,8 +1380,7 @@ mod test {
|
||||
#[test]
|
||||
fn key_prefix_iterator_works() {
|
||||
TestExternalities::default().execute_with(|| {
|
||||
use crate::storage::generator::StorageMap;
|
||||
use crate::hash::Twox64Concat;
|
||||
use crate::{hash::Twox64Concat, storage::generator::StorageMap};
|
||||
struct MyStorageMap;
|
||||
impl StorageMap<u64, u64> for MyStorageMap {
|
||||
type Query = u64;
|
||||
@@ -1426,30 +1442,21 @@ mod test {
|
||||
assert_eq!(
|
||||
ChildTriePrefixIterator::with_prefix(&child_info_a, &[2])
|
||||
.collect::<Vec<(Vec<u8>, u16)>>(),
|
||||
vec![
|
||||
(vec![], 8),
|
||||
(vec![2, 3], 8),
|
||||
],
|
||||
vec![(vec![], 8), (vec![2, 3], 8),],
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
ChildTriePrefixIterator::with_prefix(&child_info_a, &[2])
|
||||
.drain()
|
||||
.collect::<Vec<(Vec<u8>, u16)>>(),
|
||||
vec![
|
||||
(vec![], 8),
|
||||
(vec![2, 3], 8),
|
||||
],
|
||||
vec![(vec![], 8), (vec![2, 3], 8),],
|
||||
);
|
||||
|
||||
// The only remaining is the ones outside prefix
|
||||
assert_eq!(
|
||||
ChildTriePrefixIterator::with_prefix(&child_info_a, &[])
|
||||
.collect::<Vec<(Vec<u8>, u8)>>(),
|
||||
vec![
|
||||
(vec![1, 2, 3], 8),
|
||||
(vec![3], 8),
|
||||
],
|
||||
vec![(vec![1, 2, 3], 8), (vec![3], 8),],
|
||||
);
|
||||
|
||||
child::put(&child_info_a, &[1, 2, 3], &8u16);
|
||||
@@ -1461,28 +1468,21 @@ mod test {
|
||||
assert_eq!(
|
||||
ChildTriePrefixIterator::with_prefix_over_key::<Identity>(&child_info_a, &[2])
|
||||
.collect::<Vec<(u16, u16)>>(),
|
||||
vec![
|
||||
(u16::decode(&mut &[2, 3][..]).unwrap(), 8),
|
||||
],
|
||||
vec![(u16::decode(&mut &[2, 3][..]).unwrap(), 8),],
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
ChildTriePrefixIterator::with_prefix_over_key::<Identity>(&child_info_a, &[2])
|
||||
.drain()
|
||||
.collect::<Vec<(u16, u16)>>(),
|
||||
vec![
|
||||
(u16::decode(&mut &[2, 3][..]).unwrap(), 8),
|
||||
],
|
||||
vec![(u16::decode(&mut &[2, 3][..]).unwrap(), 8),],
|
||||
);
|
||||
|
||||
// The only remaining is the ones outside prefix
|
||||
assert_eq!(
|
||||
ChildTriePrefixIterator::with_prefix(&child_info_a, &[])
|
||||
.collect::<Vec<(Vec<u8>, u8)>>(),
|
||||
vec![
|
||||
(vec![1, 2, 3], 8),
|
||||
(vec![3], 8),
|
||||
],
|
||||
vec![(vec![1, 2, 3], 8), (vec![3], 8),],
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -18,14 +18,14 @@
|
||||
//! Storage map type. Implements StorageDoubleMap, StorageIterableDoubleMap,
|
||||
//! StoragePrefixedDoubleMap traits and their methods directly.
|
||||
|
||||
use codec::{Decode, Encode, EncodeLike, FullCodec, MaxEncodedLen};
|
||||
use crate::{
|
||||
storage::{
|
||||
StorageAppend, StorageTryAppend, StorageDecodeLength, StoragePrefixedMap,
|
||||
types::{OptionQuery, QueryKindTrait, OnEmptyGetter},
|
||||
types::{OnEmptyGetter, OptionQuery, QueryKindTrait},
|
||||
StorageAppend, StorageDecodeLength, StoragePrefixedMap, StorageTryAppend,
|
||||
},
|
||||
traits::{GetDefault, StorageInstance, Get, StorageInfo},
|
||||
traits::{Get, GetDefault, StorageInfo, StorageInstance},
|
||||
};
|
||||
use codec::{Decode, Encode, EncodeLike, FullCodec, MaxEncodedLen};
|
||||
use frame_metadata::{DefaultByteGetter, StorageEntryModifier};
|
||||
use sp_arithmetic::traits::SaturatedConversion;
|
||||
use sp_std::prelude::*;
|
||||
@@ -36,9 +36,9 @@ use sp_std::prelude::*;
|
||||
/// Each value is stored at:
|
||||
/// ```nocompile
|
||||
/// Twox128(Prefix::pallet_prefix())
|
||||
/// ++ Twox128(Prefix::STORAGE_PREFIX)
|
||||
/// ++ Hasher1(encode(key1))
|
||||
/// ++ Hasher2(encode(key2))
|
||||
/// ++ Twox128(Prefix::STORAGE_PREFIX)
|
||||
/// ++ Hasher1(encode(key1))
|
||||
/// ++ Hasher2(encode(key2))
|
||||
/// ```
|
||||
///
|
||||
/// # Warning
|
||||
@@ -53,18 +53,26 @@ pub struct StorageDoubleMap<
|
||||
Hasher2,
|
||||
Key2,
|
||||
Value,
|
||||
QueryKind=OptionQuery,
|
||||
OnEmpty=GetDefault,
|
||||
MaxValues=GetDefault,
|
||||
QueryKind = OptionQuery,
|
||||
OnEmpty = GetDefault,
|
||||
MaxValues = GetDefault,
|
||||
>(
|
||||
core::marker::PhantomData<
|
||||
(Prefix, Hasher1, Key1, Hasher2, Key2, Value, QueryKind, OnEmpty, MaxValues)
|
||||
>
|
||||
core::marker::PhantomData<(
|
||||
Prefix,
|
||||
Hasher1,
|
||||
Key1,
|
||||
Hasher2,
|
||||
Key2,
|
||||
Value,
|
||||
QueryKind,
|
||||
OnEmpty,
|
||||
MaxValues,
|
||||
)>,
|
||||
);
|
||||
|
||||
impl<Prefix, Hasher1, Key1, Hasher2, Key2, Value, QueryKind, OnEmpty, MaxValues>
|
||||
crate::storage::generator::StorageDoubleMap<Key1, Key2, Value> for
|
||||
StorageDoubleMap<Prefix, Hasher1, Key1, Hasher2, Key2, Value, QueryKind, OnEmpty, MaxValues>
|
||||
crate::storage::generator::StorageDoubleMap<Key1, Key2, Value>
|
||||
for StorageDoubleMap<Prefix, Hasher1, Key1, Hasher2, Key2, Value, QueryKind, OnEmpty, MaxValues>
|
||||
where
|
||||
Prefix: StorageInstance,
|
||||
Hasher1: crate::hash::StorageHasher,
|
||||
@@ -94,8 +102,8 @@ where
|
||||
}
|
||||
|
||||
impl<Prefix, Hasher1, Key1, Hasher2, Key2, Value, QueryKind, OnEmpty, MaxValues>
|
||||
StoragePrefixedMap<Value> for
|
||||
StorageDoubleMap<Prefix, Hasher1, Key1, Hasher2, Key2, Value, QueryKind, OnEmpty, MaxValues>
|
||||
StoragePrefixedMap<Value>
|
||||
for StorageDoubleMap<Prefix, Hasher1, Key1, Hasher2, Key2, Value, QueryKind, OnEmpty, MaxValues>
|
||||
where
|
||||
Prefix: StorageInstance,
|
||||
Hasher1: crate::hash::StorageHasher,
|
||||
@@ -161,7 +169,8 @@ where
|
||||
pub fn try_get<KArg1, KArg2>(k1: KArg1, k2: KArg2) -> Result<Value, ()>
|
||||
where
|
||||
KArg1: EncodeLike<Key1>,
|
||||
KArg2: EncodeLike<Key2> {
|
||||
KArg2: EncodeLike<Key2>,
|
||||
{
|
||||
<Self as crate::storage::StorageDoubleMap<Key1, Key2, Value>>::try_get(k1, k2)
|
||||
}
|
||||
|
||||
@@ -175,8 +184,12 @@ where
|
||||
}
|
||||
|
||||
/// Swap the values of two key-pairs.
|
||||
pub fn swap<XKArg1, XKArg2, YKArg1, YKArg2>(x_k1: XKArg1, x_k2: XKArg2, y_k1: YKArg1, y_k2: YKArg2)
|
||||
where
|
||||
pub fn swap<XKArg1, XKArg2, YKArg1, YKArg2>(
|
||||
x_k1: XKArg1,
|
||||
x_k2: XKArg2,
|
||||
y_k1: YKArg1,
|
||||
y_k2: YKArg2,
|
||||
) where
|
||||
XKArg1: EncodeLike<Key1>,
|
||||
XKArg2: EncodeLike<Key2>,
|
||||
YKArg1: EncodeLike<Key1>,
|
||||
@@ -206,13 +219,16 @@ where
|
||||
|
||||
/// Remove all values under the first key.
|
||||
pub fn remove_prefix<KArg1>(k1: KArg1, limit: Option<u32>) -> sp_io::KillStorageResult
|
||||
where KArg1: ?Sized + EncodeLike<Key1> {
|
||||
where
|
||||
KArg1: ?Sized + EncodeLike<Key1>,
|
||||
{
|
||||
<Self as crate::storage::StorageDoubleMap<Key1, Key2, Value>>::remove_prefix(k1, limit)
|
||||
}
|
||||
|
||||
/// Iterate over values that share the first key.
|
||||
pub fn iter_prefix_values<KArg1>(k1: KArg1) -> crate::storage::PrefixIterator<Value>
|
||||
where KArg1: ?Sized + EncodeLike<Key1>
|
||||
where
|
||||
KArg1: ?Sized + EncodeLike<Key1>,
|
||||
{
|
||||
<Self as crate::storage::StorageDoubleMap<Key1, Key2, Value>>::iter_prefix_values(k1)
|
||||
}
|
||||
@@ -266,11 +282,8 @@ where
|
||||
/// If the storage item is not encoded properly, the storage will be overwritten
|
||||
/// and set to `[item]`. Any default value set for the storage item will be ignored
|
||||
/// on overwrite.
|
||||
pub fn append<Item, EncodeLikeItem, KArg1, KArg2>(
|
||||
k1: KArg1,
|
||||
k2: KArg2,
|
||||
item: EncodeLikeItem,
|
||||
) where
|
||||
pub fn append<Item, EncodeLikeItem, KArg1, KArg2>(k1: KArg1, k2: KArg2, item: EncodeLikeItem)
|
||||
where
|
||||
KArg1: EncodeLike<Key1>,
|
||||
KArg2: EncodeLike<Key2>,
|
||||
Item: Encode,
|
||||
@@ -310,10 +323,16 @@ where
|
||||
OldHasher2: crate::StorageHasher,
|
||||
KeyArg1: EncodeLike<Key1>,
|
||||
KeyArg2: EncodeLike<Key2>,
|
||||
>(key1: KeyArg1, key2: KeyArg2) -> Option<Value> {
|
||||
<
|
||||
Self as crate::storage::StorageDoubleMap<Key1, Key2, Value>
|
||||
>::migrate_keys::<OldHasher1, OldHasher2, _, _>(key1, key2)
|
||||
>(
|
||||
key1: KeyArg1,
|
||||
key2: KeyArg2,
|
||||
) -> Option<Value> {
|
||||
<Self as crate::storage::StorageDoubleMap<Key1, Key2, Value>>::migrate_keys::<
|
||||
OldHasher1,
|
||||
OldHasher2,
|
||||
_,
|
||||
_,
|
||||
>(key1, key2)
|
||||
}
|
||||
|
||||
/// Remove all value of the storage.
|
||||
@@ -360,9 +379,9 @@ where
|
||||
EncodeLikeItem: EncodeLike<Item>,
|
||||
Value: StorageTryAppend<Item>,
|
||||
{
|
||||
<
|
||||
Self as crate::storage::TryAppendDoubleMap<Key1, Key2, Value, Item>
|
||||
>::try_append(key1, key2, item)
|
||||
<Self as crate::storage::TryAppendDoubleMap<Key1, Key2, Value, Item>>::try_append(
|
||||
key1, key2, item,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -401,7 +420,9 @@ where
|
||||
///
|
||||
/// If you add elements with first key `k1` to the map while doing this, you'll get undefined
|
||||
/// results.
|
||||
pub fn drain_prefix(k1: impl EncodeLike<Key1>) -> crate::storage::PrefixIterator<(Key2, Value)> {
|
||||
pub fn drain_prefix(
|
||||
k1: impl EncodeLike<Key1>,
|
||||
) -> crate::storage::PrefixIterator<(Key2, Value)> {
|
||||
<Self as crate::storage::IterableStorageDoubleMap<Key1, Key2, Value>>::drain_prefix(k1)
|
||||
}
|
||||
|
||||
@@ -448,8 +469,8 @@ pub trait StorageDoubleMapMetadata {
|
||||
}
|
||||
|
||||
impl<Prefix, Hasher1, Hasher2, Key1, Key2, Value, QueryKind, OnEmpty, MaxValues>
|
||||
StorageDoubleMapMetadata for
|
||||
StorageDoubleMap<Prefix, Hasher1, Key1, Hasher2, Key2, Value, QueryKind, OnEmpty, MaxValues>
|
||||
StorageDoubleMapMetadata
|
||||
for StorageDoubleMap<Prefix, Hasher1, Key1, Hasher2, Key2, Value, QueryKind, OnEmpty, MaxValues>
|
||||
where
|
||||
Prefix: StorageInstance,
|
||||
Hasher1: crate::hash::StorageHasher,
|
||||
@@ -470,8 +491,8 @@ where
|
||||
}
|
||||
|
||||
impl<Prefix, Hasher1, Hasher2, Key1, Key2, Value, QueryKind, OnEmpty, MaxValues>
|
||||
crate::traits::StorageInfoTrait for
|
||||
StorageDoubleMap<Prefix, Hasher1, Key1, Hasher2, Key2, Value, QueryKind, OnEmpty, MaxValues>
|
||||
crate::traits::StorageInfoTrait
|
||||
for StorageDoubleMap<Prefix, Hasher1, Key1, Hasher2, Key2, Value, QueryKind, OnEmpty, MaxValues>
|
||||
where
|
||||
Prefix: StorageInstance,
|
||||
Hasher1: crate::hash::StorageHasher,
|
||||
@@ -484,27 +505,25 @@ where
|
||||
MaxValues: Get<Option<u32>>,
|
||||
{
|
||||
fn storage_info() -> Vec<StorageInfo> {
|
||||
vec![
|
||||
StorageInfo {
|
||||
pallet_name: Self::module_prefix().to_vec(),
|
||||
storage_name: Self::storage_prefix().to_vec(),
|
||||
prefix: Self::final_prefix().to_vec(),
|
||||
max_values: MaxValues::get(),
|
||||
max_size: Some(
|
||||
Hasher1::max_len::<Key1>()
|
||||
.saturating_add(Hasher2::max_len::<Key2>())
|
||||
.saturating_add(Value::max_encoded_len())
|
||||
.saturated_into(),
|
||||
),
|
||||
}
|
||||
]
|
||||
vec![StorageInfo {
|
||||
pallet_name: Self::module_prefix().to_vec(),
|
||||
storage_name: Self::storage_prefix().to_vec(),
|
||||
prefix: Self::final_prefix().to_vec(),
|
||||
max_values: MaxValues::get(),
|
||||
max_size: Some(
|
||||
Hasher1::max_len::<Key1>()
|
||||
.saturating_add(Hasher2::max_len::<Key2>())
|
||||
.saturating_add(Value::max_encoded_len())
|
||||
.saturated_into(),
|
||||
),
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
||||
/// It doesn't require to implement `MaxEncodedLen` and give no information for `max_size`.
|
||||
impl<Prefix, Hasher1, Hasher2, Key1, Key2, Value, QueryKind, OnEmpty, MaxValues>
|
||||
crate::traits::PartialStorageInfoTrait for
|
||||
StorageDoubleMap<Prefix, Hasher1, Key1, Hasher2, Key2, Value, QueryKind, OnEmpty, MaxValues>
|
||||
crate::traits::PartialStorageInfoTrait
|
||||
for StorageDoubleMap<Prefix, Hasher1, Key1, Hasher2, Key2, Value, QueryKind, OnEmpty, MaxValues>
|
||||
where
|
||||
Prefix: StorageInstance,
|
||||
Hasher1: crate::hash::StorageHasher,
|
||||
@@ -517,29 +536,28 @@ where
|
||||
MaxValues: Get<Option<u32>>,
|
||||
{
|
||||
fn partial_storage_info() -> Vec<StorageInfo> {
|
||||
vec![
|
||||
StorageInfo {
|
||||
pallet_name: Self::module_prefix().to_vec(),
|
||||
storage_name: Self::storage_prefix().to_vec(),
|
||||
prefix: Self::final_prefix().to_vec(),
|
||||
max_values: MaxValues::get(),
|
||||
max_size: None
|
||||
}
|
||||
]
|
||||
vec![StorageInfo {
|
||||
pallet_name: Self::module_prefix().to_vec(),
|
||||
storage_name: Self::storage_prefix().to_vec(),
|
||||
prefix: Self::final_prefix().to_vec(),
|
||||
max_values: MaxValues::get(),
|
||||
max_size: None,
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use sp_io::{TestExternalities, hashing::twox_128};
|
||||
use crate::hash::*;
|
||||
use crate::storage::types::ValueQuery;
|
||||
use crate::{hash::*, storage::types::ValueQuery};
|
||||
use frame_metadata::StorageEntryModifier;
|
||||
use sp_io::{hashing::twox_128, TestExternalities};
|
||||
|
||||
struct Prefix;
|
||||
impl StorageInstance for Prefix {
|
||||
fn pallet_prefix() -> &'static str { "test" }
|
||||
fn pallet_prefix() -> &'static str {
|
||||
"test"
|
||||
}
|
||||
const STORAGE_PREFIX: &'static str = "foo";
|
||||
}
|
||||
|
||||
@@ -552,11 +570,17 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn test() {
|
||||
type A = StorageDoubleMap<
|
||||
Prefix, Blake2_128Concat, u16, Twox64Concat, u8, u32, OptionQuery
|
||||
>;
|
||||
type A =
|
||||
StorageDoubleMap<Prefix, Blake2_128Concat, u16, Twox64Concat, u8, u32, OptionQuery>;
|
||||
type AValueQueryWithAnOnEmpty = StorageDoubleMap<
|
||||
Prefix, Blake2_128Concat, u16, Twox64Concat, u8, u32, ValueQuery, ADefault
|
||||
Prefix,
|
||||
Blake2_128Concat,
|
||||
u16,
|
||||
Twox64Concat,
|
||||
u8,
|
||||
u32,
|
||||
ValueQuery,
|
||||
ADefault,
|
||||
>;
|
||||
type B = StorageDoubleMap<Prefix, Blake2_256, u16, Twox128, u8, u32, ValueQuery>;
|
||||
type C = StorageDoubleMap<Prefix, Blake2_128Concat, u16, Twox64Concat, u8, u8, ValueQuery>;
|
||||
@@ -598,17 +622,20 @@ mod test {
|
||||
|
||||
A::remove(2, 20);
|
||||
let _: Result<(), ()> = AValueQueryWithAnOnEmpty::try_mutate(2, 20, |v| {
|
||||
*v = *v * 2; Ok(())
|
||||
*v = *v * 2;
|
||||
Ok(())
|
||||
});
|
||||
let _: Result<(), ()> = AValueQueryWithAnOnEmpty::try_mutate(2, 20, |v| {
|
||||
*v = *v * 2; Ok(())
|
||||
*v = *v * 2;
|
||||
Ok(())
|
||||
});
|
||||
assert_eq!(A::contains_key(2, 20), true);
|
||||
assert_eq!(A::get(2, 20), Some(97 * 4));
|
||||
|
||||
A::remove(2, 20);
|
||||
let _: Result<(), ()> = AValueQueryWithAnOnEmpty::try_mutate(2, 20, |v| {
|
||||
*v = *v * 2; Err(())
|
||||
*v = *v * 2;
|
||||
Err(())
|
||||
});
|
||||
assert_eq!(A::contains_key(2, 20), false);
|
||||
|
||||
@@ -647,7 +674,6 @@ mod test {
|
||||
assert_eq!(A::contains_key(2, 20), true);
|
||||
assert_eq!(A::get(2, 20), Some(100));
|
||||
|
||||
|
||||
A::insert(2, 20, 10);
|
||||
assert_eq!(A::take(2, 20), Some(10));
|
||||
assert_eq!(A::contains_key(2, 20), false);
|
||||
@@ -672,7 +698,7 @@ mod test {
|
||||
|
||||
C::insert(3, 30, 10);
|
||||
C::insert(4, 40, 10);
|
||||
A::translate_values::<u8,_>(|v| Some((v * 2).into()));
|
||||
A::translate_values::<u8, _>(|v| Some((v * 2).into()));
|
||||
assert_eq!(A::iter().collect::<Vec<_>>(), vec![(4, 40, 20), (3, 30, 20)]);
|
||||
|
||||
A::insert(3, 30, 10);
|
||||
@@ -683,7 +709,7 @@ mod test {
|
||||
|
||||
C::insert(3, 30, 10);
|
||||
C::insert(4, 40, 10);
|
||||
A::translate::<u8,_>(|k1, k2, v| Some((k1 * k2 as u16 * v as u16).into()));
|
||||
A::translate::<u8, _>(|k1, k2, v| Some((k1 * k2 as u16 * v as u16).into()));
|
||||
assert_eq!(A::iter().collect::<Vec<_>>(), vec![(4, 40, 1600), (3, 30, 900)]);
|
||||
|
||||
assert_eq!(A::MODIFIER, StorageEntryModifier::Optional);
|
||||
|
||||
@@ -75,24 +75,16 @@ impl<H: StorageHasher, K: FullCodec> KeyGenerator for Key<H, K> {
|
||||
const HASHER_METADATA: &'static [frame_metadata::StorageHasher] = &[H::METADATA];
|
||||
|
||||
fn final_key<KArg: EncodeLikeTuple<Self::KArg> + TupleToEncodedIter>(key: KArg) -> Vec<u8> {
|
||||
H::hash(
|
||||
&key.to_encoded_iter()
|
||||
.next()
|
||||
.expect("should have at least one element!"),
|
||||
)
|
||||
.as_ref()
|
||||
.to_vec()
|
||||
H::hash(&key.to_encoded_iter().next().expect("should have at least one element!"))
|
||||
.as_ref()
|
||||
.to_vec()
|
||||
}
|
||||
|
||||
fn migrate_key<KArg: EncodeLikeTuple<Self::KArg> + TupleToEncodedIter>(
|
||||
key: &KArg,
|
||||
hash_fns: Self::HArg,
|
||||
) -> Vec<u8> {
|
||||
(hash_fns.0)(
|
||||
&key.to_encoded_iter()
|
||||
.next()
|
||||
.expect("should have at least one element!"),
|
||||
)
|
||||
(hash_fns.0)(&key.to_encoded_iter().next().expect("should have at least one element!"))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,9 +110,8 @@ impl KeyGenerator for Tuple {
|
||||
for_tuples!( type HArg = ( #(Tuple::HashFn),* ); );
|
||||
type HashFn = Box<dyn FnOnce(&[u8]) -> Vec<u8>>;
|
||||
|
||||
const HASHER_METADATA: &'static [frame_metadata::StorageHasher] = &[
|
||||
for_tuples!( #(Tuple::Hasher::METADATA),* )
|
||||
];
|
||||
const HASHER_METADATA: &'static [frame_metadata::StorageHasher] =
|
||||
&[for_tuples!( #(Tuple::Hasher::METADATA),* )];
|
||||
|
||||
fn final_key<KArg: EncodeLikeTuple<Self::KArg> + TupleToEncodedIter>(key: KArg) -> Vec<u8> {
|
||||
let mut final_key = Vec::new();
|
||||
@@ -210,9 +201,7 @@ pub trait TupleToEncodedIter {
|
||||
#[tuple_types_custom_trait_bound(Encode)]
|
||||
impl TupleToEncodedIter for Tuple {
|
||||
fn to_encoded_iter(&self) -> sp_std::vec::IntoIter<Vec<u8>> {
|
||||
[for_tuples!( #(self.Tuple.encode()),* )]
|
||||
.to_vec()
|
||||
.into_iter()
|
||||
[for_tuples!( #(self.Tuple.encode()),* )].to_vec().into_iter()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -246,7 +235,7 @@ impl ReversibleKeyGenerator for Tuple {
|
||||
fn decode_final_key(key_material: &[u8]) -> Result<(Self::Key, &[u8]), codec::Error> {
|
||||
let mut current_key_material = key_material;
|
||||
Ok((
|
||||
(for_tuples!{
|
||||
(for_tuples! {
|
||||
#({
|
||||
let (key, material) = Tuple::decode_final_key(current_key_material)?;
|
||||
current_key_material = material;
|
||||
|
||||
@@ -18,14 +18,14 @@
|
||||
//! Storage map type. Implements StorageMap, StorageIterableMap, StoragePrefixedMap traits and their
|
||||
//! methods directly.
|
||||
|
||||
use codec::{FullCodec, Decode, EncodeLike, Encode, MaxEncodedLen};
|
||||
use crate::{
|
||||
storage::{
|
||||
StorageAppend, StorageTryAppend, StorageDecodeLength, StoragePrefixedMap,
|
||||
types::{OptionQuery, QueryKindTrait, OnEmptyGetter},
|
||||
types::{OnEmptyGetter, OptionQuery, QueryKindTrait},
|
||||
StorageAppend, StorageDecodeLength, StoragePrefixedMap, StorageTryAppend,
|
||||
},
|
||||
traits::{GetDefault, StorageInstance, Get, StorageInfo},
|
||||
traits::{Get, GetDefault, StorageInfo, StorageInstance},
|
||||
};
|
||||
use codec::{Decode, Encode, EncodeLike, FullCodec, MaxEncodedLen};
|
||||
use frame_metadata::{DefaultByteGetter, StorageEntryModifier};
|
||||
use sp_arithmetic::traits::SaturatedConversion;
|
||||
use sp_std::prelude::*;
|
||||
@@ -35,8 +35,8 @@ use sp_std::prelude::*;
|
||||
/// Each value is stored at:
|
||||
/// ```nocompile
|
||||
/// Twox128(Prefix::pallet_prefix())
|
||||
/// ++ Twox128(Prefix::STORAGE_PREFIX)
|
||||
/// ++ Hasher1(encode(key))
|
||||
/// ++ Twox128(Prefix::STORAGE_PREFIX)
|
||||
/// ++ Hasher1(encode(key))
|
||||
/// ```
|
||||
///
|
||||
/// # Warning
|
||||
@@ -44,10 +44,14 @@ use sp_std::prelude::*;
|
||||
/// If the keys are not trusted (e.g. can be set by a user), a cryptographic `hasher` such as
|
||||
/// `blake2_128_concat` must be used. Otherwise, other values in storage can be compromised.
|
||||
pub struct StorageMap<
|
||||
Prefix, Hasher, Key, Value, QueryKind=OptionQuery, OnEmpty=GetDefault, MaxValues=GetDefault,
|
||||
>(
|
||||
core::marker::PhantomData<(Prefix, Hasher, Key, Value, QueryKind, OnEmpty, MaxValues)>
|
||||
);
|
||||
Prefix,
|
||||
Hasher,
|
||||
Key,
|
||||
Value,
|
||||
QueryKind = OptionQuery,
|
||||
OnEmpty = GetDefault,
|
||||
MaxValues = GetDefault,
|
||||
>(core::marker::PhantomData<(Prefix, Hasher, Key, Value, QueryKind, OnEmpty, MaxValues)>);
|
||||
|
||||
impl<Prefix, Hasher, Key, Value, QueryKind, OnEmpty, MaxValues>
|
||||
crate::storage::generator::StorageMap<Key, Value>
|
||||
@@ -77,9 +81,8 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<Prefix, Hasher, Key, Value, QueryKind, OnEmpty, MaxValues>
|
||||
StoragePrefixedMap<Value> for
|
||||
StorageMap<Prefix, Hasher, Key, Value, QueryKind, OnEmpty, MaxValues>
|
||||
impl<Prefix, Hasher, Key, Value, QueryKind, OnEmpty, MaxValues> StoragePrefixedMap<Value>
|
||||
for StorageMap<Prefix, Hasher, Key, Value, QueryKind, OnEmpty, MaxValues>
|
||||
where
|
||||
Prefix: StorageInstance,
|
||||
Hasher: crate::hash::StorageHasher,
|
||||
@@ -148,7 +151,7 @@ where
|
||||
/// Mutate the value under a key.
|
||||
pub fn mutate<KeyArg: EncodeLike<Key>, R, F: FnOnce(&mut QueryKind::Query) -> R>(
|
||||
key: KeyArg,
|
||||
f: F
|
||||
f: F,
|
||||
) -> R {
|
||||
<Self as crate::storage::StorageMap<Key, Value>>::mutate(key, f)
|
||||
}
|
||||
@@ -165,7 +168,7 @@ where
|
||||
/// Mutate the value under a key. Deletes the item if mutated to a `None`.
|
||||
pub fn mutate_exists<KeyArg: EncodeLike<Key>, R, F: FnOnce(&mut Option<Value>) -> R>(
|
||||
key: KeyArg,
|
||||
f: F
|
||||
f: F,
|
||||
) -> R {
|
||||
<Self as crate::storage::StorageMap<Key, Value>>::mutate_exists(key, f)
|
||||
}
|
||||
@@ -198,7 +201,7 @@ where
|
||||
EncodeLikeKey: EncodeLike<Key>,
|
||||
Item: Encode,
|
||||
EncodeLikeItem: EncodeLike<Item>,
|
||||
Value: StorageAppend<Item>
|
||||
Value: StorageAppend<Item>,
|
||||
{
|
||||
<Self as crate::storage::StorageMap<Key, Value>>::append(key, item)
|
||||
}
|
||||
@@ -216,7 +219,8 @@ where
|
||||
/// `None` does not mean that `get()` does not return a value. The default value is completly
|
||||
/// ignored by this function.
|
||||
pub fn decode_len<KeyArg: EncodeLike<Key>>(key: KeyArg) -> Option<usize>
|
||||
where Value: StorageDecodeLength,
|
||||
where
|
||||
Value: StorageDecodeLength,
|
||||
{
|
||||
<Self as crate::storage::StorageMap<Key, Value>>::decode_len(key)
|
||||
}
|
||||
@@ -225,7 +229,7 @@ where
|
||||
///
|
||||
/// If the key doesn't exist, then it's a no-op. If it does, then it returns its value.
|
||||
pub fn migrate_key<OldHasher: crate::hash::StorageHasher, KeyArg: EncodeLike<Key>>(
|
||||
key: KeyArg
|
||||
key: KeyArg,
|
||||
) -> Option<Value> {
|
||||
<Self as crate::storage::StorageMap<Key, Value>>::migrate_key::<OldHasher, _>(key)
|
||||
}
|
||||
@@ -263,19 +267,14 @@ where
|
||||
/// Try and append the given item to the value in the storage.
|
||||
///
|
||||
/// Is only available if `Value` of the storage implements [`StorageTryAppend`].
|
||||
pub fn try_append<KArg, Item, EncodeLikeItem>(
|
||||
key: KArg,
|
||||
item: EncodeLikeItem,
|
||||
) -> Result<(), ()>
|
||||
pub fn try_append<KArg, Item, EncodeLikeItem>(key: KArg, item: EncodeLikeItem) -> Result<(), ()>
|
||||
where
|
||||
KArg: EncodeLike<Key> + Clone,
|
||||
Item: Encode,
|
||||
EncodeLikeItem: EncodeLike<Item>,
|
||||
Value: StorageTryAppend<Item>,
|
||||
{
|
||||
<
|
||||
Self as crate::storage::TryAppendMap<Key, Value, Item>
|
||||
>::try_append(key, item)
|
||||
<Self as crate::storage::TryAppendMap<Key, Value, Item>>::try_append(key, item)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -332,7 +331,8 @@ pub trait StorageMapMetadata {
|
||||
}
|
||||
|
||||
impl<Prefix, Hasher, Key, Value, QueryKind, OnEmpty, MaxValues> StorageMapMetadata
|
||||
for StorageMap<Prefix, Hasher, Key, Value, QueryKind, OnEmpty, MaxValues> where
|
||||
for StorageMap<Prefix, Hasher, Key, Value, QueryKind, OnEmpty, MaxValues>
|
||||
where
|
||||
Prefix: StorageInstance,
|
||||
Hasher: crate::hash::StorageHasher,
|
||||
Key: FullCodec,
|
||||
@@ -348,9 +348,8 @@ impl<Prefix, Hasher, Key, Value, QueryKind, OnEmpty, MaxValues> StorageMapMetada
|
||||
DefaultByteGetter(&OnEmptyGetter::<QueryKind::Query, OnEmpty>(core::marker::PhantomData));
|
||||
}
|
||||
|
||||
impl<Prefix, Hasher, Key, Value, QueryKind, OnEmpty, MaxValues>
|
||||
crate::traits::StorageInfoTrait for
|
||||
StorageMap<Prefix, Hasher, Key, Value, QueryKind, OnEmpty, MaxValues>
|
||||
impl<Prefix, Hasher, Key, Value, QueryKind, OnEmpty, MaxValues> crate::traits::StorageInfoTrait
|
||||
for StorageMap<Prefix, Hasher, Key, Value, QueryKind, OnEmpty, MaxValues>
|
||||
where
|
||||
Prefix: StorageInstance,
|
||||
Hasher: crate::hash::StorageHasher,
|
||||
@@ -361,26 +360,24 @@ where
|
||||
MaxValues: Get<Option<u32>>,
|
||||
{
|
||||
fn storage_info() -> Vec<StorageInfo> {
|
||||
vec![
|
||||
StorageInfo {
|
||||
pallet_name: Self::module_prefix().to_vec(),
|
||||
storage_name: Self::storage_prefix().to_vec(),
|
||||
prefix: Self::final_prefix().to_vec(),
|
||||
max_values: MaxValues::get(),
|
||||
max_size: Some(
|
||||
Hasher::max_len::<Key>()
|
||||
.saturating_add(Value::max_encoded_len())
|
||||
.saturated_into(),
|
||||
),
|
||||
}
|
||||
]
|
||||
vec![StorageInfo {
|
||||
pallet_name: Self::module_prefix().to_vec(),
|
||||
storage_name: Self::storage_prefix().to_vec(),
|
||||
prefix: Self::final_prefix().to_vec(),
|
||||
max_values: MaxValues::get(),
|
||||
max_size: Some(
|
||||
Hasher::max_len::<Key>()
|
||||
.saturating_add(Value::max_encoded_len())
|
||||
.saturated_into(),
|
||||
),
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
||||
/// It doesn't require to implement `MaxEncodedLen` and give no information for `max_size`.
|
||||
impl<Prefix, Hasher, Key, Value, QueryKind, OnEmpty, MaxValues>
|
||||
crate::traits::PartialStorageInfoTrait for
|
||||
StorageMap<Prefix, Hasher, Key, Value, QueryKind, OnEmpty, MaxValues>
|
||||
crate::traits::PartialStorageInfoTrait
|
||||
for StorageMap<Prefix, Hasher, Key, Value, QueryKind, OnEmpty, MaxValues>
|
||||
where
|
||||
Prefix: StorageInstance,
|
||||
Hasher: crate::hash::StorageHasher,
|
||||
@@ -391,29 +388,28 @@ where
|
||||
MaxValues: Get<Option<u32>>,
|
||||
{
|
||||
fn partial_storage_info() -> Vec<StorageInfo> {
|
||||
vec![
|
||||
StorageInfo {
|
||||
pallet_name: Self::module_prefix().to_vec(),
|
||||
storage_name: Self::storage_prefix().to_vec(),
|
||||
prefix: Self::final_prefix().to_vec(),
|
||||
max_values: MaxValues::get(),
|
||||
max_size: None,
|
||||
}
|
||||
]
|
||||
vec![StorageInfo {
|
||||
pallet_name: Self::module_prefix().to_vec(),
|
||||
storage_name: Self::storage_prefix().to_vec(),
|
||||
prefix: Self::final_prefix().to_vec(),
|
||||
max_values: MaxValues::get(),
|
||||
max_size: None,
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use sp_io::{TestExternalities, hashing::twox_128};
|
||||
use crate::hash::*;
|
||||
use crate::storage::types::ValueQuery;
|
||||
use crate::{hash::*, storage::types::ValueQuery};
|
||||
use frame_metadata::StorageEntryModifier;
|
||||
use sp_io::{hashing::twox_128, TestExternalities};
|
||||
|
||||
struct Prefix;
|
||||
impl StorageInstance for Prefix {
|
||||
fn pallet_prefix() -> &'static str { "test" }
|
||||
fn pallet_prefix() -> &'static str {
|
||||
"test"
|
||||
}
|
||||
const STORAGE_PREFIX: &'static str = "foo";
|
||||
}
|
||||
|
||||
@@ -427,9 +423,8 @@ mod test {
|
||||
#[test]
|
||||
fn test() {
|
||||
type A = StorageMap<Prefix, Blake2_128Concat, u16, u32, OptionQuery>;
|
||||
type AValueQueryWithAnOnEmpty = StorageMap<
|
||||
Prefix, Blake2_128Concat, u16, u32, ValueQuery, ADefault
|
||||
>;
|
||||
type AValueQueryWithAnOnEmpty =
|
||||
StorageMap<Prefix, Blake2_128Concat, u16, u32, ValueQuery, ADefault>;
|
||||
type B = StorageMap<Prefix, Blake2_256, u16, u32, ValueQuery>;
|
||||
type C = StorageMap<Prefix, Blake2_128Concat, u16, u8, ValueQuery>;
|
||||
type WithLen = StorageMap<Prefix, Blake2_128Concat, u16, Vec<u32>>;
|
||||
@@ -471,17 +466,20 @@ mod test {
|
||||
|
||||
A::remove(2);
|
||||
let _: Result<(), ()> = AValueQueryWithAnOnEmpty::try_mutate(2, |v| {
|
||||
*v = *v * 2; Ok(())
|
||||
*v = *v * 2;
|
||||
Ok(())
|
||||
});
|
||||
let _: Result<(), ()> = AValueQueryWithAnOnEmpty::try_mutate(2, |v| {
|
||||
*v = *v * 2; Ok(())
|
||||
*v = *v * 2;
|
||||
Ok(())
|
||||
});
|
||||
assert_eq!(A::contains_key(2), true);
|
||||
assert_eq!(A::get(2), Some(97 * 4));
|
||||
|
||||
A::remove(2);
|
||||
let _: Result<(), ()> = AValueQueryWithAnOnEmpty::try_mutate(2, |v| {
|
||||
*v = *v * 2; Err(())
|
||||
*v = *v * 2;
|
||||
Err(())
|
||||
});
|
||||
assert_eq!(A::contains_key(2), false);
|
||||
|
||||
@@ -519,7 +517,6 @@ mod test {
|
||||
assert_eq!(A::contains_key(2), true);
|
||||
assert_eq!(A::get(2), Some(100));
|
||||
|
||||
|
||||
A::insert(2, 10);
|
||||
assert_eq!(A::take(2), Some(10));
|
||||
assert_eq!(A::contains_key(2), false);
|
||||
@@ -543,7 +540,7 @@ mod test {
|
||||
|
||||
C::insert(3, 10);
|
||||
C::insert(4, 10);
|
||||
A::translate_values::<u8,_>(|v| Some((v * 2).into()));
|
||||
A::translate_values::<u8, _>(|v| Some((v * 2).into()));
|
||||
assert_eq!(A::iter().collect::<Vec<_>>(), vec![(4, 20), (3, 20)]);
|
||||
|
||||
A::insert(3, 10);
|
||||
@@ -554,7 +551,7 @@ mod test {
|
||||
|
||||
C::insert(3, 10);
|
||||
C::insert(4, 10);
|
||||
A::translate::<u8,_>(|k, v| Some((k * v as u16).into()));
|
||||
A::translate::<u8, _>(|k, v| Some((k * v as u16).into()));
|
||||
assert_eq!(A::iter().collect::<Vec<_>>(), vec![(4, 40), (3, 30)]);
|
||||
|
||||
assert_eq!(A::MODIFIER, StorageEntryModifier::Optional);
|
||||
|
||||
@@ -30,7 +30,7 @@ mod value;
|
||||
pub use double_map::{StorageDoubleMap, StorageDoubleMapMetadata};
|
||||
pub use key::{
|
||||
EncodeLikeTuple, HasKeyPrefix, HasReversibleKeyPrefix, Key, KeyGenerator,
|
||||
ReversibleKeyGenerator, TupleToEncodedIter, KeyGeneratorMaxEncodedLen,
|
||||
KeyGeneratorMaxEncodedLen, ReversibleKeyGenerator, TupleToEncodedIter,
|
||||
};
|
||||
pub use map::{StorageMap, StorageMapMetadata};
|
||||
pub use nmap::{StorageNMap, StorageNMapMetadata};
|
||||
|
||||
@@ -21,12 +21,12 @@
|
||||
use crate::{
|
||||
storage::{
|
||||
types::{
|
||||
EncodeLikeTuple, HasKeyPrefix, HasReversibleKeyPrefix, OnEmptyGetter,
|
||||
OptionQuery, QueryKindTrait, TupleToEncodedIter,
|
||||
EncodeLikeTuple, HasKeyPrefix, HasReversibleKeyPrefix, OnEmptyGetter, OptionQuery,
|
||||
QueryKindTrait, TupleToEncodedIter,
|
||||
},
|
||||
KeyGenerator, PrefixIterator, StorageAppend, StorageDecodeLength, StoragePrefixedMap,
|
||||
},
|
||||
traits::{Get, GetDefault, StorageInstance, StorageInfo},
|
||||
traits::{Get, GetDefault, StorageInfo, StorageInstance},
|
||||
};
|
||||
use codec::{Decode, Encode, EncodeLike, FullCodec, MaxEncodedLen};
|
||||
use frame_metadata::{DefaultByteGetter, StorageEntryModifier};
|
||||
@@ -39,9 +39,9 @@ use sp_std::prelude::*;
|
||||
/// Each value is stored at:
|
||||
/// ```nocompile
|
||||
/// Twox128(Prefix::pallet_prefix())
|
||||
/// ++ Twox128(Prefix::STORAGE_PREFIX)
|
||||
/// ++ Hasher1(encode(key1))
|
||||
/// ++ Hasher2(encode(key2))
|
||||
/// ++ Twox128(Prefix::STORAGE_PREFIX)
|
||||
/// ++ Hasher1(encode(key1))
|
||||
/// ++ Hasher2(encode(key2))
|
||||
/// ++ ...
|
||||
/// ++ HasherN(encode(keyN))
|
||||
/// ```
|
||||
@@ -52,10 +52,13 @@ use sp_std::prelude::*;
|
||||
/// such as `blake2_128_concat` must be used for the key hashers. Otherwise, other values
|
||||
/// in storage can be compromised.
|
||||
pub struct StorageNMap<
|
||||
Prefix, Key, Value, QueryKind = OptionQuery, OnEmpty = GetDefault, MaxValues=GetDefault,
|
||||
>(
|
||||
core::marker::PhantomData<(Prefix, Key, Value, QueryKind, OnEmpty, MaxValues)>,
|
||||
);
|
||||
Prefix,
|
||||
Key,
|
||||
Value,
|
||||
QueryKind = OptionQuery,
|
||||
OnEmpty = GetDefault,
|
||||
MaxValues = GetDefault,
|
||||
>(core::marker::PhantomData<(Prefix, Key, Value, QueryKind, OnEmpty, MaxValues)>);
|
||||
|
||||
impl<Prefix, Key, Value, QueryKind, OnEmpty, MaxValues>
|
||||
crate::storage::generator::StorageNMap<Key, Value>
|
||||
@@ -83,8 +86,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<Prefix, Key, Value, QueryKind, OnEmpty, MaxValues>
|
||||
crate::storage::StoragePrefixedMap<Value>
|
||||
impl<Prefix, Key, Value, QueryKind, OnEmpty, MaxValues> crate::storage::StoragePrefixedMap<Value>
|
||||
for StorageNMap<Prefix, Key, Value, QueryKind, OnEmpty, MaxValues>
|
||||
where
|
||||
Prefix: StorageInstance,
|
||||
@@ -113,7 +115,9 @@ where
|
||||
MaxValues: Get<Option<u32>>,
|
||||
{
|
||||
/// Get the storage key used to fetch a value corresponding to a specific key.
|
||||
pub fn hashed_key_for<KArg: EncodeLikeTuple<Key::KArg> + TupleToEncodedIter>(key: KArg) -> Vec<u8> {
|
||||
pub fn hashed_key_for<KArg: EncodeLikeTuple<Key::KArg> + TupleToEncodedIter>(
|
||||
key: KArg,
|
||||
) -> Vec<u8> {
|
||||
<Self as crate::storage::StorageNMap<Key, Value>>::hashed_key_for(key)
|
||||
}
|
||||
|
||||
@@ -123,7 +127,9 @@ where
|
||||
}
|
||||
|
||||
/// Load the value associated with the given key from the map.
|
||||
pub fn get<KArg: EncodeLikeTuple<Key::KArg> + TupleToEncodedIter>(key: KArg) -> QueryKind::Query {
|
||||
pub fn get<KArg: EncodeLikeTuple<Key::KArg> + TupleToEncodedIter>(
|
||||
key: KArg,
|
||||
) -> QueryKind::Query {
|
||||
<Self as crate::storage::StorageNMap<Key, Value>>::get(key)
|
||||
}
|
||||
|
||||
@@ -137,7 +143,9 @@ where
|
||||
}
|
||||
|
||||
/// Take a value from storage, removing it afterwards.
|
||||
pub fn take<KArg: EncodeLikeTuple<Key::KArg> + TupleToEncodedIter>(key: KArg) -> QueryKind::Query {
|
||||
pub fn take<KArg: EncodeLikeTuple<Key::KArg> + TupleToEncodedIter>(
|
||||
key: KArg,
|
||||
) -> QueryKind::Query {
|
||||
<Self as crate::storage::StorageNMap<Key, Value>>::take(key)
|
||||
}
|
||||
|
||||
@@ -248,7 +256,9 @@ where
|
||||
///
|
||||
/// `None` does not mean that `get()` does not return a value. The default value is completly
|
||||
/// ignored by this function.
|
||||
pub fn decode_len<KArg: EncodeLikeTuple<Key::KArg> + TupleToEncodedIter>(key: KArg) -> Option<usize>
|
||||
pub fn decode_len<KArg: EncodeLikeTuple<Key::KArg> + TupleToEncodedIter>(
|
||||
key: KArg,
|
||||
) -> Option<usize>
|
||||
where
|
||||
Value: StorageDecodeLength,
|
||||
{
|
||||
@@ -260,7 +270,7 @@ where
|
||||
/// If the key doesn't exist, then it's a no-op. If it does, then it returns its value.
|
||||
pub fn migrate_keys<KArg>(key: KArg, hash_fns: Key::HArg) -> Option<Value>
|
||||
where
|
||||
KArg: EncodeLikeTuple<Key::KArg> + TupleToEncodedIter
|
||||
KArg: EncodeLikeTuple<Key::KArg> + TupleToEncodedIter,
|
||||
{
|
||||
<Self as crate::storage::StorageNMap<Key, Value>>::migrate_keys::<_>(key, hash_fns)
|
||||
}
|
||||
@@ -398,15 +408,13 @@ where
|
||||
{
|
||||
const MODIFIER: StorageEntryModifier = QueryKind::METADATA;
|
||||
const NAME: &'static str = Prefix::STORAGE_PREFIX;
|
||||
const DEFAULT: DefaultByteGetter = DefaultByteGetter(
|
||||
&OnEmptyGetter::<QueryKind::Query, OnEmpty>(core::marker::PhantomData),
|
||||
);
|
||||
const DEFAULT: DefaultByteGetter =
|
||||
DefaultByteGetter(&OnEmptyGetter::<QueryKind::Query, OnEmpty>(core::marker::PhantomData));
|
||||
const HASHERS: &'static [frame_metadata::StorageHasher] = Key::HASHER_METADATA;
|
||||
}
|
||||
|
||||
impl<Prefix, Key, Value, QueryKind, OnEmpty, MaxValues>
|
||||
crate::traits::StorageInfoTrait for
|
||||
StorageNMap<Prefix, Key, Value, QueryKind, OnEmpty, MaxValues>
|
||||
impl<Prefix, Key, Value, QueryKind, OnEmpty, MaxValues> crate::traits::StorageInfoTrait
|
||||
for StorageNMap<Prefix, Key, Value, QueryKind, OnEmpty, MaxValues>
|
||||
where
|
||||
Prefix: StorageInstance,
|
||||
Key: super::key::KeyGenerator + super::key::KeyGeneratorMaxEncodedLen,
|
||||
@@ -416,26 +424,23 @@ where
|
||||
MaxValues: Get<Option<u32>>,
|
||||
{
|
||||
fn storage_info() -> Vec<StorageInfo> {
|
||||
vec![
|
||||
StorageInfo {
|
||||
pallet_name: Self::module_prefix().to_vec(),
|
||||
storage_name: Self::storage_prefix().to_vec(),
|
||||
prefix: Self::final_prefix().to_vec(),
|
||||
max_values: MaxValues::get(),
|
||||
max_size: Some(
|
||||
Key::key_max_encoded_len()
|
||||
.saturating_add(Value::max_encoded_len())
|
||||
.saturated_into(),
|
||||
),
|
||||
}
|
||||
]
|
||||
vec![StorageInfo {
|
||||
pallet_name: Self::module_prefix().to_vec(),
|
||||
storage_name: Self::storage_prefix().to_vec(),
|
||||
prefix: Self::final_prefix().to_vec(),
|
||||
max_values: MaxValues::get(),
|
||||
max_size: Some(
|
||||
Key::key_max_encoded_len()
|
||||
.saturating_add(Value::max_encoded_len())
|
||||
.saturated_into(),
|
||||
),
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
||||
/// It doesn't require to implement `MaxEncodedLen` and give no information for `max_size`.
|
||||
impl<Prefix, Key, Value, QueryKind, OnEmpty, MaxValues>
|
||||
crate::traits::PartialStorageInfoTrait for
|
||||
StorageNMap<Prefix, Key, Value, QueryKind, OnEmpty, MaxValues>
|
||||
impl<Prefix, Key, Value, QueryKind, OnEmpty, MaxValues> crate::traits::PartialStorageInfoTrait
|
||||
for StorageNMap<Prefix, Key, Value, QueryKind, OnEmpty, MaxValues>
|
||||
where
|
||||
Prefix: StorageInstance,
|
||||
Key: super::key::KeyGenerator,
|
||||
@@ -445,22 +450,22 @@ where
|
||||
MaxValues: Get<Option<u32>>,
|
||||
{
|
||||
fn partial_storage_info() -> Vec<StorageInfo> {
|
||||
vec![
|
||||
StorageInfo {
|
||||
pallet_name: Self::module_prefix().to_vec(),
|
||||
storage_name: Self::storage_prefix().to_vec(),
|
||||
prefix: Self::final_prefix().to_vec(),
|
||||
max_values: MaxValues::get(),
|
||||
max_size: None,
|
||||
}
|
||||
]
|
||||
vec![StorageInfo {
|
||||
pallet_name: Self::module_prefix().to_vec(),
|
||||
storage_name: Self::storage_prefix().to_vec(),
|
||||
prefix: Self::final_prefix().to_vec(),
|
||||
max_values: MaxValues::get(),
|
||||
max_size: None,
|
||||
}]
|
||||
}
|
||||
}
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::hash::*;
|
||||
use crate::storage::types::{Key, ValueQuery};
|
||||
use crate::{
|
||||
hash::*,
|
||||
storage::types::{Key, ValueQuery},
|
||||
};
|
||||
use frame_metadata::StorageEntryModifier;
|
||||
use sp_io::{hashing::twox_128, TestExternalities};
|
||||
|
||||
@@ -627,15 +632,9 @@ mod test {
|
||||
assert_eq!(A::iter().collect::<Vec<_>>(), vec![(4, 40), (3, 30)]);
|
||||
|
||||
assert_eq!(A::MODIFIER, StorageEntryModifier::Optional);
|
||||
assert_eq!(
|
||||
AValueQueryWithAnOnEmpty::MODIFIER,
|
||||
StorageEntryModifier::Default
|
||||
);
|
||||
assert_eq!(AValueQueryWithAnOnEmpty::MODIFIER, StorageEntryModifier::Default);
|
||||
assert_eq!(A::NAME, "Foo");
|
||||
assert_eq!(
|
||||
AValueQueryWithAnOnEmpty::DEFAULT.0.default_byte(),
|
||||
98u32.encode()
|
||||
);
|
||||
assert_eq!(AValueQueryWithAnOnEmpty::DEFAULT.0.default_byte(), 98u32.encode());
|
||||
assert_eq!(A::DEFAULT.0.default_byte(), Option::<u32>::None.encode());
|
||||
|
||||
WithLen::remove_all(None);
|
||||
@@ -787,41 +786,23 @@ mod test {
|
||||
C::insert((3, 30), 10);
|
||||
C::insert((4, 40), 10);
|
||||
A::translate_values::<u8, _>(|v| Some((v * 2).into()));
|
||||
assert_eq!(
|
||||
A::iter().collect::<Vec<_>>(),
|
||||
vec![((4, 40), 20), ((3, 30), 20)]
|
||||
);
|
||||
assert_eq!(A::iter().collect::<Vec<_>>(), vec![((4, 40), 20), ((3, 30), 20)]);
|
||||
|
||||
A::insert((3, 30), 10);
|
||||
A::insert((4, 40), 10);
|
||||
assert_eq!(
|
||||
A::iter().collect::<Vec<_>>(),
|
||||
vec![((4, 40), 10), ((3, 30), 10)]
|
||||
);
|
||||
assert_eq!(
|
||||
A::drain().collect::<Vec<_>>(),
|
||||
vec![((4, 40), 10), ((3, 30), 10)]
|
||||
);
|
||||
assert_eq!(A::iter().collect::<Vec<_>>(), vec![((4, 40), 10), ((3, 30), 10)]);
|
||||
assert_eq!(A::drain().collect::<Vec<_>>(), vec![((4, 40), 10), ((3, 30), 10)]);
|
||||
assert_eq!(A::iter().collect::<Vec<_>>(), vec![]);
|
||||
|
||||
C::insert((3, 30), 10);
|
||||
C::insert((4, 40), 10);
|
||||
A::translate::<u8, _>(|(k1, k2), v| Some((k1 * k2 as u16 * v as u16).into()));
|
||||
assert_eq!(
|
||||
A::iter().collect::<Vec<_>>(),
|
||||
vec![((4, 40), 1600), ((3, 30), 900)]
|
||||
);
|
||||
assert_eq!(A::iter().collect::<Vec<_>>(), vec![((4, 40), 1600), ((3, 30), 900)]);
|
||||
|
||||
assert_eq!(A::MODIFIER, StorageEntryModifier::Optional);
|
||||
assert_eq!(
|
||||
AValueQueryWithAnOnEmpty::MODIFIER,
|
||||
StorageEntryModifier::Default
|
||||
);
|
||||
assert_eq!(AValueQueryWithAnOnEmpty::MODIFIER, StorageEntryModifier::Default);
|
||||
assert_eq!(A::NAME, "Foo");
|
||||
assert_eq!(
|
||||
AValueQueryWithAnOnEmpty::DEFAULT.0.default_byte(),
|
||||
98u32.encode()
|
||||
);
|
||||
assert_eq!(AValueQueryWithAnOnEmpty::DEFAULT.0.default_byte(), 98u32.encode());
|
||||
assert_eq!(A::DEFAULT.0.default_byte(), Option::<u32>::None.encode());
|
||||
|
||||
WithLen::remove_all(None);
|
||||
@@ -833,14 +814,8 @@ mod test {
|
||||
A::insert((3, 31), 12);
|
||||
A::insert((4, 40), 13);
|
||||
A::insert((4, 41), 14);
|
||||
assert_eq!(
|
||||
A::iter_prefix_values((3,)).collect::<Vec<_>>(),
|
||||
vec![12, 11]
|
||||
);
|
||||
assert_eq!(
|
||||
A::iter_prefix_values((4,)).collect::<Vec<_>>(),
|
||||
vec![13, 14]
|
||||
);
|
||||
assert_eq!(A::iter_prefix_values((3,)).collect::<Vec<_>>(), vec![12, 11]);
|
||||
assert_eq!(A::iter_prefix_values((4,)).collect::<Vec<_>>(), vec![13, 14]);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -848,52 +823,32 @@ mod test {
|
||||
fn test_3_keys() {
|
||||
type A = StorageNMap<
|
||||
Prefix,
|
||||
(
|
||||
Key<Blake2_128Concat, u16>,
|
||||
Key<Blake2_128Concat, u16>,
|
||||
Key<Twox64Concat, u16>,
|
||||
),
|
||||
(Key<Blake2_128Concat, u16>, Key<Blake2_128Concat, u16>, Key<Twox64Concat, u16>),
|
||||
u32,
|
||||
OptionQuery,
|
||||
>;
|
||||
type AValueQueryWithAnOnEmpty = StorageNMap<
|
||||
Prefix,
|
||||
(
|
||||
Key<Blake2_128Concat, u16>,
|
||||
Key<Blake2_128Concat, u16>,
|
||||
Key<Twox64Concat, u16>,
|
||||
),
|
||||
(Key<Blake2_128Concat, u16>, Key<Blake2_128Concat, u16>, Key<Twox64Concat, u16>),
|
||||
u32,
|
||||
ValueQuery,
|
||||
ADefault,
|
||||
>;
|
||||
type B = StorageNMap<
|
||||
Prefix,
|
||||
(
|
||||
Key<Blake2_256, u16>,
|
||||
Key<Blake2_256, u16>,
|
||||
Key<Twox128, u16>,
|
||||
),
|
||||
(Key<Blake2_256, u16>, Key<Blake2_256, u16>, Key<Twox128, u16>),
|
||||
u32,
|
||||
ValueQuery,
|
||||
>;
|
||||
type C = StorageNMap<
|
||||
Prefix,
|
||||
(
|
||||
Key<Blake2_128Concat, u16>,
|
||||
Key<Blake2_128Concat, u16>,
|
||||
Key<Twox64Concat, u16>,
|
||||
),
|
||||
(Key<Blake2_128Concat, u16>, Key<Blake2_128Concat, u16>, Key<Twox64Concat, u16>),
|
||||
u8,
|
||||
ValueQuery,
|
||||
>;
|
||||
type WithLen = StorageNMap<
|
||||
Prefix,
|
||||
(
|
||||
Key<Blake2_128Concat, u16>,
|
||||
Key<Blake2_128Concat, u16>,
|
||||
Key<Twox64Concat, u16>,
|
||||
),
|
||||
(Key<Blake2_128Concat, u16>, Key<Blake2_128Concat, u16>, Key<Twox64Concat, u16>),
|
||||
Vec<u32>,
|
||||
>;
|
||||
|
||||
@@ -916,11 +871,7 @@ mod test {
|
||||
assert_eq!(AValueQueryWithAnOnEmpty::get((1, 10, 100)), 30);
|
||||
|
||||
A::swap::<
|
||||
(
|
||||
Key<Blake2_128Concat, u16>,
|
||||
Key<Blake2_128Concat, u16>,
|
||||
Key<Twox64Concat, u16>,
|
||||
),
|
||||
(Key<Blake2_128Concat, u16>, Key<Blake2_128Concat, u16>, Key<Twox64Concat, u16>),
|
||||
_,
|
||||
_,
|
||||
>((1, 10, 100), (2, 20, 200));
|
||||
@@ -1020,17 +971,11 @@ mod test {
|
||||
C::insert((3, 30, 300), 10);
|
||||
C::insert((4, 40, 400), 10);
|
||||
A::translate_values::<u8, _>(|v| Some((v * 2).into()));
|
||||
assert_eq!(
|
||||
A::iter().collect::<Vec<_>>(),
|
||||
vec![((4, 40, 400), 20), ((3, 30, 300), 20)]
|
||||
);
|
||||
assert_eq!(A::iter().collect::<Vec<_>>(), vec![((4, 40, 400), 20), ((3, 30, 300), 20)]);
|
||||
|
||||
A::insert((3, 30, 300), 10);
|
||||
A::insert((4, 40, 400), 10);
|
||||
assert_eq!(
|
||||
A::iter().collect::<Vec<_>>(),
|
||||
vec![((4, 40, 400), 10), ((3, 30, 300), 10)]
|
||||
);
|
||||
assert_eq!(A::iter().collect::<Vec<_>>(), vec![((4, 40, 400), 10), ((3, 30, 300), 10)]);
|
||||
assert_eq!(
|
||||
A::drain().collect::<Vec<_>>(),
|
||||
vec![((4, 40, 400), 10), ((3, 30, 300), 10)]
|
||||
@@ -1042,21 +987,12 @@ mod test {
|
||||
A::translate::<u8, _>(|(k1, k2, k3), v| {
|
||||
Some((k1 * k2 as u16 * v as u16 / k3 as u16).into())
|
||||
});
|
||||
assert_eq!(
|
||||
A::iter().collect::<Vec<_>>(),
|
||||
vec![((4, 40, 400), 4), ((3, 30, 300), 3)]
|
||||
);
|
||||
assert_eq!(A::iter().collect::<Vec<_>>(), vec![((4, 40, 400), 4), ((3, 30, 300), 3)]);
|
||||
|
||||
assert_eq!(A::MODIFIER, StorageEntryModifier::Optional);
|
||||
assert_eq!(
|
||||
AValueQueryWithAnOnEmpty::MODIFIER,
|
||||
StorageEntryModifier::Default
|
||||
);
|
||||
assert_eq!(AValueQueryWithAnOnEmpty::MODIFIER, StorageEntryModifier::Default);
|
||||
assert_eq!(A::NAME, "Foo");
|
||||
assert_eq!(
|
||||
AValueQueryWithAnOnEmpty::DEFAULT.0.default_byte(),
|
||||
98u32.encode()
|
||||
);
|
||||
assert_eq!(AValueQueryWithAnOnEmpty::DEFAULT.0.default_byte(), 98u32.encode());
|
||||
assert_eq!(A::DEFAULT.0.default_byte(), Option::<u32>::None.encode());
|
||||
|
||||
WithLen::remove_all(None);
|
||||
@@ -1068,22 +1004,10 @@ mod test {
|
||||
A::insert((3, 30, 301), 12);
|
||||
A::insert((4, 40, 400), 13);
|
||||
A::insert((4, 40, 401), 14);
|
||||
assert_eq!(
|
||||
A::iter_prefix_values((3,)).collect::<Vec<_>>(),
|
||||
vec![11, 12]
|
||||
);
|
||||
assert_eq!(
|
||||
A::iter_prefix_values((4,)).collect::<Vec<_>>(),
|
||||
vec![14, 13]
|
||||
);
|
||||
assert_eq!(
|
||||
A::iter_prefix_values((3, 30)).collect::<Vec<_>>(),
|
||||
vec![11, 12]
|
||||
);
|
||||
assert_eq!(
|
||||
A::iter_prefix_values((4, 40)).collect::<Vec<_>>(),
|
||||
vec![14, 13]
|
||||
);
|
||||
assert_eq!(A::iter_prefix_values((3,)).collect::<Vec<_>>(), vec![11, 12]);
|
||||
assert_eq!(A::iter_prefix_values((4,)).collect::<Vec<_>>(), vec![14, 13]);
|
||||
assert_eq!(A::iter_prefix_values((3, 30)).collect::<Vec<_>>(), vec![11, 12]);
|
||||
assert_eq!(A::iter_prefix_values((4, 40)).collect::<Vec<_>>(), vec![14, 13]);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,15 +17,15 @@
|
||||
|
||||
//! Storage value type. Implements StorageValue trait and its method directly.
|
||||
|
||||
use codec::{FullCodec, Decode, EncodeLike, Encode, MaxEncodedLen};
|
||||
use crate::{
|
||||
storage::{
|
||||
StorageAppend, StorageTryAppend, StorageDecodeLength,
|
||||
types::{OptionQuery, QueryKindTrait, OnEmptyGetter},
|
||||
generator::{StorageValue as StorageValueT},
|
||||
generator::StorageValue as StorageValueT,
|
||||
types::{OnEmptyGetter, OptionQuery, QueryKindTrait},
|
||||
StorageAppend, StorageDecodeLength, StorageTryAppend,
|
||||
},
|
||||
traits::{GetDefault, StorageInstance, StorageInfo},
|
||||
traits::{GetDefault, StorageInfo, StorageInstance},
|
||||
};
|
||||
use codec::{Decode, Encode, EncodeLike, FullCodec, MaxEncodedLen};
|
||||
use frame_metadata::{DefaultByteGetter, StorageEntryModifier};
|
||||
use sp_arithmetic::traits::SaturatedConversion;
|
||||
use sp_std::prelude::*;
|
||||
@@ -36,12 +36,12 @@ use sp_std::prelude::*;
|
||||
/// ```nocompile
|
||||
/// Twox128(Prefix::pallet_prefix()) ++ Twox128(Prefix::STORAGE_PREFIX)
|
||||
/// ```
|
||||
pub struct StorageValue<Prefix, Value, QueryKind=OptionQuery, OnEmpty=GetDefault>(
|
||||
core::marker::PhantomData<(Prefix, Value, QueryKind, OnEmpty)>
|
||||
pub struct StorageValue<Prefix, Value, QueryKind = OptionQuery, OnEmpty = GetDefault>(
|
||||
core::marker::PhantomData<(Prefix, Value, QueryKind, OnEmpty)>,
|
||||
);
|
||||
|
||||
impl<Prefix, Value, QueryKind, OnEmpty> crate::storage::generator::StorageValue<Value> for
|
||||
StorageValue<Prefix, Value, QueryKind, OnEmpty>
|
||||
impl<Prefix, Value, QueryKind, OnEmpty> crate::storage::generator::StorageValue<Value>
|
||||
for StorageValue<Prefix, Value, QueryKind, OnEmpty>
|
||||
where
|
||||
Prefix: StorageInstance,
|
||||
Value: FullCodec,
|
||||
@@ -71,13 +71,19 @@ where
|
||||
OnEmpty: crate::traits::Get<QueryKind::Query> + 'static,
|
||||
{
|
||||
/// Get the storage key.
|
||||
pub fn hashed_key() -> [u8; 32] { <Self as crate::storage::StorageValue<Value>>::hashed_key() }
|
||||
pub fn hashed_key() -> [u8; 32] {
|
||||
<Self as crate::storage::StorageValue<Value>>::hashed_key()
|
||||
}
|
||||
|
||||
/// Does the value (explicitly) exist in storage?
|
||||
pub fn exists() -> bool { <Self as crate::storage::StorageValue<Value>>::exists() }
|
||||
pub fn exists() -> bool {
|
||||
<Self as crate::storage::StorageValue<Value>>::exists()
|
||||
}
|
||||
|
||||
/// Load the value from the provided storage instance.
|
||||
pub fn get() -> QueryKind::Query { <Self as crate::storage::StorageValue<Value>>::get() }
|
||||
pub fn get() -> QueryKind::Query {
|
||||
<Self as crate::storage::StorageValue<Value>>::get()
|
||||
}
|
||||
|
||||
/// Try to get the underlying value from the provided storage instance; `Ok` if it exists,
|
||||
/// `Err` if not.
|
||||
@@ -120,7 +126,9 @@ where
|
||||
/// Store a value under this key into the provided storage instance.
|
||||
///
|
||||
/// this uses the query type rather than the underlying value.
|
||||
pub fn set(val: QueryKind::Query) { <Self as crate::storage::StorageValue<Value>>::set(val) }
|
||||
pub fn set(val: QueryKind::Query) {
|
||||
<Self as crate::storage::StorageValue<Value>>::set(val)
|
||||
}
|
||||
|
||||
/// Mutate the value
|
||||
pub fn mutate<R, F: FnOnce(&mut QueryKind::Query) -> R>(f: F) -> R {
|
||||
@@ -135,10 +143,14 @@ where
|
||||
}
|
||||
|
||||
/// Clear the storage value.
|
||||
pub fn kill() { <Self as crate::storage::StorageValue<Value>>::kill() }
|
||||
pub fn kill() {
|
||||
<Self as crate::storage::StorageValue<Value>>::kill()
|
||||
}
|
||||
|
||||
/// Take a value from storage, removing it afterwards.
|
||||
pub fn take() -> QueryKind::Query { <Self as crate::storage::StorageValue<Value>>::take() }
|
||||
pub fn take() -> QueryKind::Query {
|
||||
<Self as crate::storage::StorageValue<Value>>::take()
|
||||
}
|
||||
|
||||
/// Append the given item to the value in the storage.
|
||||
///
|
||||
@@ -153,7 +165,7 @@ where
|
||||
where
|
||||
Item: Encode,
|
||||
EncodeLikeItem: EncodeLike<Item>,
|
||||
Value: StorageAppend<Item>
|
||||
Value: StorageAppend<Item>,
|
||||
{
|
||||
<Self as crate::storage::StorageValue<Value>>::append(item)
|
||||
}
|
||||
@@ -169,7 +181,10 @@ where
|
||||
///
|
||||
/// `None` does not mean that `get()` does not return a value. The default value is completly
|
||||
/// ignored by this function.
|
||||
pub fn decode_len() -> Option<usize> where Value: StorageDecodeLength {
|
||||
pub fn decode_len() -> Option<usize>
|
||||
where
|
||||
Value: StorageDecodeLength,
|
||||
{
|
||||
<Self as crate::storage::StorageValue<Value>>::decode_len()
|
||||
}
|
||||
|
||||
@@ -194,7 +209,8 @@ pub trait StorageValueMetadata {
|
||||
}
|
||||
|
||||
impl<Prefix, Value, QueryKind, OnEmpty> StorageValueMetadata
|
||||
for StorageValue<Prefix, Value, QueryKind, OnEmpty> where
|
||||
for StorageValue<Prefix, Value, QueryKind, OnEmpty>
|
||||
where
|
||||
Prefix: StorageInstance,
|
||||
Value: FullCodec,
|
||||
QueryKind: QueryKindTrait<Value, OnEmpty>,
|
||||
@@ -206,64 +222,57 @@ impl<Prefix, Value, QueryKind, OnEmpty> StorageValueMetadata
|
||||
DefaultByteGetter(&OnEmptyGetter::<QueryKind::Query, OnEmpty>(core::marker::PhantomData));
|
||||
}
|
||||
|
||||
impl<Prefix, Value, QueryKind, OnEmpty>
|
||||
crate::traits::StorageInfoTrait for
|
||||
StorageValue<Prefix, Value, QueryKind, OnEmpty>
|
||||
impl<Prefix, Value, QueryKind, OnEmpty> crate::traits::StorageInfoTrait
|
||||
for StorageValue<Prefix, Value, QueryKind, OnEmpty>
|
||||
where
|
||||
Prefix: StorageInstance,
|
||||
Value: FullCodec + MaxEncodedLen,
|
||||
QueryKind: QueryKindTrait<Value, OnEmpty>,
|
||||
OnEmpty: crate::traits::Get<QueryKind::Query> + 'static
|
||||
OnEmpty: crate::traits::Get<QueryKind::Query> + 'static,
|
||||
{
|
||||
fn storage_info() -> Vec<StorageInfo> {
|
||||
vec![
|
||||
StorageInfo {
|
||||
pallet_name: Self::module_prefix().to_vec(),
|
||||
storage_name: Self::storage_prefix().to_vec(),
|
||||
prefix: Self::hashed_key().to_vec(),
|
||||
max_values: Some(1),
|
||||
max_size: Some(
|
||||
Value::max_encoded_len()
|
||||
.saturated_into(),
|
||||
),
|
||||
}
|
||||
]
|
||||
vec![StorageInfo {
|
||||
pallet_name: Self::module_prefix().to_vec(),
|
||||
storage_name: Self::storage_prefix().to_vec(),
|
||||
prefix: Self::hashed_key().to_vec(),
|
||||
max_values: Some(1),
|
||||
max_size: Some(Value::max_encoded_len().saturated_into()),
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
||||
/// It doesn't require to implement `MaxEncodedLen` and give no information for `max_size`.
|
||||
impl<Prefix, Value, QueryKind, OnEmpty>
|
||||
crate::traits::PartialStorageInfoTrait for
|
||||
StorageValue<Prefix, Value, QueryKind, OnEmpty>
|
||||
impl<Prefix, Value, QueryKind, OnEmpty> crate::traits::PartialStorageInfoTrait
|
||||
for StorageValue<Prefix, Value, QueryKind, OnEmpty>
|
||||
where
|
||||
Prefix: StorageInstance,
|
||||
Value: FullCodec,
|
||||
QueryKind: QueryKindTrait<Value, OnEmpty>,
|
||||
OnEmpty: crate::traits::Get<QueryKind::Query> + 'static
|
||||
OnEmpty: crate::traits::Get<QueryKind::Query> + 'static,
|
||||
{
|
||||
fn partial_storage_info() -> Vec<StorageInfo> {
|
||||
vec![
|
||||
StorageInfo {
|
||||
pallet_name: Self::module_prefix().to_vec(),
|
||||
storage_name: Self::storage_prefix().to_vec(),
|
||||
prefix: Self::hashed_key().to_vec(),
|
||||
max_values: Some(1),
|
||||
max_size: None,
|
||||
}
|
||||
]
|
||||
vec![StorageInfo {
|
||||
pallet_name: Self::module_prefix().to_vec(),
|
||||
storage_name: Self::storage_prefix().to_vec(),
|
||||
prefix: Self::hashed_key().to_vec(),
|
||||
max_values: Some(1),
|
||||
max_size: None,
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use sp_io::{TestExternalities, hashing::twox_128};
|
||||
use crate::storage::types::ValueQuery;
|
||||
use frame_metadata::StorageEntryModifier;
|
||||
use sp_io::{hashing::twox_128, TestExternalities};
|
||||
|
||||
struct Prefix;
|
||||
impl StorageInstance for Prefix {
|
||||
fn pallet_prefix() -> &'static str { "test" }
|
||||
fn pallet_prefix() -> &'static str {
|
||||
"test"
|
||||
}
|
||||
const STORAGE_PREFIX: &'static str = "foo";
|
||||
}
|
||||
|
||||
@@ -309,10 +318,16 @@ mod test {
|
||||
assert_eq!(A::try_get(), Ok(4));
|
||||
|
||||
A::set(Some(4));
|
||||
let _: Result<(), ()> = A::try_mutate(|v| { *v = Some(v.unwrap() * 2); Ok(()) });
|
||||
let _: Result<(), ()> = A::try_mutate(|v| {
|
||||
*v = Some(v.unwrap() * 2);
|
||||
Ok(())
|
||||
});
|
||||
assert_eq!(A::try_get(), Ok(8));
|
||||
|
||||
let _: Result<(), ()> = A::try_mutate(|v| { *v = Some(v.unwrap() * 2); Err(()) });
|
||||
let _: Result<(), ()> = A::try_mutate(|v| {
|
||||
*v = Some(v.unwrap() * 2);
|
||||
Err(())
|
||||
});
|
||||
assert_eq!(A::try_get(), Ok(8));
|
||||
|
||||
A::kill();
|
||||
@@ -321,7 +336,8 @@ mod test {
|
||||
|
||||
AValueQueryWithAnOnEmpty::kill();
|
||||
let _: Result<(), ()> = AValueQueryWithAnOnEmpty::try_mutate(|v| {
|
||||
*v = *v * 2; Ok(())
|
||||
*v = *v * 2;
|
||||
Ok(())
|
||||
});
|
||||
assert_eq!(AValueQueryWithAnOnEmpty::try_get(), Ok(97 * 2));
|
||||
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
|
||||
//! Operation on unhashed runtime storage.
|
||||
|
||||
use codec::{Decode, Encode};
|
||||
use sp_std::prelude::*;
|
||||
use codec::{Encode, Decode};
|
||||
|
||||
/// Return the value of the item in storage under `key`, or `None` if there is no explicit entry.
|
||||
pub fn get<T: Decode + Sized>(key: &[u8]) -> Option<T> {
|
||||
|
||||
@@ -18,17 +18,16 @@
|
||||
//! Traits, types and structs to support putting a bounded vector into storage, as a raw value, map
|
||||
//! or a double map.
|
||||
|
||||
use sp_std::prelude::*;
|
||||
use sp_std::{convert::TryFrom, fmt, marker::PhantomData};
|
||||
use codec::{Encode, Decode, MaxEncodedLen};
|
||||
use crate::{
|
||||
storage::{StorageDecodeLength, StorageTryAppend},
|
||||
traits::Get,
|
||||
};
|
||||
use codec::{Decode, Encode, MaxEncodedLen};
|
||||
use core::{
|
||||
ops::{Deref, Index, IndexMut},
|
||||
slice::SliceIndex,
|
||||
};
|
||||
use crate::{
|
||||
traits::Get,
|
||||
storage::{StorageDecodeLength, StorageTryAppend},
|
||||
};
|
||||
use sp_std::{convert::TryFrom, fmt, marker::PhantomData, prelude::*};
|
||||
|
||||
/// A weakly bounded vector.
|
||||
///
|
||||
@@ -317,9 +316,9 @@ where
|
||||
#[cfg(test)]
|
||||
pub mod test {
|
||||
use super::*;
|
||||
use crate::Twox128;
|
||||
use sp_io::TestExternalities;
|
||||
use sp_std::convert::TryInto;
|
||||
use crate::Twox128;
|
||||
|
||||
crate::parameter_types! {
|
||||
pub const Seven: u32 = 7;
|
||||
|
||||
Reference in New Issue
Block a user