Skip to content

Commit

Permalink
Merge pull request #316 from NYBACHOK/range
Browse files Browse the repository at this point in the history
Rev iterator for tree
  • Loading branch information
joneskm authored Oct 10, 2024
2 parents a8ab9b7 + 065e0ac commit f4c0ed6
Show file tree
Hide file tree
Showing 40 changed files with 1,299 additions and 386 deletions.
4 changes: 2 additions & 2 deletions database/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,12 @@ pub trait Database: Clone + Send + Sync + 'static {

fn put(&self, key: Vec<u8>, value: Vec<u8>);

fn iterator<'a>(&'a self) -> Box<dyn Iterator<Item = (Box<[u8]>, Box<[u8]>)> + 'a>;
fn iterator<'a>(&'a self) -> impl Iterator<Item = (Box<[u8]>, Box<[u8]>)> + 'a;

fn prefix_iterator<'a>(
&'a self,
prefix: Vec<u8>,
) -> Box<dyn Iterator<Item = (Box<[u8]>, Box<[u8]>)> + 'a>;
) -> impl Iterator<Item = (Box<[u8]>, Box<[u8]>)> + 'a;
}

pub trait DatabaseBuilder<DB> {
Expand Down
20 changes: 9 additions & 11 deletions database/src/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,21 +37,19 @@ impl Database for MemDB {
.insert(key, value);
}

fn iterator<'a>(&'a self) -> Box<dyn Iterator<Item = (Box<[u8]>, Box<[u8]>)> + 'a> {
Box::new(
self.store
.read()
.expect("poisoned lock")
.clone()
.into_iter()
.map(|(key, value)| (key.into_boxed_slice(), value.into_boxed_slice())),
)
fn iterator<'a>(&'a self) -> impl Iterator<Item = (Box<[u8]>, Box<[u8]>)> + 'a {
self.store
.read()
.expect("poisoned lock")
.clone()
.into_iter()
.map(|(key, value)| (key.into_boxed_slice(), value.into_boxed_slice()))
}

fn prefix_iterator<'a>(
&'a self,
prefix: Vec<u8>,
) -> Box<dyn Iterator<Item = (Box<[u8]>, Box<[u8]>)> + 'a> {
) -> impl Iterator<Item = (Box<[u8]>, Box<[u8]>)> + 'a {
let start = Bound::Included(prefix.clone());
let end = prefix_end_bound(prefix);

Expand All @@ -68,7 +66,7 @@ impl Database for MemDB {
pairs.push(pair)
}

Box::new(pairs.into_iter())
pairs.into_iter()
}
}

Expand Down
23 changes: 11 additions & 12 deletions database/src/prefix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,29 +24,28 @@ impl<T: Database> Database for PrefixDB<T> {
self.db.put(key, value)
}

fn iterator<'a>(&'a self) -> Box<dyn Iterator<Item = (Box<[u8]>, Box<[u8]>)> + 'a> {
fn iterator<'a>(&'a self) -> impl Iterator<Item = (Box<[u8]>, Box<[u8]>)> + 'a {
let prefix_length = self.prefix.len();
Box::new(
self.db
.prefix_iterator(self.prefix.clone())
.map(move |(k, v)| {
let key = k[prefix_length..].to_vec();
(key.into_boxed_slice(), v)
}),
)

self.db
.prefix_iterator(self.prefix.clone())
.map(move |(k, v)| {
let key = k[prefix_length..].to_vec();
(key.into_boxed_slice(), v)
})
}

fn prefix_iterator<'a>(
&'a self,
prefix: Vec<u8>,
) -> Box<dyn Iterator<Item = (Box<[u8]>, Box<[u8]>)> + 'a> {
) -> impl Iterator<Item = (Box<[u8]>, Box<[u8]>)> + 'a {
let prefix = [self.prefix.clone(), prefix].concat();
let prefix_length = prefix.len();

Box::new(self.db.prefix_iterator(prefix).map(move |(k, v)| {
self.db.prefix_iterator(prefix).map(move |(k, v)| {
let key = k[prefix_length..].to_vec();
(key.into_boxed_slice(), v)
}))
})
}
}

Expand Down
22 changes: 9 additions & 13 deletions database/src/rocks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,24 +42,20 @@ impl Database for RocksDB {
.unwrap_or_else(|e| panic!("unrecoverable database error {}", e))
}

