use sled::IVec;
use std::{marker::PhantomData, ops::RangeBounds};
use crate::{
encoding::Encoding,
error::{coerce, Result},
};
#[derive(Clone)]
pub struct StructuredTree<V, E>(sled::Tree, String, PhantomData<V>, PhantomData<E>);
pub struct StructuredIter<V, E>(sled::Iter, PhantomData<V>, PhantomData<E>);
#[derive(Clone, Debug, Default)]
pub struct StructuredBatch<V, E>(sled::Batch, PhantomData<V>, PhantomData<E>);
#[derive(Clone)]
pub struct StructuredTransactionalTree<'a, V, E>(
&'a sled::TransactionalTree,
PhantomData<V>,
PhantomData<E>,
);
impl<V, E> StructuredTree<V, E>
where
E: Encoding<V> + 'static,
{
pub(crate) fn new(db: &sled::Db, name: &str) -> Result<Self> {
Ok(StructuredTree(
db.open_tree(name)?,
name.to_owned(),
PhantomData,
PhantomData,
))
}
pub fn cloned(&self) -> Self {
StructuredTree(self.0.clone(), self.1.clone(), PhantomData, PhantomData)
}
pub fn transaction<F, R>(&self, f: F) -> sled::TransactionResult<Result<R>>
where
F: Fn(StructuredTransactionalTree<V, E>) -> sled::TransactionResult<Result<R>>,
{
self.0.transaction(move |trans_tree| {
(f)(StructuredTransactionalTree(
trans_tree,
PhantomData,
PhantomData,
))
})
}
pub fn apply_batch(&self, batch: StructuredBatch<V, E>) -> Result<()> {
Ok(self.0.apply_batch(batch.0)?)
}
pub fn cas<K>(
&self,
key: K,
old: Option<V>,
new: Option<V>,
) -> Result<std::result::Result<(), Option<V>>>
where
K: AsRef<[u8]>,
{
let ov = coerce(old.map(|value| E::encode(&value)))?;
let nv = coerce(new.map(|value| E::encode(&value)))?;
match self.0.cas(key, ov, nv)? {
Ok(()) => Ok(Ok(())),
Err(None) => Ok(Err(None)),
Err(Some(v)) => Ok(Err(Some(E::decode(&v)?))),
}
}
pub fn get<K>(&self, key: K) -> Result<Option<V>>
where
K: AsRef<[u8]>,
{
let opt = self.0.get(key)?;
if let Some(v) = opt {
Ok(Some(E::decode(&v)?))
} else {
Ok(None)
}
}
pub fn insert<K>(&self, key: K, value: V) -> Result<Option<V>>
where
IVec: From<K>,
K: AsRef<[u8]>,
{
let v = E::encode(&value)?;
let opt = self.0.insert::<K, Vec<u8>>(key, v)?;
if let Some(v) = opt {
Ok(Some(E::decode(&v)?))
} else {
Ok(None)
}
}
pub fn remove<K>(&self, key: K) -> Result<Option<V>>
where
K: AsRef<[u8]>,
{
let opt = self.0.remove(key)?;
if let Some(v) = opt {
Ok(Some(E::decode(&v)?))
} else {
Ok(None)
}
}
pub fn update_and_fetch<K>(
&self,
key: K,
f: impl Fn(Option<V>) -> Option<V>,
) -> Result<Option<V>>
where
K: AsRef<[u8]>,
{
let opt = self.0.update_and_fetch(key, |opt| {
let o = opt.and_then(|v| E::decode(&v).ok());
(f)(o).and_then(|value| E::encode(&value).ok())
})?;
if let Some(v) = opt {
Ok(Some(E::decode(&v)?))
} else {
Ok(None)
}
}
pub fn fetch_and_update<K>(
&self,
key: K,
f: impl Fn(Option<V>) -> Option<V>,
) -> Result<Option<V>>
where
K: AsRef<[u8]>,
{
let opt = self.0.fetch_and_update(key, |opt| {
let o = opt.and_then(|v| E::decode(&v).ok());
(f)(o).and_then(|value| E::encode(&value).ok())
})?;
if let Some(v) = opt {
Ok(Some(E::decode(&v)?))
} else {
Ok(None)
}
}
pub fn watch_prefix(&self, prefix: Vec<u8>) -> sled::Subscriber {
self.0.watch_prefix(prefix)
}
pub fn flush(&self) -> Result<()> {
self.0.flush()?;
Ok(())
}
pub fn contains_key<K>(&self, key: K) -> Result<bool>
where
K: AsRef<[u8]>,
{
Ok(self.0.contains_key(key)?)
}
pub fn iter(&self) -> StructuredIter<V, E> {
StructuredIter::new(self.0.iter())
}
pub fn range<K, R>(&self, range: R) -> StructuredIter<V, E>
where
K: AsRef<[u8]>,
R: RangeBounds<K>,
{
StructuredIter::new(self.0.range(range))
}
pub fn get_lt<K>(&self, key: K) -> Result<Option<(IVec, V)>>
where
K: AsRef<[u8]>,
{
match self.0.get_lt(key)? {
Some((k, v)) => {
let value = E::decode(&v)?;
Ok(Some((k, value)))
}
None => Ok(None),
}
}
pub fn get_gt<K>(&self, key: K) -> Result<Option<(IVec, V)>>
where
K: AsRef<[u8]>,
{
match self.0.get_gt(key)? {
Some((k, v)) => {
let value = E::decode(&v)?;
Ok(Some((k, value)))
}
None => Ok(None),
}
}
pub fn scan_prefix<P>(&self, prefix: P) -> StructuredIter<V, E>
where
P: AsRef<[u8]>,
{
StructuredIter::new(self.0.scan_prefix(prefix))
}
pub fn pop_max(&self) -> Result<Option<(IVec, V)>> {
match self.0.pop_max()? {
Some((k, v)) => {
let value = E::decode(&v)?;
Ok(Some((k, value)))
}
None => Ok(None),
}
}
pub fn pop_min(&self) -> Result<Option<(IVec, V)>> {
match self.0.pop_min()? {
Some((k, v)) => {
let value = E::decode(&v)?;
Ok(Some((k, value)))
}
None => Ok(None),
}
}
pub fn len(&self) -> usize {
self.0.len()
}
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
pub fn clear(&self) -> Result<()> {
Ok(self.0.clear()?)
}
pub fn name(&self) -> String {
self.1.clone()
}
}
impl<V, E> StructuredIter<V, E>
where
E: Encoding<V> + 'static,
{
fn new(iter: sled::Iter) -> Self {
StructuredIter(iter, PhantomData, PhantomData)
}
pub fn keys(self) -> impl DoubleEndedIterator<Item = Result<IVec>> {
self.map(|res| res.map(|(key, _)| key))
}
pub fn values(self) -> impl DoubleEndedIterator<Item = Result<V>> {
self.map(|res| res.map(|(_, v)| v))
}
}
impl<V, E> StructuredBatch<V, E>
where
E: Encoding<V>,
{
pub fn insert<K>(&mut self, key: K, value: V) -> Result<()>
where
IVec: From<K>,
{
let v = E::encode(&value)?;
self.0.insert::<_, Vec<u8>>(key, v);
Ok(())
}
pub fn remove<K>(&mut self, key: K)
where
IVec: From<K>,
{
self.0.remove(key)
}
}
impl<'a, V, E> StructuredTransactionalTree<'a, V, E>
where
E: Encoding<V>,
{
pub fn insert<K>(&self, key: K, value: V) -> sled::TransactionResult<Result<Option<V>>>
where
IVec: From<K>,
K: AsRef<[u8]>,
{
let v = match E::encode(&value) {
Ok(v) => v,
Err(e) => return Ok(Err(e)),
};
let opt = self.0.insert::<_, Vec<_>>(key, v)?;
if let Some(v) = opt {
match E::decode(&v) {
Ok(i) => return Ok(Ok(Some(i))),
Err(e) => return Ok(Err(e)),
}
} else {
Ok(Ok(None))
}
}
pub fn remove<K>(&self, key: K) -> sled::TransactionResult<Result<Option<V>>>
where
IVec: From<K>,
K: AsRef<[u8]>,
{
let opt = self.0.remove(key)?;
if let Some(v) = opt {
match E::decode(&v) {
Ok(i) => return Ok(Ok(Some(i))),
Err(e) => return Ok(Err(e)),
}
} else {
Ok(Ok(None))
}
}
pub fn get<K>(&self, key: K) -> sled::TransactionResult<Result<Option<V>>>
where
K: AsRef<[u8]>,
{
let opt = self.0.get(key)?;
if let Some(v) = opt {
match E::decode(&v) {
Ok(i) => return Ok(Ok(Some(i))),
Err(e) => return Ok(Err(e)),
}
} else {
Ok(Ok(None))
}
}
pub fn apply_batch(&self, batch: StructuredBatch<V, E>) -> sled::TransactionResult<()> {
self.0.apply_batch(batch.0)
}
}
impl<V, E> Iterator for StructuredIter<V, E>
where
E: Encoding<V>,
{
type Item = Result<(IVec, V)>;
fn next(&mut self) -> Option<Self::Item> {
match self.0.next()? {
Ok((key, v)) => Some(E::decode(&v).map(move |value| (key, value))),
Err(e) => Some(Err(e.into())),
}
}
}
impl<V, E> DoubleEndedIterator for StructuredIter<V, E>
where
E: Encoding<V>,
{
fn next_back(&mut self) -> Option<<Self as Iterator>::Item> {
match self.0.next_back()? {
Ok((key, v)) => Some(E::decode(&v).map(move |value| (key, value))),
Err(e) => Some(Err(e.into())),
}
}
}