Skip to content

Commit

Permalink
Add prefix
Browse files Browse the repository at this point in the history
  • Loading branch information
ethanfrey committed Oct 10, 2020
1 parent eef12bd commit d57a0ee
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 2 deletions.
6 changes: 6 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -590,6 +590,12 @@ jobs:
- run:
name: Run unit tests
command: cargo test --locked
- run:
name: Build library for native target (with iterator)
command: cargo build --locked --features iterator
- run:
name: Run unit tests (with iterator)
command: cargo test --locked --features iterator
- save_cache:
paths:
- /usr/local/cargo/registry
Expand Down
2 changes: 2 additions & 0 deletions packages/storage-plus/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ homepage = "https://cosmwasm.com"
documentation = "https://docs.cosmwasm.com"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[features]
iterator = ["cosmwasm-std/iterator"]

[dependencies]
cosmwasm-std = { version = "0.11.0-alpha3" }
Expand Down
3 changes: 3 additions & 0 deletions packages/storage-plus/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@ mod length_prefixed;
mod map;
mod namespace_helpers;
mod path;
mod prefix;
mod type_helpers;

pub use map::Map;
pub use path::Path;
#[cfg(feature = "iterator")]
pub use prefix::Prefix;

#[cfg(test)]
mod test {
Expand Down
13 changes: 13 additions & 0 deletions packages/storage-plus/src/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ use std::marker::PhantomData;

use crate::path::Path;

// TODO: where to add PREFIX_PK???? Only in an Indexed Map?

pub struct Map<'a, K, T> {
namespaces: &'a [&'a [u8]],
// see https://doc.rust-lang.org/std/marker/struct.PhantomData.html#unused-type-parameters for why this is needed
Expand All @@ -30,6 +32,8 @@ where
let (namespaces, key) = k.namespaced(self.namespaces);
Path::new(namespaces, key)
}

// TODO: how to do range queries on the prefix...
}

pub trait PrimaryKey<'a> {
Expand All @@ -54,6 +58,15 @@ impl<'a> PrimaryKey<'a> for (&'a [u8], &'a [u8]) {
}
}

impl<'a> PrimaryKey<'a> for (&'a [u8], &'a [u8], &'a [u8]) {
fn namespaced(&self, namespaces: &'a [&'a [u8]]) -> (Vec<&'a [u8]>, Vec<u8>) {
let mut spaces = namespaces.to_vec();
spaces.extend_from_slice(&[self.0, self.1]);
// move the first parts into the namespace, last as key
(spaces, self.2.to_vec())
}
}

#[cfg(test)]
mod test {
use super::*;
Expand Down
3 changes: 1 addition & 2 deletions packages/storage-plus/src/path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ use crate::length_prefixed::namespaces_with_key;
use crate::type_helpers::{may_deserialize, must_deserialize};
use cosmwasm_std::{to_vec, StdResult, Storage};

// TODO: where to add PREFIX_PK????

// TODO: build the final storage key (build_storage_key()) in the constructor, so cheap when we reuse
pub struct Path<'a, T>
where
T: Serialize + DeserializeOwned,
Expand Down
51 changes: 51 additions & 0 deletions packages/storage-plus/src/prefix.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#![cfg(feature = "iterator")]

use serde::de::DeserializeOwned;
use serde::Serialize;
use std::marker::PhantomData;

use crate::length_prefixed::namespaces_with_key;
use crate::namespace_helpers::range_with_prefix;
use crate::type_helpers::deserialize_kv;
use cosmwasm_std::{Order, StdResult, Storage, KV};

pub struct Prefix<'a, T>
where
T: Serialize + DeserializeOwned,
{
// these are not prefixed
namespaces: Vec<&'a [u8]>,
// see https://doc.rust-lang.org/std/marker/struct.PhantomData.html#unused-type-parameters for why this is needed
data: PhantomData<T>,
}

impl<'a, T> Prefix<'a, T>
where
T: Serialize + DeserializeOwned,
{
pub fn new(namespaces: Vec<&'a [u8]>) -> Self {
Prefix {
namespaces,
data: PhantomData,
}
}

// TODO: parse out composite key prefix???
pub fn range<'c, S: Storage>(
&'c self,
store: &'c S,
start: Option<&[u8]>,
end: Option<&[u8]>,
order: Order,
) -> Box<dyn Iterator<Item = StdResult<KV<T>>> + 'c> {
let namespace = self.build_storage_prefix();
let mapped =
range_with_prefix(store, &namespace, start, end, order).map(deserialize_kv::<T>);
Box::new(mapped)
}

/// This provides the raw storage prefix that we use for ranges
pub(crate) fn build_storage_prefix(&self) -> Vec<u8> {
namespaces_with_key(&self.namespaces, b"")
}
}

0 comments on commit d57a0ee

Please sign in to comment.