Skip to content

Commit 9762613

Browse files
muracaggwpez
andauthored
mutate_exists for StorageValue with ValueQuery (paritytech#13245)
* mutate_exists for StorageValue with ValueQuery Signed-off-by: muraca <mmuraca247@gmail.com> * added `#[crate::storage_alias]` to tests Signed-off-by: muraca <mmuraca247@gmail.com> * added StorageEntryMetadata Signed-off-by: muraca <mmuraca247@gmail.com> * Update frame/support/src/lib.rs --------- Signed-off-by: muraca <mmuraca247@gmail.com> Co-authored-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>
1 parent ce2cee3 commit 9762613

File tree

4 files changed

+105
-0
lines changed

4 files changed

+105
-0
lines changed

frame/support/src/lib.rs

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -874,6 +874,7 @@ pub mod tests {
874874

875875
decl_storage! {
876876
trait Store for Module<T: Config> as Test {
877+
pub Value get(fn value): u64;
877878
pub Data get(fn data) build(|_| vec![(15u32, 42u64)]):
878879
map hasher(twox_64_concat) u32 => u64;
879880
pub OptionLinkedMap: map hasher(blake2_128_concat) u32 => Option<u32>;
@@ -946,6 +947,61 @@ pub mod tests {
946947
});
947948
}
948949

950+
#[test]
951+
fn storage_value_mutate_exists_should_work() {
952+
new_test_ext().execute_with(|| {
953+
#[crate::storage_alias]
954+
pub type Value = StorageValue<Test, u32>;
955+
956+
assert!(!Value::exists());
957+
958+
Value::mutate_exists(|v| *v = Some(1));
959+
assert!(Value::exists());
960+
assert_eq!(Value::get(), Some(1));
961+
962+
// removed if mutated to `None`
963+
Value::mutate_exists(|v| *v = None);
964+
assert!(!Value::exists());
965+
});
966+
}
967+
968+
#[test]
969+
fn storage_value_try_mutate_exists_should_work() {
970+
new_test_ext().execute_with(|| {
971+
#[crate::storage_alias]
972+
pub type Value = StorageValue<Test, u32>;
973+
974+
type TestResult = result::Result<(), &'static str>;
975+
976+
assert!(!Value::exists());
977+
978+
// mutated if `Ok`
979+
assert_ok!(Value::try_mutate_exists(|v| -> TestResult {
980+
*v = Some(1);
981+
Ok(())
982+
}));
983+
assert!(Value::exists());
984+
assert_eq!(Value::get(), Some(1));
985+
986+
// no-op if `Err`
987+
assert_noop!(
988+
Value::try_mutate_exists(|v| -> TestResult {
989+
*v = Some(2);
990+
Err("nah")
991+
}),
992+
"nah"
993+
);
994+
assert_eq!(Value::get(), Some(1));
995+
996+
// removed if mutated to`None`
997+
assert_ok!(Value::try_mutate_exists(|v| -> TestResult {
998+
*v = None;
999+
Ok(())
1000+
}));
1001+
assert!(!Value::exists());
1002+
});
1003+
}
1004+
9491005
#[test]
9501006
fn map_issue_3318() {
9511007
new_test_ext().execute_with(|| {
@@ -1257,6 +1313,13 @@ pub mod tests {
12571313
PalletStorageMetadata {
12581314
prefix: "Test",
12591315
entries: vec![
1316+
StorageEntryMetadata {
1317+
name: "Value",
1318+
modifier: StorageEntryModifier::Default,
1319+
ty: StorageEntryType::Plain(scale_info::meta_type::<u64>()),
1320+
default: vec![0, 0, 0, 0, 0, 0, 0, 0],
1321+
docs: vec![],
1322+
},
12601323
StorageEntryMetadata {
12611324
name: "Data",
12621325
modifier: StorageEntryModifier::Default,

frame/support/src/storage/generator/value.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,30 @@ impl<T: FullCodec, G: StorageValue<T>> storage::StorageValue<T> for G {
118118
ret
119119
}
120120

121+
fn mutate_exists<R, F>(f: F) -> R
122+
where
123+
F: FnOnce(&mut Option<T>) -> R,
124+
{
125+
Self::try_mutate_exists(|v| Ok::<R, Never>(f(v)))
126+
.expect("`Never` can not be constructed; qed")
127+
}
128+
129+
fn try_mutate_exists<R, E, F>(f: F) -> Result<R, E>
130+
where
131+
F: FnOnce(&mut Option<T>) -> Result<R, E>,
132+
{
133+
let mut val = G::from_query_to_optional_value(Self::get());
134+
135+
let ret = f(&mut val);
136+
if ret.is_ok() {
137+
match val {
138+
Some(ref val) => Self::put(val),
139+
None => Self::kill(),
140+
}
141+
}
142+
ret
143+
}
144+
121145
fn take() -> G::Query {
122146
let key = Self::storage_value_final_key();
123147
let value = unhashed::get(&key);

frame/support/src/storage/mod.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,12 @@ pub trait StorageValue<T: FullCodec> {
114114
/// Mutate the value if closure returns `Ok`
115115
fn try_mutate<R, E, F: FnOnce(&mut Self::Query) -> Result<R, E>>(f: F) -> Result<R, E>;
116116

117+
/// Mutate the value. Deletes the item if mutated to a `None`.
118+
fn mutate_exists<R, F: FnOnce(&mut Option<T>) -> R>(f: F) -> R;
119+
120+
/// Mutate the value if closure returns `Ok`. Deletes the item if mutated to a `None`.
121+
fn try_mutate_exists<R, E, F: FnOnce(&mut Option<T>) -> Result<R, E>>(f: F) -> Result<R, E>;
122+
117123
/// Clear the storage value.
118124
fn kill();
119125

frame/support/src/storage/types/value.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,18 @@ where
142142
<Self as crate::storage::StorageValue<Value>>::try_mutate(f)
143143
}
144144

145+
/// Mutate the value. Deletes the item if mutated to a `None`.
146+
pub fn mutate_exists<R, F: FnOnce(&mut Option<Value>) -> R>(f: F) -> R {
147+
<Self as crate::storage::StorageValue<Value>>::mutate_exists(f)
148+
}
149+
150+
/// Mutate the value if closure returns `Ok`. Deletes the item if mutated to a `None`.
151+
pub fn try_mutate_exists<R, E, F: FnOnce(&mut Option<Value>) -> Result<R, E>>(
152+
f: F,
153+
) -> Result<R, E> {
154+
<Self as crate::storage::StorageValue<Value>>::try_mutate_exists(f)
155+
}
156+
145157
/// Clear the storage value.
146158
pub fn kill() {
147159
<Self as crate::storage::StorageValue<Value>>::kill()

0 commit comments

Comments
 (0)