Skip to content

Commit

Permalink
Merge pull request #827 from CosmWasm/remove-cosmwasm-storage-dependency
Browse files Browse the repository at this point in the history
Remove `cosmwasm-storage` dependency
  • Loading branch information
uint authored Oct 12, 2022
2 parents 04f9ebb + 3bf4cd2 commit 1e534bd
Show file tree
Hide file tree
Showing 10 changed files with 585 additions and 155 deletions.
11 changes: 0 additions & 11 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion packages/multi-test/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ backtrace = ["anyhow/backtrace"]
cw-utils = { path = "../../packages/utils", version = "0.15.1" }
cw-storage-plus = { path = "../../packages/storage-plus", version = "0.15.1"}
cosmwasm-std = { version = "1.1.0", features = ["staking"] }
cosmwasm-storage = "1.1.0"
itertools = "0.10.1"
schemars = "0.8.1"
serde = { version = "1.0.103", default-features = false, features = ["derive"] }
Expand Down
2 changes: 1 addition & 1 deletion packages/multi-test/src/bank.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ use cosmwasm_std::{
coin, to_binary, Addr, AllBalanceResponse, Api, BalanceResponse, BankMsg, BankQuery, Binary,
BlockInfo, Coin, Event, Querier, Storage,
};
use cosmwasm_storage::{prefixed, prefixed_read};
use cw_storage_plus::Map;
use cw_utils::NativeBalance;

use crate::app::CosmosRouter;
use crate::executor::AppResponse;
use crate::module::Module;
use crate::prefixed_storage::{prefixed, prefixed_read};

const BALANCES: Map<&Addr, NativeBalance> = Map::new("balances");

Expand Down
1 change: 1 addition & 0 deletions packages/multi-test/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ pub mod custom_handler;
pub mod error;
mod executor;
mod module;
mod prefixed_storage;
mod staking;
mod test_helpers;
mod transactions;
Expand Down
185 changes: 185 additions & 0 deletions packages/multi-test/src/prefixed_storage.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
mod length_prefixed;
mod namespace_helpers;

use cosmwasm_std::Storage;
#[cfg(feature = "iterator")]
use cosmwasm_std::{Order, Record};

use length_prefixed::{to_length_prefixed, to_length_prefixed_nested};
#[cfg(feature = "iterator")]
use namespace_helpers::range_with_prefix;
use namespace_helpers::{get_with_prefix, remove_with_prefix, set_with_prefix};

/// An alias of PrefixedStorage::new for less verbose usage
pub fn prefixed<'a>(storage: &'a mut dyn Storage, namespace: &[u8]) -> PrefixedStorage<'a> {
PrefixedStorage::new(storage, namespace)
}

/// An alias of ReadonlyPrefixedStorage::new for less verbose usage
pub fn prefixed_read<'a>(
storage: &'a dyn Storage,
namespace: &[u8],
) -> ReadonlyPrefixedStorage<'a> {
ReadonlyPrefixedStorage::new(storage, namespace)
}

pub struct PrefixedStorage<'a> {
storage: &'a mut dyn Storage,
prefix: Vec<u8>,
}

impl<'a> PrefixedStorage<'a> {
pub fn new(storage: &'a mut dyn Storage, namespace: &[u8]) -> Self {
PrefixedStorage {
storage,
prefix: to_length_prefixed(namespace),
}
}

// Nested namespaces as documented in
// https://github.com/webmaster128/key-namespacing#nesting
pub fn multilevel(storage: &'a mut dyn Storage, namespaces: &[&[u8]]) -> Self {
PrefixedStorage {
storage,
prefix: to_length_prefixed_nested(namespaces),
}
}
}

impl<'a> Storage for PrefixedStorage<'a> {
fn get(&self, key: &[u8]) -> Option<Vec<u8>> {
get_with_prefix(self.storage, &self.prefix, key)
}

fn set(&mut self, key: &[u8], value: &[u8]) {
set_with_prefix(self.storage, &self.prefix, key, value);
}

fn remove(&mut self, key: &[u8]) {
remove_with_prefix(self.storage, &self.prefix, key);
}

#[cfg(feature = "iterator")]
/// range allows iteration over a set of keys, either forwards or backwards
/// uses standard rust range notation, and eg db.range(b"foo"..b"bar") also works reverse
fn range<'b>(
&'b self,
start: Option<&[u8]>,
end: Option<&[u8]>,
order: Order,
) -> Box<dyn Iterator<Item = Record> + 'b> {
range_with_prefix(self.storage, &self.prefix, start, end, order)
}
}

