Skip to content

Commit

Permalink
Merge pull request #46 from CosmWasm/cw-fix-approach-2
Browse files Browse the repository at this point in the history
Make cw-storey work with &mut dyn cosmwasm_std::Storage
  • Loading branch information
uint authored Jun 19, 2024
2 parents 01656c2 + cd5f4a9 commit ac3210b
Show file tree
Hide file tree
Showing 3 changed files with 260 additions and 14 deletions.
141 changes: 133 additions & 8 deletions packages/cw-storey/src/backend.rs
Original file line number Diff line number Diff line change
@@ -1,26 +1,151 @@
use storey::storage::{StorageBackend, StorageBackendMut};
use storey::storage::{IterableStorage, RevIterableStorage, StorageBackend, StorageBackendMut};

/// A wrapper around a type implementing [`cosmwasm_std::Storage`] that integrates it with [`storey`].
pub struct CwStorage<S>(pub S);

impl<S> StorageBackend for CwStorage<S>
impl<S> StorageBackend for CwStorage<&S>
where
S: cosmwasm_std::Storage,
S: cosmwasm_std::Storage + ?Sized,
{
fn get(&self, key: &[u8]) -> Option<Vec<u8>> {
cosmwasm_std::Storage::get(&self.0, key)
cosmwasm_std::Storage::get(self.0, key)
}
}

impl<S> StorageBackendMut for CwStorage<S>
impl<S> StorageBackend for CwStorage<&mut S>
where
S: cosmwasm_std::Storage,
S: cosmwasm_std::Storage + ?Sized,
{
fn get(&self, key: &[u8]) -> Option<Vec<u8>> {
cosmwasm_std::Storage::get(self.0, key)
}
}

impl<S> StorageBackendMut for CwStorage<&mut S>
where
S: cosmwasm_std::Storage + ?Sized,
{
fn set(&mut self, key: &[u8], value: &[u8]) {
cosmwasm_std::Storage::set(&mut self.0, key, value)
cosmwasm_std::Storage::set(self.0, key, value)
}

fn remove(&mut self, key: &[u8]) {
cosmwasm_std::Storage::remove(&mut self.0, key)
cosmwasm_std::Storage::remove(self.0, key)
}
}

impl<S> IterableStorage for CwStorage<&S>
where
S: cosmwasm_std::Storage + ?Sized,
{
type KeysIterator<'a> = Box<dyn Iterator<Item = Vec<u8>> + 'a> where Self: 'a;
type ValuesIterator<'a> = Box<dyn Iterator<Item = Vec<u8>> + 'a> where Self: 'a;
type PairsIterator<'a> = Box<dyn Iterator<Item = (Vec<u8>, Vec<u8>)> + 'a> where Self: 'a;

fn keys<'a>(&'a self, start: Option<&[u8]>, end: Option<&[u8]>) -> Self::KeysIterator<'a> {
self.0
.range_keys(start, end, cosmwasm_std::Order::Ascending)
}

fn values<'a>(&'a self, start: Option<&[u8]>, end: Option<&[u8]>) -> Self::ValuesIterator<'a> {
self.0
.range_values(start, end, cosmwasm_std::Order::Ascending)
}

fn pairs<'a>(&'a self, start: Option<&[u8]>, end: Option<&[u8]>) -> Self::PairsIterator<'a> {
self.0.range(start, end, cosmwasm_std::Order::Ascending)
}
}

impl<S> IterableStorage for CwStorage<&mut S>
where
S: cosmwasm_std::Storage + ?Sized,
{
type KeysIterator<'a> = Box<dyn Iterator<Item = Vec<u8>> + 'a> where Self: 'a;
type ValuesIterator<'a> = Box<dyn Iterator<Item = Vec<u8>> + 'a> where Self: 'a;
type PairsIterator<'a> = Box<dyn Iterator<Item = (Vec<u8>, Vec<u8>)> + 'a> where Self: 'a;

fn keys<'a>(&'a self, start: Option<&[u8]>, end: Option<&[u8]>) -> Self::KeysIterator<'a> {
self.0
.range_keys(start, end, cosmwasm_std::Order::Ascending)
}

fn values<'a>(&'a self, start: Option<&[u8]>, end: Option<&[u8]>) -> Self::ValuesIterator<'a> {
self.0
.range_values(start, end, cosmwasm_std::Order::Ascending)
}

fn pairs<'a>(&'a self, start: Option<&[u8]>, end: Option<&[u8]>) -> Self::PairsIterator<'a> {
self.0.range(start, end, cosmwasm_std::Order::Ascending)
}
}

