pub mod sled_adapter; #[cfg(test)] pub mod test; use core::ops::{Bound, RangeBounds}; use std::borrow::Cow; use std::sync::Arc; use arc_swap::ArcSwapOption; use err_derive::Error; #[derive(Clone)] pub struct Db(pub(crate) Arc); #[derive(Clone, Copy)] pub struct Transaction<'a>(pub(crate) &'a dyn ITx<'a>); #[derive(Clone)] pub struct Tree(pub(crate) Arc, pub(crate) usize); pub type Value<'a> = Cow<'a, [u8]>; pub type ValueIter<'a> = Box, Value<'a>)>> + Send + Sync + 'a>; pub type Exporter<'a> = Box)>> + Send + Sync + 'a>; // ---- #[derive(Debug, Error)] #[error(display = "{}", _0)] pub struct Error(Cow<'static, str>); pub type Result = std::result::Result; #[derive(Debug)] pub enum TxError { Abort(E), Db(Error), } pub type TxResult = std::result::Result>; impl From for TxError { fn from(e: Error) -> TxError { TxError::Db(e) } } // ---- impl Db { pub fn open_tree>(&self, name: S) -> Result { let tree_id = self.0.open_tree(name.as_ref())?; Ok(Tree(self.0.clone(), tree_id)) } pub fn transaction(&self, fun: F) -> TxResult where F: Fn(Transaction<'_>) -> TxResult, R: Send + Sync, E: Send + Sync, { let f = TxFn { function: fun, result: ArcSwapOption::new(None), }; match self.0.transaction(&f) { Err(TxError::Db(e)) => Err(TxError::Db(e)), Err(TxError::Abort(())) => { let r_arc = f .result .into_inner() .expect("Transaction did not store result"); let r = Arc::try_unwrap(r_arc).ok().expect("Many refs"); assert!(matches!(r, Err(TxError::Abort(_)))); r } Ok(()) => { let r_arc = f .result .into_inner() .expect("Transaction did not store result"); let r = Arc::try_unwrap(r_arc).ok().expect("Many refs"); assert!(matches!(r, Ok(_))); r } } } } impl Tree { pub fn db(&self) -> Db { Db(self.0.clone()) } pub fn get<'a, T: AsRef<[u8]>>(&'a self, key: T) -> Result>> { self.0.get(self.1, key.as_ref()) } pub fn len(&self) -> Result { self.0.len(self.1) } pub fn insert, U: AsRef<[u8]>>(&self, key: T, value: U) -> Result<()> { self.0.insert(self.1, key.as_ref(), value.as_ref()) } pub fn remove<'a, T: AsRef<[u8]>>(&'a self, key: T) -> Result { self.0.remove(self.1, key.as_ref()) } pub fn iter<'a>(&'a self) -> Result> { self.0.iter(self.1) } pub fn iter_rev<'a>(&'a self) -> Result> { self.0.iter_rev(self.1) } pub fn range<'a, K, R>(&'a self, range: R) -> Result> where K: AsRef<[u8]>, R: RangeBounds, { let sb = range.start_bound(); let eb = range.end_bound(); self.0.range(self.1, get_bound(sb), get_bound(eb)) } pub fn range_rev<'a, K, R>(&'a self, range: R) -> Result> where K: AsRef<[u8]>, R: RangeBounds, { let sb = range.start_bound(); let eb = range.end_bound(); self.0.range_rev(self.1, get_bound(sb), get_bound(eb)) } } impl<'a> Transaction<'a> { pub fn get>(&self, tree: &Tree, key: T) -> Result>> { self.0.get(tree.1, key.as_ref()) } pub fn len(&self, tree: &Tree) -> Result { self.0.len(tree.1) } pub fn insert, U: AsRef<[u8]>>( &self, tree: &Tree, key: T, value: U, ) -> Result<()> { self.0.insert(tree.1, key.as_ref(), value.as_ref()) } pub fn remove>(&self, tree: &Tree, key: T) -> Result { self.0.remove(tree.1, key.as_ref()) } pub fn iter(&self, tree: &Tree) -> Result> { self.0.iter(tree.1) } pub fn iter_rev(&self, tree: &Tree) -> Result> { self.0.iter_rev(tree.1) } pub fn range(&self, tree: &Tree, range: R) -> Result> where K: AsRef<[u8]>, R: RangeBounds, { let sb = range.start_bound(); let eb = range.end_bound(); self.0.range(tree.1, get_bound(sb), get_bound(eb)) } pub fn range_rev(&self, tree: &Tree, range: R) -> Result> where K: AsRef<[u8]>, R: RangeBounds, { let sb = range.start_bound(); let eb = range.end_bound(); self.0.range_rev(tree.1, get_bound(sb), get_bound(eb)) } // ---- #[must_use] pub fn abort(self, e: E) -> TxResult where R: Send + Sync, E: Send + Sync, { Err(TxError::Abort(e)) } #[must_use] pub fn commit(self, r: R) -> TxResult where R: Send + Sync, E: Send + Sync, { Ok(r) } } // ---- Internal interfaces pub(crate) trait IDb: Send + Sync { fn open_tree(&self, name: &str) -> Result; fn get<'a>(&'a self, tree: usize, key: &[u8]) -> Result>>; fn len(&self, tree: usize) -> Result; fn insert(&self, tree: usize, key: &[u8], value: &[u8]) -> Result<()>; fn remove(&self, tree: usize, key: &[u8]) -> Result; fn iter<'a>(&'a self, tree: usize) -> Result>; fn iter_rev<'a>(&'a self, tree: usize) -> Result>; fn range<'a, 'r>( &'a self, tree: usize, low: Bound<&'r [u8]>, high: Bound<&'r [u8]>, ) -> Result>; fn range_rev<'a, 'r>( &'a self, tree: usize, low: Bound<&'r [u8]>, high: Bound<&'r [u8]>, ) -> Result>; fn transaction(&self, f: &dyn ITxFn) -> TxResult<(), ()>; } pub(crate) trait ITx<'a> { fn get(&self, tree: usize, key: &[u8]) -> Result>>; fn len(&self, tree: usize) -> Result; fn insert(&self, tree: usize, key: &[u8], value: &[u8]) -> Result<()>; fn remove(&self, tree: usize, key: &[u8]) -> Result; fn iter(&self, tree: usize) -> Result>; fn iter_rev(&self, tree: usize) -> Result>; fn range<'r>( &self, tree: usize, low: Bound<&'r [u8]>, high: Bound<&'r [u8]>, ) -> Result>; fn range_rev<'r>( &self, tree: usize, low: Bound<&'r [u8]>, high: Bound<&'r [u8]>, ) -> Result>; } pub(crate) trait ITxFn { fn try_on<'a>(&'a self, tx: &'a dyn ITx<'a>) -> TxFnResult; } enum TxFnResult { Abort, Ok, Err, } struct TxFn where F: Fn(Transaction<'_>) -> TxResult, R: Send + Sync, E: Send + Sync, { function: F, result: ArcSwapOption>, } impl ITxFn for TxFn where F: Fn(Transaction<'_>) -> TxResult, R: Send + Sync, E: Send + Sync, { fn try_on<'a>(&'a self, tx: &'a dyn ITx<'a>) -> TxFnResult { let res = (self.function)(Transaction(tx)); let retval = match &res { Ok(_) => TxFnResult::Ok, Err(TxError::Abort(_)) => TxFnResult::Abort, Err(TxError::Db(_)) => TxFnResult::Err, }; self.result.store(Some(Arc::new(res))); retval } } // ---- fn get_bound>(b: Bound<&K>) -> Bound<&[u8]> { match b { Bound::Included(v) => Bound::Included(v.as_ref()), Bound::Excluded(v) => Bound::Excluded(v.as_ref()), Bound::Unbounded => Bound::Unbounded, } }