use core::{
borrow::Borrow,
ops::{Bound, RangeBounds},
};
use dbutils::equivalent::Comparable;
use either::Either;
use iter::*;
use ref_cast::RefCast;
use skl::{among::Among, error::Error, KeyBuilder, VacantBuffer, ValueBuilder};
use super::{generic::Memtable as GenericMemtable, sealed::Constructable};
mod entry;
pub mod iter;
pub use dbutils::{
equivalentor::{Ascend, Descend, StaticComparator, StaticEquivalentor, StaticRangeComparator},
types::SliceRef,
};
pub use entry::*;
use sealed::Key;
mod sealed {
use core::marker::PhantomData;
use super::{StaticComparator, StaticEquivalentor};
use dbutils::{
buffer::VacantBuffer,
equivalent::{Comparable, Equivalent},
types::{SliceRef, Type},
};
#[derive(ref_cast::RefCast)]
#[repr(transparent)]
#[doc(hidden)]
pub struct Key<C: ?Sized> {
_marker: PhantomData<C>,
data: [u8],
}
impl<C: ?Sized> core::fmt::Debug for Key<C> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
core::fmt::Debug::fmt(&self.data, f)
}
}
impl<C> PartialEq for Key<C>
where
C: StaticEquivalentor + ?Sized,
{
#[inline]
fn eq(&self, other: &Self) -> bool {
C::equivalent(&self.data, &other.data)
}
}
impl<C: ?Sized> Eq for Key<C> where C: StaticComparator {}
impl<C> PartialOrd for Key<C>
where
C: StaticComparator + ?Sized,
{
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl<C> Ord for Key<C>
where
C: StaticComparator + ?Sized,
{
#[inline]
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
C::compare(&self.data, &other.data)
}
}
impl<C: ?Sized> Type for Key<C> {
type Ref<'a> = <[u8] as Type>::Ref<'a>;
type Error = <[u8] as Type>::Error;
#[inline]
fn encoded_len(&self) -> usize {
<[u8] as Type>::encoded_len(&self.data)
}
#[inline]
fn encode_to_buffer(&self, buf: &mut VacantBuffer<'_>) -> Result<usize, Self::Error> {
<[u8] as Type>::encode_to_buffer(&self.data, buf)
}
}
impl<C> Equivalent<Key<C>> for SliceRef<'_>
where
C: ?Sized + StaticEquivalentor,
{
#[inline]
fn equivalent(&self, other: &Key<C>) -> bool {
C::equivalent(self, &other.data)
}
}
impl<C> Comparable<Key<C>> for SliceRef<'_>
where
C: ?Sized + StaticComparator,
{
#[inline]
fn compare(&self, other: &Key<C>) -> core::cmp::Ordering {
C::compare(self, &other.data)
}
}
}
pub struct Memtable<C: ?Sized = Ascend>(GenericMemtable<Key<C>, [u8]>);
impl<C: ?Sized> Clone for Memtable<C> {
#[inline]
fn clone(&self) -> Self {
Self(self.0.clone())
}
}
impl<C> Constructable for Memtable<C>
where
C: ?Sized + 'static,
{
#[inline]
fn construct(opts: super::Options) -> Result<Self, super::Error> {
GenericMemtable::construct(opts).map(Self)
}
#[cfg(all(feature = "memmap", not(target_family = "wasm")))]
fn map_anon(opts: super::Options) -> std::io::Result<Self> {
GenericMemtable::map_anon(opts).map(Self)
}
}
impl<C> Memtable<C>
where
C: ?Sized + 'static,
{
#[inline]
pub fn maximum_version(&self) -> u64 {
self.0.maximum_version()
}
#[inline]
pub fn minimum_version(&self) -> u64 {
self.0.minimum_version()
}
#[inline]
pub fn reserved_slice(&self) -> &[u8] {
self.0.reserved_slice()
}
#[allow(clippy::mut_from_ref)]
#[inline]
pub unsafe fn reserved_slice_mut(&self) -> &mut [u8] {
self.0.reserved_slice_mut()
}
}
impl<C> Memtable<C>
where
C: StaticComparator + ?Sized + 'static,
{
pub fn contains_key<'a, Q>(&'a self, version: u64, k: &Q) -> bool
where
Q: ?Sized + Comparable<SliceRef<'a>>,
{
self.0.contains_key(version, k)
}
#[inline]
pub fn get<'a, Q>(&'a self, version: u64, k: &Q) -> Option<Entry<'a, C>>
where
Q: ?Sized + Comparable<SliceRef<'a>>,
{
self.0.get(version, k)
}
#[inline]
pub fn first(&self, version: u64) -> Option<Entry<'_, C>> {
self.iter(version).next()
}
#[inline]
pub fn last(&self, version: u64) -> Option<Entry<'_, C>> {
self.iter(version).next_back()
}
#[inline]
pub fn upper_bound<'a, Q>(&'a self, version: u64, key: Bound<&Q>) -> Option<Entry<'a, C>>
where
Q: ?Sized + Comparable<SliceRef<'a>>,
{
self
.range::<Q, _>(version, (Bound::Unbounded, key))
.next_back()
}
#[inline]
pub fn lower_bound<'a, Q>(&'a self, version: u64, key: Bound<&Q>) -> Option<Entry<'a, C>>
where
Q: ?Sized + Comparable<SliceRef<'a>>,
{
self.range::<Q, _>(version, (key, Bound::Unbounded)).next()
}
#[inline]
pub fn iter(&self, version: u64) -> Iter<'_, C> {
self.0.iter(version)
}
#[inline]
pub fn iter_points(&self, version: u64) -> PointIter<'_, C> {
self.0.iter_points(version)
}
#[inline]
pub fn iter_points_all_versions(&self, version: u64) -> IterAllPoints<'_, C> {
self.0.iter_points_all_versions(version)
}
#[inline]
pub fn iter_bulk_deletions(&self, version: u64) -> BulkDeletionIter<'_, C> {
self.0.iter_bulk_deletions(version)
}
#[inline]
pub fn iter_bulk_deletions_all_versions(&self, version: u64) -> BulkDeletionIterAll<'_, C> {
self.0.iter_bulk_deletions_all_versions(version)
}
#[inline]
pub fn iter_bulk_updates(&self, version: u64) -> BulkUpdateIter<'_, C> {
self.0.iter_bulk_updates(version)
}
#[inline]
pub fn iter_bulk_updates_all_versions(&self, version: u64) -> BulkUpdateIterAll<'_, C> {
self.0.iter_bulk_updates_all_versions(version)
}
#[inline]
pub fn range<'a, Q, R>(&'a self, version: u64, r: R) -> Range<'a, C, Q, R>
where
R: RangeBounds<Q>,
Q: ?Sized + Comparable<SliceRef<'a>>,
{
self.0.range(version, r)
}
#[inline]
pub fn range_points<'a, Q, R>(&'a self, version: u64, r: R) -> PointRange<'a, C, Q, R>
where
R: RangeBounds<Q>,
Q: ?Sized + Comparable<SliceRef<'a>>,
{
self.0.range_points(version, r)
}
#[inline]
pub fn range_all_points<'a, Q, R>(&'a self, version: u64, r: R) -> RangeAllPoints<'a, C, Q, R>
where
R: RangeBounds<Q>,
Q: ?Sized + Comparable<SliceRef<'a>>,
{
self.0.range_all_points(version, r)
}
#[inline]
pub fn range_bulk_deletions<'a, Q, R>(
&'a self,
version: u64,
r: R,
) -> BulkDeletionRange<'a, C, Q, R>
where
R: RangeBounds<Q>,
Q: ?Sized + Comparable<SliceRef<'a>>,
{
self.0.range_bulk_deletions(version, r)
}
#[inline]
pub fn range_bulk_deletions_all_versions<'a, Q, R>(
&'a self,
version: u64,
r: R,
) -> BulkDeletionRangeAll<'a, C, Q, R>
where
R: RangeBounds<Q>,
Q: ?Sized + Comparable<SliceRef<'a>>,
{
self.0.range_bulk_deletions_all_versions(version, r)
}
#[inline]
pub fn range_bulk_updates<'a, Q, R>(&'a self, version: u64, r: R) -> BulkUpdateRange<'a, C, Q, R>
where
R: RangeBounds<Q>,
Q: ?Sized + Comparable<SliceRef<'a>>,
{
self.0.range_bulk_updates(version, r)
}
#[inline]
pub fn range_bulk_updates_all_versions<'a, Q, R>(
&'a self,
version: u64,
r: R,
) -> BulkUpdateRangeAll<'a, C, Q, R>
where
R: RangeBounds<Q>,
Q: ?Sized + Comparable<SliceRef<'a>>,
{
self.0.range_bulk_updates_all_versions(version, r)
}
#[inline]
pub fn insert(&self, version: u64, key: &[u8], value: &[u8]) -> Result<(), Error> {
self
.0
.insert(version, Key::ref_cast(key), value)
.map_err(Among::unwrap_right)
}
pub fn insert_with_value_builder<'a, E>(
&'a self,
version: u64,
key: &'a [u8],
value_builder: ValueBuilder<impl FnOnce(&mut VacantBuffer<'a>) -> Result<usize, E>>,
) -> Result<(), Either<E, Error>> {
self
.0
.insert_with_value_builder(version, Key::ref_cast(key), value_builder)
.map(|_| ())
.map_err(Among::into_middle_right)
}
#[allow(single_use_lifetimes)]
pub fn insert_with_builders<'a, KE, VE>(
&'a self,
version: u64,
key_builder: KeyBuilder<impl FnOnce(&mut VacantBuffer<'a>) -> Result<usize, KE>>,
value_builder: ValueBuilder<impl FnOnce(&mut VacantBuffer<'a>) -> Result<usize, VE>>,
) -> Result<(), Among<KE, VE, Error>> {
self
.0
.insert_with_builders(version, key_builder, value_builder)
.map(|_| ())
}
pub fn remove<'a>(&'a self, version: u64, key: &'a [u8]) -> Result<(), Error> {
self
.0
.remove(version, Key::ref_cast(key))
.map_err(Either::unwrap_right)
}
#[inline]
pub fn remove_with_builder<'a, E>(
&'a self,
version: u64,
key_builder: KeyBuilder<impl FnOnce(&mut VacantBuffer<'a>) -> Result<usize, E>>,
) -> Result<(), Either<E, Error>> {
self.0.remove_with_builder(version, key_builder)
}
pub fn remove_range<Q, R>(&self, version: u64, range: R) -> Result<(), Error>
where
R: RangeBounds<Q>,
Q: ?Sized + Borrow<[u8]>,
{
let s = range.start_bound().map(|b| Key::<C>::ref_cast(b.borrow()));
let e = range.end_bound().map(|b| Key::<C>::ref_cast(b.borrow()));
self
.0
.remove_range::<Key<C>, _>(version, (s, e))
.map_err(Either::unwrap_right)
}
pub fn update_range<Q, R>(&self, version: u64, range: R, value: &[u8]) -> Result<(), Error>
where
R: RangeBounds<Q>,
Q: ?Sized + Borrow<[u8]>,
{
let s = range.start_bound().map(|b| Key::<C>::ref_cast(b.borrow()));
let e = range.end_bound().map(|b| Key::<C>::ref_cast(b.borrow()));
self
.0
.update_range::<Key<C>, _>(version, (s, e), value)
.map_err(Among::unwrap_right)
}
}