Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Commit

Permalink
Adds try_get for StorageMap and StorageDoubleMap (#7774)
Browse files Browse the repository at this point in the history
* Adds `try_get` for `StorageMap` and `StorageDoubleMap`

* Switch to Value as return type
  • Loading branch information
bkchr authored Dec 22, 2020
1 parent 5c70d7b commit 37a7727
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 9 deletions.
7 changes: 7 additions & 0 deletions frame/support/src/storage/generator/double_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,13 @@ impl<K1, K2, V, G> storage::StorageDoubleMap<K1, K2, V> for G where
G::from_optional_value_to_query(unhashed::get(&Self::storage_double_map_final_key(k1, k2)))
}

fn try_get<KArg1, KArg2>(k1: KArg1, k2: KArg2) -> Result<V, ()>
where
KArg1: EncodeLike<K1>,
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
KArg1: EncodeLike<K1>,
KArg2: EncodeLike<K2>,
Expand Down
4 changes: 4 additions & 0 deletions frame/support/src/storage/generator/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,10 @@ impl<K: FullEncode, V: FullCodec, G: StorageMap<K, V>> storage::StorageMap<K, V>
G::from_optional_value_to_query(unhashed::get(Self::storage_map_final_key(key).as_ref()))
}

fn try_get<KeyArg: EncodeLike<K>>(key: KeyArg) -> Result<V, ()> {
unhashed::get(Self::storage_map_final_key(key).as_ref()).ok_or(())
}

