Skip to content

Commit

Permalink
Consolidate Prefix and Prefix2 functionality
Browse files Browse the repository at this point in the history
Implements range() using deserialize_kv
  • Loading branch information
maurolacy committed Sep 22, 2021
1 parent f0fd1be commit a0fc176
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 85 deletions.
1 change: 1 addition & 0 deletions packages/storage-plus/src/iter_helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use crate::de::Deserializable;
use crate::helpers::encode_length;
use crate::prefix::Pair2;

#[allow(dead_code)]
pub(crate) fn deserialize_v<T: DeserializeOwned>(kv: Pair) -> StdResult<Pair<T>> {
let (k, v) = kv;
let t = from_slice::<T>(&v)?;
Expand Down
2 changes: 1 addition & 1 deletion packages/storage-plus/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,6 @@ pub use keys::{Prefixer, PrimaryKey, U128Key, U16Key, U32Key, U64Key, U8Key};
pub use map::Map;
pub use path::Path;
#[cfg(feature = "iterator")]
pub use prefix::{range_with_prefix, Bound, Prefix, Prefix2};
pub use prefix::{range_with_prefix, Bound, Prefix};
#[cfg(feature = "iterator")]
pub use snapshot::{SnapshotItem, SnapshotMap, Strategy};
14 changes: 7 additions & 7 deletions packages/storage-plus/src/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use crate::keys::Prefixer;
use crate::keys::PrimaryKey;
use crate::path::Path;
#[cfg(feature = "iterator")]
use crate::prefix::{Bound, Pair2, Prefix, Prefix2};
use crate::prefix::{Bound, Pair2, Prefix};
use cosmwasm_std::{from_slice, Addr, QuerierWrapper, StdError, StdResult, Storage};

#[derive(Debug, Clone)]
Expand Down Expand Up @@ -116,12 +116,12 @@ where
T: Serialize + DeserializeOwned,
K: PrimaryKey<'a>,
{
pub fn sub_prefix_de(&self, p: K::SubPrefix) -> Prefix2<K::SuperSuffix, T> {
Prefix2::new(self.namespace, &p.prefix())
pub fn sub_prefix_de(&self, p: K::SubPrefix) -> Prefix<T, K::SuperSuffix> {
Prefix::new(self.namespace, &p.prefix())
}

pub fn prefix_de(&self, p: K::Prefix) -> Prefix2<K::Suffix, T> {
Prefix2::new(self.namespace, &p.prefix())
pub fn prefix_de(&self, p: K::Prefix) -> Prefix<T, K::Suffix> {
Prefix::new(self.namespace, &p.prefix())
}
}

Expand Down Expand Up @@ -194,8 +194,8 @@ where
self.no_prefix_de().keys_de(store, min, max, order)
}

fn no_prefix_de(&self) -> Prefix2<K, T> {
Prefix2::new(self.namespace, &[])
fn no_prefix_de(&self) -> Prefix<T, K> {
Prefix::new(self.namespace, &[])
}
}

Expand Down
103 changes: 26 additions & 77 deletions packages/storage-plus/src/prefix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use std::ops::Deref;

use crate::de::Deserializable;
use crate::helpers::nested_namespaces_with_key;
use crate::iter_helpers::{concat, deserialize_kv, deserialize_v, trim};
use crate::iter_helpers::{concat, deserialize_kv, trim};
use crate::Endian;

/// Bound is used to defines the two ends of a range, more explicit than Option<u8>
Expand Down Expand Up @@ -45,25 +45,26 @@ impl Bound {

pub type Pair2<K = Vec<u8>, V = Vec<u8>> = (K, V);

type DeserializeVFn<T> = fn(&dyn Storage, &[u8], Pair) -> StdResult<Pair<T>>;
type DeserializeKvFn<K, T> =
fn(&dyn Storage, &[u8], Pair) -> StdResult<Pair2<<K as Deserializable>::Output, T>>;

#[derive(Clone)]
pub struct Prefix<T>
pub struct Prefix<T, K = Vec<u8>>
where
K: Deserializable,
T: Serialize + DeserializeOwned,
{
/// all namespaces prefixes and concatenated with the key
storage_prefix: Vec<u8>,
// see https://doc.rust-lang.org/std/marker/struct.PhantomData.html#unused-type-parameters for why this is needed
data: PhantomData<T>,
pk_name: Vec<u8>,
de_fn: DeserializeVFn<T>,
de_fn: DeserializeKvFn<K, T>,
}

impl<T> Deref for Prefix<T>
impl<K, T> Deref for Prefix<T, K>
where
K: Deserializable,
T: Serialize + DeserializeOwned,
{
type Target = [u8];
Expand All @@ -73,23 +74,23 @@ where
}
}

impl<T> Prefix<T>
impl<K, T> Prefix<T, K>
where
K: Deserializable,
T: Serialize + DeserializeOwned,
{
pub fn new(top_name: &[u8], sub_names: &[&[u8]]) -> Self {
Prefix::with_deserialization_function(top_name, sub_names, &[], |_, _, kv| {
deserialize_v(kv)
deserialize_kv::<K, T>(kv)
})
}

pub fn with_deserialization_function(
top_name: &[u8],
sub_names: &[&[u8]],
pk_name: &[u8],
de_fn: DeserializeVFn<T>,
de_fn: DeserializeKvFn<K, T>,
) -> Self {
// FIXME: we can use a custom function here, probably make this cleaner
let storage_prefix = nested_namespaces_with_key(&[top_name], sub_names, b"");
Prefix {
storage_prefix,
Expand All @@ -105,9 +106,10 @@ where
min: Option<Bound>,
max: Option<Bound>,
order: Order,
) -> Box<dyn Iterator<Item = StdResult<Pair<T>>> + 'a>
) -> Box<dyn Iterator<Item = StdResult<Pair2<K::Output, T>>> + 'a>
where
T: 'a,
K::Output: 'a,
{
let de_fn = self.de_fn;
let pk_name = self.pk_name.clone();
Expand All @@ -116,71 +118,6 @@ where
Box::new(mapped)
}

pub fn keys<'a>(
&self,
store: &'a dyn Storage,
min: Option<Bound>,
max: Option<Bound>,
order: Order,
) -> Box<dyn Iterator<Item = Vec<u8>> + 'a> {
let mapped =
range_with_prefix(store, &self.storage_prefix, min, max, order).map(|(k, _)| k);
Box::new(mapped)
}
}