fn iterator<'a>(&'a self) -> Box<dyn Iterator<Item = (Box<[u8]>, Box<[u8]>)> + 'a> {
Box::new(
self.db
.iterator(rocksdb::IteratorMode::Start)
.map(|res| res.unwrap_or_else(|e| panic!("unrecoverable database error {}", e))),
)
fn iterator<'a>(&'a self) -> impl Iterator<Item = (Box<[u8]>, Box<[u8]>)> + 'a {
self.db
.iterator(rocksdb::IteratorMode::Start)
.map(|res| res.unwrap_or_else(|e| panic!("unrecoverable database error {}", e)))
}

fn prefix_iterator<'a>(
&'a self,
prefix: Vec<u8>,
) -> Box<dyn Iterator<Item = (Box<[u8]>, Box<[u8]>)> + 'a> {
Box::new(
self.db
.prefix_iterator(&prefix)
.map(|res| res.unwrap_or_else(|e| panic!("unrecoverable database error {}", e)))
.take_while(move |(k, _)| k.starts_with(&prefix)), //rocks db returns keys beyond the prefix see https://github.com/rust-rocksdb/rust-rocksdb/issues/577
)
) -> impl Iterator<Item = (Box<[u8]>, Box<[u8]>)> + 'a {
self.db
.prefix_iterator(&prefix)
.map(|res| res.unwrap_or_else(|e| panic!("unrecoverable database error {}", e)))
.take_while(move |(k, _)| k.starts_with(&prefix)) //rocks db returns keys beyond the prefix see https://github.com/rust-rocksdb/rust-rocksdb/issues/577
}
}

Expand Down
44 changes: 20 additions & 24 deletions database/src/sled.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,34 +31,30 @@ impl Database for SledDb {
let _ = self.0.insert(key, value).unwrap_or_corrupt();
}

fn iterator<'a>(&'a self) -> Box<dyn Iterator<Item = (Box<[u8]>, Box<[u8]>)> + 'a> {
Box::new(
self.0
.iter()
.map(|this| this.unwrap_or_corrupt())
.map(|(key, value)| {
(
key.to_vec().into_boxed_slice(),
value.to_vec().into_boxed_slice(),
)
}),
)
fn iterator<'a>(&'a self) -> impl Iterator<Item = (Box<[u8]>, Box<[u8]>)> + 'a {
self.0
.iter()
.map(|this| this.unwrap_or_corrupt())
.map(|(key, value)| {
(
key.to_vec().into_boxed_slice(),
value.to_vec().into_boxed_slice(),
)
})
}

fn prefix_iterator<'a>(
&'a self,
prefix: Vec<u8>,
) -> Box<dyn Iterator<Item = (Box<[u8]>, Box<[u8]>)> + 'a> {
Box::new(
self.0
.scan_prefix(prefix)
.map(|this| this.unwrap_or_corrupt())
.map(|(key, value)| {
(
key.to_vec().into_boxed_slice(),
value.to_vec().into_boxed_slice(),
)
}),
)
) -> impl Iterator<Item = (Box<[u8]>, Box<[u8]>)> + 'a {
self.0
.scan_prefix(prefix)
.map(|this| this.unwrap_or_corrupt())
.map(|(key, value)| {
(
key.to_vec().into_boxed_slice(),
value.to_vec().into_boxed_slice(),
)
})
}
}
2 changes: 1 addition & 1 deletion gears/src/types/store/gas/kv/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ impl<'a, DB: Database> GasKVStore<'a, DB> {
Self { guard, inner }
}

pub fn into_range<R: RangeBounds<Vec<u8>> + Clone>(self, range: R) -> GasRange<'a, DB> {
pub fn into_range<R: RangeBounds<Vec<u8>> + Clone>(self, range: R) -> GasRange<'a, DB, Vec<u8>, R> {
GasRange::new_kv(self.inner.into_range(range), self.guard.clone())
}

Expand Down
2 changes: 1 addition & 1 deletion gears/src/types/store/gas/kv/mutable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ impl<'a, DB: Database> GasKVStoreMut<'a, DB> {
}
}

