use std::{
borrow::Borrow,
ops::{Bound, RangeBounds},
sync::Arc,
};
use crate::{
basic::persistent_btree::RootLease,
common::{
ende::{KeyEnDeOrdered, OrderedKeyRef, ValueEnDe},
error::Result,
},
};
use super::{BranchId, CommitId, map::VerMap};
pub struct Snapshot<'a, K, V> {
map: &'a VerMap<K, V>,
lease: Arc<RootLease>,
}
struct PinnedIter<I> {
inner: I,
_lease: Arc<RootLease>,
}
impl<I: Iterator> Iterator for PinnedIter<I> {
type Item = I::Item;
fn next(&mut self) -> Option<Self::Item> {
self.inner.next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
}
impl<'a, K, V> Snapshot<'a, K, V>
where
K: KeyEnDeOrdered,
V: ValueEnDe,
{
pub fn get<Q>(&self, key: &Q) -> Option<V>
where
K: Borrow<Q>,
Q: OrderedKeyRef + ?Sized,
{
self.map
.tree
.get(self.lease.root, &key.ordered_key_bytes())
.map(|v| V::decode(&v).unwrap())
}
pub fn contains_key<Q>(&self, key: &Q) -> bool
where
K: Borrow<Q>,
Q: OrderedKeyRef + ?Sized,
{
self.map
.tree
.contains_key(self.lease.root, &key.ordered_key_bytes())
}
pub fn iter(&self) -> impl Iterator<Item = (K, V)> + use<'a, K, V> {
PinnedIter {
inner: self.map.tree.iter(self.lease.root),
_lease: Arc::clone(&self.lease),
}
.map(decode_entry)
}
pub fn range<R: RangeBounds<K>>(
&self,
range: R,
) -> impl Iterator<Item = (K, V)> + use<'a, K, V, R> {
let lo = encode_bound(range.start_bound());
let hi = encode_bound(range.end_bound());
PinnedIter {
inner: self
.map
.tree
.range(self.lease.root, as_slice(&lo), as_slice(&hi)),
_lease: Arc::clone(&self.lease),
}
.map(decode_entry)
}
pub fn raw_iter(&self) -> impl Iterator<Item = (Vec<u8>, Vec<u8>)> + use<'a, K, V> {
PinnedIter {
inner: self.map.tree.iter(self.lease.root),
_lease: Arc::clone(&self.lease),
}
}
}
impl<K, V> VerMap<K, V>
where
K: KeyEnDeOrdered,
V: ValueEnDe,
{
pub fn at(&self, commit: CommitId) -> Result<Snapshot<'_, K, V>> {
let lease = self
.tree
.lease_root(|| Ok(self.get_commit_inner(commit)?.root))?;
Ok(Snapshot { map: self, lease })
}
pub fn snapshot(&self, branch: BranchId) -> Result<Snapshot<'_, K, V>> {
let lease = self
.tree
.lease_root(|| Ok(self.get_branch(branch)?.dirty_root))?;
Ok(Snapshot { map: self, lease })
}
pub fn get<Q>(&self, branch: BranchId, key: &Q) -> Result<Option<V>>
where
K: Borrow<Q>,
Q: OrderedKeyRef + ?Sized,
{
Ok(self.snapshot(branch)?.get(key))
}
pub fn contains_key<Q>(&self, branch: BranchId, key: &Q) -> Result<bool>
where
K: Borrow<Q>,
Q: OrderedKeyRef + ?Sized,
{
Ok(self.snapshot(branch)?.contains_key(key))
}
pub fn iter(&self, branch: BranchId) -> Result<impl Iterator<Item = (K, V)> + '_> {
Ok(self.snapshot(branch)?.iter())
}
pub fn range<R: RangeBounds<K>>(
&self,
branch: BranchId,
range: R,
) -> Result<impl Iterator<Item = (K, V)> + use<'_, K, V, R>> {
Ok(self.snapshot(branch)?.range(range))
}
}
fn decode_entry<K: KeyEnDeOrdered, V: ValueEnDe>((k, v): (Vec<u8>, Vec<u8>)) -> (K, V) {
(K::from_slice(&k).unwrap(), V::decode(&v).unwrap())
}
fn encode_bound<K: KeyEnDeOrdered>(b: Bound<&K>) -> Bound<Vec<u8>> {
match b {
Bound::Included(k) => Bound::Included(k.to_bytes()),
Bound::Excluded(k) => Bound::Excluded(k.to_bytes()),
Bound::Unbounded => Bound::Unbounded,
}
}
fn as_slice(b: &Bound<Vec<u8>>) -> Bound<&[u8]> {
b.as_ref().map(Vec::as_slice)
}