use super::*; use db_key::Key; use leveldb::database::kv::KV; use leveldb::database::Database; use leveldb::error::Error as LevelDBError; use leveldb::options::{Options, ReadOptions, WriteOptions}; use parking_lot::RwLock; use std::path::Path; pub struct LevelDB { db: RwLock>, } impl LevelDB { pub fn open(path: &Path) -> Result { let mut options = Options::new(); options.create_if_missing = true; let db = Database::open(path, options)?; Ok(Self { db: RwLock::new(db), }) } fn read_options(&self) -> ReadOptions { ReadOptions::new() } fn write_options(&self) -> WriteOptions { WriteOptions::new() } fn get_key_for_col(col: &str, key: &[u8]) -> BytesKey { let mut col = col.as_bytes().to_vec(); col.append(&mut key.to_vec()); BytesKey { key: col } } } pub struct BytesKey { key: Vec, } impl Key for BytesKey { fn from_u8(key: &[u8]) -> Self { Self { key: key.to_vec() } } fn as_slice T>(&self, f: F) -> T { f(self.key.as_slice()) } } impl Store for LevelDB { fn get_bytes(&self, col: &str, key: &[u8]) -> Result, Error> { let column_key = Self::get_key_for_col(col, key); self.db .read() .get(self.read_options(), column_key) .map_err(Into::into) } fn put_bytes(&self, col: &str, key: &[u8], val: &[u8]) -> Result<(), Error> { let column_key = Self::get_key_for_col(col, key); self.db .write() .put(self.write_options(), column_key, val) .map_err(Into::into) } fn key_exists(&self, col: &str, key: &[u8]) -> Result { let column_key = Self::get_key_for_col(col, key); self.db .read() .get(self.read_options(), column_key) .map_err(Into::into) .and_then(|val| Ok(val.is_some())) } fn key_delete(&self, col: &str, key: &[u8]) -> Result<(), Error> { let column_key = Self::get_key_for_col(col, key); self.db .write() .delete(self.write_options(), column_key) .map_err(Into::into) } } impl From for Error { fn from(e: LevelDBError) -> Error { Error::DBError { message: format!("{:?}", e), } } }