use cosmwasm::traits::{ReadonlyStorage, Storage};
use crate::namespace_helpers::{get_with_prefix, key_prefix, key_prefix_nested, set_with_prefix};
pub fn prefixed_read<'a, T: ReadonlyStorage>(
prefix: &[u8],
storage: &'a T,
) -> ReadonlyPrefixedStorage<'a, T> {
ReadonlyPrefixedStorage::new(prefix, storage)
}
pub fn prefixed<'a, T: Storage>(prefix: &[u8], storage: &'a mut T) -> PrefixedStorage<'a, T> {
PrefixedStorage::new(prefix, storage)
}
pub struct ReadonlyPrefixedStorage<'a, T: ReadonlyStorage> {
prefix: Vec<u8>,
storage: &'a T,
}
impl<'a, T: ReadonlyStorage> ReadonlyPrefixedStorage<'a, T> {
pub fn new(namespace: &[u8], storage: &'a T) -> Self {
ReadonlyPrefixedStorage {
prefix: key_prefix(namespace),
storage,
}
}
pub fn multilevel(namespaces: &[&[u8]], storage: &'a T) -> Self {
ReadonlyPrefixedStorage {
prefix: key_prefix_nested(namespaces),
storage,
}
}
}
impl<'a, T: ReadonlyStorage> ReadonlyStorage for ReadonlyPrefixedStorage<'a, T> {
fn get(&self, key: &[u8]) -> Option<Vec<u8>> {
get_with_prefix(self.storage, &self.prefix, key)
}
}
pub struct PrefixedStorage<'a, T: Storage> {
prefix: Vec<u8>,
storage: &'a mut T,
}
impl<'a, T: Storage> PrefixedStorage<'a, T> {
pub fn new(namespace: &[u8], storage: &'a mut T) -> Self {
PrefixedStorage {
prefix: key_prefix(namespace),
storage,
}
}
pub fn multilevel(namespaces: &[&[u8]], storage: &'a mut T) -> Self {
PrefixedStorage {
prefix: key_prefix_nested(namespaces),
storage,
}
}
}
impl<'a, T: Storage> ReadonlyStorage for PrefixedStorage<'a, T> {
fn get(&self, key: &[u8]) -> Option<Vec<u8>> {
get_with_prefix(self.storage, &self.prefix, key)
}
}
impl<'a, T: Storage> Storage for PrefixedStorage<'a, T> {
fn set(&mut self, key: &[u8], value: &[u8]) {
set_with_prefix(self.storage, &self.prefix, key, value)
}
}
#[cfg(test)]
mod test {
use super::*;
use cosmwasm::mock::MockStorage;
#[test]
fn prefix_safe() {
let mut storage = MockStorage::new();
let mut foo = PrefixedStorage::new(b"foo", &mut storage);
foo.set(b"bar", b"gotcha");
assert_eq!(Some(b"gotcha".to_vec()), foo.get(b"bar"));
let rfoo = ReadonlyPrefixedStorage::new(b"foo", &storage);
assert_eq!(Some(b"gotcha".to_vec()), rfoo.get(b"bar"));
let fo = ReadonlyPrefixedStorage::new(b"fo", &storage);
assert_eq!(None, fo.get(b"obar"));
}
#[test]
fn multi_level() {
let mut storage = MockStorage::new();
let mut foo = PrefixedStorage::new(b"foo", &mut storage);
let mut bar = PrefixedStorage::new(b"bar", &mut foo);
bar.set(b"baz", b"winner");
let loader = ReadonlyPrefixedStorage::multilevel(&[b"foo", b"bar"], &storage);
assert_eq!(Some(b"winner".to_vec()), loader.get(b"baz"));
let mut foobar = PrefixedStorage::multilevel(&[b"foo", b"bar"], &mut storage);
foobar.set(b"second", b"time");
let a = ReadonlyPrefixedStorage::new(b"foo", &storage);
let b = ReadonlyPrefixedStorage::new(b"bar", &a);
assert_eq!(Some(b"time".to_vec()), b.get(b"second"));
}
}