use codec::{FullCodec, Encode, Decode, EncodeLike, Ref};
use crate::{storage::{self, unhashed}, hash::{StorageHasher, Twox128}, traits::Len};
use sp_std::{prelude::*, marker::PhantomData};
pub trait StorageLinkedMap<K: FullCodec, V: FullCodec> {
type Query;
type KeyFormat: KeyFormat;
fn from_optional_value_to_query(v: Option<V>) -> Self::Query;
fn from_query_to_optional_value(v: Self::Query) -> Option<V>;
fn storage_linked_map_final_key<KeyArg>(key: KeyArg) -> Vec<u8>
where
KeyArg: EncodeLike<K>,
{
<Self::KeyFormat as KeyFormat>::storage_linked_map_final_key::<KeyArg>(&key)
}
fn storage_linked_map_final_head_key() -> Vec<u8> {
<Self::KeyFormat as KeyFormat>::storage_linked_map_final_head_key()
}
}
pub trait KeyFormat {
type Hasher: StorageHasher;
fn module_prefix() -> &'static [u8];
fn storage_prefix() -> &'static [u8];
fn head_prefix() -> &'static [u8];
fn storage_linked_map_final_key<K>(key: &K) -> Vec<u8>
where
K: Encode,
{
let module_prefix_hashed = Twox128::hash(Self::module_prefix());
let storage_prefix_hashed = Twox128::hash(Self::storage_prefix());
let key_hashed = key.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()
);
final_key.extend_from_slice(&module_prefix_hashed[..]);
final_key.extend_from_slice(&storage_prefix_hashed[..]);
final_key.extend_from_slice(key_hashed.as_ref());
final_key
}
fn storage_linked_map_final_head_key() -> Vec<u8> {
[
Twox128::hash(Self::module_prefix()),
Twox128::hash(Self::head_prefix()),
].concat()
}
}
#[derive(Encode, Decode)]
pub struct Linkage<Key> {
pub previous: Option<Key>,
pub next: Option<Key>,
}
impl<Key> Default for Linkage<Key> {
fn default() -> Self {
Self {
previous: None,
next: None,
}
}
}
#[derive(Encode)]
struct EncodeLikeLinkage<PKey: EncodeLike<Key>, NKey: EncodeLike<Key>, Key: Encode> {
previous: Option<PKey>,
next: Option<NKey>,
phantom: core::marker::PhantomData<Key>,
}
pub struct Enumerator<K, V, F> {
next: Option<K>,
_phantom: PhantomData<(V, F)>,
}
impl<K, V, F> Enumerator<K, V, F> {
#[cfg(test)]
pub fn from_head(head: K) -> Self {
Enumerator {
next: Some(head),
_phantom: Default::default(),
}
}
}
impl<K, V, F> Iterator for Enumerator<K, V, F>
where
K: FullCodec,
V: FullCodec,
F: KeyFormat,
{
type Item = (K, V);
fn next(&mut self) -> Option<Self::Item> {
let next = self.next.take()?;
let (val, linkage): (V, Linkage<K>) = {
let next_full_key = F::storage_linked_map_final_key(&next);
match read_with_linkage::<K, V>(next_full_key.as_ref()) {
Some(value) => value,
None => {
runtime_print!(
"ERROR: Corrupted state: linked map {:?}{:?}: \
next value doesn't exist at {:?}",
F::module_prefix(), F::storage_prefix(), next_full_key,
);
return None
}
}
};
self.next = linkage.next;
Some((next, val))
}
}
fn remove_linkage<K, V, F>(linkage: Linkage<K>)
where
K: FullCodec,
V: FullCodec,
F: KeyFormat,
{
let next_key = linkage.next.as_ref().map(|k| F::storage_linked_map_final_key(k));
let prev_key = linkage.previous.as_ref().map(|k| F::storage_linked_map_final_key(k));
if let Some(prev_key) = prev_key {
if let Some(mut res) = read_with_linkage::<K, V>(prev_key.as_ref()) {
res.1.next = linkage.next;
unhashed::put(prev_key.as_ref(), &res);
} else {
runtime_print!(
"ERROR: Corrupted state: linked map {:?}{:?}: \
previous value doesn't exist at {:?}",
F::module_prefix(), F::storage_prefix(), prev_key,
);
}
} else {
write_head::<&K, K, F>(linkage.next.as_ref());
}
if let Some(next_key) = next_key {
if let Some(mut res) = read_with_linkage::<K, V>(next_key.as_ref()) {
res.1.previous = linkage.previous;
unhashed::put(next_key.as_ref(), &res);
} else {
runtime_print!(
"ERROR: Corrupted state: linked map {:?}{:?}: \
next value doesn't exist at {:?}",
F::module_prefix(), F::storage_prefix(), next_key,
);
}
}
}
pub(super) fn read_with_linkage<K, V>(key: &[u8]) -> Option<(V, Linkage<K>)>
where
K: Decode,
V: Decode,
{
unhashed::get(key)
}
pub(super) fn new_head_linkage<KeyArg, K, V, F>(key: KeyArg) -> Linkage<K>
where
KeyArg: EncodeLike<K>,
K: FullCodec,
V: FullCodec,
F: KeyFormat,
{
if let Some(head) = read_head::<K, F>() {
{
let head_key = F::storage_linked_map_final_key(&head);
if let Some((data, linkage)) = read_with_linkage::<K, V>(head_key.as_ref()) {
let new_linkage = EncodeLikeLinkage::<_, _, K> {
previous: Some(Ref::from(&key)),
next: linkage.next.as_ref(),
phantom: Default::default(),
};
unhashed::put(head_key.as_ref(), &(data, new_linkage));
} else {
runtime_print!(
"ERROR: Corrupted state: linked map {:?}{:?}: \
head value doesn't exist at {:?}",
F::module_prefix(), F::storage_prefix(), head_key,
);
write_head::<_, _, F>(Some(key));
return Linkage::default();
}
}
write_head::<_, _, F>(Some(key));
let mut linkage = Linkage::default();
linkage.next = Some(head);
linkage
} else {
write_head::<_, _, F>(Some(key));
Linkage::default()
}
}
pub(crate) fn read_head<K, F>() -> Option<K>
where
K: Decode,
F: KeyFormat,
{
unhashed::get(F::storage_linked_map_final_head_key().as_ref())
}
pub(super) fn write_head<KeyArg, K, F>(head: Option<KeyArg>)
where
KeyArg: EncodeLike<K>,
K: FullCodec,
F: KeyFormat,
{
match head.as_ref() {
Some(head) => unhashed::put(F::storage_linked_map_final_head_key().as_ref(), head),
None => unhashed::kill(F::storage_linked_map_final_head_key().as_ref()),
}
}
impl<K, V, G> storage::StorageLinkedMap<K, V> for G
where
K: FullCodec,
V: FullCodec,
G: StorageLinkedMap<K, V>,
{
type Query = G::Query;
type Enumerator = Enumerator<K, V, G::KeyFormat>;
fn exists<KeyArg: EncodeLike<K>>(key: KeyArg) -> bool {
unhashed::exists(Self::storage_linked_map_final_key(key).as_ref())
}
fn get<KeyArg: EncodeLike<K>>(key: KeyArg) -> Self::Query {
let val = unhashed::get(Self::storage_linked_map_final_key(key).as_ref());
G::from_optional_value_to_query(val)
}
fn swap<KeyArg1: EncodeLike<K>, KeyArg2: EncodeLike<K>>(key1: KeyArg1, key2: KeyArg2) {
let final_key1 = Self::storage_linked_map_final_key(Ref::from(&key1));
let final_key2 = Self::storage_linked_map_final_key(Ref::from(&key2));
let full_value_1 = read_with_linkage::<K, V>(final_key1.as_ref());
let full_value_2 = read_with_linkage::<K, V>(final_key2.as_ref());
match (full_value_1, full_value_2) {
(Some((value1, linkage1)), Some((value2, linkage2))) => {
unhashed::put(final_key1.as_ref(), &(value2, linkage1));
unhashed::put(final_key2.as_ref(), &(value1, linkage2));
}
(Some((value, _linkage)), None) => {
Self::remove(key1);
let linkage = new_head_linkage::<_, _, V, G::KeyFormat>(key2);
unhashed::put(final_key2.as_ref(), &(value, linkage));
}
(None, Some((value, _linkage))) => {
Self::remove(key2);
let linkage = new_head_linkage::<_, _, V, G::KeyFormat>(key1);
unhashed::put(final_key1.as_ref(), &(value, linkage));
}
(None, None) => (),
}
}
fn insert<KeyArg: EncodeLike<K>, ValArg: EncodeLike<V>>(key: KeyArg, val: ValArg) {
let final_key = Self::storage_linked_map_final_key(Ref::from(&key));
let linkage = match read_with_linkage::<_, V>(final_key.as_ref()) {
Some((_data, linkage)) => linkage,
None => new_head_linkage::<_, _, V, G::KeyFormat>(key),
};
unhashed::put(final_key.as_ref(), &(val, linkage))
}
fn remove<KeyArg: EncodeLike<K>>(key: KeyArg) {
G::take(key);
}
fn mutate<KeyArg: EncodeLike<K>, R, F: FnOnce(&mut Self::Query) -> R>(key: KeyArg, f: F) -> R {
let final_key = Self::storage_linked_map_final_key(Ref::from(&key));
let (mut val, _linkage) = read_with_linkage::<K, V>(final_key.as_ref())
.map(|(data, linkage)| (G::from_optional_value_to_query(Some(data)), Some(linkage)))
.unwrap_or_else(|| (G::from_optional_value_to_query(None), None));
let ret = f(&mut val);
match G::from_query_to_optional_value(val) {
Some(ref val) => G::insert(key, val),
None => G::remove(key),
}
ret
}
fn take<KeyArg: EncodeLike<K>>(key: KeyArg) -> Self::Query {
let final_key = Self::storage_linked_map_final_key(key);
let full_value: Option<(V, Linkage<K>)> = unhashed::take(final_key.as_ref());
let value = full_value.map(|(data, linkage)| {
remove_linkage::<K, V, G::KeyFormat>(linkage);
data
});
G::from_optional_value_to_query(value)
}
fn enumerate() -> Self::Enumerator {
Enumerator::<_, _, G::KeyFormat> {
next: read_head::<_, G::KeyFormat>(),
_phantom: Default::default(),
}
}
fn head() -> Option<K> {
read_head::<_, G::KeyFormat>()
}
fn decode_len<KeyArg: EncodeLike<K>>(key: KeyArg) -> Result<usize, &'static str>
where V: codec::DecodeLength + Len
{
let key = Self::storage_linked_map_final_key(key);
if let Some(v) = unhashed::get_raw(key.as_ref()) {
<V as codec::DecodeLength>::len(&v).map_err(|e| e.what())
} else {
let len = G::from_query_to_optional_value(G::from_optional_value_to_query(None))
.map(|v| v.len())
.unwrap_or(0);
Ok(len)
}
}
fn translate<K2, V2, TK, TV>(translate_key: TK, translate_val: TV) -> Result<(), Option<K2>>
where K2: FullCodec + Clone, V2: Decode, TK: Fn(K2) -> K, TV: Fn(V2) -> V
{
let head_key = read_head::<K2, G::KeyFormat>().ok_or(None)?;
let mut last_key = None;
let mut current_key = head_key.clone();
write_head::<&K, K, G::KeyFormat>(Some(&translate_key(head_key)));
let translate_linkage = |old: Linkage<K2>| -> Linkage<K> {
Linkage {
previous: old.previous.map(&translate_key),
next: old.next.map(&translate_key),
}
};
loop {
let old_raw_key = G::KeyFormat::storage_linked_map_final_key(¤t_key);
let x = unhashed::take(old_raw_key.as_ref());
let (val, linkage): (V2, Linkage<K2>) = match x {
Some(v) => v,
None => {
if let Some(last_key) = last_key {
let last_raw_key = G::storage_linked_map_final_key(&last_key);
if let Some((val, mut linkage))
= read_with_linkage::<K, V>(last_raw_key.as_ref())
{
linkage.next = None;
unhashed::put(last_raw_key.as_ref(), &(&val, &linkage));
}
}
return Err(Some(current_key));
}
};
let next = linkage.next.clone();
let val = translate_val(val);
let linkage = translate_linkage(linkage);
let new_key = translate_key(current_key.clone());
let new_raw_key = G::storage_linked_map_final_key(&new_key);
unhashed::put(new_raw_key.as_ref(), &(&val, &linkage));
match next {
None => break,
Some(next) => {
last_key = Some(new_key);
current_key = next
},
}
}
Ok(())
}
}