fn insert<KeyArg: EncodeLike<K>, ValArg: EncodeLike<V>>(key: KeyArg, val: ValArg) {
unhashed::put(Self::storage_map_final_key(key).as_ref(), &val)
}
Expand Down
31 changes: 22 additions & 9 deletions frame/support/src/storage/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,7 @@ pub fn with_transaction<R>(f: impl FnOnce() -> TransactionOutcome<R>) -> R {

/// A trait for working with macro-generated storage values under the substrate storage API.
///
/// Details on implementation can be found at
/// [`generator::StorageValue`]
/// Details on implementation can be found at [`generator::StorageValue`].
pub trait StorageValue<T: FullCodec> {
/// The type that get/take return.
type Query;
Expand All @@ -122,8 +121,9 @@ pub trait StorageValue<T: FullCodec> {
/// Load the value from the provided storage instance.
fn get() -> Self::Query;

/// Try to get the underlying value from the provided storage instance; `Ok` if it exists,
/// `Err` if not.
/// Try to get the underlying value from the provided storage instance.
///
/// Returns `Ok` if it exists, `Err` if not.
fn try_get() -> Result<T, ()>;

/// Translate a value from some previous type (`O`) to the current type.
Expand Down Expand Up @@ -200,8 +200,7 @@ pub trait StorageValue<T: FullCodec> {

/// A strongly-typed map in storage.
///
/// Details on implementation can be found at
/// [`generator::StorageMap`]
/// Details on implementation can be found at [`generator::StorageMap`].
pub trait StorageMap<K: FullEncode, V: FullCodec> {
/// The type that get/take return.
type Query;
Expand All @@ -215,6 +214,11 @@ pub trait StorageMap<K: FullEncode, V: FullCodec> {
/// Load the value associated with the given key from the map.
fn get<KeyArg: EncodeLike<K>>(key: KeyArg) -> Self::Query;

/// Try to get the value for the given key from the map.
///
/// Returns `Ok` if it exists, `Err` if not.
fn try_get<KeyArg: EncodeLike<K>>(key: KeyArg) -> Result<V, ()>;

/// Swap the values of two keys.
fn swap<KeyArg1: EncodeLike<K>, KeyArg2: EncodeLike<K>>(key1: KeyArg1, key2: KeyArg2);

Expand All @@ -233,7 +237,9 @@ pub trait StorageMap<K: FullEncode, V: FullCodec> {
f: F,
) -> Result<R, E>;

/// Mutate the value under a key. Deletes the item if mutated to a `None`.
/// 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;

/// Mutate the item, only if an `Ok` value is returned. Deletes the item if mutated to a `None`.
Expand Down Expand Up @@ -354,8 +360,7 @@ pub trait IterableStorageDoubleMap<
/// It provides an important ability to efficiently remove all entries
/// that have a common first key.
///
/// Details on implementation can be found at
/// [`generator::StorageDoubleMap`]
/// Details on implementation can be found at [`generator::StorageDoubleMap`].
pub trait StorageDoubleMap<K1: FullEncode, K2: FullEncode, V: FullCodec> {
/// The type that get/take returns.
type Query;
Expand All @@ -378,6 +383,14 @@ pub trait StorageDoubleMap<K1: FullEncode, K2: FullEncode, V: FullCodec> {
KArg1: EncodeLike<K1>,
KArg2: EncodeLike<K2>;

/// Try to get the value for the given key from the double map.
///
/// Returns `Ok` if it exists, `Err` if not.
fn try_get<KArg1, KArg2>(k1: KArg1, k2: KArg2) -> Result<V, ()>
where
KArg1: EncodeLike<K1>,
KArg2: EncodeLike<K2>;

/// Take a value from storage, removing it afterwards.
fn take<KArg1, KArg2>(k1: KArg1, k2: KArg2) -> Self::Query
where
Expand Down
12 changes: 12 additions & 0 deletions frame/support/src/storage/types/double_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,16 @@ where
<Self as crate::storage::StorageDoubleMap<Key1, Key2, Value>>::get(k1, k2)
}

/// Try to get the value for the given key from the double map.
///
/// Returns `Ok` if it exists, `Err` if not.
pub fn try_get<KArg1, KArg2>(k1: KArg1, k2: KArg2) -> Result<Value, ()>
where
KArg1: EncodeLike<Key1>,
KArg2: EncodeLike<Key2> {
<Self as crate::storage::StorageDoubleMap<Key1, Key2, Value>>::try_get(k1, k2)
}

/// Take a value from storage, removing it afterwards.
pub fn take<KArg1, KArg2>(k1: KArg1, k2: KArg2) -> QueryKind::Query
where
Expand Down Expand Up @@ -514,6 +524,7 @@ mod test {
});
assert_eq!(A::contains_key(2, 20), true);
assert_eq!(A::get(2, 20), Some(100));
assert_eq!(A::try_get(2, 20), Ok(100));
let _: Result<(), ()> = AValueQueryWithAnOnEmpty::try_mutate_exists(2, 20, |v| {
*v = Some(v.unwrap() * 10);
Err(())
Expand All @@ -527,6 +538,7 @@ mod test {
assert_eq!(A::contains_key(2, 20), false);
assert_eq!(AValueQueryWithAnOnEmpty::take(2, 20), 97);
assert_eq!(A::contains_key(2, 20), false);
assert_eq!(A::try_get(2, 20), Err(()));

B::insert(2, 20, 10);
assert_eq!(A::migrate_keys::<Blake2_256, Twox128, _, _>(2, 20), Some(10));
Expand Down
9 changes: 9 additions & 0 deletions frame/support/src/storage/types/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,13 @@ where
<Self as crate::storage::StorageMap<Key, Value>>::get(key)
}

/// Try to get the value for the given key from the map.
///
/// Returns `Ok` if it exists, `Err` if not.
pub fn try_get<KeyArg: EncodeLike<Key>>(key: KeyArg) -> Result<Value, ()> {
<Self as crate::storage::StorageMap<Key, Value>>::try_get(key)
}

/// Swap the values of two keys.
pub fn swap<KeyArg1: EncodeLike<Key>, KeyArg2: EncodeLike<Key>>(key1: KeyArg1, key2: KeyArg2) {
<Self as crate::storage::StorageMap<Key, Value>>::swap(key1, key2)
Expand Down Expand Up @@ -352,12 +359,14 @@ mod test {
A::insert(3, 10);
assert_eq!(A::contains_key(3), true);
assert_eq!(A::get(3), Some(10));
assert_eq!(A::try_get(3), Ok(10));
assert_eq!(AValueQueryWithAnOnEmpty::get(3), 10);

A::swap(3, 2);
assert_eq!(A::contains_key(3), false);
assert_eq!(A::contains_key(2), true);
assert_eq!(A::get(3), None);
assert_eq!(A::try_get(3), Err(()));
assert_eq!(AValueQueryWithAnOnEmpty::get(3), 97);
assert_eq!(A::get(2), Some(10));
assert_eq!(AValueQueryWithAnOnEmpty::get(2), 10);
Expand Down

0 comments on commit 37a7727

Please sign in to comment.