#[derive(Clone)]
pub struct Prefix2<K, T>
where
K: Deserializable,
T: Serialize + DeserializeOwned,
{
/// all namespaces prefixes and concatenated with the key
storage_prefix: Vec<u8>,
// see https://doc.rust-lang.org/std/marker/struct.PhantomData.html#unused-type-parameters for why this is needed
data: PhantomData<T>,
pk_name: Vec<u8>,
de_fn: DeserializeKvFn<K, T>,
}

impl<K, T> Deref for Prefix2<K, T>
where
K: Deserializable,
T: Serialize + DeserializeOwned,
{
type Target = [u8];

fn deref(&self) -> &[u8] {
&self.storage_prefix
}
}

impl<K, T> Prefix2<K, T>
where
K: Deserializable,
T: Serialize + DeserializeOwned,
{
pub fn new(top_name: &[u8], sub_names: &[&[u8]]) -> Self {
Prefix2::with_deserialization_function(top_name, sub_names, &[], |_, _, kv| {
deserialize_kv::<K, T>(kv)
})
}

pub fn with_deserialization_function(
top_name: &[u8],
sub_names: &[&[u8]],
pk_name: &[u8],
de_fn: DeserializeKvFn<K, T>,
) -> Self {
let storage_prefix = nested_namespaces_with_key(&[top_name], sub_names, b"");
Prefix2 {
storage_prefix,
data: PhantomData,
pk_name: pk_name.to_vec(),
de_fn,
}
}

pub fn range_de<'a>(
&self,
store: &'a dyn Storage,
Expand All @@ -199,6 +136,18 @@ where
Box::new(mapped)
}

pub fn keys<'a>(
&self,
store: &'a dyn Storage,
min: Option<Bound>,
max: Option<Bound>,
order: Order,
) -> Box<dyn Iterator<Item = Vec<u8>> + 'a> {
let mapped =
range_with_prefix(store, &self.storage_prefix, min, max, order).map(|(k, _)| k);
Box::new(mapped)
}

pub fn keys_de<'a>(
&self,
store: &'a dyn Storage,
Expand Down Expand Up @@ -288,11 +237,11 @@ mod test {
fn ensure_proper_range_bounds() {
let mut store = MockStorage::new();
// manually create this - not testing nested prefixes here
let prefix = Prefix {
let prefix: Prefix<u64, Vec<u8>> = Prefix {
storage_prefix: b"foo".to_vec(),
data: PhantomData::<u64>,
pk_name: vec![],
de_fn: |_, _, kv| deserialize_v(kv),
de_fn: |_, _, kv| deserialize_kv::<Vec<u8>, u64>(kv),
};

// set some data, we care about "foo" prefix
Expand Down

0 comments on commit a0fc176

Please sign in to comment.