diff --git a/packages/cw-storey/src/backend.rs b/packages/cw-storey/src/backend.rs index 112eb06..8c2bd54 100644 --- a/packages/cw-storey/src/backend.rs +++ b/packages/cw-storey/src/backend.rs @@ -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(pub S); -impl StorageBackend for CwStorage +impl StorageBackend for CwStorage<&S> where - S: cosmwasm_std::Storage, + S: cosmwasm_std::Storage + ?Sized, { fn get(&self, key: &[u8]) -> Option> { - cosmwasm_std::Storage::get(&self.0, key) + cosmwasm_std::Storage::get(self.0, key) } } -impl StorageBackendMut for CwStorage +impl StorageBackend for CwStorage<&mut S> where - S: cosmwasm_std::Storage, + S: cosmwasm_std::Storage + ?Sized, +{ + fn get(&self, key: &[u8]) -> Option> { + cosmwasm_std::Storage::get(self.0, key) + } +} + +impl 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 IterableStorage for CwStorage<&S> +where + S: cosmwasm_std::Storage + ?Sized, +{ + type KeysIterator<'a> = Box> + 'a> where Self: 'a; + type ValuesIterator<'a> = Box> + 'a> where Self: 'a; + type PairsIterator<'a> = Box, Vec)> + '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 IterableStorage for CwStorage<&mut S> +where + S: cosmwasm_std::Storage + ?Sized, +{ + type KeysIterator<'a> = Box> + 'a> where Self: 'a; + type ValuesIterator<'a> = Box> + 'a> where Self: 'a; + type PairsIterator<'a> = Box, Vec)> + '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 RevIterableStorage for CwStorage<&S> +where + S: cosmwasm_std::Storage + ?Sized, +{ + type RevKeysIterator<'a> = Box> + 'a> where Self: 'a; + type RevValuesIterator<'a> = Box> + 'a> where Self: 'a; + type RevPairsIterator<'a> = Box, Vec)> + '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 RevIterableStorage for CwStorage<&mut S> +where + S: cosmwasm_std::Storage + ?Sized, +{ + type RevKeysIterator<'a> = Box> + 'a> where Self: 'a; + type RevValuesIterator<'a> = Box> + 'a> where Self: 'a; + type RevPairsIterator<'a> = Box, Vec)> + '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) } } diff --git a/packages/cw-storey/tests/smoke_test.rs b/packages/cw-storey/tests/smoke_test.rs index 4aece9a..ee0e69a 100644 --- a/packages/cw-storey/tests/smoke_test.rs +++ b/packages/cw-storey/tests/smoke_test.rs @@ -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::::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::::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::>::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::>::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()); +} diff --git a/packages/storey/src/storage/branch.rs b/packages/storey/src/storage/branch.rs index 1599882..eefbab4 100644 --- a/packages/storey/src/storage/branch.rs +++ b/packages/storey/src/storage/branch.rs @@ -71,7 +71,7 @@ impl StorageMut for StorageBranch<&mut S> { } } -impl IterableStorage for StorageBranch { +impl IterableStorage for StorageBranch<&S> { type KeysIterator<'a> = BranchKeysIter> where Self: 'a; type ValuesIterator<'a> = S::ValuesIterator<'a> where Self: 'a; type PairsIterator<'a> = BranchKVIter> where Self: 'a; @@ -110,7 +110,97 @@ impl IterableStorage for StorageBranch { } } -impl RevIterableStorage for StorageBranch { +impl IterableStorage for StorageBranch<&mut S> { + type KeysIterator<'a> = BranchKeysIter> where Self: 'a; + type ValuesIterator<'a> = S::ValuesIterator<'a> where Self: 'a; + type PairsIterator<'a> = BranchKVIter> 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 RevIterableStorage for StorageBranch<&S> { + type RevKeysIterator<'a> = BranchKeysIter> where Self: 'a; + type RevValuesIterator<'a> = S::RevValuesIterator<'a> where Self: 'a; + type RevPairsIterator<'a> = BranchKVIter> 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 RevIterableStorage for StorageBranch<&mut S> { type RevKeysIterator<'a> = BranchKeysIter> where Self: 'a; type RevValuesIterator<'a> = S::RevValuesIterator<'a> where Self: 'a; type RevPairsIterator<'a> = BranchKVIter> where Self: 'a;