extern crate alloc;
use alloc::vec::Vec;
use crate::backend::MemoryStorage;
use crate::codec::{BytesCodec, Codec32};
use crate::collections::{Namespace, StorageBlob, StorageMap, StorageVec};
use crate::error::Result;
#[derive(Clone, Debug, Default)]
pub struct StorageHarness {
backend: MemoryStorage,
}
impl StorageHarness {
pub fn new() -> Self {
Self {
backend: MemoryStorage::new(),
}
}
pub fn from_backend(backend: MemoryStorage) -> Self {
Self { backend }
}
pub fn backend(&self) -> &MemoryStorage {
&self.backend
}
pub fn backend_mut(&mut self) -> &mut MemoryStorage {
&mut self.backend
}
pub fn read_raw(&self, key: &[u8; 32]) -> Result<[u8; 32]> {
use crate::backend::StorageBackend;
self.backend.read_32(key)
}
pub fn write_raw(&mut self, key: [u8; 32], value: [u8; 32]) -> Result<()> {
use crate::backend::StorageBackend;
self.backend.write_32(key, value)
}
pub fn map<V: Codec32>(&mut self, namespace: Namespace) -> TestMap<'_, V> {
TestMap {
map: StorageMap::new(namespace),
backend: &mut self.backend,
}
}
pub fn vec<V: Codec32>(&mut self, namespace: Namespace) -> TestVec<'_, V> {
TestVec {
list: StorageVec::new(namespace),
backend: &mut self.backend,
}
}
pub fn blob(&mut self, namespace: Namespace) -> TestBlob<'_> {
TestBlob {
blob: StorageBlob::new(namespace),
backend: &mut self.backend,
}
}
}
pub struct TestMap<'a, V: Codec32> {
map: StorageMap<V>,
backend: &'a mut MemoryStorage,
}
impl<'a, V: Codec32> TestMap<'a, V> {
pub fn contains_key(&self, key: &[u8]) -> Result<bool> {
self.map.contains_key_in(&*self.backend, key)
}
pub fn get(&self, key: &[u8]) -> Result<Option<V>> {
self.map.get_in(&*self.backend, key)
}
pub fn insert(&mut self, key: &[u8], value: &V) -> Result<()> {
self.map.insert_in(self.backend, key, value)
}
pub fn remove(&mut self, key: &[u8]) -> Result<()> {
self.map.remove_in(self.backend, key)
}
}
pub struct TestVec<'a, V: Codec32> {
list: StorageVec<V>,
backend: &'a mut MemoryStorage,
}
impl<'a, V: Codec32> TestVec<'a, V> {
pub fn len(&self) -> Result<u64> {
self.list.len_in(&*self.backend)
}
pub fn get(&self, index: u64) -> Result<Option<V>> {
self.list.get_in(&*self.backend, index)
}
pub fn set(&mut self, index: u64, value: &V) -> Result<bool> {
self.list.set_in(self.backend, index, value)
}
pub fn push(&mut self, value: &V) -> Result<u64> {
self.list.push_in(self.backend, value)
}
pub fn pop(&mut self) -> Result<Option<V>> {
self.list.pop_in(self.backend)
}
pub fn clear(&mut self) -> Result<()> {
self.list.clear_in(self.backend)
}
}
pub struct TestBlob<'a> {
blob: StorageBlob,
backend: &'a mut MemoryStorage,
}
impl<'a> TestBlob<'a> {
pub fn write(&mut self, data: &[u8]) -> Result<()> {
self.blob.write_in(self.backend, data)
}
pub fn read(&self) -> Result<Vec<u8>> {
self.blob.read_in(&*self.backend)
}
pub fn put<T: BytesCodec>(&mut self, value: &T) -> Result<()> {
self.blob.put_in(self.backend, value)
}
pub fn get<T: BytesCodec>(&self) -> Result<T> {
self.blob.get_in(&*self.backend)
}
pub fn clear(&mut self) -> Result<()> {
self.blob.clear_in(self.backend)
}
}
#[cfg(test)]
mod tests {
use super::*;
const NS_MAP: Namespace = Namespace([9u8; 32]);
const NS_VEC: Namespace = Namespace([8u8; 32]);
const NS_BLOB: Namespace = Namespace([7u8; 32]);
#[test]
fn harness_map_vec_blob() {
let mut harness = StorageHarness::new();
{
let mut map = harness.map::<u64>(NS_MAP);
map.insert(b"alice", &7).unwrap();
assert_eq!(map.get(b"alice").unwrap(), Some(7));
}
{
let mut list = harness.vec::<u64>(NS_VEC);
list.push(&11).unwrap();
assert_eq!(list.get(0).unwrap(), Some(11));
}
{
let mut blob = harness.blob(NS_BLOB);
blob.put(&alloc::string::String::from("hello")).unwrap();
let decoded: alloc::string::String = blob.get().unwrap();
assert_eq!(decoded, "hello");
}
}
}