pub struct ReadonlyPrefixedStorage<'a> {
storage: &'a dyn Storage,
prefix: Vec<u8>,
}

impl<'a> ReadonlyPrefixedStorage<'a> {
pub fn new(storage: &'a dyn Storage, namespace: &[u8]) -> Self {
ReadonlyPrefixedStorage {
storage,
prefix: to_length_prefixed(namespace),
}
}

// Nested namespaces as documented in
// https://github.com/webmaster128/key-namespacing#nesting
pub fn multilevel(storage: &'a dyn Storage, namespaces: &[&[u8]]) -> Self {
ReadonlyPrefixedStorage {
storage,
prefix: to_length_prefixed_nested(namespaces),
}
}
}

impl<'a> Storage for ReadonlyPrefixedStorage<'a> {
fn get(&self, key: &[u8]) -> Option<Vec<u8>> {
get_with_prefix(self.storage, &self.prefix, key)
}

fn set(&mut self, _key: &[u8], _value: &[u8]) {
unimplemented!();
}

fn remove(&mut self, _key: &[u8]) {
unimplemented!();
}

#[cfg(feature = "iterator")]
/// range allows iteration over a set of keys, either forwards or backwards
fn range<'b>(
&'b self,
start: Option<&[u8]>,
end: Option<&[u8]>,
order: Order,
) -> Box<dyn Iterator<Item = Record> + 'b> {
range_with_prefix(self.storage, &self.prefix, start, end, order)
}
}

#[cfg(test)]
mod tests {
use super::*;
use cosmwasm_std::testing::MockStorage;

#[test]
fn prefixed_storage_set_and_get() {
let mut storage = MockStorage::new();

// set
let mut s1 = PrefixedStorage::new(&mut storage, b"foo");
s1.set(b"bar", b"gotcha");
assert_eq!(storage.get(b"\x00\x03foobar").unwrap(), b"gotcha".to_vec());

// get
let s2 = PrefixedStorage::new(&mut storage, b"foo");
assert_eq!(s2.get(b"bar"), Some(b"gotcha".to_vec()));
assert_eq!(s2.get(b"elsewhere"), None);
}

#[test]
fn prefixed_storage_multilevel_set_and_get() {
let mut storage = MockStorage::new();

// set
let mut bar = PrefixedStorage::multilevel(&mut storage, &[b"foo", b"bar"]);
bar.set(b"baz", b"winner");
assert_eq!(
storage.get(b"\x00\x03foo\x00\x03barbaz").unwrap(),
b"winner".to_vec()
);

// get
let bar = PrefixedStorage::multilevel(&mut storage, &[b"foo", b"bar"]);
assert_eq!(bar.get(b"baz"), Some(b"winner".to_vec()));
assert_eq!(bar.get(b"elsewhere"), None);
}

#[test]
fn readonly_prefixed_storage_get() {
let mut storage = MockStorage::new();
storage.set(b"\x00\x03foobar", b"gotcha");

// try readonly correctly
let s1 = ReadonlyPrefixedStorage::new(&storage, b"foo");
assert_eq!(s1.get(b"bar"), Some(b"gotcha".to_vec()));
assert_eq!(s1.get(b"elsewhere"), None);

// no collisions with other prefixes
let s2 = ReadonlyPrefixedStorage::new(&storage, b"fo");
assert_eq!(s2.get(b"obar"), None);
}

#[test]
fn readonly_prefixed_storage_multilevel_get() {
let mut storage = MockStorage::new();
storage.set(b"\x00\x03foo\x00\x03barbaz", b"winner");

let bar = ReadonlyPrefixedStorage::multilevel(&storage, &[b"foo", b"bar"]);
assert_eq!(bar.get(b"baz"), Some(b"winner".to_vec()));
assert_eq!(bar.get(b"elsewhere"), None);
}
}
Loading

0 comments on commit 1e534bd

Please sign in to comment.