impl<S> RevIterableStorage for CwStorage<&S>
where
S: cosmwasm_std::Storage + ?Sized,
{
type RevKeysIterator<'a> = Box<dyn Iterator<Item = Vec<u8>> + 'a> where Self: 'a;
type RevValuesIterator<'a> = Box<dyn Iterator<Item = Vec<u8>> + 'a> where Self: 'a;
type RevPairsIterator<'a> = Box<dyn Iterator<Item = (Vec<u8>, Vec<u8>)> + 'a> where Self: 'a;

fn rev_keys<'a>(
&'a self,
start: Option<&[u8]>,
end: Option<&[u8]>,
) -> Self::RevKeysIterator<'a> {
self.0
.range_keys(start, end, cosmwasm_std::Order::Descending)
}

fn rev_values<'a>(
&'a self,
start: Option<&[u8]>,
end: Option<&[u8]>,
) -> Self::RevValuesIterator<'a> {
self.0
.range_values(start, end, cosmwasm_std::Order::Descending)
}

fn rev_pairs<'a>(
&'a self,
start: Option<&[u8]>,
end: Option<&[u8]>,
) -> Self::RevPairsIterator<'a> {
self.0.range(start, end, cosmwasm_std::Order::Descending)
}
}

impl<S> RevIterableStorage for CwStorage<&mut S>
where
S: cosmwasm_std::Storage + ?Sized,
{
type RevKeysIterator<'a> = Box<dyn Iterator<Item = Vec<u8>> + 'a> where Self: 'a;
type RevValuesIterator<'a> = Box<dyn Iterator<Item = Vec<u8>> + 'a> where Self: 'a;
type RevPairsIterator<'a> = Box<dyn Iterator<Item = (Vec<u8>, Vec<u8>)> + 'a> where Self: 'a;

fn rev_keys<'a>(
&'a self,
start: Option<&[u8]>,
end: Option<&[u8]>,
) -> Self::RevKeysIterator<'a> {
self.0
.range_keys(start, end, cosmwasm_std::Order::Descending)
}

fn rev_values<'a>(
&'a self,
start: Option<&[u8]>,
end: Option<&[u8]>,
) -> Self::RevValuesIterator<'a> {
self.0
.range_values(start, end, cosmwasm_std::Order::Descending)
}

fn rev_pairs<'a>(
&'a self,
start: Option<&[u8]>,
end: Option<&[u8]>,
) -> Self::RevPairsIterator<'a> {
self.0.range(start, end, cosmwasm_std::Order::Descending)
}
}
39 changes: 35 additions & 4 deletions packages/cw-storey/tests/smoke_test.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,49 @@
use cw_storey::{containers::Item, CwStorage};

use cosmwasm_std::Storage as _;
use storey::containers::{IterableAccessor as _, Map};

#[test]
fn smoke_test() {
let mut storage = CwStorage(cosmwasm_std::testing::MockStorage::new());
let mut raw_storage = cosmwasm_std::testing::MockStorage::new();
let dyn_storage: &mut dyn cosmwasm_std::Storage = &mut raw_storage;
let mut storage = CwStorage(dyn_storage);

let item1 = Item::<u64>::new(0);

item1.access(&mut storage).set(&42).unwrap();
assert_eq!(item1.access(&storage).get().unwrap(), Some(42));
assert_eq!(item1.access(&mut storage).get().unwrap(), Some(42));

let item2 = Item::<u64>::new(1);
assert_eq!(item2.access(&storage).get().unwrap(), None);
assert_eq!(item2.access(&mut storage).get().unwrap(), None);

assert_eq!(storage.0.get(&[0]), Some(vec![42]));
}

#[test]
fn map() {
let mut raw_storage = cosmwasm_std::testing::MockStorage::new();
let dyn_storage: &mut dyn cosmwasm_std::Storage = &mut raw_storage;
let mut storage = CwStorage(dyn_storage);

let map = Map::<String, Item<u32>>::new(0);

map.access(&mut storage).entry_mut("foo").set(&42).unwrap();
}

#[test]
fn iteration() {
let mut raw_storage = cosmwasm_std::testing::MockStorage::new();
let dyn_storage: &mut dyn cosmwasm_std::Storage = &mut raw_storage;
let mut storage = CwStorage(dyn_storage);

let map = Map::<String, Item<u32>>::new(0);

map.access(&mut storage).entry_mut("foo").set(&42).unwrap();
map.access(&mut storage).entry_mut("bar").set(&43).unwrap();

let access = map.access(&mut storage);
let mut iter = access.keys();
assert_eq!(iter.next().unwrap().unwrap().0, "bar");
assert_eq!(iter.next().unwrap().unwrap().0, "foo");
assert!(iter.next().is_none());
}
94 changes: 92 additions & 2 deletions packages/storey/src/storage/branch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ impl<S: StorageMut> StorageMut for StorageBranch<&mut S> {
}
}

