diff --git a/packages/storage-plus/src/de.rs b/packages/storage-plus/src/de.rs index d65382b86..4aca0b78b 100644 --- a/packages/storage-plus/src/de.rs +++ b/packages/storage-plus/src/de.rs @@ -98,7 +98,7 @@ impl KeyDeserialize for &Addr { macro_rules! integer_de { (for $($t:ty),+) => { - $(impl KeyDeserialize for IntKey<$t> { + $(impl KeyDeserialize for $t { type Output = $t; #[inline(always)] @@ -112,6 +112,22 @@ macro_rules! integer_de { integer_de!(for i8, u8, i16, u16, i32, u32, i64, u64, i128, u128); +macro_rules! intkey_de { + (for $($t:ty),+) => { + $(impl KeyDeserialize for IntKey<$t> { + type Output = $t; + + #[inline(always)] + fn from_vec(value: Vec) -> StdResult { + Ok(<$t>::from_be_bytes(value.as_slice().try_into() + .map_err(|err: TryFromSliceError| StdError::generic_err(err.to_string()))?)) + } + })* + } +} + +intkey_de!(for i8, u8, i16, u16, i32, u32, i64, u64, i128, u128); + impl KeyDeserialize for TimestampKey { type Output = u64; diff --git a/packages/storage-plus/src/helpers.rs b/packages/storage-plus/src/helpers.rs index 6cc25755f..6f566ea2e 100644 --- a/packages/storage-plus/src/helpers.rs +++ b/packages/storage-plus/src/helpers.rs @@ -7,6 +7,8 @@ use serde::de::DeserializeOwned; use std::any::type_name; +use crate::keys::Key; + use cosmwasm_std::{ from_slice, to_vec, Addr, Binary, ContractResult, Empty, QuerierWrapper, QueryRequest, StdError, StdResult, SystemResult, WasmQuery, @@ -20,7 +22,7 @@ pub(crate) fn may_deserialize( value: &Option>, ) -> StdResult> { match value { - Some(vec) => Ok(Some(from_slice(&vec)?)), + Some(vec) => Ok(Some(from_slice(vec)?)), None => Ok(None), } } @@ -28,7 +30,7 @@ pub(crate) fn may_deserialize( /// must_deserialize parses json bytes from storage (Option), returning NotFound error if no data present pub(crate) fn must_deserialize(value: &Option>) -> StdResult { match value { - Some(vec) => from_slice(&vec), + Some(vec) => from_slice(vec), None => Err(StdError::not_found(type_name::())), } } @@ -54,15 +56,15 @@ pub(crate) fn namespaces_with_key(namespaces: &[&[u8]], key: &[u8]) -> Vec { /// there are multiple sets we do not want to combine just to call this pub(crate) fn nested_namespaces_with_key( top_names: &[&[u8]], - sub_names: &[&[u8]], + sub_names: &[Key], key: &[u8], ) -> Vec { let mut size = key.len(); for &namespace in top_names { size += namespace.len() + 2; } - for &namespace in sub_names { - size += namespace.len() + 2; + for namespace in sub_names { + size += namespace.as_ref().len() + 2; } let mut out = Vec::with_capacity(size); @@ -70,9 +72,9 @@ pub(crate) fn nested_namespaces_with_key( out.extend_from_slice(&encode_length(namespace)); out.extend_from_slice(namespace); } - for &namespace in sub_names { - out.extend_from_slice(&encode_length(namespace)); - out.extend_from_slice(namespace); + for namespace in sub_names { + out.extend_from_slice(&encode_length(namespace.as_ref())); + out.extend_from_slice(namespace.as_ref()); } out.extend_from_slice(key); out diff --git a/packages/storage-plus/src/keys.rs b/packages/storage-plus/src/keys.rs index ca90ecf9f..dbedd90a5 100644 --- a/packages/storage-plus/src/keys.rs +++ b/packages/storage-plus/src/keys.rs @@ -5,6 +5,33 @@ use crate::de::KeyDeserialize; use crate::helpers::namespaces_with_key; use crate::Endian; +#[derive(Debug)] +pub enum Key<'a> { + Ref(&'a [u8]), + Val8([u8; 1]), + Val16([u8; 2]), + Val32([u8; 4]), + Val64([u8; 8]), +} + +impl<'a> AsRef<[u8]> for Key<'a> { + fn as_ref(&self) -> &[u8] { + match self { + Key::Ref(r) => r, + Key::Val8(v) => v, + Key::Val16(v) => v, + Key::Val32(v) => v, + Key::Val64(v) => v, + } + } +} + +impl<'a> PartialEq<&[u8]> for Key<'a> { + fn eq(&self, other: &&[u8]) -> bool { + self.as_ref() == *other + } +} + /// `PrimaryKey` needs to be implemented for types that want to be a `Map` (or `Map`-like) key, /// or part of a key. /// @@ -36,12 +63,15 @@ pub trait PrimaryKey<'a>: Clone { type SuperSuffix: KeyDeserialize; /// returns a slice of key steps, which can be optionally combined - fn key(&self) -> Vec<&[u8]>; + fn key(&self) -> Vec; fn joined_key(&self) -> Vec { let keys = self.key(); let l = keys.len(); - namespaces_with_key(&keys[0..l - 1], &keys[l - 1]) + namespaces_with_key( + &keys[0..l - 1].iter().map(Key::as_ref).collect::>(), + keys[l - 1].as_ref(), + ) } } @@ -52,7 +82,7 @@ impl<'a> PrimaryKey<'a> for () { type Suffix = Self; type SuperSuffix = Self; - fn key(&self) -> Vec<&[u8]> { + fn key(&self) -> Vec { vec![] } } @@ -63,9 +93,9 @@ impl<'a> PrimaryKey<'a> for &'a [u8] { type Suffix = Self; type SuperSuffix = Self; - fn key(&self) -> Vec<&[u8]> { + fn key(&self) -> Vec { // this is simple, we don't add more prefixes - vec![self] + vec![Key::Ref(self)] } } @@ -76,9 +106,9 @@ impl<'a> PrimaryKey<'a> for &'a str { type Suffix = Self; type SuperSuffix = Self; - fn key(&self) -> Vec<&[u8]> { + fn key(&self) -> Vec { // this is simple, we don't add more prefixes - vec![self.as_bytes()] + vec![Key::Ref(self.as_bytes())] } } @@ -91,9 +121,9 @@ impl<'a, T: PrimaryKey<'a> + Prefixer<'a> + KeyDeserialize, U: PrimaryKey<'a> + type Suffix = U; type SuperSuffix = Self; - fn key(&self) -> Vec<&[u8]> { + fn key(&self) -> Vec { let mut keys = self.0.key(); - keys.extend(&self.1.key()); + keys.extend(self.1.key()); keys } } @@ -111,38 +141,38 @@ impl< type Suffix = V; type SuperSuffix = (U, V); - fn key(&self) -> Vec<&[u8]> { + fn key(&self) -> Vec { let mut keys = self.0.key(); - keys.extend(&self.1.key()); - keys.extend(&self.2.key()); + keys.extend(self.1.key()); + keys.extend(self.2.key()); keys } } pub trait Prefixer<'a> { /// returns 0 or more namespaces that should be length-prefixed and concatenated for range searches - fn prefix(&self) -> Vec<&[u8]>; + fn prefix(&self) -> Vec; fn joined_prefix(&self) -> Vec { let prefixes = self.prefix(); - namespaces_with_key(&prefixes, &[]) + namespaces_with_key(&prefixes.iter().map(Key::as_ref).collect::>(), &[]) } } impl<'a> Prefixer<'a> for () { - fn prefix(&self) -> Vec<&[u8]> { + fn prefix(&self) -> Vec { vec![] } } impl<'a> Prefixer<'a> for &'a [u8] { - fn prefix(&self) -> Vec<&[u8]> { - vec![self] + fn prefix(&self) -> Vec { + vec![Key::Ref(self)] } } impl<'a, T: Prefixer<'a>, U: Prefixer<'a>> Prefixer<'a> for (T, U) { - fn prefix(&self) -> Vec<&[u8]> { + fn prefix(&self) -> Vec { let mut res = self.0.prefix(); res.extend(self.1.prefix().into_iter()); res @@ -150,7 +180,7 @@ impl<'a, T: Prefixer<'a>, U: Prefixer<'a>> Prefixer<'a> for (T, U) { } impl<'a, T: Prefixer<'a>, U: Prefixer<'a>, V: Prefixer<'a>> Prefixer<'a> for (T, U, V) { - fn prefix(&self) -> Vec<&[u8]> { + fn prefix(&self) -> Vec { let mut res = self.0.prefix(); res.extend(self.1.prefix().into_iter()); res.extend(self.2.prefix().into_iter()); @@ -160,8 +190,8 @@ impl<'a, T: Prefixer<'a>, U: Prefixer<'a>, V: Prefixer<'a>> Prefixer<'a> for (T, // Provide a string version of this to raw encode strings impl<'a> Prefixer<'a> for &'a str { - fn prefix(&self) -> Vec<&[u8]> { - vec![self.as_bytes()] + fn prefix(&self) -> Vec { + vec![Key::Ref(self.as_bytes())] } } @@ -171,14 +201,14 @@ impl<'a> PrimaryKey<'a> for Vec { type Suffix = Self; type SuperSuffix = Self; - fn key(&self) -> Vec<&[u8]> { - vec![&self] + fn key(&self) -> Vec { + vec![Key::Ref(self)] } } impl<'a> Prefixer<'a> for Vec { - fn prefix(&self) -> Vec<&[u8]> { - vec![&self] + fn prefix(&self) -> Vec { + vec![Key::Ref(self.as_ref())] } } @@ -188,14 +218,14 @@ impl<'a> PrimaryKey<'a> for String { type Suffix = Self; type SuperSuffix = Self; - fn key(&self) -> Vec<&[u8]> { - vec![self.as_bytes()] + fn key(&self) -> Vec { + vec![Key::Ref(self.as_bytes())] } } impl<'a> Prefixer<'a> for String { - fn prefix(&self) -> Vec<&[u8]> { - vec![self.as_bytes()] + fn prefix(&self) -> Vec { + vec![Key::Ref(self.as_bytes())] } } @@ -206,15 +236,15 @@ impl<'a> PrimaryKey<'a> for &'a Addr { type Suffix = Self; type SuperSuffix = Self; - fn key(&self) -> Vec<&[u8]> { + fn key(&self) -> Vec { // this is simple, we don't add more prefixes - vec![self.as_ref().as_bytes()] + vec![Key::Ref(self.as_ref().as_bytes())] } } impl<'a> Prefixer<'a> for &'a Addr { - fn prefix(&self) -> Vec<&[u8]> { - vec![&self.as_ref().as_bytes()] + fn prefix(&self) -> Vec { + vec![Key::Ref(self.as_bytes())] } } @@ -225,18 +255,47 @@ impl<'a> PrimaryKey<'a> for Addr { type Suffix = Self; type SuperSuffix = Self; - fn key(&self) -> Vec<&[u8]> { + fn key(&self) -> Vec { // this is simple, we don't add more prefixes - vec![self.as_bytes()] + vec![Key::Ref(self.as_bytes())] } } impl<'a> Prefixer<'a> for Addr { - fn prefix(&self) -> Vec<&[u8]> { - vec![&self.as_bytes()] + fn prefix(&self) -> Vec { + vec![Key::Ref(self.as_bytes())] } } +macro_rules! integer_key { + (for $($t:ty, $v:tt),+) => { + $(impl<'a> PrimaryKey<'a> for $t { + type Prefix = (); + type SubPrefix = (); + type Suffix = Self; + type SuperSuffix = Self; + + fn key(&self) -> Vec { + vec![Key::$v(self.to_be_bytes())] + } + })* + } +} + +integer_key!(for i8, Val8, u8, Val8, i16, Val16, u16, Val16, i32, Val32, u32, Val32, i64, Val64, u64, Val64); + +macro_rules! integer_prefix { + (for $($t:ty, $v:tt),+) => { + $(impl<'a> Prefixer<'a> for $t { + fn prefix(&self) -> Vec { + vec![Key::$v(self.to_be_bytes())] + } + })* + } +} + +integer_prefix!(for i8, Val8, u8, Val8, i16, Val16, u16, Val16, i32, Val32, u32, Val32, i64, Val64, u64, Val64); + // this auto-implements PrimaryKey for all the IntKey types impl<'a, T: Endian + Clone> PrimaryKey<'a> for IntKey where @@ -247,14 +306,14 @@ where type Suffix = Self; type SuperSuffix = Self; - fn key(&self) -> Vec<&[u8]> { + fn key(&self) -> Vec { self.wrapped.key() } } // this auto-implements Prefixer for all the IntKey types impl<'a, T: Endian> Prefixer<'a> for IntKey { - fn prefix(&self) -> Vec<&[u8]> { + fn prefix(&self) -> Vec { self.wrapped.prefix() } } @@ -330,14 +389,14 @@ impl<'a> PrimaryKey<'a> for TimestampKey { type Suffix = Self; type SuperSuffix = Self; - fn key(&self) -> Vec<&[u8]> { + fn key(&self) -> Vec { self.0.key() } } impl<'a> Prefixer<'a> for TimestampKey { - fn prefix(&self) -> Vec<&[u8]> { - self.0.key() + fn prefix(&self) -> Vec { + self.0.prefix() } } @@ -362,7 +421,7 @@ mod test { let k: U64Key = 134u64.into(); let path = k.key(); assert_eq!(1, path.len()); - assert_eq!(134u64.to_be_bytes().to_vec(), path[0].to_vec()); + assert_eq!(134u64.to_be_bytes(), path[0].as_ref()); } #[test] @@ -370,7 +429,59 @@ mod test { let k: U32Key = 4242u32.into(); let path = k.key(); assert_eq!(1, path.len()); - assert_eq!(4242u32.to_be_bytes().to_vec(), path[0].to_vec()); + assert_eq!(4242u32.to_be_bytes(), path[0].as_ref()); + } + + #[test] + fn naked_8key_works() { + let k: u8 = 42u8; + let path = k.key(); + assert_eq!(1, path.len()); + assert_eq!(42u8.to_be_bytes(), path[0].as_ref()); + + let k: i8 = 42i8; + let path = k.key(); + assert_eq!(1, path.len()); + assert_eq!(42i8.to_be_bytes(), path[0].as_ref()); + } + + #[test] + fn naked_16key_works() { + let k: u16 = 4242u16; + let path = k.key(); + assert_eq!(1, path.len()); + assert_eq!(4242u16.to_be_bytes(), path[0].as_ref()); + + let k: i16 = 4242i16; + let path = k.key(); + assert_eq!(1, path.len()); + assert_eq!(4242i16.to_be_bytes(), path[0].as_ref()); + } + + #[test] + fn naked_32key_works() { + let k: u32 = 4242u32; + let path = k.key(); + assert_eq!(1, path.len()); + assert_eq!(4242u32.to_be_bytes(), path[0].as_ref()); + + let k: i32 = 4242i32; + let path = k.key(); + assert_eq!(1, path.len()); + assert_eq!(4242i32.to_be_bytes(), path[0].as_ref()); + } + + #[test] + fn naked_64key_works() { + let k: u64 = 4242u64; + let path = k.key(); + assert_eq!(1, path.len()); + assert_eq!(4242u64.to_be_bytes(), path[0].as_ref()); + + let k: i64 = 4242i64; + let path = k.key(); + assert_eq!(1, path.len()); + assert_eq!(4242i64.to_be_bytes(), path[0].as_ref()); } #[test] @@ -380,7 +491,7 @@ mod test { let k: K = "hello"; let path = k.key(); assert_eq!(1, path.len()); - assert_eq!("hello".as_bytes(), path[0]); + assert_eq!(b"hello", path[0].as_ref()); let joined = k.joined_key(); assert_eq!(joined, b"hello") @@ -393,7 +504,7 @@ mod test { let k: K = "hello".to_string(); let path = k.key(); assert_eq!(1, path.len()); - assert_eq!("hello".as_bytes(), path[0]); + assert_eq!(b"hello", path[0].as_ref()); let joined = k.joined_key(); assert_eq!(joined, b"hello") @@ -406,16 +517,16 @@ mod test { let k: K = ("hello", b"world"); let path = k.key(); assert_eq!(2, path.len()); - assert_eq!("hello".as_bytes(), path[0]); - assert_eq!("world".as_bytes(), path[1]); + assert_eq!(b"hello", path[0].as_ref()); + assert_eq!(b"world", path[1].as_ref()); } #[test] fn composite_byte_key() { - let k: (&[u8], &[u8]) = (b"foo", b"bar"); + let k: (&[u8], &[u8]) = ("foo".as_bytes(), b"bar"); let path = k.key(); assert_eq!(2, path.len()); - assert_eq!(path, vec![b"foo", b"bar"]); + assert_eq!(path, vec!["foo".as_bytes(), b"bar"],); } #[test] @@ -425,10 +536,21 @@ mod test { let k: (U32Key, U64Key) = (123.into(), 87654.into()); let path = k.key(); assert_eq!(2, path.len()); - assert_eq!(4, path[0].len()); - assert_eq!(8, path[1].len()); - assert_eq!(path[0].to_vec(), 123u32.to_be_bytes().to_vec()); - assert_eq!(path[1].to_vec(), 87654u64.to_be_bytes().to_vec()); + assert_eq!(4, path[0].as_ref().len()); + assert_eq!(8, path[1].as_ref().len()); + assert_eq!(path[0].as_ref(), 123u32.to_be_bytes()); + assert_eq!(path[1].as_ref(), 87654u64.to_be_bytes()); + } + + #[test] + fn naked_composite_int_key() { + let k: (u32, U64Key) = (123, 87654.into()); + let path = k.key(); + assert_eq!(2, path.len()); + assert_eq!(4, path[0].as_ref().len()); + assert_eq!(8, path[1].as_ref().len()); + assert_eq!(path[0].as_ref(), 123u32.to_be_bytes()); + assert_eq!(path[1].as_ref(), 87654u64.to_be_bytes()); } #[test] @@ -450,7 +572,8 @@ mod test { #[test] fn proper_prefixes() { let simple: &str = "hello"; - assert_eq!(simple.prefix(), vec![b"hello"]); + assert_eq!(simple.prefix().len(), 1); + assert_eq!(simple.prefix()[0].as_ref(), b"hello"); let pair: (U32Key, &[u8]) = (12345.into(), b"random"); let one: Vec = vec![0, 0, 48, 57]; @@ -474,4 +597,67 @@ mod test { vec![one.as_slice(), two.as_slice(), three.as_slice()] ); } + + #[test] + fn naked_8bit_prefixes() { + let pair: (u8, &[u8]) = (123, b"random"); + let one: Vec = vec![123]; + let two: Vec = b"random".to_vec(); + assert_eq!(pair.prefix(), vec![one.as_slice(), two.as_slice()]); + + let pair: (i8, &[u8]) = (123, b"random"); + let one: Vec = vec![123]; + let two: Vec = b"random".to_vec(); + assert_eq!(pair.prefix(), vec![one.as_slice(), two.as_slice()]); + } + + #[test] + fn naked_16bit_prefixes() { + let pair: (u16, &[u8]) = (12345, b"random"); + let one: Vec = vec![48, 57]; + let two: Vec = b"random".to_vec(); + assert_eq!(pair.prefix(), vec![one.as_slice(), two.as_slice()]); + + let pair: (i16, &[u8]) = (12345, b"random"); + let one: Vec = vec![48, 57]; + let two: Vec = b"random".to_vec(); + assert_eq!(pair.prefix(), vec![one.as_slice(), two.as_slice()]); + } + + #[test] + fn naked_64bit_prefixes() { + let pair: (u64, &[u8]) = (12345, b"random"); + let one: Vec = vec![0, 0, 0, 0, 0, 0, 48, 57]; + let two: Vec = b"random".to_vec(); + assert_eq!(pair.prefix(), vec![one.as_slice(), two.as_slice()]); + + let pair: (i64, &[u8]) = (12345, b"random"); + let one: Vec = vec![0, 0, 0, 0, 0, 0, 48, 57]; + let two: Vec = b"random".to_vec(); + assert_eq!(pair.prefix(), vec![one.as_slice(), two.as_slice()]); + } + + #[test] + fn naked_proper_prefixes() { + let pair: (u32, &[u8]) = (12345, b"random"); + let one: Vec = vec![0, 0, 48, 57]; + let two: Vec = b"random".to_vec(); + assert_eq!(pair.prefix(), vec![one.as_slice(), two.as_slice()]); + + let triple: (&str, u32, &[u8]) = ("begin", 12345, b"end"); + let one: Vec = b"begin".to_vec(); + let two: Vec = vec![0, 0, 48, 57]; + let three: Vec = b"end".to_vec(); + assert_eq!( + triple.prefix(), + vec![one.as_slice(), two.as_slice(), three.as_slice()] + ); + + // same works with owned variants (&str -> String, &[u8] -> Vec) + let owned_triple: (String, u32, Vec) = ("begin".to_string(), 12345, b"end".to_vec()); + assert_eq!( + owned_triple.prefix(), + vec![one.as_slice(), two.as_slice(), three.as_slice()] + ); + } } diff --git a/packages/storage-plus/src/map.rs b/packages/storage-plus/src/map.rs index b2f4c72d2..2ac1fe0b1 100644 --- a/packages/storage-plus/src/map.rs +++ b/packages/storage-plus/src/map.rs @@ -9,7 +9,7 @@ use crate::helpers::query_raw; use crate::iter_helpers::{deserialize_kv, deserialize_v}; #[cfg(feature = "iterator")] use crate::keys::Prefixer; -use crate::keys::PrimaryKey; +use crate::keys::{Key, PrimaryKey}; use crate::path::Path; #[cfg(feature = "iterator")] use crate::prefix::{namespaced_prefix_range, Bound, Prefix, PrefixBound}; @@ -43,7 +43,10 @@ where } pub fn key(&self, k: K) -> Path { - Path::new(self.namespace, &k.key()) + Path::new( + self.namespace, + &k.key().iter().map(Key::as_ref).collect::>(), + ) } #[cfg(feature = "iterator")] diff --git a/packages/storage-plus/src/path.rs b/packages/storage-plus/src/path.rs index cfae9b6de..e6a3cb526 100644 --- a/packages/storage-plus/src/path.rs +++ b/packages/storage-plus/src/path.rs @@ -3,6 +3,7 @@ use serde::Serialize; use std::marker::PhantomData; use crate::helpers::{may_deserialize, must_deserialize, nested_namespaces_with_key}; +use crate::keys::Key; use cosmwasm_std::{to_vec, StdError, StdResult, Storage}; use std::ops::Deref; @@ -35,7 +36,14 @@ where pub fn new(namespace: &[u8], keys: &[&[u8]]) -> Self { let l = keys.len(); // FIXME: make this more efficient - let storage_key = nested_namespaces_with_key(&[namespace], &keys[0..l - 1], keys[l - 1]); + let storage_key = nested_namespaces_with_key( + &[namespace], + &keys[0..l - 1] + .iter() + .map(|k| Key::Ref(k)) + .collect::>(), + keys[l - 1], + ); Path { storage_key, data: PhantomData, diff --git a/packages/storage-plus/src/prefix.rs b/packages/storage-plus/src/prefix.rs index 823bf1841..808d62638 100644 --- a/packages/storage-plus/src/prefix.rs +++ b/packages/storage-plus/src/prefix.rs @@ -9,6 +9,7 @@ use std::ops::Deref; use crate::de::KeyDeserialize; use crate::helpers::{namespaces_with_key, nested_namespaces_with_key}; use crate::iter_helpers::{concat, deserialize_kv, deserialize_v, trim}; +use crate::keys::Key; use crate::{Endian, Prefixer}; /// Bound is used to defines the two ends of a range, more explicit than Option @@ -117,7 +118,7 @@ where K: KeyDeserialize, T: Serialize + DeserializeOwned, { - pub fn new(top_name: &[u8], sub_names: &[&[u8]]) -> Self { + pub fn new(top_name: &[u8], sub_names: &[Key]) -> Self { Prefix::with_deserialization_function( top_name, sub_names, @@ -128,7 +129,7 @@ where pub fn with_deserialization_function( top_name: &[u8], - sub_names: &[&[u8]], + sub_names: &[Key], pk_name: &[u8], de_fn: DeserializeKvFn, ) -> Self {