From 2c1b9111f8b0f8f165ee027dd3150e40fa8e9167 Mon Sep 17 00:00:00 2001 From: Tomasz Kurcz Date: Fri, 5 Apr 2024 14:28:58 +0200 Subject: [PATCH 1/3] feat(stork): generic iteration (for any collection) --- crates/storey/src/containers/column.rs | 18 ++++++++++++++++-- crates/storey/src/containers/map.rs | 19 ++++++++----------- crates/storey/src/containers/mod.rs | 18 ++++++++++++++++++ crates/storey/tests/containers.rs | 2 +- 4 files changed, 43 insertions(+), 14 deletions(-) diff --git a/crates/storey/src/containers/column.rs b/crates/storey/src/containers/column.rs index 3195eaa..e99d95b 100644 --- a/crates/storey/src/containers/column.rs +++ b/crates/storey/src/containers/column.rs @@ -4,10 +4,10 @@ use thiserror::Error; use crate::encoding::Encoding; use crate::encoding::{DecodableWith, EncodableWith}; -use crate::storage::StorageBranch; +use crate::storage::{IterableStorage, StorageBranch}; use crate::storage::{Storage, StorageMut}; -use super::{KeyDecodeError, Storable}; +use super::{IterableAccessor, KeyDecodeError, Storable}; const META_NEXT_IX: &[u8] = &[0]; const META_LEN: &[u8] = &[1]; @@ -67,6 +67,20 @@ pub struct ColumnAccess { phantom: PhantomData<(E, T)>, } +impl IterableAccessor for ColumnAccess +where + E: Encoding, + T: EncodableWith + DecodableWith, + S: IterableStorage, +{ + type StorableT = Column; + type StorageT = S; + + fn storage(&self) -> &Self::StorageT { + &self.storage + } +} + impl ColumnAccess where E: Encoding, diff --git a/crates/storey/src/containers/map.rs b/crates/storey/src/containers/map.rs index 24de4ac..7a0e7d5 100644 --- a/crates/storey/src/containers/map.rs +++ b/crates/storey/src/containers/map.rs @@ -3,7 +3,8 @@ use std::{borrow::Borrow, marker::PhantomData}; use crate::storage::IterableStorage; use crate::storage::StorageBranch; -use super::{KeyDecodeError, Storable, StorableIter}; +use super::IterableAccessor; +use super::{KeyDecodeError, Storable}; pub struct Map { prefix: &'static [u8], @@ -103,21 +104,17 @@ where } } -impl MapAccess +impl IterableAccessor for MapAccess where K: OwnedKey, V: Storable, S: IterableStorage, { - pub fn iter<'s>( - &'s self, - start: Option<&[u8]>, - end: Option<&[u8]>, - ) -> StorableIter<'s, Map, S> { - StorableIter { - inner: self.storage.pairs(start, end), - phantom: PhantomData, - } + type StorableT = Map; + type StorageT = S; + + fn storage(&self) -> &Self::StorageT { + &self.storage } } diff --git a/crates/storey/src/containers/mod.rs b/crates/storey/src/containers/mod.rs index f242e33..562a3ea 100644 --- a/crates/storey/src/containers/mod.rs +++ b/crates/storey/src/containers/mod.rs @@ -57,3 +57,21 @@ pub enum KVDecodeError { Key, Value(V), } + +pub trait IterableAccessor { + type StorableT: Storable; + type StorageT: IterableStorage; + + fn storage(&self) -> &Self::StorageT; + + fn iter<'s>( + &'s self, + start: Option<&[u8]>, + end: Option<&[u8]>, + ) -> StorableIter<'s, Self::StorableT, Self::StorageT> { + StorableIter { + inner: self.storage().pairs(start, end), + phantom: PhantomData, + } + } +} diff --git a/crates/storey/tests/containers.rs b/crates/storey/tests/containers.rs index aa2e90e..dd23b63 100644 --- a/crates/storey/tests/containers.rs +++ b/crates/storey/tests/containers.rs @@ -1,6 +1,6 @@ mod common; -use storey::containers::{Column, Item, Map}; +use storey::containers::{Column, Item, IterableAccessor as _, Map}; use storey::storage::Storage as _; use common::backend::TestStorage; From e80671b0df632d0c60b6f2149c8a9f894eb7f6d4 Mon Sep 17 00:00:00 2001 From: Tomasz Kurcz Date: Sun, 7 Apr 2024 12:55:20 +0200 Subject: [PATCH 2/3] feat(stork): keys and value iteration --- crates/storey/src/containers/mod.rs | 67 ++++++++++++++++++++++++++++- crates/storey/tests/containers.rs | 42 ++++++++++++++++-- 2 files changed, 104 insertions(+), 5 deletions(-) diff --git a/crates/storey/src/containers/mod.rs b/crates/storey/src/containers/mod.rs index 562a3ea..2b7e9a8 100644 --- a/crates/storey/src/containers/mod.rs +++ b/crates/storey/src/containers/mod.rs @@ -23,6 +23,7 @@ pub trait Storable { fn decode_value(value: &[u8]) -> Result; } +#[derive(Debug, PartialEq)] pub struct KeyDecodeError; pub struct StorableIter<'i, S, B> @@ -52,6 +53,48 @@ where } } +pub struct StorableKeys<'i, S, B> +where + S: Storable, + B: IterableStorage + 'i, +{ + inner: B::KeysIterator<'i>, + phantom: PhantomData, +} + +impl<'i, S, B> Iterator for StorableKeys<'i, S, B> +where + S: Storable, + B: IterableStorage + 'i, +{ + type Item = Result; + + fn next(&mut self) -> Option { + self.inner.next().map(|k| S::decode_key(&k)) + } +} + +pub struct StorableValues<'i, S, B> +where + S: Storable, + B: IterableStorage + 'i, +{ + inner: B::ValuesIterator<'i>, + phantom: PhantomData, +} + +impl<'i, S, B> Iterator for StorableValues<'i, S, B> +where + S: Storable, + B: IterableStorage + 'i, +{ + type Item = Result; + + fn next(&mut self) -> Option { + self.inner.next().map(|v| S::decode_value(&v)) + } +} + #[derive(Debug, PartialEq)] pub enum KVDecodeError { Key, @@ -64,7 +107,7 @@ pub trait IterableAccessor { fn storage(&self) -> &Self::StorageT; - fn iter<'s>( + fn pairs<'s>( &'s self, start: Option<&[u8]>, end: Option<&[u8]>, @@ -74,4 +117,26 @@ pub trait IterableAccessor { phantom: PhantomData, } } + + fn keys<'s>( + &'s self, + start: Option<&[u8]>, + end: Option<&[u8]>, + ) -> StorableKeys<'s, Self::StorableT, Self::StorageT> { + StorableKeys { + inner: self.storage().keys(start, end), + phantom: PhantomData, + } + } + + fn values<'s>( + &'s self, + start: Option<&[u8]>, + end: Option<&[u8]>, + ) -> StorableValues<'s, Self::StorableT, Self::StorageT> { + StorableValues { + inner: self.storage().values(start, end), + phantom: PhantomData, + } + } } diff --git a/crates/storey/tests/containers.rs b/crates/storey/tests/containers.rs index dd23b63..8055b53 100644 --- a/crates/storey/tests/containers.rs +++ b/crates/storey/tests/containers.rs @@ -86,7 +86,7 @@ fn simple_iteration() { access.entry_mut("bar").set(&42).unwrap(); let items = access - .iter(None, None) + .pairs(None, None) .collect::, _>>() .unwrap(); assert_eq!( @@ -98,6 +98,40 @@ fn simple_iteration() { ); } +#[test] +fn keys_iteration() { + let mut storage = TestStorage::new(); + + let map = Map::>::new(&[0]); + let mut access = map.access(&mut storage); + + access.entry_mut("foo").set(&1337).unwrap(); + access.entry_mut("bar").set(&42).unwrap(); + + let keys = access + .keys(None, None) + .collect::, _>>() + .unwrap(); + assert_eq!(keys, vec![("bar".to_string(), ()), ("foo".to_string(), ())]) +} + +#[test] +fn values_iteration() { + let mut storage = TestStorage::new(); + + let map = Map::>::new(&[0]); + let mut access = map.access(&mut storage); + + access.entry_mut("foo").set(&1337).unwrap(); + access.entry_mut("bar").set(&42).unwrap(); + + let values = access + .values(None, None) + .collect::, _>>() + .unwrap(); + assert_eq!(values, vec![42, 1337]) +} + #[test] fn composable_iteration() { let mut storage = TestStorage::new(); @@ -116,7 +150,7 @@ fn composable_iteration() { // iterate over all items let items = access - .iter(None, None) + .pairs(None, None) .collect::, _>>() .unwrap(); assert_eq!( @@ -131,7 +165,7 @@ fn composable_iteration() { // iterate over items under "foo" let items = access .entry("foo") - .iter(None, None) + .pairs(None, None) .collect::, _>>() .unwrap(); assert_eq!( @@ -190,7 +224,7 @@ fn map_of_column() { assert_eq!(access.entry("bar").len().unwrap(), 1); let all = access - .iter(None, None) + .pairs(None, None) .collect::, _>>() .unwrap(); assert_eq!( From e5bed8b2f6387d59a9c510015a11fb97233c9a3e Mon Sep 17 00:00:00 2001 From: Tomasz Kurcz Date: Sun, 7 Apr 2024 16:47:45 +0200 Subject: [PATCH 3/3] style --- crates/storey/src/containers/mod.rs | 92 ++++++++++++++--------------- 1 file changed, 46 insertions(+), 46 deletions(-) diff --git a/crates/storey/src/containers/mod.rs b/crates/storey/src/containers/mod.rs index 2b7e9a8..0e0c6c1 100644 --- a/crates/storey/src/containers/mod.rs +++ b/crates/storey/src/containers/mod.rs @@ -26,6 +26,52 @@ pub trait Storable { #[derive(Debug, PartialEq)] pub struct KeyDecodeError; +#[derive(Debug, PartialEq)] +pub enum KVDecodeError { + Key, + Value(V), +} + +pub trait IterableAccessor { + type StorableT: Storable; + type StorageT: IterableStorage; + + fn storage(&self) -> &Self::StorageT; + + fn pairs<'s>( + &'s self, + start: Option<&[u8]>, + end: Option<&[u8]>, + ) -> StorableIter<'s, Self::StorableT, Self::StorageT> { + StorableIter { + inner: self.storage().pairs(start, end), + phantom: PhantomData, + } + } + + fn keys<'s>( + &'s self, + start: Option<&[u8]>, + end: Option<&[u8]>, + ) -> StorableKeys<'s, Self::StorableT, Self::StorageT> { + StorableKeys { + inner: self.storage().keys(start, end), + phantom: PhantomData, + } + } + + fn values<'s>( + &'s self, + start: Option<&[u8]>, + end: Option<&[u8]>, + ) -> StorableValues<'s, Self::StorableT, Self::StorageT> { + StorableValues { + inner: self.storage().values(start, end), + phantom: PhantomData, + } + } +} + pub struct StorableIter<'i, S, B> where S: Storable, @@ -94,49 +140,3 @@ where self.inner.next().map(|v| S::decode_value(&v)) } } - -#[derive(Debug, PartialEq)] -pub enum KVDecodeError { - Key, - Value(V), -} - -pub trait IterableAccessor { - type StorableT: Storable; - type StorageT: IterableStorage; - - fn storage(&self) -> &Self::StorageT; - - fn pairs<'s>( - &'s self, - start: Option<&[u8]>, - end: Option<&[u8]>, - ) -> StorableIter<'s, Self::StorableT, Self::StorageT> { - StorableIter { - inner: self.storage().pairs(start, end), - phantom: PhantomData, - } - } - - fn keys<'s>( - &'s self, - start: Option<&[u8]>, - end: Option<&[u8]>, - ) -> StorableKeys<'s, Self::StorableT, Self::StorageT> { - StorableKeys { - inner: self.storage().keys(start, end), - phantom: PhantomData, - } - } - - fn values<'s>( - &'s self, - start: Option<&[u8]>, - end: Option<&[u8]>, - ) -> StorableValues<'s, Self::StorableT, Self::StorageT> { - StorableValues { - inner: self.storage().values(start, end), - phantom: PhantomData, - } - } -}