mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
feat(interface): implicit trait bound for DB cursors (#122)
* feat(interface): implicit trait bound for DB cursors * test cursor * walking fixed for RO * impl for Walker for DupCursor
This commit is contained in:
@ -1,5 +1,7 @@
|
|||||||
//! Cursor wrapper for libmdbx-sys.
|
//! Cursor wrapper for libmdbx-sys.
|
||||||
|
|
||||||
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
use crate::utils::*;
|
use crate::utils::*;
|
||||||
use libmdbx::{self, TransactionKind, WriteFlags, RO, RW};
|
use libmdbx::{self, TransactionKind, WriteFlags, RO, RW};
|
||||||
use reth_interfaces::db::{
|
use reth_interfaces::db::{
|
||||||
@ -67,14 +69,20 @@ impl<'tx, K: TransactionKind, T: Table> DbCursorRO<'tx, T> for Cursor<'tx, K, T>
|
|||||||
decode!(self.inner.get_current())
|
decode!(self.inner.get_current())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn walk(&'tx mut self, start_key: <T as Table>::Key) -> Result<Walker<'tx, T>, Error> {
|
fn walk<'cursor>(
|
||||||
|
&'cursor mut self,
|
||||||
|
start_key: T::Key,
|
||||||
|
) -> Result<Walker<'cursor, 'tx, T, Self>, Error>
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
{
|
||||||
let start = self
|
let start = self
|
||||||
.inner
|
.inner
|
||||||
.set_range(start_key.encode().as_ref())
|
.set_range(start_key.encode().as_ref())
|
||||||
.map_err(|e| Error::Internal(e.into()))?
|
.map_err(|e| Error::Internal(e.into()))?
|
||||||
.map(decoder::<T>);
|
.map(decoder::<T>);
|
||||||
|
|
||||||
Ok(Walker::<'tx, T> { cursor: self, start })
|
Ok(Walker::<'cursor, 'tx, T, Self> { cursor: self, start, _tx_phantom: PhantomData {} })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,14 +107,18 @@ impl<'tx, K: TransactionKind, T: DupSort> DbDupCursorRO<'tx, T> for Cursor<'tx,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns an iterator starting at a key greater or equal than `start_key` of a DUPSORT table.
|
/// Returns an iterator starting at a key greater or equal than `start_key` of a DUPSORT table.
|
||||||
fn walk_dup(&'tx mut self, key: T::Key, subkey: T::SubKey) -> Result<DupWalker<'tx, T>, Error> {
|
fn walk_dup<'cursor>(
|
||||||
|
&'cursor mut self,
|
||||||
|
key: T::Key,
|
||||||
|
subkey: T::SubKey,
|
||||||
|
) -> Result<DupWalker<'cursor, 'tx, T, Self>, Error> {
|
||||||
let start = self
|
let start = self
|
||||||
.inner
|
.inner
|
||||||
.get_both_range(key.encode().as_ref(), subkey.encode().as_ref())
|
.get_both_range(key.encode().as_ref(), subkey.encode().as_ref())
|
||||||
.map_err(|e| Error::Internal(e.into()))?
|
.map_err(|e| Error::Internal(e.into()))?
|
||||||
.map(decode_one::<T>);
|
.map(decode_one::<T>);
|
||||||
|
|
||||||
Ok(DupWalker::<'tx, T> { cursor: self, start })
|
Ok(DupWalker::<'cursor, 'tx, T, Self> { cursor: self, start, _tx_phantom: PhantomData {} })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -137,7 +137,7 @@ mod tests {
|
|||||||
use libmdbx::{NoWriteMap, WriteMap};
|
use libmdbx::{NoWriteMap, WriteMap};
|
||||||
use reth_interfaces::db::{
|
use reth_interfaces::db::{
|
||||||
tables::{Headers, PlainState},
|
tables::{Headers, PlainState},
|
||||||
Database, DbTx, DbTxMut,
|
Database, DbCursorRO, DbTx, DbTxMut,
|
||||||
};
|
};
|
||||||
use reth_primitives::{Account, Address, Header, H256, U256};
|
use reth_primitives::{Account, Address, Header, H256, U256};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
@ -175,6 +175,31 @@ mod tests {
|
|||||||
tx.commit().expect(ERROR_COMMIT);
|
tx.commit().expect(ERROR_COMMIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn db_cursor_walk() {
|
||||||
|
let env = test_utils::create_test_db::<NoWriteMap>(EnvKind::RW);
|
||||||
|
|
||||||
|
let value = Header::default();
|
||||||
|
let key = (1u64, H256::zero());
|
||||||
|
|
||||||
|
// PUT
|
||||||
|
let tx = env.tx_mut().expect(ERROR_INIT_TX);
|
||||||
|
tx.put::<Headers>(key.into(), value.clone()).expect(ERROR_PUT);
|
||||||
|
tx.commit().expect(ERROR_COMMIT);
|
||||||
|
|
||||||
|
// Cursor
|
||||||
|
let tx = env.tx().expect(ERROR_INIT_TX);
|
||||||
|
let mut cursor = tx.cursor::<Headers>().unwrap();
|
||||||
|
|
||||||
|
let first = cursor.first().unwrap();
|
||||||
|
assert!(first.is_some(), "First should be our put");
|
||||||
|
|
||||||
|
// Walk
|
||||||
|
let walk = cursor.walk(key.into()).unwrap();
|
||||||
|
let first = walk.into_iter().next().unwrap().unwrap();
|
||||||
|
assert_eq!(first.1, value, "First next should be put value");
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn db_closure_put_get() {
|
fn db_closure_put_get() {
|
||||||
let path = TempDir::new().expect(test_utils::ERROR_TEMPDIR).into_path();
|
let path = TempDir::new().expect(test_utils::ERROR_TEMPDIR).into_path();
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
use crate::{kv::cursor::Cursor, utils::decode_one};
|
use crate::{kv::cursor::Cursor, utils::decode_one};
|
||||||
use libmdbx::{EnvironmentKind, Transaction, TransactionKind, WriteFlags, RW};
|
use libmdbx::{EnvironmentKind, Transaction, TransactionKind, WriteFlags, RW};
|
||||||
use reth_interfaces::db::{DbTx, DbTxMut, DupSort, Encode, Error, Table};
|
use reth_interfaces::db::{DbTx, DbTxGAT, DbTxMut, DbTxMutGAT, DupSort, Encode, Error, Table};
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
/// Wrapper for the libmdbx transaction.
|
/// Wrapper for the libmdbx transaction.
|
||||||
@ -39,18 +39,24 @@ impl<'env, K: TransactionKind, E: EnvironmentKind> Tx<'env, K, E> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'env, K: TransactionKind, E: EnvironmentKind> DbTx<'env> for Tx<'env, K, E> {
|
impl<'a, K: TransactionKind, E: EnvironmentKind> DbTxGAT<'a> for Tx<'_, K, E> {
|
||||||
/// Cursor GAT
|
type Cursor<T: Table> = Cursor<'a, K, T>;
|
||||||
type Cursor<T: Table> = Cursor<'env, K, T>;
|
type DupCursor<T: DupSort> = Cursor<'a, K, T>;
|
||||||
/// DupCursor GAT
|
}
|
||||||
type DupCursor<T: DupSort> = Cursor<'env, K, T>;
|
|
||||||
/// Iterate over read only values in database.
|
impl<'a, K: TransactionKind, E: EnvironmentKind> DbTxMutGAT<'a> for Tx<'_, K, E> {
|
||||||
fn cursor<T: Table>(&self) -> Result<Self::Cursor<T>, Error> {
|
type CursorMut<T: Table> = Cursor<'a, RW, T>;
|
||||||
|
type DupCursorMut<T: DupSort> = Cursor<'a, RW, T>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tx, K: TransactionKind, E: EnvironmentKind> DbTx<'tx> for Tx<'tx, K, E> {
|
||||||
|
// Iterate over read only values in database.
|
||||||
|
fn cursor<T: Table>(&'tx self) -> Result<<Self as DbTxGAT<'tx>>::Cursor<T>, Error> {
|
||||||
self.new_cursor()
|
self.new_cursor()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Iterate over read only values in database.
|
/// Iterate over read only values in database.
|
||||||
fn cursor_dup<T: DupSort>(&self) -> Result<Self::DupCursor<T>, Error> {
|
fn cursor_dup<T: DupSort>(&'tx self) -> Result<<Self as DbTxGAT<'tx>>::DupCursor<T>, Error> {
|
||||||
self.new_cursor()
|
self.new_cursor()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,11 +76,7 @@ impl<'env, K: TransactionKind, E: EnvironmentKind> DbTx<'env> for Tx<'env, K, E>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'env, E: EnvironmentKind> DbTxMut<'env> for Tx<'env, RW, E> {
|
impl<E: EnvironmentKind> DbTxMut<'_> for Tx<'_, RW, E> {
|
||||||
type CursorMut<T: Table> = Cursor<'env, RW, T>;
|
|
||||||
|
|
||||||
type DupCursorMut<T: DupSort> = Cursor<'env, RW, T>;
|
|
||||||
|
|
||||||
fn put<T: Table>(&self, key: T::Key, value: T::Value) -> Result<(), Error> {
|
fn put<T: Table>(&self, key: T::Key, value: T::Value) -> Result<(), Error> {
|
||||||
self.inner
|
self.inner
|
||||||
.put(
|
.put(
|
||||||
@ -111,11 +113,13 @@ impl<'env, E: EnvironmentKind> DbTxMut<'env> for Tx<'env, RW, E> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cursor_mut<T: Table>(&self) -> Result<Self::CursorMut<T>, Error> {
|
fn cursor_mut<T: Table>(&self) -> Result<<Self as DbTxMutGAT<'_>>::CursorMut<T>, Error> {
|
||||||
self.new_cursor()
|
self.new_cursor()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cursor_dup_mut<T: DupSort>(&self) -> Result<Self::DupCursorMut<T>, Error> {
|
fn cursor_dup_mut<T: DupSort>(
|
||||||
|
&self,
|
||||||
|
) -> Result<<Self as DbTxMutGAT<'_>>::DupCursorMut<T>, Error> {
|
||||||
self.new_cursor()
|
self.new_cursor()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,8 +2,8 @@
|
|||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
Database, DatabaseGAT, DbCursorRO, DbCursorRW, DbDupCursorRO, DbDupCursorRW, DbTx, DbTxMut,
|
Database, DatabaseGAT, DbCursorRO, DbCursorRW, DbDupCursorRO, DbDupCursorRW, DbTx, DbTxGAT,
|
||||||
DupSort, Table,
|
DbTxMut, DbTxMutGAT, DupSort, DupWalker, Error, Table, Walker,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Mock database used for testing with inner BTreeMap structure
|
/// Mock database used for testing with inner BTreeMap structure
|
||||||
@ -37,11 +37,17 @@ pub struct TxMock {
|
|||||||
_table: BTreeMap<Vec<u8>, Vec<u8>>,
|
_table: BTreeMap<Vec<u8>, Vec<u8>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> DbTxGAT<'a> for TxMock {
|
||||||
|
type Cursor<T: Table> = CursorMock;
|
||||||
|
type DupCursor<T: DupSort> = CursorMock;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> DbTxMutGAT<'a> for TxMock {
|
||||||
|
type CursorMut<T: Table> = CursorMock;
|
||||||
|
type DupCursorMut<T: DupSort> = CursorMock;
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a> DbTx<'a> for TxMock {
|
impl<'a> DbTx<'a> for TxMock {
|
||||||
type Cursor<T: super::Table> = CursorMock;
|
|
||||||
|
|
||||||
type DupCursor<T: super::DupSort> = CursorMock;
|
|
||||||
|
|
||||||
fn get<T: super::Table>(&self, _key: T::Key) -> Result<Option<T::Value>, super::Error> {
|
fn get<T: super::Table>(&self, _key: T::Key) -> Result<Option<T::Value>, super::Error> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
@ -50,20 +56,18 @@ impl<'a> DbTx<'a> for TxMock {
|
|||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cursor<T: super::Table>(&self) -> Result<Self::Cursor<T>, super::Error> {
|
fn cursor<T: super::Table>(&self) -> Result<<Self as DbTxGAT<'_>>::Cursor<T>, super::Error> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cursor_dup<T: super::DupSort>(&self) -> Result<Self::DupCursor<T>, super::Error> {
|
fn cursor_dup<T: super::DupSort>(
|
||||||
|
&self,
|
||||||
|
) -> Result<<Self as DbTxGAT<'_>>::DupCursor<T>, super::Error> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> DbTxMut<'a> for TxMock {
|
impl<'a> DbTxMut<'a> for TxMock {
|
||||||
type CursorMut<T: super::Table> = CursorMock;
|
|
||||||
|
|
||||||
type DupCursorMut<T: super::DupSort> = CursorMock;
|
|
||||||
|
|
||||||
fn put<T: super::Table>(&self, _key: T::Key, _value: T::Value) -> Result<(), super::Error> {
|
fn put<T: super::Table>(&self, _key: T::Key, _value: T::Value) -> Result<(), super::Error> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
@ -76,11 +80,15 @@ impl<'a> DbTxMut<'a> for TxMock {
|
|||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cursor_mut<T: super::Table>(&self) -> Result<Self::CursorMut<T>, super::Error> {
|
fn cursor_mut<T: super::Table>(
|
||||||
|
&self,
|
||||||
|
) -> Result<<Self as DbTxMutGAT<'_>>::CursorMut<T>, super::Error> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cursor_dup_mut<T: super::DupSort>(&self) -> Result<Self::DupCursorMut<T>, super::Error> {
|
fn cursor_dup_mut<T: super::DupSort>(
|
||||||
|
&self,
|
||||||
|
) -> Result<<Self as DbTxMutGAT<'_>>::DupCursorMut<T>, super::Error> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,7 +131,13 @@ impl<'tx, T: Table> DbCursorRO<'tx, T> for CursorMock {
|
|||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn walk(&'tx mut self, _start_key: T::Key) -> Result<super::Walker<'tx, T>, super::Error> {
|
fn walk<'cursor>(
|
||||||
|
&'cursor mut self,
|
||||||
|
_start_key: T::Key,
|
||||||
|
) -> Result<Walker<'cursor, 'tx, T, Self>, Error>
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
{
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -141,11 +155,14 @@ impl<'tx, T: DupSort> DbDupCursorRO<'tx, T> for CursorMock {
|
|||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn walk_dup(
|
fn walk_dup<'cursor>(
|
||||||
&'tx mut self,
|
&'cursor mut self,
|
||||||
_key: <T>::Key,
|
_key: <T>::Key,
|
||||||
_subkey: <T as DupSort>::SubKey,
|
_subkey: <T as DupSort>::SubKey,
|
||||||
) -> Result<super::DupWalker<'tx, T>, super::Error> {
|
) -> Result<DupWalker<'cursor, 'tx, T, Self>, Error>
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
{
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,6 +6,8 @@ pub mod models;
|
|||||||
mod table;
|
mod table;
|
||||||
pub mod tables;
|
pub mod tables;
|
||||||
|
|
||||||
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
pub use error::Error;
|
pub use error::Error;
|
||||||
pub use table::*;
|
pub use table::*;
|
||||||
|
|
||||||
@ -67,25 +69,22 @@ pub trait Database: for<'a> DatabaseGAT<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read only transaction
|
/// Implements the GAT method from:
|
||||||
pub trait DbTx<'a> {
|
/// https://sabrinajewson.org/blog/the-better-alternative-to-lifetime-gats#the-better-gats.
|
||||||
|
///
|
||||||
|
/// Sealed trait which cannot be implemented by 3rd parties, exposed only for implementers
|
||||||
|
pub trait DbTxGAT<'a, __ImplicitBounds: Sealed = Bounds<&'a Self>>: Send + Sync {
|
||||||
/// Cursor GAT
|
/// Cursor GAT
|
||||||
type Cursor<T: Table>: DbCursorRO<'a, T>;
|
type Cursor<T: Table>: DbCursorRO<'a, T>;
|
||||||
/// DupCursor GAT
|
/// DupCursor GAT
|
||||||
type DupCursor<T: DupSort>: DbDupCursorRO<'a, T> + DbCursorRO<'a, T>;
|
type DupCursor<T: DupSort>: DbDupCursorRO<'a, T> + DbCursorRO<'a, T>;
|
||||||
/// Get value
|
|
||||||
fn get<T: Table>(&self, key: T::Key) -> Result<Option<T::Value>, Error>;
|
|
||||||
/// Commit for read only transaction will consume and free transaction and allows
|
|
||||||
/// freeing of memory pages
|
|
||||||
fn commit(self) -> Result<bool, Error>;
|
|
||||||
/// Iterate over read only values in table.
|
|
||||||
fn cursor<T: Table>(&self) -> Result<Self::Cursor<T>, Error>;
|
|
||||||
/// Iterate over read only values in dup sorted table.
|
|
||||||
fn cursor_dup<T: DupSort>(&self) -> Result<Self::DupCursor<T>, Error>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read write transaction that allows writing to database
|
/// Implements the GAT method from:
|
||||||
pub trait DbTxMut<'a> {
|
/// https://sabrinajewson.org/blog/the-better-alternative-to-lifetime-gats#the-better-gats.
|
||||||
|
///
|
||||||
|
/// Sealed trait which cannot be implemented by 3rd parties, exposed only for implementers
|
||||||
|
pub trait DbTxMutGAT<'a, __ImplicitBounds: Sealed = Bounds<&'a Self>>: Send + Sync {
|
||||||
/// Cursor GAT
|
/// Cursor GAT
|
||||||
type CursorMut<T: Table>: DbCursorRW<'a, T> + DbCursorRO<'a, T>;
|
type CursorMut<T: Table>: DbCursorRW<'a, T> + DbCursorRO<'a, T>;
|
||||||
/// DupCursor GAT
|
/// DupCursor GAT
|
||||||
@ -93,6 +92,23 @@ pub trait DbTxMut<'a> {
|
|||||||
+ DbCursorRW<'a, T>
|
+ DbCursorRW<'a, T>
|
||||||
+ DbDupCursorRO<'a, T>
|
+ DbDupCursorRO<'a, T>
|
||||||
+ DbCursorRO<'a, T>;
|
+ DbCursorRO<'a, T>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Read only transaction
|
||||||
|
pub trait DbTx<'tx>: for<'a> DbTxGAT<'a> {
|
||||||
|
/// Get value
|
||||||
|
fn get<T: Table>(&self, key: T::Key) -> Result<Option<T::Value>, Error>;
|
||||||
|
/// Commit for read only transaction will consume and free transaction and allows
|
||||||
|
/// freeing of memory pages
|
||||||
|
fn commit(self) -> Result<bool, Error>;
|
||||||
|
/// Iterate over read only values in table.
|
||||||
|
fn cursor<T: Table>(&'tx self) -> Result<<Self as DbTxGAT<'tx>>::Cursor<T>, Error>;
|
||||||
|
/// Iterate over read only values in dup sorted table.
|
||||||
|
fn cursor_dup<T: DupSort>(&'tx self) -> Result<<Self as DbTxGAT<'tx>>::DupCursor<T>, Error>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Read write transaction that allows writing to database
|
||||||
|
pub trait DbTxMut<'tx>: for<'a> DbTxMutGAT<'a> {
|
||||||
/// Put value to database
|
/// Put value to database
|
||||||
fn put<T: Table>(&self, key: T::Key, value: T::Value) -> Result<(), Error>;
|
fn put<T: Table>(&self, key: T::Key, value: T::Value) -> Result<(), Error>;
|
||||||
/// Delete value from database
|
/// Delete value from database
|
||||||
@ -100,9 +116,11 @@ pub trait DbTxMut<'a> {
|
|||||||
/// Clears database.
|
/// Clears database.
|
||||||
fn clear<T: Table>(&self) -> Result<(), Error>;
|
fn clear<T: Table>(&self) -> Result<(), Error>;
|
||||||
/// Cursor mut
|
/// Cursor mut
|
||||||
fn cursor_mut<T: Table>(&self) -> Result<Self::CursorMut<T>, Error>;
|
fn cursor_mut<T: Table>(&self) -> Result<<Self as DbTxMutGAT<'tx>>::CursorMut<T>, Error>;
|
||||||
/// DupCursor mut.
|
/// DupCursor mut.
|
||||||
fn cursor_dup_mut<T: DupSort>(&self) -> Result<Self::DupCursorMut<T>, Error>;
|
fn cursor_dup_mut<T: DupSort>(
|
||||||
|
&self,
|
||||||
|
) -> Result<<Self as DbTxMutGAT<'tx>>::DupCursorMut<T>, Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Alias type for a `(key, value)` result coming from a cursor.
|
/// Alias type for a `(key, value)` result coming from a cursor.
|
||||||
@ -136,8 +154,18 @@ pub trait DbCursorRO<'tx, T: Table> {
|
|||||||
/// Returns the current `(key, value)` pair of the cursor.
|
/// Returns the current `(key, value)` pair of the cursor.
|
||||||
fn current(&mut self) -> PairResult<T>;
|
fn current(&mut self) -> PairResult<T>;
|
||||||
|
|
||||||
|
/// Inner
|
||||||
|
fn inner(&'tx mut self) -> &'tx mut Self {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns an iterator starting at a key greater or equal than `start_key`.
|
/// Returns an iterator starting at a key greater or equal than `start_key`.
|
||||||
fn walk(&'tx mut self, start_key: T::Key) -> Result<Walker<'tx, T>, Error>;
|
fn walk<'cursor>(
|
||||||
|
&'cursor mut self,
|
||||||
|
start_key: T::Key,
|
||||||
|
) -> Result<Walker<'cursor, 'tx, T, Self>, Error>
|
||||||
|
where
|
||||||
|
Self: Sized;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read only curor over DupSort table.
|
/// Read only curor over DupSort table.
|
||||||
@ -153,7 +181,13 @@ pub trait DbDupCursorRO<'tx, T: DupSort> {
|
|||||||
|
|
||||||
/// Returns an iterator starting at a key greater or equal than `start_key` of a DUPSORT
|
/// Returns an iterator starting at a key greater or equal than `start_key` of a DUPSORT
|
||||||
/// table.
|
/// table.
|
||||||
fn walk_dup(&'tx mut self, key: T::Key, subkey: T::SubKey) -> Result<DupWalker<'tx, T>, Error>;
|
fn walk_dup<'cursor>(
|
||||||
|
&'cursor mut self,
|
||||||
|
key: T::Key,
|
||||||
|
subkey: T::SubKey,
|
||||||
|
) -> Result<DupWalker<'cursor, 'tx, T, Self>, Error>
|
||||||
|
where
|
||||||
|
Self: Sized;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read write cursor over table.
|
/// Read write cursor over table.
|
||||||
@ -178,14 +212,18 @@ pub trait DbDupCursorRW<'tx, T: DupSort> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Provides an iterator to `Cursor` when handling `Table`.
|
/// Provides an iterator to `Cursor` when handling `Table`.
|
||||||
pub struct Walker<'cursor, T: Table> {
|
pub struct Walker<'cursor, 'tx, T: Table, CURSOR: DbCursorRO<'tx, T> + Sized> {
|
||||||
/// Cursor to be used to walk through the table.
|
/// Cursor to be used to walk through the table.
|
||||||
pub cursor: &'cursor mut dyn DbCursorRO<'cursor, T>,
|
pub cursor: &'cursor mut CURSOR,
|
||||||
/// `(key, value)` where to start the walk.
|
/// `(key, value)` where to start the walk.
|
||||||
pub start: IterPairResult<T>,
|
pub start: IterPairResult<T>,
|
||||||
|
/// Phantom data for 'tx.
|
||||||
|
pub _tx_phantom: PhantomData<&'tx T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'cursor, T: Table> std::iter::Iterator for Walker<'cursor, T> {
|
impl<'cursor, 'tx, T: Table, CURSOR: DbCursorRO<'tx, T> + Sized> std::iter::Iterator
|
||||||
|
for Walker<'cursor, 'tx, T, CURSOR>
|
||||||
|
{
|
||||||
type Item = Result<(T::Key, T::Value), Error>;
|
type Item = Result<(T::Key, T::Value), Error>;
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
let start = self.start.take();
|
let start = self.start.take();
|
||||||
@ -198,14 +236,18 @@ impl<'cursor, T: Table> std::iter::Iterator for Walker<'cursor, T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Provides an iterator to `Cursor` when handling a `DupSort` table.
|
/// Provides an iterator to `Cursor` when handling a `DupSort` table.
|
||||||
pub struct DupWalker<'cursor, T: DupSort> {
|
pub struct DupWalker<'cursor, 'tx, T: DupSort, CURSOR: DbDupCursorRO<'tx, T> + Sized> {
|
||||||
/// Cursor to be used to walk through the table.
|
/// Cursor to be used to walk through the table.
|
||||||
pub cursor: &'cursor mut dyn DbDupCursorRO<'cursor, T>,
|
pub cursor: &'cursor mut CURSOR,
|
||||||
/// Value where to start the walk.
|
/// Value where to start the walk.
|
||||||
pub start: Option<Result<T::Value, Error>>,
|
pub start: Option<Result<T::Value, Error>>,
|
||||||
|
/// Phantom data for 'tx.
|
||||||
|
pub _tx_phantom: PhantomData<&'tx T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'cursor, T: DupSort> std::iter::Iterator for DupWalker<'cursor, T> {
|
impl<'cursor, 'tx, T: DupSort, CURSOR: DbDupCursorRO<'tx, T> + Sized> std::iter::Iterator
|
||||||
|
for DupWalker<'cursor, 'tx, T, CURSOR>
|
||||||
|
{
|
||||||
type Item = Result<T::Value, Error>;
|
type Item = Result<T::Value, Error>;
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
let start = self.start.take();
|
let start = self.start.take();
|
||||||
|
|||||||
@ -21,7 +21,7 @@ pub type HeaderHash = H256;
|
|||||||
/// element as BlockNumber, helps out with querying/sorting.
|
/// element as BlockNumber, helps out with querying/sorting.
|
||||||
///
|
///
|
||||||
/// Since it's used as a key, the `BlockNumber` is not compressed when encoding it.
|
/// Since it's used as a key, the `BlockNumber` is not compressed when encoding it.
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
pub struct BlockNumHash((BlockNumber, BlockHash));
|
pub struct BlockNumHash((BlockNumber, BlockHash));
|
||||||
|
|
||||||
@ -58,7 +58,9 @@ impl Decode for BlockNumHash {
|
|||||||
let value: bytes::Bytes = value.into();
|
let value: bytes::Bytes = value.into();
|
||||||
|
|
||||||
let num = u64::from_be_bytes(
|
let num = u64::from_be_bytes(
|
||||||
value.as_ref().try_into().map_err(|_| Error::Decode(eyre!("Into bytes error.")))?,
|
value.as_ref()[..8]
|
||||||
|
.try_into()
|
||||||
|
.map_err(|_| Error::Decode(eyre!("Into bytes error.")))?,
|
||||||
);
|
);
|
||||||
let hash = H256::decode(value.slice(8..))?;
|
let hash = H256::decode(value.slice(8..))?;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user