use std::{
iter,
ops::{Deref, DerefMut},
};
use anyhow::{Error, Result};
use crate::common::{crypto::hash::Hash, namespace::Namespace};
use self::sync::Proof;
#[macro_use]
mod tree;
mod cache;
#[cfg(test)]
pub mod interop;
pub mod marshal;
pub mod sync;
#[cfg(test)]
mod tests;
pub use tree::{Depth, Key, NodeBox, NodePointer, NodePtrRef, OverlayTree, Root, RootType, Tree};
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum LogEntryKind {
Insert,
Delete,
}
#[derive(Clone, Debug, Default, Eq, PartialEq, Hash, cbor::Encode, cbor::Decode)]
#[cbor(as_array)]
pub struct LogEntry {
pub key: Vec<u8>,
pub value: Option<Vec<u8>>,
}
impl LogEntry {
pub fn new(key: &[u8], value: &[u8]) -> Self {
Self {
key: key.to_owned(),
value: Some(value.to_owned()),
}
}
pub fn kind(&self) -> LogEntryKind {
match self.value {
Some(_) => LogEntryKind::Insert,
None => LogEntryKind::Delete,
}
}
}
pub type WriteLog = Vec<LogEntry>;
#[derive(Clone, Debug, Default, Eq, PartialEq, PartialOrd, Ord, cbor::Encode, cbor::Decode)]
#[cbor(transparent)]
pub struct Prefix(Vec<u8>);
impl AsRef<[u8]> for Prefix {
fn as_ref(&self) -> &[u8] {
&self.0
}
}
impl Deref for Prefix {
type Target = Vec<u8>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for Prefix {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl From<Prefix> for Vec<u8> {
fn from(val: Prefix) -> Self {
val.0
}
}
impl From<Vec<u8>> for Prefix {
fn from(v: Vec<u8>) -> Prefix {
Prefix(v)
}
}
pub trait MKVS {
fn get(&self, key: &[u8]) -> Option<Vec<u8>>;
fn get_proof(&self, key: &[u8]) -> Option<Proof>;
fn cache_contains_key(&self, key: &[u8]) -> bool;
fn insert(&mut self, key: &[u8], value: &[u8]) -> Option<Vec<u8>>;
fn remove(&mut self, key: &[u8]) -> Option<Vec<u8>>;
fn prefetch_prefixes(&self, prefixes: &[Prefix], limit: u16);
fn iter(&self) -> Box<dyn Iterator + '_>;
fn commit(&mut self, namespace: Namespace, version: u64) -> Result<(WriteLog, Hash)>;
}
pub trait FallibleMKVS {
fn get(&self, key: &[u8]) -> Result<Option<Vec<u8>>>;
fn get_proof(&self, key: &[u8]) -> Result<Option<Proof>>;
fn cache_contains_key(&self, key: &[u8]) -> bool;
fn insert(&mut self, key: &[u8], value: &[u8]) -> Result<Option<Vec<u8>>>;
fn remove(&mut self, key: &[u8]) -> Result<Option<Vec<u8>>>;
fn prefetch_prefixes(&self, prefixes: &[Prefix], limit: u16) -> Result<()>;
fn iter(&self) -> Box<dyn Iterator + '_>;
fn commit(&mut self, namespace: Namespace, version: u64) -> Result<Hash>;
}
pub trait ImmutableMKVS {
fn get(&self, key: &[u8]) -> Result<Option<Vec<u8>>>;
fn get_proof(&self, key: &[u8]) -> Result<Option<Proof>>;
fn prefetch_prefixes(&self, prefixes: &[Prefix], limit: u16) -> Result<()>;
fn iter(&self) -> Box<dyn Iterator + '_>;
}
impl<T> ImmutableMKVS for T
where
T: FallibleMKVS,
{
fn get(&self, key: &[u8]) -> Result<Option<Vec<u8>>> {
T::get(self, key)
}
fn get_proof(&self, key: &[u8]) -> Result<Option<Proof>> {
T::get_proof(self, key)
}
fn prefetch_prefixes(&self, prefixes: &[Prefix], limit: u16) -> Result<()> {
T::prefetch_prefixes(self, prefixes, limit)
}
fn iter(&self) -> Box<dyn Iterator + '_> {
T::iter(self)
}
}
pub trait Iterator: iter::Iterator<Item = (Vec<u8>, Vec<u8>)> {
fn set_prefetch(&mut self, prefetch: usize);
fn is_valid(&self) -> bool;
fn error(&self) -> &Option<Error>;
fn rewind(&mut self);
fn seek(&mut self, key: &[u8]);
fn get_key(&self) -> &Option<Key>;
fn get_value(&self) -> &Option<Vec<u8>>;
fn next(&mut self);
}
impl<T: MKVS + ?Sized> MKVS for &mut T {
fn get(&self, key: &[u8]) -> Option<Vec<u8>> {
T::get(self, key)
}
fn get_proof(&self, key: &[u8]) -> Option<Proof> {
T::get_proof(self, key)
}
fn cache_contains_key(&self, key: &[u8]) -> bool {
T::cache_contains_key(self, key)
}
fn insert(&mut self, key: &[u8], value: &[u8]) -> Option<Vec<u8>> {
T::insert(self, key, value)
}
fn remove(&mut self, key: &[u8]) -> Option<Vec<u8>> {
T::remove(self, key)
}
fn prefetch_prefixes(&self, prefixes: &[Prefix], limit: u16) {
T::prefetch_prefixes(self, prefixes, limit)
}
fn iter(&self) -> Box<dyn Iterator + '_> {
T::iter(self)
}
fn commit(&mut self, namespace: Namespace, version: u64) -> Result<(WriteLog, Hash)> {
T::commit(self, namespace, version)
}
}
impl<T: FallibleMKVS + ?Sized> FallibleMKVS for &mut T {
fn get(&self, key: &[u8]) -> Result<Option<Vec<u8>>> {
T::get(self, key)
}
fn get_proof(&self, key: &[u8]) -> Result<Option<Proof>> {
T::get_proof(self, key)
}
fn cache_contains_key(&self, key: &[u8]) -> bool {
T::cache_contains_key(self, key)
}
fn insert(&mut self, key: &[u8], value: &[u8]) -> Result<Option<Vec<u8>>> {
T::insert(self, key, value)
}
fn remove(&mut self, key: &[u8]) -> Result<Option<Vec<u8>>> {
T::remove(self, key)
}
fn prefetch_prefixes(&self, prefixes: &[Prefix], limit: u16) -> Result<()> {
T::prefetch_prefixes(self, prefixes, limit)
}
fn iter(&self) -> Box<dyn Iterator + '_> {
T::iter(self)
}
fn commit(&mut self, namespace: Namespace, version: u64) -> Result<Hash> {
T::commit(self, namespace, version)
}
}
#[cfg(test)]
mod _tests {
use super::*;
#[test]
fn test_write_log_serialization() {
let write_log = vec![LogEntry {
key: b"foo".to_vec(),
value: Some(b"bar".to_vec()),
}];
let raw = cbor::to_vec(write_log.clone());
let deserialized: WriteLog = cbor::from_slice(&raw).unwrap();
assert_eq!(write_log, deserialized);
}
}