pub fn into_range<R: RangeBounds<Vec<u8>> + Clone>(self, range: R) -> GasRange<'a, DB> {
pub fn into_range<R: RangeBounds<Vec<u8>> + Clone>(self, range: R) -> GasRange<'a, DB, Vec<u8>, R> {
GasRange::new_kv(self.inner.into_range(range), self.guard.clone())
}

Expand Down
7 changes: 5 additions & 2 deletions gears/src/types/store/gas/prefix/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::ops::RangeBounds;
use std::ops::{Bound, RangeBounds};

use database::Database;
use kv_store::store::prefix::immutable::ImmutablePrefixStore;
Expand Down Expand Up @@ -34,7 +34,10 @@ impl<DB: Database> GasPrefixStore<'_, DB> {
}

impl<'a, DB: Database> GasPrefixStore<'a, DB> {
pub fn into_range<R: RangeBounds<Vec<u8>> + Clone>(self, range: R) -> GasRange<'a, DB> {
pub fn into_range<R: RangeBounds<Vec<u8>> + Clone>(
self,
range: R,
) -> GasRange<'a, DB, Vec<u8>, (Bound<Vec<u8>>, Bound<Vec<u8>>)> {
GasRange::new_prefix(self.inner.into_range(range), self.guard.clone())
}
}
19 changes: 12 additions & 7 deletions gears/src/types/store/gas/range/infallible.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::borrow::Cow;
use std::{borrow::Cow, ops::RangeBounds};

use database::Database;

Expand All @@ -7,27 +7,32 @@ use crate::types::store::gas::errors::GasStoreErrors;
use super::{GasRange, RangeBackend};

#[derive(Debug)]
pub struct RangeIter<'a, DB> {
range: GasRange<'a, DB>,
pub struct RangeIter<'a, DB, RB, R> {
range: GasRange<'a, DB, RB, R>,
err: Option<GasStoreErrors>,
}

impl<DB> RangeIter<'_, DB> {
impl<DB: Database, RB: AsRef<[u8]>, R: RangeBounds<RB>> RangeIter<'_, DB, RB, R> {
pub fn rev_iter(mut self) -> Self {
self.range = self.range.rev_iter();
self
}

pub fn error(&self) -> Option<&GasStoreErrors> {
self.err.as_ref()
}
}

impl<'a, DB> From<GasRange<'a, DB>> for RangeIter<'a, DB> {
fn from(value: GasRange<'a, DB>) -> Self {
impl<'a, DB, RB, R> From<GasRange<'a, DB, RB, R>> for RangeIter<'a, DB, RB, R> {
fn from(value: GasRange<'a, DB, RB, R>) -> Self {
Self {
range: value,
err: None,
}
}
}

