use crate::{
Error as StorageError,
Result as StorageResult,
};
use std::sync::Arc;
pub type Value = Arc<Vec<u8>>;
pub type KVItem = StorageResult<(Vec<u8>, Value)>;
pub trait StorageColumn: Copy + core::fmt::Debug {
fn name(&self) -> &'static str;
fn id(&self) -> u32;
fn as_usize(&self) -> usize {
self.id() as usize
}
}
#[impl_tools::autoimpl(for<T: trait> &T, &mut T, Box<T>, Arc<T>)]
pub trait KeyValueInspect {
type Column: StorageColumn;
fn exists(&self, key: &[u8], column: Self::Column) -> StorageResult<bool> {
Ok(self.size_of_value(key, column)?.is_some())
}
fn size_of_value(
&self,
key: &[u8],
column: Self::Column,
) -> StorageResult<Option<usize>> {
Ok(self.get(key, column)?.map(|value| value.len()))
}
fn get(&self, key: &[u8], column: Self::Column) -> StorageResult<Option<Value>>;
fn read(
&self,
key: &[u8],
column: Self::Column,
buf: &mut [u8],
) -> StorageResult<Option<usize>> {
self.get(key, column)?
.map(|value| {
let read = value.len();
if read != buf.len() {
return Err(StorageError::Other(anyhow::anyhow!(
"Buffer size is not equal to the value size"
)));
}
buf.copy_from_slice(value.as_ref());
Ok(read)
})
.transpose()
}
}
#[impl_tools::autoimpl(for<T: trait> &mut T, Box<T>)]
pub trait KeyValueMutate: KeyValueInspect {
fn put(
&mut self,
key: &[u8],
column: Self::Column,
value: Value,
) -> StorageResult<()> {
self.write(key, column, value.as_ref()).map(|_| ())
}
fn replace(
&mut self,
key: &[u8],
column: Self::Column,
value: Value,
) -> StorageResult<Option<Value>> {
let old_value = self.get(key, column)?;
self.put(key, column, value)?;
Ok(old_value)
}
fn write(
&mut self,
key: &[u8],
column: Self::Column,
buf: &[u8],
) -> StorageResult<usize>;
fn take(&mut self, key: &[u8], column: Self::Column) -> StorageResult<Option<Value>> {
let old_value = self.get(key, column)?;
self.delete(key, column)?;
Ok(old_value)
}
fn delete(&mut self, key: &[u8], column: Self::Column) -> StorageResult<()>;
}
#[derive(serde::Serialize, serde::Deserialize, Clone, Debug, PartialEq, Eq)]
pub enum WriteOperation {
Insert(Value),
Remove,
}
#[impl_tools::autoimpl(for<T: trait> &mut T, Box<T>)]
pub trait BatchOperations: KeyValueMutate {
fn batch_write<I>(&mut self, column: Self::Column, entries: I) -> StorageResult<()>
where
I: Iterator<Item = (Vec<u8>, WriteOperation)>;
}