use std::hash::Hash;
use std::io::Result;
use std::path::Path;
pub mod filedb;
pub mod memdb;
pub use filedb::{DbBytes, DbInt, DbString};
pub use filedb::{DbXxxIter, DbXxxIterMut};
pub fn open_memory<'a>() -> memdb::MemoryDb<'a> {
memdb::MemoryDb::open()
}
pub fn open_file<P: AsRef<Path>>(path: P) -> Result<filedb::FileDb> {
filedb::FileDb::open(path)
}
pub trait DbXxxBase {
fn read_fill_buffer(&mut self) -> Result<()>;
fn flush(&mut self) -> Result<()>;
fn sync_all(&mut self) -> Result<()>;
fn sync_data(&mut self) -> Result<()>;
}
pub trait DbXxxObjectSafe<KT: DbMapKeyType>: DbXxxBase {
fn get_kt(&mut self, key: &KT) -> Result<Option<Vec<u8>>>;
fn put_kt(&mut self, key: &KT, value: &[u8]) -> Result<()>;
fn del_kt(&mut self, key: &KT) -> Result<Option<Vec<u8>>>;
}
pub trait DbXxx<KT: DbMapKeyType>: DbXxxObjectSafe<KT> {
#[inline]
fn get<'a, Q>(&mut self, key: &'a Q) -> Result<Option<Vec<u8>>>
where
KT: From<&'a Q>,
Q: Ord + ?Sized,
{
let key_kt: KT = From::from(key);
self.get_kt(&key_kt)
}
#[inline]
fn get_string<'a, Q>(&mut self, key: &'a Q) -> Result<Option<String>>
where
KT: From<&'a Q>,
Q: Ord + ?Sized,
{
self.get(key)
.map(|opt| opt.map(|val| String::from_utf8_lossy(&val).to_string()))
}
fn bulk_get<'a, Q>(&mut self, bulk_keys: &[&'a Q]) -> Result<Vec<Option<Vec<u8>>>>
where
KT: From<&'a Q>,
Q: Ord + ?Sized,
{
let mut result: Vec<(usize, Option<Vec<u8>>)> = Vec::new();
let mut vec: Vec<(usize, &Q)> =
bulk_keys.iter().enumerate().map(|(i, &a)| (i, a)).collect();
vec.sort_unstable_by(|a, b| b.1.cmp(a.1));
while let Some(ik) = vec.pop() {
let result_value = self.get(ik.1)?;
result.push((ik.0, result_value));
}
result.sort_by(|a, b| a.0.cmp(&(b.0)));
let ret: Vec<Option<Vec<u8>>> = result.iter().map(|a| a.1.clone()).collect();
Ok(ret)
}
#[inline]
fn bulk_get_string<'a, Q>(&mut self, bulk_keys: &[&'a Q]) -> Result<Vec<Option<String>>>
where
KT: From<&'a Q>,
Q: Ord + ?Sized,
{
let vec = self.bulk_get(bulk_keys)?;
let mut ret = Vec::new();
for opt in vec {
let b = opt.map(|val| String::from_utf8_lossy(&val).to_string());
ret.push(b);
}
Ok(ret)
}
#[inline]
fn put<'a, Q>(&mut self, key: &'a Q, value: &[u8]) -> Result<()>
where
KT: From<&'a Q>,
Q: Ord + ?Sized,
{
let key_kt: KT = From::from(key);
self.put_kt(&key_kt, value)
}
#[inline]
fn put_string<'a, Q>(&mut self, key: &'a Q, value: &str) -> Result<()>
where
KT: From<&'a Q>,
Q: Ord + ?Sized,
{
self.put(key, value.as_bytes())
}
fn bulk_put<'a, Q>(&mut self, bulk: &[(&'a Q, &[u8])]) -> Result<()>
where
KT: From<&'a Q>,
Q: Ord + ?Sized,
{
let mut vec = bulk.to_vec();
vec.sort_by(|a, b| b.0.cmp(a.0));
while let Some(kv) = vec.pop() {
self.put(kv.0, kv.1)?;
}
Ok(())
}
#[inline]
fn bulk_put_string<'a, Q>(&mut self, bulk: &[(&'a Q, String)]) -> Result<()>
where
KT: From<&'a Q>,
Q: Ord + ?Sized,
{
let mut vec = bulk.to_vec();
vec.sort_unstable_by(|a, b| b.0.cmp(a.0));
while let Some(kv) = vec.pop() {
self.put(kv.0, kv.1.as_bytes())?;
}
Ok(())
}
#[inline]
fn delete<'a, Q>(&mut self, key: &'a Q) -> Result<Option<Vec<u8>>>
where
KT: From<&'a Q>,
Q: Ord + ?Sized,
{
let key_kt: KT = From::from(key);
self.del_kt(&key_kt)
}
#[inline]
fn delete_string<'a, Q>(&mut self, key: &'a Q) -> Result<Option<String>>
where
KT: From<&'a Q>,
Q: Ord + ?Sized,
{
self.delete(key)
.map(|opt| opt.map(|val| String::from_utf8_lossy(&val).to_string()))
}
fn bulk_delete<'a, Q>(&mut self, bulk_keys: &[&'a Q]) -> Result<Vec<Option<Vec<u8>>>>
where
KT: From<&'a Q>,
Q: Ord + ?Sized,
{
let mut result: Vec<(usize, Option<Vec<u8>>)> = Vec::new();
let mut vec: Vec<(usize, &Q)> =
bulk_keys.iter().enumerate().map(|(i, &a)| (i, a)).collect();
vec.sort_unstable_by(|a, b| b.1.cmp(a.1));
while let Some(ik) = vec.pop() {
let result_value = self.delete(ik.1)?;
result.push((ik.0, result_value));
}
result.sort_by(|a, b| a.0.cmp(&(b.0)));
let ret: Vec<Option<Vec<u8>>> = result.iter().map(|a| a.1.clone()).collect();
Ok(ret)
}
#[inline]
fn bulk_delete_string<'a, Q>(&mut self, bulk_keys: &[&'a Q]) -> Result<Vec<Option<String>>>
where
KT: From<&'a Q>,
Q: Ord + ?Sized,
{
let vec = self.bulk_delete(bulk_keys)?;
let mut ret = Vec::new();
for opt in vec {
let b = opt.map(|val| String::from_utf8_lossy(&val).to_string());
ret.push(b);
}
Ok(ret)
}
}
pub trait DbMap<KT: DbMapKeyType>: DbXxx<KT> {
fn iter(&self) -> DbXxxIter<KT>;
fn iter_mut(&mut self) -> DbXxxIterMut<KT>;
}
pub trait DbMapDbString: DbXxx<DbString> {}
pub trait DbMapDbInt: DbXxx<DbInt> {}
pub trait DbMapDbBytes: DbXxx<DbBytes> {}
pub trait DbMapKeyType: Ord + Clone + Default + HashValue {
fn from_bytes(bytes: &[u8]) -> Self;
fn signature() -> [u8; 8];
fn as_bytes(&self) -> &[u8];
fn cmp_u8(&self, other: &[u8]) -> std::cmp::Ordering;
#[cfg(feature = "tr_has_short_key")]
fn as_short_bytes(&self) -> Option<&[u8]> {
let b_sl = self.as_bytes();
if b_sl.len() <= 32 {
Some(b_sl)
} else {
None
}
}
}
pub trait HashValue: Hash {
fn hash_value(&self) -> u64 {
use std::hash::Hasher;
#[cfg(not(feature = "myhasher"))]
let mut hasher = std::collections::hash_map::DefaultHasher::new();
#[cfg(feature = "myhasher")]
let mut hasher = MyHasher::default();
self.hash(&mut hasher);
hasher.finish()
}
}
#[derive(Default)]
struct MyHasher(u64);
impl std::hash::Hasher for MyHasher {
fn finish(&self) -> u64 {
self.0
}
fn write(&mut self, bytes: &[u8]) {
for chunk8 in bytes.chunks(8) {
let len = chunk8.len();
if len == 8 {
let mut ary = [0u8; 8];
ary.copy_from_slice(chunk8);
let a = u64::from_le_bytes(ary);
self.0 = _xorshift64s(self.0.wrapping_add(a));
} else {
let mut a = 0;
for b in chunk8 {
a = (a << 8) | *b as u64;
}
self.0 = _xorshift64s(self.0.wrapping_add(a));
}
}
}
}
#[inline]
fn _xorshift64s(a: u64) -> u64 {
let mut x = a;
x ^= x >> 12;
x ^= x << 25;
x ^= x >> 27;
x
}