impl<'a, DB: Database> Iterator for RangeIter<'a, DB> {
impl<'a, DB: Database, RB: AsRef<[u8]>, R: RangeBounds<RB>> Iterator for RangeIter<'a, DB, RB, R> {
type Item = (Cow<'a, Vec<u8>>, Cow<'a, Vec<u8>>);

fn next(&mut self) -> Option<Self::Item> {
Expand Down
34 changes: 23 additions & 11 deletions gears/src/types/store/gas/range/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::borrow::Cow;
use std::{borrow::Cow, ops::RangeBounds};

use database::Database;
use infallible::RangeIter;
Expand All @@ -9,38 +9,50 @@ use super::{errors::GasStoreErrors, guard::GasGuard};
pub mod infallible;

#[derive(Debug)]
enum RangeBackend<'a, DB> {
Kv(Range<'a, DB>),
Prefix(PrefixRange<'a, DB>),
enum RangeBackend<'a, DB, RB, R> {
Kv(Range<'a, DB, RB, R>),
Prefix(PrefixRange<'a, DB, RB, R>),
}

#[derive(Debug)]
pub struct GasRange<'a, DB> {
inner: RangeBackend<'a, DB>,
pub struct GasRange<'a, DB, RB, R> {
inner: RangeBackend<'a, DB, RB, R>,
guard: GasGuard,
}

impl<'a, DB> GasRange<'a, DB> {
pub(super) fn new_kv(inner: Range<'a, DB>, guard: GasGuard) -> Self {
impl<'a, DB: Database, RB: AsRef<[u8]>, R: RangeBounds<RB>> GasRange<'a, DB, RB, R> {
pub fn rev_iter(self) -> Self {
let Self { inner, guard } = self;
let inner = match inner {
RangeBackend::Kv(range) => RangeBackend::Kv(range.rev_iter()),
RangeBackend::Prefix(range) => RangeBackend::Prefix(range.rev_iter()),
};

Self { inner, guard }
}
}

impl<'a, DB, RB, R> GasRange<'a, DB, RB, R> {
pub(super) fn new_kv(inner: Range<'a, DB, RB, R>, guard: GasGuard) -> Self {
Self {
inner: RangeBackend::Kv(inner),
guard,
}
}

pub(super) fn new_prefix(inner: PrefixRange<'a, DB>, guard: GasGuard) -> Self {
pub(super) fn new_prefix(inner: PrefixRange<'a, DB, RB, R>, guard: GasGuard) -> Self {
Self {
inner: RangeBackend::Prefix(inner),
guard,
}
}

pub fn to_infallible_iter(self) -> RangeIter<'a, DB> {
pub fn to_infallible_iter(self) -> RangeIter<'a, DB, RB, R> {
RangeIter::from(self)
}
}

impl<'a, DB: Database> Iterator for GasRange<'a, DB> {
impl<'a, DB: Database, RB: AsRef<[u8]>, R: RangeBounds<RB>> Iterator for GasRange<'a, DB, RB, R> {
type Item = Result<(Cow<'a, Vec<u8>>, Cow<'a, Vec<u8>>), GasStoreErrors>;

fn next(&mut self) -> Option<Self::Item> {
Expand Down
5 changes: 4 additions & 1 deletion gears/src/types/store/kv/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,10 @@ impl<'a, DB> From<KVStore<'a, DB>> for Store<'a, DB> {
}

impl<'a, DB: Database> Store<'a, DB> {
pub fn into_range<R: RangeBounds<Vec<u8>> + Clone>(self, range: R) -> StoreRange<'a, DB> {
pub fn into_range<R: RangeBounds<Vec<u8>> + Clone>(
self,
range: R,
) -> StoreRange<'a, DB, Vec<u8>, R> {
match self.0 {
StoreBackend::Gas(var) => StoreRange::from(var.into_range(range)),
StoreBackend::Kv(var) => StoreRange::from(var.into_range(range)),
Expand Down
5 changes: 4 additions & 1 deletion gears/src/types/store/kv/mutable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,10 @@ impl<'a, DB> From<KVStoreMut<'a, DB>> for StoreMut<'a, DB> {
}

impl<'a, DB: Database> StoreMut<'a, DB> {
pub fn into_range<R: RangeBounds<Vec<u8>> + Clone>(self, range: R) -> StoreRange<'a, DB> {
pub fn into_range<R: RangeBounds<Vec<u8>> + Clone>(
self,
range: R,
) -> StoreRange<'a, DB, Vec<u8>, R> {
match self.0 {
StoreMutBackend::Gas(var) => StoreRange::from(var.into_range(range)),
StoreMutBackend::Kv(var) => StoreRange::from(var.into_range(range)),
Expand Down
7 changes: 5 additions & 2 deletions gears/src/types/store/prefix/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::ops::RangeBounds;
use std::ops::{Bound, RangeBounds};

use database::Database;
use kv_store::store::prefix::immutable::ImmutablePrefixStore;
Expand Down Expand Up @@ -32,7 +32,10 @@ impl<'a, DB> From<ImmutablePrefixStore<'a, DB>> for PrefixStore<'a, DB> {
}

impl<'a, DB: Database> PrefixStore<'a, DB> {
pub fn into_range<R: RangeBounds<Vec<u8>> + Clone>(self, range: R) -> StoreRange<'a, DB> {
pub fn into_range<R: RangeBounds<Vec<u8>> + Clone>(
self,
range: R,
) -> StoreRange<'a, DB, Vec<u8>, (Bound<Vec<u8>>, Bound<Vec<u8>>)> {
match self.0 {
PrefixStoreBackend::Gas(var) => var.into_range(range).into(),
PrefixStoreBackend::Kv(var) => var.into_range(range).into(),
Expand Down
Loading

0 comments on commit f4c0ed6

Please sign in to comment.