frame-support Add translate_next (#14043)

* Frame Add translate_next

This works similarly to to `translate` but only translate a single entry.
This function will be useful in the context of multi-block migration.

* Add test

* add None return case

* fixes

* PR comment use `?`
This commit is contained in:
PG Herveou
2023-06-02 16:11:11 +02:00
committed by GitHub
parent 31f9593324
commit 9dedddafad
3 changed files with 59 additions and 27 deletions
@@ -178,35 +178,49 @@ where
}
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))
{
previous_key = next;
let value = match unhashed::get::<O>(&previous_key) {
Some(value) => value,
None => {
log::error!("Invalid translate: fail to decode old value");
continue
},
};
let mut key_material = G::Hasher::reverse(&previous_key[prefix.len()..]);
let key = match K::decode(&mut key_material) {
Ok(key) => key,
Err(_) => {
log::error!("Invalid translate: fail to decode key");
continue
},
};
match f(key, value) {
Some(new) => unhashed::put::<V>(&previous_key, &new),
None => unhashed::kill(&previous_key),
let mut previous_key = None;
loop {
previous_key = Self::translate_next(previous_key, &mut f);
if previous_key.is_none() {
break
}
}
}
fn translate_next<O: Decode, F: FnMut(K, O) -> Option<V>>(
previous_key: Option<Vec<u8>>,
mut f: F,
) -> Option<Vec<u8>> {
let prefix = G::prefix_hash();
let previous_key = previous_key.unwrap_or_else(|| prefix.clone());
let current_key =
sp_io::storage::next_key(&previous_key).filter(|n| n.starts_with(&prefix))?;
let value = match unhashed::get::<O>(&current_key) {
Some(value) => value,
None => {
log::error!("Invalid translate: fail to decode old value");
return Some(current_key)
},
};
let mut key_material = G::Hasher::reverse(&current_key[prefix.len()..]);
let key = match K::decode(&mut key_material) {
Ok(key) => key,
Err(_) => {
log::error!("Invalid translate: fail to decode key");
return Some(current_key)
},
};
match f(key, value) {
Some(new) => unhashed::put::<V>(&current_key, &new),
None => unhashed::kill(&current_key),
}
Some(current_key)
}
}
impl<K: FullEncode, V: FullCodec, G: StorageMap<K, V>> storage::StorageMap<K, V> for G {