#[cfg(feature = "macros")]
pub use ::leveldb_orm_derive::LeveldbOrm;
use leveldb::database::batch::Writebatch;
use leveldb::database::Database;
use leveldb::kv::KV;
use leveldb::options::ReadOptions;
use serde::de::DeserializeOwned;
use serde::Serialize;
use std::marker::PhantomData;
pub type Result<T> = std::result::Result<T, Box<dyn std::error::Error + Send + Sync + 'static>>;
#[derive(Debug, PartialEq)]
pub struct EncodedKey<T: 'static> {
pub inner: Vec<u8>,
phantom: PhantomData<T>,
}
impl<T> db_key::Key for EncodedKey<T> {
#[inline]
fn from_u8(key: &[u8]) -> Self {
EncodedKey {
inner: key.into(),
phantom: PhantomData,
}
}
#[inline]
fn as_slice<S, F: Fn(&[u8]) -> S>(&self, f: F) -> S {
f(&self.inner)
}
}
impl<T> From<Vec<u8>> for EncodedKey<T> {
#[inline]
fn from(inner: Vec<u8>) -> Self {
EncodedKey {
inner,
phantom: PhantomData,
}
}
}
impl<T> From<&[u8]> for EncodedKey<T> {
#[inline]
fn from(v: &[u8]) -> Self {
EncodedKey {
inner: v.into(),
phantom: PhantomData,
}
}
}
pub trait KeyOrm<'a>: Sized {
type KeyType: DeserializeOwned;
type KeyTypeRef: Serialize + 'a;
#[cfg(not(feature = "macros"))]
fn encode_key(key: Self::KeyTypeRef) -> Result<EncodedKey<Self>>;
#[cfg(feature = "macros")]
#[inline]
fn encode_key(key: Self::KeyTypeRef) -> Result<EncodedKey<Self>> {
bincode::serialize(&key)
.map(EncodedKey::from)
.map_err(|e| e.into())
}
#[cfg(not(feature = "macros"))]
fn decode_key(data: &EncodedKey<Self>) -> Result<Self::KeyType>;
#[cfg(feature = "macros")]
#[inline]
fn decode_key(data: &EncodedKey<Self>) -> Result<Self::KeyType> {
bincode::deserialize(&data.inner).map_err(|e| e.into())
}
fn key(&self) -> Result<EncodedKey<Self>>;
}
pub trait KVOrm<'a>: KeyOrm<'a> + Serialize + DeserializeOwned {
#[inline]
fn encode(&self) -> Result<Vec<u8>> {
bincode::serialize(self).map_err(|e| e.into())
}
#[inline]
fn decode(data: &[u8]) -> Result<Self> {
bincode::deserialize(data).map_err(|e| e.into())
}
fn put_sync(&self, db: &Database<EncodedKey<Self>>, sync: bool) -> Result<()> {
let key = self.key()?;
let value = self.encode()?;
db.put(leveldb::options::WriteOptions { sync }, key, &value)
.map_err(|e| e.into())
}
fn put(&self, db: &Database<EncodedKey<Self>>) -> Result<()> {
self.put_sync(db, false)
}
fn get_with_option(
db: &Database<EncodedKey<Self>>,
options: ReadOptions<'a, EncodedKey<Self>>,
key: &EncodedKey<Self>,
) -> Result<Option<Self>> {
if let Some(data) = db.get(options, key)? {
Ok(Some(bincode::deserialize(&data)?))
} else {
Ok(None)
}
}
fn get(db: &Database<EncodedKey<Self>>, key: &EncodedKey<Self>) -> Result<Option<Self>> {
Self::get_with_option(db, ReadOptions::new(), key)
}
fn delete(db: &Database<EncodedKey<Self>>, sync: bool, key: &EncodedKey<Self>) -> Result<()> {
db.delete(leveldb::options::WriteOptions { sync }, key)
.map_err(|e| e.into())
}
}
pub trait WritebatchOrm<'a>: KVOrm<'a> {
fn put_batch(&self, batch: &mut Writebatch<EncodedKey<Self>>) -> Result<()> {
let key = self.key()?;
let value = self.encode()?;
batch.put(key, &value);
Ok(())
}
}
impl<'a, T: KeyOrm<'a> + Serialize + DeserializeOwned> KVOrm<'a> for T {}
impl<'a, T: KVOrm<'a>> WritebatchOrm<'a> for T {}