oasis_runtime_sdk/storage/
typed.rs

1use std::{convert::TryFrom, marker::PhantomData};
2
3use oasis_core_runtime::storage::mkvs;
4
5use super::Store;
6
7/// A key-value store that transparently handles serialization/deserialization.
8pub struct TypedStore<S: Store> {
9    parent: S,
10}
11
12impl<S: Store> TypedStore<S> {
13    /// Create a new typed store.
14    pub fn new(parent: S) -> Self {
15        Self { parent }
16    }
17
18    /// Fetch entry with given key.
19    pub fn get<K: AsRef<[u8]>, T: cbor::Decode>(&self, key: K) -> Option<T> {
20        self.parent
21            .get(key.as_ref())
22            .map(|data| cbor::from_slice(&data).unwrap())
23    }
24
25    /// Update entry with given key to the given value.
26    pub fn insert<K: AsRef<[u8]>, T: cbor::Encode>(&mut self, key: K, value: T) {
27        self.parent.insert(key.as_ref(), &cbor::to_vec(value))
28    }
29
30    /// Remove entry with given key.
31    pub fn remove<K: AsRef<[u8]>>(&mut self, key: K) {
32        self.parent.remove(key.as_ref())
33    }
34
35    pub fn iter<'store, K, V>(&'store self) -> TypedStoreIterator<'store, K, V>
36    where
37        K: for<'k> TryFrom<&'k [u8]>,
38        V: cbor::Decode + Default,
39    {
40        TypedStoreIterator::new(self.parent.iter())
41    }
42}
43
44/// An iterator over the `TypedStore`.
45pub struct TypedStoreIterator<'store, K, V>
46where
47    K: for<'k> TryFrom<&'k [u8]>,
48    V: Default + cbor::Decode,
49{
50    inner: Box<dyn mkvs::Iterator + 'store>,
51
52    _key: PhantomData<K>,
53    _value: PhantomData<V>,
54}
55
56impl<'store, K, V> TypedStoreIterator<'store, K, V>
57where
58    K: for<'k> TryFrom<&'k [u8]>,
59    V: cbor::Decode + Default,
60{
61    fn new(inner: Box<dyn mkvs::Iterator + 'store>) -> Self {
62        Self {
63            inner,
64            _key: PhantomData,
65            _value: PhantomData,
66        }
67    }
68}
69
70impl<K, V, E> Iterator for TypedStoreIterator<'_, K, V>
71where
72    K: for<'k> TryFrom<&'k [u8], Error = E>,
73    E: std::fmt::Display,
74    V: cbor::Decode + Default,
75{
76    type Item = (K, V);
77
78    fn next(&mut self) -> Option<Self::Item> {
79        Iterator::next(&mut self.inner).map(|(k, v)| {
80            let key = K::try_from(&k).unwrap_or_else(|e| panic!("corrupted storage key: {e}"));
81            let value = if v.is_empty() {
82                // Ignore empty values as those would fail CBOR decoding.
83                Default::default()
84            } else {
85                cbor::from_slice(&v).unwrap()
86            };
87            (key, value)
88        })
89    }
90}