mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-09 20:11:09 +00:00
Maps are appendable too (#2716)
* Maps are appendable too * Update srml/support/src/storage/hashed/generator.rs Co-Authored-By: Tomasz Drwięga <tomusdrw@users.noreply.github.com> * Update srml/support/src/storage/mod.rs Co-Authored-By: Tomasz Drwięga <tomusdrw@users.noreply.github.com> * Fix docs * Make Appendable public * Bump runtime version
This commit is contained in:
@@ -59,7 +59,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
|
||||
impl_name: create_runtime_str!("substrate-node"),
|
||||
authoring_version: 10,
|
||||
spec_version: 88,
|
||||
impl_version: 88,
|
||||
impl_version: 89,
|
||||
apis: RUNTIME_API_VERSIONS,
|
||||
};
|
||||
|
||||
|
||||
@@ -225,8 +225,11 @@ impl<'a, I: Iterator<Item=syn::Meta>> Impls<'a, I> {
|
||||
#mutate_impl ;
|
||||
ret
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl<#traitinstance: 'static + #traittype, #instance #bound_instantiable>
|
||||
#scrate::storage::hashed::generator::AppendableStorageMap<#kty, #typ> for #name<#traitinstance, #instance>
|
||||
{}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -57,7 +57,9 @@ pub mod unsigned;
|
||||
mod double_map;
|
||||
pub mod traits;
|
||||
|
||||
pub use self::storage::{StorageList, StorageValue, StorageMap, EnumerableStorageMap, StorageDoubleMap};
|
||||
pub use self::storage::{
|
||||
StorageList, StorageValue, StorageMap, EnumerableStorageMap, StorageDoubleMap, AppendableStorageMap
|
||||
};
|
||||
pub use self::hashable::Hashable;
|
||||
pub use self::dispatch::{Parameter, Dispatchable, Callable, IsSubType};
|
||||
pub use self::double_map::StorageDoubleMapWithHasher;
|
||||
|
||||
@@ -281,5 +281,25 @@ pub trait EnumerableStorageMap<K: codec::Codec, V: codec::Codec>: StorageMap<K,
|
||||
fn head<S: HashedStorage<Self::Hasher>>(storage: &S) -> Option<K>;
|
||||
|
||||
/// Enumerate all elements in the map.
|
||||
fn enumerate<'a, S: HashedStorage<Self::Hasher>>(storage: &'a S) -> Box<dyn Iterator<Item = (K, V)> + 'a> where K: 'a, V: 'a;
|
||||
fn enumerate<'a, S: HashedStorage<Self::Hasher>>(
|
||||
storage: &'a S
|
||||
) -> Box<dyn Iterator<Item = (K, V)> + 'a> where K: 'a, V: 'a;
|
||||
}
|
||||
|
||||
/// A `StorageMap` with appendable entries.
|
||||
pub trait AppendableStorageMap<K: codec::Codec, V: codec::Codec>: StorageMap<K, V> {
|
||||
/// Append the given items to the value in the storage.
|
||||
///
|
||||
/// `T` is required to implement `codec::EncodeAppend`.
|
||||
fn append<S: HashedStorage<Self::Hasher>, I: codec::Encode>(
|
||||
key : &K, items: &[I], storage: &mut S
|
||||
) -> Result<(), &'static str> where V: codec::EncodeAppend<Item=I> {
|
||||
let k = Self::key_for(key);
|
||||
let new_val = <V as codec::EncodeAppend>::append(
|
||||
storage.get_raw(&k[..]).unwrap_or_default(),
|
||||
items,
|
||||
).ok_or_else(|| "Could not append given item")?;
|
||||
storage.put_raw(&k[..], &new_val);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -330,6 +330,25 @@ impl<K: Codec, V: Codec, U> StorageMap<K, V> for U where U: hashed::generator::S
|
||||
}
|
||||
}
|
||||
|
||||
/// A storage map with values that can be appended to.
|
||||
pub trait AppendableStorageMap<K: Codec, V: Codec>: StorageMap<K, V> {
|
||||
/// Append the given item to the value in the storage.
|
||||
///
|
||||
/// `T` is required to implement `codec::EncodeAppend`.
|
||||
fn append<KeyArg: Borrow<K>, I: Encode>(key: KeyArg, items: &[I]) -> Result<(), &'static str>
|
||||
where V: EncodeAppend<Item=I>;
|
||||
}
|
||||
|
||||
impl<K: Codec, V: Codec, U> AppendableStorageMap<K, V> for U
|
||||
where U: hashed::generator::AppendableStorageMap<K, V>
|
||||
{
|
||||
fn append<KeyArg: Borrow<K>, I: Encode>(key: KeyArg, items: &[I]) -> Result<(), &'static str>
|
||||
where V: EncodeAppend<Item=I>
|
||||
{
|
||||
U::append(key.borrow(), items, &mut RuntimeStorage)
|
||||
}
|
||||
}
|
||||
|
||||
/// A storage map that can be enumerated.
|
||||
///
|
||||
/// Primarily useful for off-chain computations.
|
||||
@@ -342,7 +361,9 @@ pub trait EnumerableStorageMap<K: Codec, V: Codec>: StorageMap<K, V> {
|
||||
fn enumerate() -> Box<dyn Iterator<Item = (K, V)>> where K: 'static, V: 'static;
|
||||
}
|
||||
|
||||
impl<K: Codec, V: Codec, U> EnumerableStorageMap<K, V> for U where U: hashed::generator::EnumerableStorageMap<K, V> {
|
||||
impl<K: Codec, V: Codec, U> EnumerableStorageMap<K, V> for U
|
||||
where U: hashed::generator::EnumerableStorageMap<K, V>
|
||||
{
|
||||
fn head() -> Option<K> {
|
||||
<U as hashed::generator::EnumerableStorageMap<K, V>>::head(&RuntimeStorage)
|
||||
}
|
||||
|
||||
@@ -900,3 +900,46 @@ mod test3 {
|
||||
type BlockNumber = u32;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[allow(dead_code)]
|
||||
mod test_map_vec_append {
|
||||
pub trait Trait {
|
||||
type Origin;
|
||||
type BlockNumber;
|
||||
}
|
||||
decl_module! {
|
||||
pub struct Module<T: Trait> for enum Call where origin: T::Origin {}
|
||||
}
|
||||
crate::decl_storage! {
|
||||
trait Store for Module<T: Trait> as Test {
|
||||
JustVec: Vec<u32>;
|
||||
MapVec: map u32 => Vec<u32>;
|
||||
}
|
||||
}
|
||||
|
||||
struct Test {}
|
||||
|
||||
impl Trait for Test {
|
||||
type Origin = u32;
|
||||
type BlockNumber = u32;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn append_works() {
|
||||
use crate::storage::{AppendableStorageMap, StorageMap, StorageValue};
|
||||
use runtime_io::{with_externalities, TestExternalities};
|
||||
|
||||
with_externalities(&mut TestExternalities::default(), || {
|
||||
let _ = <MapVec<Test>>::append(1, &[1, 2, 3]);
|
||||
let _ = <MapVec<Test>>::append(1, &[4, 5]);
|
||||
assert_eq!(<MapVec<Test>>::get(1), vec![1, 2, 3, 4, 5]);
|
||||
|
||||
let _ = <JustVec<Test>>::append(&[1, 2, 3]);
|
||||
let _ = <JustVec<Test>>::append(&[4, 5]);
|
||||
assert_eq!(<JustVec<Test>>::get(), vec![1, 2, 3, 4, 5]);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user