impl<S: IterableStorage> IterableStorage for StorageBranch<S> {
impl<S: IterableStorage> IterableStorage for StorageBranch<&S> {
type KeysIterator<'a> = BranchKeysIter<S::KeysIterator<'a>> where Self: 'a;
type ValuesIterator<'a> = S::ValuesIterator<'a> where Self: 'a;
type PairsIterator<'a> = BranchKVIter<S::PairsIterator<'a>> where Self: 'a;
Expand Down Expand Up @@ -110,7 +110,97 @@ impl<S: IterableStorage> IterableStorage for StorageBranch<S> {
}
}

impl<S: RevIterableStorage> RevIterableStorage for StorageBranch<S> {
impl<S: IterableStorage> IterableStorage for StorageBranch<&mut S> {
type KeysIterator<'a> = BranchKeysIter<S::KeysIterator<'a>> where Self: 'a;
type ValuesIterator<'a> = S::ValuesIterator<'a> where Self: 'a;
type PairsIterator<'a> = BranchKVIter<S::PairsIterator<'a>> where Self: 'a;

fn keys<'a>(&'a self, start: Option<&[u8]>, end: Option<&[u8]>) -> Self::KeysIterator<'a> {
let (start, end) = sub_bounds(&self.prefix, start, end);

BranchKeysIter {
inner: self.backend.keys(
start.as_ref().map(AsRef::as_ref),
end.as_ref().map(AsRef::as_ref),
),
prefix_len: self.prefix.len(),
}
}

fn values<'a>(&'a self, start: Option<&[u8]>, end: Option<&[u8]>) -> Self::ValuesIterator<'a> {
let (start, end) = sub_bounds(&self.prefix, start, end);

self.backend.values(
start.as_ref().map(AsRef::as_ref),
end.as_ref().map(AsRef::as_ref),
)
}

fn pairs<'a>(&'a self, start: Option<&[u8]>, end: Option<&[u8]>) -> Self::PairsIterator<'a> {
let (start, end) = sub_bounds(&self.prefix, start, end);

BranchKVIter {
inner: self.backend.pairs(
start.as_ref().map(AsRef::as_ref),
end.as_ref().map(AsRef::as_ref),
),
prefix_len: self.prefix.len(),
}
}
}

impl<S: RevIterableStorage> RevIterableStorage for StorageBranch<&S> {
type RevKeysIterator<'a> = BranchKeysIter<S::RevKeysIterator<'a>> where Self: 'a;
type RevValuesIterator<'a> = S::RevValuesIterator<'a> where Self: 'a;
type RevPairsIterator<'a> = BranchKVIter<S::RevPairsIterator<'a>> where Self: 'a;

fn rev_keys<'a>(
&'a self,
start: Option<&[u8]>,
end: Option<&[u8]>,
) -> Self::RevKeysIterator<'a> {
let (start, end) = sub_bounds(&self.prefix, start, end);

BranchKeysIter {
inner: self.backend.rev_keys(
start.as_ref().map(AsRef::as_ref),
end.as_ref().map(AsRef::as_ref),
),
prefix_len: self.prefix.len(),
}
}

fn rev_values<'a>(
&'a self,
start: Option<&[u8]>,
end: Option<&[u8]>,
) -> Self::RevValuesIterator<'a> {
let (start, end) = sub_bounds(&self.prefix, start, end);

self.backend.rev_values(
start.as_ref().map(AsRef::as_ref),
end.as_ref().map(AsRef::as_ref),
)
}

fn rev_pairs<'a>(
&'a self,
start: Option<&[u8]>,
end: Option<&[u8]>,
) -> Self::RevPairsIterator<'a> {
let (start, end) = sub_bounds(&self.prefix, start, end);

BranchKVIter {
inner: self.backend.rev_pairs(
start.as_ref().map(AsRef::as_ref),
end.as_ref().map(AsRef::as_ref),
),
prefix_len: self.prefix.len(),
}
}
}

impl<S: RevIterableStorage> RevIterableStorage for StorageBranch<&mut S> {
type RevKeysIterator<'a> = BranchKeysIter<S::RevKeysIterator<'a>> where Self: 'a;
type RevValuesIterator<'a> = S::RevValuesIterator<'a> where Self: 'a;
type RevPairsIterator<'a> = BranchKVIter<S::RevPairsIterator<'a>> where Self: 'a;
Expand Down

0 comments on commit ac3210b

Please sign in to comment.