pub mod codecs; mod container; mod error; pub mod mock; pub mod models; mod table; pub mod tables; use std::marker::PhantomData; pub use error::Error; pub use table::*; pub use container::DBContainer; // Sealed trait helper to prevent misuse of the API. mod sealed { pub trait Sealed: Sized {} pub struct Bounds(T); impl Sealed for Bounds {} } use sealed::{Bounds, Sealed}; /// Implements the GAT method from: /// 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 DatabaseGAT<'a, __ImplicitBounds: Sealed = Bounds<&'a Self>>: Send + Sync { /// RO database transaction type TX: DbTx<'a> + Send + Sync; /// RW database transaction type TXMut: DbTxMut<'a> + DbTx<'a> + Send + Sync; } /// Main Database trait that spawns transactions to be executed. pub trait Database: for<'a> DatabaseGAT<'a> { /// Create read only transaction. fn tx(&self) -> Result<>::TX, Error>; /// Create read write transaction only possible if database is open with write access. fn tx_mut(&self) -> Result<>::TXMut, Error>; /// Takes a function and passes a read-only transaction into it, making sure it's closed in the /// end of the execution. fn view(&self, f: F) -> Result where F: Fn(&>::TX) -> T, { let tx = self.tx()?; let res = f(&tx); tx.commit()?; Ok(res) } /// Takes a function and passes a write-read transaction into it, making sure it's committed in /// the end of the execution. fn update(&self, f: F) -> Result where F: Fn(&>::TXMut) -> T, { let tx = self.tx_mut()?; let res = f(&tx); tx.commit()?; Ok(res) } } /// Implements the GAT method from: /// 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 type Cursor: DbCursorRO<'a, T>; /// DupCursor GAT type DupCursor: DbDupCursorRO<'a, T> + DbCursorRO<'a, T>; } /// Implements the GAT method from: /// 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 type CursorMut: DbCursorRW<'a, T> + DbCursorRO<'a, T>; /// DupCursor GAT type DupCursorMut: DbDupCursorRW<'a, T> + DbCursorRW<'a, T> + DbDupCursorRO<'a, T> + DbCursorRO<'a, T>; } /// Read only transaction pub trait DbTx<'tx>: for<'a> DbTxGAT<'a> { /// Get value fn get(&self, key: T::Key) -> Result, Error>; /// Commit for read only transaction will consume and free transaction and allows /// freeing of memory pages fn commit(self) -> Result; /// Iterate over read only values in table. fn cursor(&'tx self) -> Result<>::Cursor, Error>; /// Iterate over read only values in dup sorted table. fn cursor_dup(&'tx self) -> Result<>::DupCursor, Error>; } /// Read write transaction that allows writing to database pub trait DbTxMut<'tx>: for<'a> DbTxMutGAT<'a> { /// Put value to database fn put(&self, key: T::Key, value: T::Value) -> Result<(), Error>; /// Delete value from database fn delete(&self, key: T::Key, value: Option) -> Result; /// Clears database. fn clear(&self) -> Result<(), Error>; /// Cursor mut fn cursor_mut(&self) -> Result<>::CursorMut, Error>; /// DupCursor mut. fn cursor_dup_mut( &self, ) -> Result<>::DupCursorMut, Error>; } /// Alias type for a `(key, value)` result coming from a cursor. pub type PairResult = Result::Key, ::Value)>, Error>; /// Alias type for a `(key, value)` result coming from an iterator. pub type IterPairResult = Option::Key, ::Value), Error>>; /// Alias type for a value result coming from a cursor without its key. pub type ValueOnlyResult = Result::Value>, Error>; /// Read only cursor over table. pub trait DbCursorRO<'tx, T: Table> { /// First item in table fn first(&mut self) -> PairResult; /// Seeks for a `(key, value)` pair greater or equal than `key`. fn seek(&mut self, key: T::SeekKey) -> PairResult; /// Seeks for the exact `(key, value)` pair with `key`. fn seek_exact(&mut self, key: T::Key) -> PairResult; /// Returns the next `(key, value)` pair. #[allow(clippy::should_implement_trait)] fn next(&mut self) -> PairResult; /// Returns the previous `(key, value)` pair. fn prev(&mut self) -> PairResult; /// Returns the last `(key, value)` pair. fn last(&mut self) -> PairResult; /// Returns the current `(key, value)` pair of the cursor. fn current(&mut self) -> PairResult; /// Inner fn inner(&'tx mut self) -> &'tx mut Self { self } /// Returns an iterator starting at a key greater or equal than `start_key`. fn walk<'cursor>( &'cursor mut self, start_key: T::Key, ) -> Result, Error> where Self: Sized; } /// Read only curor over DupSort table. pub trait DbDupCursorRO<'tx, T: DupSort> { /// Returns the next `(key, value)` pair of a DUPSORT table. fn next_dup(&mut self) -> PairResult; /// Returns the next `(key, value)` pair skipping the duplicates. fn next_no_dup(&mut self) -> PairResult; /// Returns the next `value` of a duplicate `key`. fn next_dup_val(&mut self) -> ValueOnlyResult; /// Returns an iterator starting at a key greater or equal than `start_key` of a DUPSORT /// table. fn walk_dup<'cursor>( &'cursor mut self, key: T::Key, subkey: T::SubKey, ) -> Result, Error> where Self: Sized; } /// Read write cursor over table. pub trait DbCursorRW<'tx, T: Table> { /// Database operation that will update an existing row if a specified value already /// exists in a table, and insert a new row if the specified value doesn't already exist fn upsert(&mut self, key: T::Key, value: T::Value) -> Result<(), Error>; /// Append value to next cursor item fn append(&mut self, key: T::Key, value: T::Value) -> Result<(), Error>; /// Delete current value that cursor points to fn delete_current(&mut self) -> Result<(), Error>; } /// Read Write Cursor over DupSorted table. pub trait DbDupCursorRW<'tx, T: DupSort> { /// Append value to next cursor item fn delete_current_duplicates(&mut self) -> Result<(), Error>; /// Append duplicate value fn append_dup(&mut self, key: T::Key, value: T::Value) -> Result<(), Error>; } /// Provides an iterator to `Cursor` when handling `Table`. pub struct Walker<'cursor, 'tx, T: Table, CURSOR: DbCursorRO<'tx, T> + Sized> { /// Cursor to be used to walk through the table. pub cursor: &'cursor mut CURSOR, /// `(key, value)` where to start the walk. pub start: IterPairResult, /// Phantom data for 'tx. pub _tx_phantom: PhantomData<&'tx 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>; fn next(&mut self) -> Option { let start = self.start.take(); if start.is_some() { return start } self.cursor.next().transpose() } } /// Provides an iterator to `Cursor` when handling a `DupSort` table. pub struct DupWalker<'cursor, 'tx, T: DupSort, CURSOR: DbDupCursorRO<'tx, T> + Sized> { /// Cursor to be used to walk through the table. pub cursor: &'cursor mut CURSOR, /// Value where to start the walk. pub start: Option>, /// Phantom data for 'tx. pub _tx_phantom: PhantomData<&'tx T>, } impl<'cursor, 'tx, T: DupSort, CURSOR: DbDupCursorRO<'tx, T> + Sized> std::iter::Iterator for DupWalker<'cursor, 'tx, T, CURSOR> { type Item = Result; fn next(&mut self) -> Option { let start = self.start.take(); if start.is_some() { return start } self.cursor.next_dup_val().transpose() } }